[
  {
    "path": ".claude/CLAUDE.md",
    "content": "# CLAUDE.md\n\nWrenAI is an open-source GenBI (Generative BI) agent that converts natural language questions into SQL queries and charts. It uses a semantic layer (MDL - Metadata Definition Language) to guide LLM-powered text-to-SQL generation via retrieval-augmented generation (RAG).\n\n## Repository Structure\n\nThis is a monorepo with three main services:\n\n- **wren-ui/** — Next.js 14 frontend + Apollo GraphQL backend (TypeScript, Yarn 4.5.3)\n- **wren-ai-service/** — AI/LLM service (Python 3.12, FastAPI, Poetry, Just command runner)\n- **wren-launcher/** — CLI deployment tool (Go 1.18+, Make)\n- **docker/** — Docker Compose configs for running all services together\n- **deployment/** — Kubernetes/Kustomize manifests\n- **wren-engine/** — SQL engine (git submodule, not developed here)\n- **wren-mdl/** — MDL JSON schema definitions\n\n## Build, Test, and Lint Commands\n\n### wren-ui (TypeScript/Next.js)\n\n```bash\ncd wren-ui\nyarn install\nyarn dev                # Dev server on port 3000 (TZ=UTC)\nyarn build              # Production build (max-old-space-size=8192)\nyarn lint               # TypeScript type check + ESLint\nyarn check-types        # tsc --noEmit\nyarn test               # Jest unit tests\nyarn test:e2e           # Playwright E2E tests (installs chromium)\nyarn migrate            # Knex database migrations\nyarn rollback           # Knex migration rollback\nyarn generate-gql       # GraphQL codegen from codegen.yaml\n```\n\nEnvironment: set `DB_TYPE=sqlite` (default) or `DB_TYPE=pg` with PostgreSQL connection vars. The UI needs `WREN_ENGINE_ENDPOINT`, `WREN_AI_ENDPOINT`, and `IBIS_SERVER_ENDPOINT` to connect to backend services.\n\n### wren-ai-service (Python/FastAPI)\n\n```bash\ncd wren-ai-service\npoetry install\njust init               # Creates config.yaml and .env.dev from examples\njust up                 # Start dev Docker services (Qdrant, engine, etc.)\njust start              # Run AI service (poetry run python -m src.__main__)\njust test               # pytest (spins up Docker deps, ignores usecases)\njust test [test_args]   # e.g., just test tests/pytest/pipelines/\njust test-usecases      # Run use-case integration tests\njust down               # Stop Docker services\njust load-test          # Locust load tests\n```\n\nConfiguration is via `config.yaml` (multi-document YAML with sections for LLM, embedder, engine, document_store, pipeline, and settings). Environment variables in `.env.dev` (API keys). Settings load order: defaults → env vars → .env.dev → config.yaml.\n\nPre-commit hooks: `poetry run pre-commit install` then `poetry run pre-commit run --all-files`\n\n### wren-launcher (Go)\n\n```bash\ncd wren-launcher\nmake build              # Cross-compile for macOS/Linux/Windows\nmake test               # go test ./...\nmake check              # fmt + vet + lint (golangci-lint)\nmake lint-fix           # Auto-fix lint issues\n```\n\n## Architecture\n\n### Service Communication Flow\n\n```\nUser → Wren UI (Next.js :3000)\n         ↓ GraphQL (Apollo Server embedded in Next.js API routes)\n       Apollo Server → Wren AI Service (FastAPI :5556) [HTTP REST]\n                     → Wren Engine (:8080) [SQL validation/execution]\n                     → Ibis Server (:8000) [SQL abstraction for data sources]\n       Wren AI Service → Qdrant (:6333) [vector search for RAG]\n                       → LLM Provider (OpenAI/Azure/etc.) [text-to-SQL generation]\n```\n\n### Wren UI Internal Architecture\n\nThe Next.js app embeds an Apollo GraphQL server in its API routes (`src/apollo/`):\n\n- **`src/apollo/server/resolvers/`** — GraphQL resolvers (asking, model, project, dashboard, etc.)\n- **`src/apollo/server/services/`** — Business logic layer (askingService, deployService, mdlService, queryService, etc.)\n- **`src/apollo/server/repositories/`** — Data access layer using Knex (SQLite or PostgreSQL)\n- **`src/apollo/server/adaptors/`** — External service adapters (AI service, engine)\n- **`src/apollo/client/`** — Frontend GraphQL operations\n- **`src/components/`** — React components organized by page (home, setup, modeling, knowledge)\n- **`src/pages/`** — Next.js page routes\n\nPath aliases: `@/*` → `./src/*`, `@server/*` → `./src/apollo/server/*`\n\n### Wren AI Service Internal Architecture\n\nThe Python service uses a pipeline-based architecture:\n\n- **`src/pipelines/`** — RAG pipeline implementations:\n  - `indexing/` — MDL schema, table descriptions, historical questions, SQL pairs → Qdrant\n  - `retrieval/` — Semantic search for relevant context from Qdrant\n  - `generation/` — SQL generation, chart generation, intent classification\n  - `ask/` — Orchestrates retrieval + generation for text-to-SQL\n  - `ask_details/` — SQL breakdown and explanation\n  - `semantics/` — Semantic processing helpers\n- **`src/web/v1/services/`** — Service layer (AskService, SemanticsPreparationService, ChartService, SqlPairsService, etc.)\n- **`src/web/v1/routers/`** — FastAPI route handlers\n- **`src/core/`** — Base abstractions (pipeline, provider, engine interfaces)\n- **`src/globals.py`** — ServiceContainer wiring all services and pipelines together\n- **`src/config.py`** — Pydantic Settings with all configuration knobs\n\nPipelines are configured declaratively in `config.yaml`, wiring LLM providers, embedders, document stores, and engines to named pipeline components.\n\n### Data Flow for \"Ask\" (Text-to-SQL)\n\n1. User submits natural language question in UI\n2. UI sends GraphQL mutation to Apollo Server\n3. Apollo Server calls AI Service REST API\n4. AI Service runs intent classification → retrieves relevant schema/context from Qdrant → generates SQL via LLM\n5. Generated SQL is validated against Wren Engine\n6. SQL corrections are attempted if validation fails (up to `max_sql_correction_retries`)\n7. Results returned through the chain back to UI\n\n### MDL (Metadata Definition Language)\n\nThe semantic layer that maps business concepts to database schema. Defines models, columns, relationships, metrics, and calculated fields. MDL is indexed into Qdrant as vector embeddings to provide context for LLM SQL generation. Schema defined in `wren-mdl/mdl.schema.json`.\n\n## Docker Development\n\nTo run the full stack locally:\n```bash\ncd docker\ncp .env.example .env.local    # Configure API keys and ports\ncp config.example.yaml config.yaml\ndocker compose --env-file .env.local up -d\n```\n\nFor developing a single service while others run in Docker, use `docker-compose-dev.yaml` in the AI service's `tools/dev/` directory.\n\n## Commit Convention\n\nFollows conventional commits: `type(scope): description`\n- Scopes: `wren-ui`, `wren-ai-service`, `wren-launcher`\n- Types: `feat`, `fix`, `chore`, `refactor`\n- Examples: `feat(wren-ui): add dashboard widget`, `fix(wren-ai-service): handle empty MDL`\n\n## CI/CD\n\n- PR labels trigger service-specific CI: `ci/ui` for UI tests/lint, `ci/ai-service` for AI service tests\n- Docker images published to `ghcr.io/canner/`\n"
  },
  {
    "path": ".claude/settings.json",
    "content": "{\n  \"permissions\": {\n    \"allow\": [\n      \"Bash(cd wren-ui && yarn:*)\",\n      \"Bash(cd wren-ai-service && just:*)\",\n      \"Bash(cd wren-ai-service && poetry run:*)\",\n      \"Bash(cd wren-ai-service && poetry install:*)\",\n      \"Bash(cd wren-launcher && make:*)\",\n      \"Bash(git status:*)\",\n      \"Bash(git diff:*)\",\n      \"Bash(git log:*)\",\n      \"Bash(git branch:*)\",\n      \"Bash(gh pr:*)\",\n      \"Bash(gh run:*)\",\n      \"Bash(ls:*)\",\n      \"Bash(wc:*)\"\n    ]\n  }\n}\n"
  },
  {
    "path": ".editorconfig",
    "content": "# Editor configuration, see http://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.md]\nmax_line_length = off\ntrim_trailing_whitespace = false\n\n# Makefile\n[Makefile]\nindent_style = tab\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Desktop (please complete the following information):**\n- OS: [e.g. iOS]\n- Browser [e.g. chrome, safari]\n\n**Wren AI Information**\n- Version: [e.g, 0.1.0]\n\n**Additional context**\nAdd any other context about the problem here.\n\n**Relevant log output**\n- Please share `config.yaml` with us, it should be located at `~/.wrenai/config.yaml`.\n- Please share your logs with us with the following command:\n    ```bash\n    docker logs wrenai-wren-ui-1 >& wrenai-wren-ui.log && \\\n    docker logs wrenai-wren-ai-service-1 >& wrenai-wren-ai-service.log && \\\n    docker logs wrenai-wren-engine-1 >& wrenai-wren-engine.log && \\\n    docker logs wrenai-ibis-server-1 >& wrenai-ibis-server.log\n    ```\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: feature-request\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/dependabot.yaml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"pip\"\n    directory: \"/wren-ai-service\"\n    schedule:\n      interval: \"weekly\"\n    groups:\n      all:\n        patterns: [\"*\"]\n    commit-message:\n      prefix: \"chore(wren-ai-service)\"\n    labels:\n      - \"dependencies\"\n      - \"python\"\n      - \"ci/ai-service\"\n      - \"module/ai-service\"\n"
  },
  {
    "path": ".github/workflows/ai-service-release-image.yaml",
    "content": "name: AI Service Release image\n\non:\n  workflow_dispatch:\n    inputs:\n      tag_name:\n        description: Docker image tag name (Optional)\n        type: string\n\nenv:\n  WREN_AI_SERVICE_IMAGE: ghcr.io/canner/wren-ai-service\n\ndefaults:\n  run:\n    working-directory: wren-ai-service\n\njobs:\n  build-image:\n    outputs:\n      tag_name: ${{ steps.tag-preparation.outputs.TAG_NAME }}\n    strategy:\n      fail-fast: false\n      matrix:\n        arch:\n          - runner: ubuntu-latest\n            platform: linux/amd64\n          - runner: linux_arm64_runner\n            platform: linux/arm64\n    runs-on: ${{ matrix.arch.runner }}\n    steps:\n      - uses: actions/checkout@v4\n      - name: Login to GitHub Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: Prepare tag name\n        id: tag-preparation\n        run: |\n          if [ -n \"${{ github.event.inputs.tag_name }}\" ]; then\n            tag_name=${{ github.event.inputs.tag_name }}\n          else\n            tag_name=commit-$(git log -1 --pretty=%h)\n          fi\n          echo \"TAG_NAME=$tag_name\" >> $GITHUB_OUTPUT\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n      - name: Prepare platform\n        run: |\n          platform=${{ matrix.arch.platform }}\n          echo \"PLATFORM_PAIR=${platform//\\//-}\" >> $GITHUB_ENV\n      - name: Build and push by digest\n        id: build\n        uses: docker/build-push-action@v6\n        with:\n          platforms: ${{ matrix.arch.platform }}\n          labels: ${{ env.WREN_AI_SERVICE_IMAGE }}\n          context: ./wren-ai-service\n          file: ./wren-ai-service/docker/Dockerfile\n          outputs: type=image,name=${{ env.WREN_AI_SERVICE_IMAGE }},push-by-digest=true,name-canonical=true,push=true\n      - name: Export digest\n        run: |\n          mkdir -p /tmp/digests\n          digest=\"${{ steps.build.outputs.digest }}\"\n          touch \"/tmp/digests/${digest#sha256:}\"\n      - name: Upload digest\n        uses: actions/upload-artifact@v4\n        with:\n          name: digests-${{ env.PLATFORM_PAIR }}\n          path: /tmp/digests/*\n          if-no-files-found: error\n          retention-days: 1\n  merge:\n    runs-on: ubuntu-latest\n    needs: [ build-image ]\n    steps:\n      - name: Download digests\n        uses: actions/download-artifact@v4\n        with:\n          path: /tmp/digests\n          pattern: digests-*\n          merge-multiple: true\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n      - name: Docker meta\n        id: meta\n        uses: docker/metadata-action@v5\n        with:\n          images: ${{ env.WREN_AI_SERVICE_IMAGE }}\n          tags: |\n            ${{ needs.build-image.outputs.tag_name }}\n      - name: Login to GitHub Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: Create manifest list and push\n        working-directory: /tmp/digests\n        run: |\n          TAGS=$(echo \"${{ steps.meta.outputs.tags }}\" | awk '{printf \"--tag %s \", $0}')\n          docker buildx imagetools create $(jq -cr '.tags | map(\"-t \" + .) | join(\" \")' <<< \"$DOCKER_METADATA_OUTPUT_JSON\") \\\n            $(printf '${{ env.WREN_AI_SERVICE_IMAGE }}@sha256:%s ' *) \\\n            $TAGS\n"
  },
  {
    "path": ".github/workflows/ai-service-release-nightly-image.yaml",
    "content": "name: AI Service Release nightly image\n\non:\n  push:\n    branches: [main]\n    paths:\n      - 'wren-ai-service/**'\n\nenv:\n  WREN_AI_SERVICE_IMAGE: ghcr.io/canner/wren-ai-service\n\ndefaults:\n  run:\n    working-directory: wren-ai-service\n\njobs:\n  build-image:\n    outputs:\n      tag_name: ${{ steps.tag-preparation.outputs.TAG_NAME }}\n    strategy:\n      fail-fast: false\n      matrix:\n        arch:\n          - runner: ubuntu-latest\n            platform: linux/amd64\n          - runner: linux_arm64_runner\n            platform: linux/arm64\n    runs-on: ${{ matrix.arch.runner }}\n    steps:\n      - uses: actions/checkout@v4\n      - name: Login to GitHub Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: Prepare tag name\n        id: tag-preparation\n        run: |\n          tag_name=main-$(git log -1 --pretty=%h)\n          echo \"TAG_NAME=$tag_name\" >> $GITHUB_OUTPUT\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n      - name: Prepare platform\n        run: |\n          platform=${{ matrix.arch.platform }}\n          echo \"PLATFORM_PAIR=${platform//\\//-}\" >> $GITHUB_ENV\n      - name: Build and push by digest\n        id: build\n        uses: docker/build-push-action@v6\n        with:\n          platforms: ${{ matrix.arch.platform }}\n          labels: ${{ env.WREN_AI_SERVICE_IMAGE }}\n          context: ./wren-ai-service\n          file: ./wren-ai-service/docker/Dockerfile\n          outputs: type=image,name=${{ env.WREN_AI_SERVICE_IMAGE }},push-by-digest=true,name-canonical=true,push=true\n      - name: Export digest\n        run: |\n          mkdir -p /tmp/digests\n          digest=\"${{ steps.build.outputs.digest }}\"\n          touch \"/tmp/digests/${digest#sha256:}\"\n      - name: Upload digest\n        uses: actions/upload-artifact@v4\n        with:\n          name: digests-${{ env.PLATFORM_PAIR }}\n          path: /tmp/digests/*\n          if-no-files-found: error\n          retention-days: 1\n  merge:\n    runs-on: ubuntu-latest\n    needs: [ build-image ]\n    steps:\n      - name: Download digests\n        uses: actions/download-artifact@v4\n        with:\n          path: /tmp/digests\n          pattern: digests-*\n          merge-multiple: true\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n      - name: Docker meta\n        id: meta\n        uses: docker/metadata-action@v5\n        with:\n          images: ${{ env.WREN_AI_SERVICE_IMAGE }}\n          tags: |\n            type=raw,${{ needs.build-image.outputs.tag_name }}\n            type=raw,nightly\n      - name: Login to GitHub Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: Create manifest list and push\n        working-directory: /tmp/digests\n        run: |\n          TAGS=$(echo \"${{ steps.meta.outputs.tags }}\" | awk '{printf \"--tag %s \", $0}')\n          docker buildx imagetools create $(jq -cr '.tags | map(\"-t \" + .) | join(\" \")' <<< \"$DOCKER_METADATA_OUTPUT_JSON\") \\\n            $(printf '${{ env.WREN_AI_SERVICE_IMAGE }}@sha256:%s ' *) \\\n            $TAGS\n"
  },
  {
    "path": ".github/workflows/ai-service-release-stable-image.yaml",
    "content": "name: AI Service Release stable image\n\non:\n  workflow_dispatch:\n    inputs:\n      version:\n        description: Give a version for this release\n        type: string\n        required: true\n\nenv:\n  WREN_AI_SERVICE_IMAGE: ghcr.io/canner/wren-ai-service\n\ndefaults:\n  run:\n    working-directory: wren-ai-service\n\njobs:\n  upgrade-ai-service-version:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Generate a token\n        id: generate-token\n        uses: actions/create-github-app-token@v1\n        with:\n          app-id: ${{ vars.CI_APP_ID }}\n          private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}\n      - uses: actions/checkout@v4\n        with:\n          token: ${{ steps.generate-token.outputs.token }}\n          fetch-depth: 0\n      - name: Set up Git\n        run: |\n          git config --global user.name \"wren-ai[bot]\"\n          git config --global user.email \"dev@cannerdata.com\"\n      - name: Set up Python 3.12.0\n        uses: actions/setup-python@v4\n        with:\n          python-version: 3.12.0\n      - name: Install Poetry\n        uses: abatilo/actions-poetry@v2\n        with:\n          poetry-version: 1.8.3\n      - name: Generate and Save Change Log\n        id: changelog\n        run: |\n          echo \"Generating change log...\"\n          PREVIOUS_VERSION=release/ai-service/$(poetry version -s)\n          echo \"Previous version: $PREVIOUS_VERSION\"\n\n          # Get the change log from the previous version to the current HEAD\n          # If there is no change log, the command will return an error, so we use || true to ignore the error\n          CHANGE_LOG=$(git log --pretty=format:\"%s\" $PREVIOUS_VERSION..HEAD | grep wren-ai-service || true)\n\n          # Separate the change log into categories\n          FEATURES=$(echo \"$CHANGE_LOG\" | grep \"^feat\" | sed 's/^/- /')\n          FIXES_AND_CHORES=$(echo \"$CHANGE_LOG\" | grep -E \"^(fix|chore)\" | sed 's/^/- /')\n\n          # Create the full change log\n          FULL_CHANGE_LOG=\"\\nChangelog for the version\\n\"\n          if [ -n \"$FEATURES\" ]; then\n            FULL_CHANGE_LOG+=\"\\nFeature and Enhancement\\n$FEATURES\"\n          fi\n          if [ -n \"$FIXES_AND_CHORES\" ]; then\n            FULL_CHANGE_LOG+=\"\\n\\nFixes and Chores\\n$FIXES_AND_CHORES\"\n          fi\n\n          {\n            echo \"CHANGE_LOG<<EOF\"\n            echo -e \"$FULL_CHANGE_LOG\"\n            echo EOF\n          } >> $GITHUB_ENV\n      - name: Upgrade AI Service version\n        run: |\n          version=${{ github.event.inputs.version }}\n          poetry version --next-phase $version\n          git add pyproject.toml\n          git commit -m \"Upgrade AI Service version to $version\"\n          git push\n          git tag -a \"release/ai-service/$version\" -m \"${{ env.CHANGE_LOG }}\"\n          git push origin \"release/ai-service/$version\"\n  build-image:\n    needs: upgrade-ai-service-version\n    strategy:\n      fail-fast: false\n      matrix:\n        arch:\n          - runner: ubuntu-latest\n            platform: linux/amd64\n          - runner: linux_arm64_runner\n            platform: linux/arm64\n    runs-on: ${{ matrix.arch.runner }}\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ github.ref }}\n      - name: Login to GitHub Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n      - name: Prepare platform\n        run: |\n          platform=${{ matrix.arch.platform }}\n          echo \"PLATFORM_PAIR=${platform//\\//-}\" >> $GITHUB_ENV\n      - name: Build and push by digest\n        id: build\n        uses: docker/build-push-action@v6\n        with:\n          platforms: ${{ matrix.arch.platform }}\n          labels: ${{ env.WREN_AI_SERVICE_IMAGE }}\n          context: ./wren-ai-service\n          file: ./wren-ai-service/docker/Dockerfile\n          outputs: type=image,name=${{ env.WREN_AI_SERVICE_IMAGE }},push-by-digest=true,name-canonical=true,push=true\n      - name: Export digest\n        run: |\n          mkdir -p /tmp/digests\n          digest=\"${{ steps.build.outputs.digest }}\"\n          touch \"/tmp/digests/${digest#sha256:}\"\n      - name: Upload digest\n        uses: actions/upload-artifact@v4\n        with:\n          name: digests-${{ env.PLATFORM_PAIR }}\n          path: /tmp/digests/*\n          if-no-files-found: error\n          retention-days: 1\n  merge:\n    runs-on: ubuntu-latest\n    needs: [ build-image ]\n    steps:\n      - name: Download digests\n        uses: actions/download-artifact@v4\n        with:\n          path: /tmp/digests\n          pattern: digests-*\n          merge-multiple: true\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n      - name: Docker meta\n        id: meta\n        uses: docker/metadata-action@v5\n        with:\n          images: ${{ env.WREN_AI_SERVICE_IMAGE }}\n          tags: |\n            type=raw,${{ github.event.inputs.version }}\n            type=raw,latest\n      - name: Login to GitHub Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: Create manifest list and push\n        working-directory: /tmp/digests\n        run: |\n          TAGS=$(echo \"${{ steps.meta.outputs.tags }}\" | awk '{printf \"--tag %s \", $0}')\n          docker buildx imagetools create $(jq -cr '.tags | map(\"-t \" + .) | join(\" \")' <<< \"$DOCKER_METADATA_OUTPUT_JSON\") \\\n            $(printf '${{ env.WREN_AI_SERVICE_IMAGE }}@sha256:%s ' *) \\\n            $TAGS\n"
  },
  {
    "path": ".github/workflows/ai-service-test.yaml",
    "content": "# This workflow will install Python dependencies, run tests and lint with a single version of Python\n# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python\n\nname: AI Service Test\n\non:\n  push:\n    branches:\n      - main\n    paths:\n      - \"wren-ai-service/**\"\n  pull_request:\n    types: [synchronize, labeled]\n  workflow_dispatch:\n\npermissions:\n  contents: read\n\nconcurrency:\n  # avoid mis-canceling the ci runs while other labels are added to the PR, so we add the label name as the condition\n  group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.event.label.name == 'ci/ai-service' && github.event.number || github.sha }}\n  cancel-in-progress: true\n\ndefaults:\n  run:\n    working-directory: wren-ai-service\n\njobs:\n  pytest:\n    if: ${{ contains(github.event.pull_request.labels.*.name, 'ci/ai-service') || github.event_name == 'push' }}\n    runs-on: ubuntu-22.04\n    timeout-minutes: 10\n    steps:\n      - uses: actions/checkout@v4\n      - name: Install Poetry\n        uses: abatilo/actions-poetry@v3\n        with:\n          poetry-version: \"1.8.3\"\n      - name: Set up Python\n        uses: actions/setup-python@v5\n        with:\n          python-version-file: ./wren-ai-service/pyproject.toml\n          cache: \"poetry\"\n      - name: Install the project dependencies\n        run: poetry install --without eval\n      - name: Install Just\n        uses: extractions/setup-just@v2\n        with:\n          just-version: \"1.36.0\"\n      - name: Initialize the config\n        run: |\n          just init --non-dev\n      - name: Prepare testing environment and Run tests\n        run: |\n          just test\n        env:\n          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}\n"
  },
  {
    "path": ".github/workflows/create-rc-release-pr.yaml",
    "content": "name: Create RC Release PR\n\non:\n  workflow_dispatch:\n    inputs:\n      release_version:\n        description: \"Release version (e.g., 0.23.0-rc.1)\"\n        required: true\n      ui_version:\n        description: \"UI version (e.g., 0.22.0)\"\n        required: true\n      ai_version:\n        description: \"AI service version (e.g., 0.17.0)\"\n        required: true\n      engine_version:\n        description: \"Engine version (e.g., 0.14.7)\"\n        required: true\n\npermissions:\n  contents: write\n  pull-requests: write\n\njobs:\n  create-release-pr:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v3\n\n      - name: Setup Git Identity\n        run: |\n          git config --global user.name \"wren-ai[bot]\"\n          git config --global user.email \"dev@cannerdata.com\"\n\n      - name: Update docker.go\n        run: |\n          FILE_PATH=\"wren-launcher/utils/docker.go\"\n\n          # Replace the WREN_PRODUCT_VERSION value with the new release version\n          sed -i \"s/WREN_PRODUCT_VERSION\\s*string = \\\"[^\\\"]*\\\"/WREN_PRODUCT_VERSION\\tstring = \\\"${{ github.event.inputs.release_version }}\\\"/\" $FILE_PATH\n\n          # Verify the changes\n          grep \"WREN_PRODUCT_VERSION\" $FILE_PATH\n\n      - name: Update .env.example\n        run: |\n          FILE_PATH=\"docker/.env.example\"\n\n          # Update all versions in the .env.example file\n          sed -i \"s/WREN_PRODUCT_VERSION=.*/WREN_PRODUCT_VERSION=${{ github.event.inputs.release_version }}/\" $FILE_PATH\n          sed -i \"s/WREN_ENGINE_VERSION=.*/WREN_ENGINE_VERSION=${{ github.event.inputs.engine_version }}/\" $FILE_PATH\n          sed -i \"s/IBIS_SERVER_VERSION=.*/IBIS_SERVER_VERSION=${{ github.event.inputs.engine_version }}/\" $FILE_PATH\n          sed -i \"s/WREN_AI_SERVICE_VERSION=.*/WREN_AI_SERVICE_VERSION=${{ github.event.inputs.ai_version }}/\" $FILE_PATH\n          sed -i \"s/WREN_UI_VERSION=.*/WREN_UI_VERSION=${{ github.event.inputs.ui_version }}/\" $FILE_PATH\n\n          # Verify the changes\n          grep \"VERSION\" $FILE_PATH\n\n      - name: Show git status\n        run: git status\n\n      - name: Show git diff\n        run: |\n          echo \"===== Git diff for changed files =====\"\n          git diff\n\n      - name: Create PR\n        uses: peter-evans/create-pull-request@v7\n        with:\n          base: main\n          branch: \"release/${{ github.event.inputs.release_version }}\"\n          commit-message: \"release ${{ github.event.inputs.release_version }}\"\n          title: \"Release ${{ github.event.inputs.release_version }}\"\n          body: \"Release ${{ github.event.inputs.release_version }}\"\n          draft: false\n"
  },
  {
    "path": ".github/workflows/create-rc-release.yaml",
    "content": "name: Create RC Release\n\non:\n  workflow_dispatch:\n    inputs:\n      release_version:\n        description: \"Release version\"\n        required: true\n  issue_comment:\n    types: [created]\n\njobs:\n  release:\n    runs-on: macos-latest\n    if: ${{ github.event_name == 'issue_comment' && contains(github.event.comment.body, '/release-rc') && startsWith(github.event.issue.title, 'Release') }}\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n        with:\n          ref: main\n\n      - name: Set up Go\n        uses: actions/setup-go@v4\n        with:\n          go-version: \"1.23.0\"\n\n      - name: Add rocket emoji to comment\n        run: |\n          curl -X POST -H \"Authorization: token ${{ secrets.GITHUB_TOKEN }}\" \\\n          -d '{\"body\": \"🚀 Starting the release process!\"}' \\\n          \"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments\"\n\n      - name: Parse release version from PR title\n        id: parse_release_version\n        env:\n          GITHUB_ISSUE_TITLE: ${{ github.event.issue.title }}\n        run: |\n          release_version=$(echo \"$GITHUB_ISSUE_TITLE\" | sed 's/ /\\n/g' | tail -n 1)\n          echo \"Release version: $release_version\"\n          echo \"release_version=$release_version\" >> $GITHUB_OUTPUT\n\n      - name: Build for macOS\n        working-directory: ./wren-launcher\n        run: |\n          mkdir -p dist\n          env GOARCH=amd64 GOOS=darwin CGO_ENABLED=1 go build -o dist/wren-launcher-darwin main.go\n          cd dist && chmod +x wren-launcher-darwin && tar zcvf wren-launcher-darwin.tar.gz wren-launcher-darwin\n\n      - name: Build for macOS(arm64)\n        working-directory: ./wren-launcher\n        run: |\n          mkdir -p dist\n          env GOARCH=arm64 GOOS=darwin CGO_ENABLED=1 go build -o dist/wren-launcher-darwin-arm64 main.go\n          cd dist && chmod +x wren-launcher-darwin-arm64 && tar zcvf wren-launcher-darwin-arm64.tar.gz wren-launcher-darwin-arm64\n\n      - name: Build for Linux\n        working-directory: ./wren-launcher\n        run: |\n          mkdir -p dist\n          env GOARCH=amd64 GOOS=linux CGO_ENABLED=0 go build -o dist/wren-launcher-linux main.go\n          cd dist && chmod +x wren-launcher-linux && tar zcvf wren-launcher-linux.tar.gz wren-launcher-linux\n\n      - name: Build for Linux(arm64)\n        working-directory: ./wren-launcher\n        run: |\n          mkdir -p dist\n          env GOARCH=arm64 GOOS=linux CGO_ENABLED=0 go build -o dist/wren-launcher-linux-arm64 main.go\n          cd dist && chmod +x wren-launcher-linux-arm64 && tar zcvf wren-launcher-linux-arm64.tar.gz wren-launcher-linux-arm64\n\n      - name: Build for Windows\n        working-directory: ./wren-launcher\n        run: |\n          mkdir -p dist\n          env GOARCH=amd64 GOOS=windows CGO_ENABLED=0 go build -o dist/wren-launcher-windows.exe main.go\n          cd dist && zip wren-launcher-windows.zip wren-launcher-windows.exe\n\n      - name: Create GitHub Release\n        uses: softprops/action-gh-release@v2\n        with:\n          files: |\n            ./wren-launcher/dist/wren-launcher-darwin.tar.gz\n            ./wren-launcher/dist/wren-launcher-linux.tar.gz\n            ./wren-launcher/dist/wren-launcher-windows.zip\n            ./wren-launcher/dist/wren-launcher-darwin-arm64.tar.gz\n            ./wren-launcher/dist/wren-launcher-linux-arm64.tar.gz\n          tag_name: ${{ steps.parse_release_version.outputs.release_version }}\n          prerelease: true\n          generate_release_notes: true\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Comment with release link\n        run: |\n          release_url=\"https://github.com/${{ github.repository }}/releases/tag/${{ steps.parse_release_version.outputs.release_version }}\"\n          curl -X POST -H \"Authorization: token ${{ secrets.GITHUB_TOKEN }}\" \\\n          -d \"{\\\"body\\\": \\\"🚀 A new release has been created! [View Release](${release_url})\\\"}\" \\\n          \"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments\"\n"
  },
  {
    "path": ".github/workflows/pr-tagger.yaml",
    "content": "name: PR Tagger\n\non:\n  pull_request:\n    types: [opened, synchronize, reopened]\n    paths:\n      - \"wren-ui/src/**\"\n      - \"deployment/**\"\n      - \"wren-launcher/**\"\n      - \"wren-ai-service/**\"\n      - \"docker/**\"\n\njobs:\n  tag-pr:\n    runs-on: ubuntu-latest\n    permissions:\n      pull-requests: write\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v3\n        with:\n          fetch-depth: 0\n\n      - name: Get changed files\n        id: changed-files\n        uses: tj-actions/changed-files@v46\n\n      - name: Tag PR based on changed files and title\n        uses: actions/github-script@v6\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          script: |\n            const changedFiles = '${{ steps.changed-files.outputs.all_changed_files }}'.split(' ');\n            const labels = new Set();\n\n            // Define label colors\n            const labelColors = {\n              'wren-ui': 'f29513',        // Orange\n              'launcher': 'f29513',       // Orange (same as wren-ui)\n              'wren-ai-service': 'f29513', // Orange (same as wren-ui)\n              'deployment': '0075ca',     // Blue\n              'ai-env-changed': 'd73a4a',  // Red\n              'ui-env-changed': 'd73a4a'   // Red\n            };\n\n\n            // Check for files in specific directories\n            for (const file of changedFiles) {\n              if (file.startsWith('wren-ui/src/')) {\n                labels.add('wren-ui');\n              } else if (file.startsWith('deployment/')) {\n                labels.add('deployment');\n              } else if (file.startsWith('wren-launcher/')) {\n                labels.add('launcher');\n              } else if (file.startsWith('wren-ai-service/')) {\n                labels.add('wren-ai-service');\n              } \n              if (file.startsWith('docker/') && file.includes('.example')) {\n                labels.add('ai-env-changed'); \n              }\n              if (file.startsWith('wren-ui/src/apollo/server/config.ts')) {\n                labels.add('ui-env-changed');\n              }\n            }\n\n            // Extract milestone from PR title\n            const prTitle = context.payload.pull_request.title;\n            const milestoneMatch = prTitle.match(/\\(milestone:\\s*([^)]+)\\)/i);\n\n            if (milestoneMatch && milestoneMatch[1]) {\n              const milestone = milestoneMatch[1].trim();\n              if (milestone) {\n                labels.add(milestone);\n                console.log(`Found milestone in PR title: ${milestone}`);\n              }\n            }\n\n            // Append env changed label to PR title\n            if (labels.has('ai-env-changed')) {\n              // check if pr title contains \"ai-env-changed\"\n              if (!prTitle.includes('ai-env-changed')) {\n                const newTitle = `${prTitle} (ai-env-changed)`;\n                await github.rest.issues.update({\n                  owner: context.repo.owner,\n                  repo: context.repo.repo,\n                  issue_number: context.issue.number,\n                  title: newTitle\n                });\n              }\n            }\n\n            if (labels.has('ui-env-changed')) {\n              // check if pr title contains \"ui-env-changed\"\n              if (!prTitle.includes('ui-env-changed')) {\n                const newTitle = `${prTitle} (ui-env-changed)`;\n                await github.rest.issues.update({\n                  owner: context.repo.owner,\n                  repo: context.repo.repo,\n                  issue_number: context.issue.number,\n                  title: newTitle\n                });\n              }\n            }\n\n            if (labels.size > 0) {\n              // Create or update labels with colors\n              for (const label of labels) {\n                try {\n                  // Try to create the label with color\n                  if (labelColors[label]) {\n                    await github.rest.issues.createLabel({\n                      owner: context.repo.owner,\n                      repo: context.repo.repo,\n                      name: label,\n                      color: labelColors[label]\n                    });\n                  }\n                } catch (error) {\n                  // Label already exists, update its color if needed\n                  if (labelColors[label]) {\n                    try {\n                      await github.rest.issues.updateLabel({\n                        owner: context.repo.owner,\n                        repo: context.repo.repo,\n                        name: label,\n                        color: labelColors[label]\n                      });\n                    } catch (updateError) {\n                      console.log(`Could not update color for label ${label}: ${updateError.message}`);\n                    }\n                  }\n                }\n              }\n              \n              // Add labels to PR\n              await github.rest.issues.addLabels({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                issue_number: context.issue.number,\n                labels: Array.from(labels)\n              });\n              \n              console.log(`Added labels: ${Array.from(labels).join(', ')}`);\n            } else {\n              console.log('No matching directories or milestone found');\n            }\n"
  },
  {
    "path": ".github/workflows/pull-request-title-validator.yaml",
    "content": "name: Pull Request Title Validator\n\non:\n  pull_request:\n    paths:\n      - \"wren-ai-service/**\"\n      - \".github/workflows/pull-request-title-validator.yaml\"\n      - \".github/workflows/ai-service-*.yaml\"\n    types: [opened, edited, synchronize]\n\npermissions:\n  pull-requests: read\n\njobs:\n  validator:\n    name: validate-pull-request-title\n    runs-on: ubuntu-latest\n    steps:\n      - name: validate pull request title\n        uses: kontrolplane/pull-request-title-validator@v1.3.1\n        with:\n          types: \"fix,feat,chore\"\n          scopes: \"wren-ai-service\""
  },
  {
    "path": ".github/workflows/ui-lint.yaml",
    "content": "# create the github action to run the yarn lint when PR created or pushed to main branch\n#\n\nname: Wren-UI Lint\n\non:\n  pull_request:\n    types: [ labeled, synchronize ]\n\npermissions:\n  contents: read\n\nconcurrency:\n  # avoid mis-canceling the ci runs while other labels are added to the PR, so we add the label name as the condition\n  group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.event.label.name == 'ci/ui' && github.event.number || github.sha }}\n  cancel-in-progress: true\n\ndefaults:\n  run:\n    working-directory: wren-ui\n\njobs:\n  eslint:\n     # run this job only if the PR is labeled with \"ci/ui\"\n    if: ${{ github.event.label.name == 'ci/ui' }}\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      - name: Set up Node.js\n        uses: actions/setup-node@v2\n        with:\n          node-version: '18'\n      - name: Get yarn cache directory path\n        id: yarn-cache-dir-path\n        run: echo \"::set-output name=dir::$(yarn cache dir)\"\n      - uses: actions/cache@v2\n        id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)\n        with:\n          path: | # should cache node_modules as well\n            ${{ steps.yarn-cache-dir-path.outputs.dir }}\n          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}\n          restore-keys: |\n            ${{ runner.os }}-yarn-\n      - if: ${{ steps.yarn-cache.outputs.cache-hit != 'true' }}\n        name: List the state of node modules\n        continue-on-error: true\n        run: yarn list\n      - name: Install Node.js dependencies\n        run: yarn install\n      - name: Run lint\n        run: yarn lint\n          "
  },
  {
    "path": ".github/workflows/ui-release-image-stable.yaml",
    "content": "name: Wren-UI Release stable image\n\non:\n  workflow_dispatch:\n    inputs:\n      version:\n        description: Give a version for this release\n        type: string\n        required: true\n\nenv:\n  WREN_UI_IMAGE: ghcr.io/canner/wren-ui\n\ndefaults:\n  run:\n    working-directory: wren-ui\n\njobs:\n  build-image:\n    strategy:\n      fail-fast: false\n      matrix:\n        arch:\n          - runner: ubuntu-latest\n            platform: linux/amd64\n          - runner: linux_arm64_runner\n            platform: linux/arm64\n    runs-on: ${{ matrix.arch.runner }}\n    steps:\n      - uses: actions/checkout@v4\n      - name: Login to GitHub Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n      - name: Prepare platform\n        run: |\n          platform=${{ matrix.arch.platform }}\n          echo \"PLATFORM_PAIR=${platform//\\//-}\" >> $GITHUB_ENV\n      - name: Build and push by digest\n        id: build\n        uses: docker/build-push-action@v6\n        with:\n          platforms: ${{ matrix.arch.platform }}\n          labels: ${{ env.WREN_UI_IMAGE }}\n          context: ./wren-ui\n          outputs: type=image,name=${{ env.WREN_UI_IMAGE }},push-by-digest=true,name-canonical=true,push=true\n      - name: Export digest\n        run: |\n          mkdir -p /tmp/digests\n          digest=\"${{ steps.build.outputs.digest }}\"\n          touch \"/tmp/digests/${digest#sha256:}\"\n      - name: Upload digest\n        uses: actions/upload-artifact@v4\n        with:\n          name: digests-${{ env.PLATFORM_PAIR }}\n          path: /tmp/digests/*\n          if-no-files-found: error\n          retention-days: 1\n  merge:\n    runs-on: ubuntu-latest\n    needs: [build-image]\n    steps:\n      - name: Download digests\n        uses: actions/download-artifact@v4\n        with:\n          path: /tmp/digests\n          pattern: digests-*\n          merge-multiple: true\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n      - name: Docker meta\n        id: meta\n        uses: docker/metadata-action@v5\n        with:\n          images: ${{ env.WREN_UI_IMAGE }}\n          tags: |\n            ${{ github.event.inputs.version }}\n      - name: Login to GitHub Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: Create manifest list and push\n        working-directory: /tmp/digests\n        # tag with input version and latest\n        run: |\n          TAGS=$(echo \"${{ steps.meta.outputs.tags }}\" | awk '{printf \"--tag %s \", $0}')\n          docker buildx imagetools create $(jq -cr '.tags | map(\"-t \" + .) | join(\" \")' <<< \"$DOCKER_METADATA_OUTPUT_JSON\") \\\n            $(printf '${{ env.WREN_UI_IMAGE }}@sha256:%s ' *) \\\n            $TAGS\n  tag-ui-version:\n    runs-on: ubuntu-latest\n    needs: [merge]\n    steps:\n      - name: Generate a token\n        id: generate-token\n        uses: actions/create-github-app-token@v1\n        with:\n          app-id: ${{ vars.CI_APP_ID }}\n          private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}\n      - uses: actions/checkout@v4\n        with:\n          token: ${{ steps.generate-token.outputs.token }}\n          fetch-depth: 0\n      - name: Set up Git\n        run: |\n          git config --global user.name \"wren-ai[bot]\"\n          git config --global user.email \"dev@cannerdata.com\"\n      - name: Generate and Save Change Log\n        id: changelog\n        run: |\n          echo \"Generating change log...\"\n          PREVIOUS_VERSION=release/ui/$(jq -r '.version' package.json)\n          echo \"Previous version: $PREVIOUS_VERSION\"\n          echo \"================ change log ================\"\n          CHANGE_LOG=$(git log --pretty=format:\"%s\" $PREVIOUS_VERSION..HEAD | grep wren-ui)\n          echo \"================ change log ================\"\n\n          # Separate the change log into categories\n          FEATURES=$(echo \"$CHANGE_LOG\" | grep \"^feat\" | sed 's/^/- /')\n          FIXES_AND_CHORES=$(echo \"$CHANGE_LOG\" | grep -E \"^(fix|chore)\" | sed 's/^/- /')\n\n          # Create the full change log\n          FULL_CHANGE_LOG=\"\\nChangelog for the version\\n\"\n          if [ -n \"$FEATURES\" ]; then\n            FULL_CHANGE_LOG+=\"\\nFeature and Enhancement\\n$FEATURES\"\n          fi\n          if [ -n \"$FIXES_AND_CHORES\" ]; then\n            FULL_CHANGE_LOG+=\"\\n\\nFixes and Chores\\n$FIXES_AND_CHORES\"\n          fi\n\n          {\n            echo \"CHANGE_LOG<<EOF\"\n            echo -e \"$FULL_CHANGE_LOG\"\n            echo EOF\n          } >> $GITHUB_ENV\n      - name: Update Wren-UI version\n        run: |\n          version=${{ github.event.inputs.version }}\n          sed -i 's/\"version\": \"[^\"]*\"/\"version\": \"'\"$version\"'\"/' package.json\n          git add package.json\n          git commit -m \"update wren-ui version to $version\"\n          git push\n          git tag -a \"release/ui/$version\" -m \"${{ env.CHANGE_LOG }}\"\n          git push origin \"release/ui/$version\"\n"
  },
  {
    "path": ".github/workflows/ui-release-image.yaml",
    "content": "name: Wren-UI Release image\n\non:\n  workflow_dispatch:\n    inputs:\n      docker_image_tag_name:\n        description: Docker image tag name (optional, default branch name/tag name replaced with hyphens)\n        type: string\n\nenv:\n  WREN_UI_IMAGE: ghcr.io/canner/wren-ui\n\ndefaults:\n  run:\n    working-directory: wren-ui\n\njobs:\n  build-image:\n    outputs:\n      tag_name: ${{ steps.tag-preparation.outputs.TAG_NAME }}\n    strategy:\n      fail-fast: false\n      matrix:\n        arch:\n          - runner: ubuntu-latest\n            platform: linux/amd64\n          - runner: linux_arm64_runner\n            platform: linux/arm64\n    runs-on: ${{ matrix.arch.runner }}\n    steps:\n      - uses: actions/checkout@v4\n      - name: Login to GitHub Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: Prepare tag name\n        id: tag-preparation\n        run: |\n          if [ -n \"${{ github.event.inputs.docker_image_tag_name }}\" ]; then\n            tag_name=${{ github.event.inputs.docker_image_tag_name }}\n          else\n            tag_name=$(echo ${{ github.ref_name }} | sed 's/[^a-zA-Z0-9]/-/g')-$(git log -1 --pretty=%h)\n          fi\n          echo \"TAG_NAME=$tag_name\" >> $GITHUB_OUTPUT\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n      - name: Prepare platform\n        run: |\n          platform=${{ matrix.arch.platform }}\n          echo \"PLATFORM_PAIR=${platform//\\//-}\" >> $GITHUB_ENV\n      - name: Build and push by digest\n        id: build\n        uses: docker/build-push-action@v6\n        with:\n          platforms: ${{ matrix.arch.platform }}\n          labels: ${{ env.WREN_UI_IMAGE }}\n          context: ./wren-ui\n          outputs: type=image,name=${{ env.WREN_UI_IMAGE }},push-by-digest=true,name-canonical=true,push=true\n      - name: Export digest\n        run: |\n          mkdir -p /tmp/digests\n          digest=\"${{ steps.build.outputs.digest }}\"\n          touch \"/tmp/digests/${digest#sha256:}\"\n      - name: Upload digest\n        uses: actions/upload-artifact@v4\n        with:\n          name: digests-${{ env.PLATFORM_PAIR }}\n          path: /tmp/digests/*\n          if-no-files-found: error\n          retention-days: 1\n  merge:\n    runs-on: ubuntu-latest\n    needs: [ build-image ]\n    steps:\n      - name: Download digests\n        uses: actions/download-artifact@v4\n        with:\n          path: /tmp/digests\n          pattern: digests-*\n          merge-multiple: true\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n      - name: Docker meta\n        id: meta\n        uses: docker/metadata-action@v5\n        with:\n          images: ${{ env.WREN_UI_IMAGE }}\n          tags: |\n            ${{ needs.build-image.outputs.tag_name }}\n      - name: Login to GitHub Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: Create manifest list and push\n        working-directory: /tmp/digests\n        run: |\n          TAGS=$(echo \"${{ steps.meta.outputs.tags }}\" | awk '{printf \"--tag %s \", $0}')\n          docker buildx imagetools create $(jq -cr '.tags | map(\"-t \" + .) | join(\" \")' <<< \"$DOCKER_METADATA_OUTPUT_JSON\") \\\n            $(printf '${{ env.WREN_UI_IMAGE }}@sha256:%s ' *) \\\n            $TAGS\n"
  },
  {
    "path": ".github/workflows/ui-test.yaml",
    "content": "# create the github action to run the UI tests when PR created\n\nname: Wren-UI Test\n\non:\n  pull_request:\n    types: [ labeled, synchronize ]\n\npermissions:\n  contents: read\n\nconcurrency:\n  # avoid mis-canceling the ci runs while other labels are added to the PR, so we add the label name as the condition\n  group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.event.label.name == 'ci/ui' && github.event.number || github.sha }}\n  cancel-in-progress: true\n\ndefaults:\n  run:\n    working-directory: wren-ui\n\njobs:\n  unit-test:\n    # run this job only if the PR is labeled with \"ci/ui\"\n    if: ${{ github.event.label.name == 'ci/ui'}}\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Set up Node.js\n        uses: actions/setup-node@v2\n        with:\n          node-version: '18'\n      - name: Get yarn cache directory path\n        id: yarn-cache-dir-path\n        run: echo \"::set-output name=dir::$(yarn cache dir)\"\n      - uses: actions/cache@v2\n        id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)\n        with:\n          path: | # should cache node_modules as well\n            ${{ steps.yarn-cache-dir-path.outputs.dir }}\n          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}\n          restore-keys: |\n            ${{ runner.os }}-yarn-\n      - if: ${{ steps.yarn-cache.cache-hit != 'true' }}\n        name: List the state of node modules\n        continue-on-error: true\n        run: yarn list\n      - name: Install dependencies\n        run: yarn\n      - name: Run tests\n        run: yarn test"
  },
  {
    "path": ".github/workflows/wren-launcher-ci.yaml",
    "content": "name: Wren Launcher CI\n\non:\n  pull_request:\n    types: [synchronize, labeled]\n    paths:\n      - 'wren-launcher/**'\n      - '.github/workflows/wren-launcher-ci.yaml'\n\npermissions:\n  contents: read\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.event.number || github.sha }}\n  cancel-in-progress: true\n\ndefaults:\n  run:\n    working-directory: wren-launcher\n\njobs:\n  golangci:\n    name: lint\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-go@v5\n        with:\n          go-version: '1.24'\n          cache-dependency-path: wren-launcher/go.sum\n      - name: golangci-lint\n        uses: golangci/golangci-lint-action@v8\n        with:\n          version: v2.3.1\n          working-directory: wren-launcher\n\n  fmt-and-test:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n      - name: Setup Go\n        uses: actions/setup-go@v5\n        with:\n          go-version: '1.24'\n          cache-dependency-path: wren-launcher/go.sum\n      - name: Install goimports\n        run: go install golang.org/x/tools/cmd/goimports@latest\n      - name: Download dependencies\n        run: go mod download\n      - name: Run format check\n        run: |\n          make fmt\n          # Check if there are any formatting changes\n          if [ -n \"$(git diff --name-only)\" ]; then\n            echo \"Code is not formatted properly. Please run 'make fmt' and commit the changes.\"\n            git diff\n            exit 1\n          fi\n      - name: Run go vet\n        run: make vet\n      - name: Run tests\n        run: go test ./commands/dbt\n\n  security-scan:\n    runs-on: ubuntu-latest\n    needs: fmt-and-test\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n      - name: Setup Go\n        uses: actions/setup-go@v5\n        with:\n          go-version: '1.24'\n          cache-dependency-path: wren-launcher/go.sum\n      - name: Run Gosec Security Scanner\n        run: |\n          go install github.com/securego/gosec/v2/cmd/gosec@latest\n          gosec ./...\n      - name: Run Go mod audit\n        run: |\n          go mod verify\n          go list -json -deps ./... | jq -r '.Module | select(.Version) | \"\\(.Path) \\(.Version)\"' | sort -u\n"
  },
  {
    "path": ".gitignore",
    "content": "# wren-ai-service\nwren-ai-service/.env.*\nwren-ai-service/config.yaml*\n!wren-ai-service/.env.*.example\n!wren-ai-service/src/eval/wren-engine/.env\nwren-ai-service/src/eval/wren-engine/**/config.properties\nwren-ai-service/src/eval/wren-engine/etc/mdl/*\nwren-ai-service/src/eval/wren-engine/etc/duckdb\nwren-ai-service/src/eval/wren-engine/etc/archived\nwren-ai-service/src/eval/data\nwren-ai-service/**/outputs/\nwren-ai-service/**/spider/\nwren-ai-service/tests/data/usecases/\n!wren-ai-service/**/metrics/spider/\n!wren-ai-service/tests/data\n!wren-ai-service/src/eval/data/book_2*.json\n!wren-ai-service/src/eval/data/baseball_1*.json\n!wren-ai-service/src/eval/data/college_3*.json\n!wren-ai-service/src/eval/data/college_3_optimal_ddl.json\nwren-ai-service/*.csv\nwren-ai-service/*.json\nwren-ai-service/assertion.log\nwren-ai-service/redis.*\nwren-ai-service/demo/spider\nwren-ai-service/demo/poetry.lock\nwren-ai-service/demo/custom_dataset\nwren-ai-service/demo/.env\nwren-ai-service/tools/dev/etc/**\n.deepeval-cache.json\n.deepeval_telemtry.txt\ndocker/config.yaml\ndocker/docker-compose-local.yaml\ndocker/data\n\n# python\n.python-version\n\n# cache\n__pycache__\nlocal_cache\n.ruff_cache\n.pytest_cache\n\n# ide\n.idea\n.vscode/\n\n# os\n.DS_Store\n__MACOSX/\n*.pem\n\n# sqlite\n*.sqlite\n*.sqlite3\n\n# ui\n## dependencies\nnode_modules\n.pnp\n.pnp.js\n\n## testing\nwren-ui/coverage\nwren-ui/test-results\nwren-ui/playwright-report\nwren-ui/e2e/e2e.config.json\n\n## next.js\nwren-ui/.next\nwren-ui/out\n\nwren-ui/.yarn/install-state.gz\n\n## production\nwren-ui/build\n\n## debug\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n## local env files\n.env*.local\n.env*\n.env.ai\n\n## vercel\n.vercel\n\n## typescript\n*.tsbuildinfo\nnext-env.d.ts\n\n# wren-launcher\nwren-launcher/dist\nwren-launcher/main\n\n## temporary files\n.tmp\n\n!wren-ai-service/tools/.env.example"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"wren-engine\"]\n\tpath = wren-engine\n\turl = git@github.com:Canner/wren-engine.git\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "## Code of Conduct\n\n### Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.\n\n### Our Standards\n\nExamples of behavior that contributes to a positive environment for our community include:\n\n- Demonstrating empathy and kindness toward other people\n- Being respectful of differing opinions, viewpoints, and experiences\n- Giving and gracefully accepting constructive feedback\n- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience\n- Focusing on what is best not just for us as individuals, but for the overall community\n\nExamples of unacceptable behavior include:\n\n- The use of sexualized language or imagery, and sexual attention or advances of any kind\n- Trolling, insulting or derogatory comments, and personal or political attacks\n- Public or private harassment\n- Publishing others’ private information, such as a physical or email address, without their explicit permission\n- Other conduct which could reasonably be considered inappropriate in a professional setting\n\n### Enforcement Responsibilities\n\nProject maintainers are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.\n\n### Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.\n\n### Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported to the project team responsible for enforcement at [contact@getwren.ai](mailto:contact@getwren.ai). All complaints will be reviewed and investigated promptly and fairly.\n\nAll project maintainers are obligated to respect the privacy and security of the reporter of any incident.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n### Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1,\navailable at [https://www.contributor-covenant.org/version/2/1/code_of_conduct/][version]\n\n[homepage]: http://contributor-covenant.org\n[version]: https://www.contributor-covenant.org/version/2/1\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing Guidelines\n\n*Pull requests, bug reports, and all other forms of contribution are welcomed and highly encouraged!* :octocat:\n\n### Contents\n\n- [Code of Conduct](#book-code-of-conduct)\n- [Overview](#mag-overview)\n- [Contribution Guide of Different Services](#love_letter-contribution-guide-of-different-services)\n- [Creating a New Data Source Connector](#electric_plug-creating-a-new-data-source-connector)\n\n> **This guide serves to set clear expectations for everyone involved with the project so that we can improve it together while also creating a welcoming space for everyone to participate. Following these guidelines will help ensure a positive experience for contributors and maintainers.**\n\n## :book: Code of Conduct\n\nPlease review our [Code of Conduct](https://github.com/Canner/WrenAI/blob/main/CODE_OF_CONDUCT.md). It is in effect at all times. We expect it to be honored by everyone who contributes to this project. Acting like an asshole will not be tolerated.\n\n\n## :rocket: Get Started\n1. Visit [How Wren AI works?](https://docs.getwren.ai/oss/overview/how_wrenai_works) to understand the architecture of Wren AI\n1. After you understand the architecture of Wren AI, understand the scope of the services you want to contribute to.\n  Check each service's section under [Contribution Guide of Different Services](#love_letter-contribution-guide-of-different-services) to learn how to contribute to each service.\n    1. If you are dealing with UI-related tasks, such as adding a dark mode, you only need to contribute to the [Wren UI Service](#wren-ui-service).\n    2. If you are dealing with LLM-related tasks, such as enhancing the prompts used in the LLM pipelines, you only need to contribute to the [Wren AI Service](#wren-ai-service).\n    3. If you are working on data-source-related tasks, such as fixing a bug in SQL server connector, you will need to contribute to the [Wren Engine Service](#wren-engine-service).\n1. If you are not sure which service to contribute to, please reach out to us in [Discord](https://discord.gg/canner) or [GitHub Issues](https://github.com/Canner/WrenAI/issues).\n1. It's possible that you need to contribute to multiple services. For example, if you are adding a new data source, you will need to contribute to the [Wren UI Service](#wren-ui-service) and [Wren Engine Service](#wren-engine-service). Follow [Guide for Contributing to Multiple Services](#guide-for-contributing-to-multiple-services) to learn how to contribute to multiple services.\n\n## :love_letter: Contribution Guide of Different Services\n\n### Wren AI Service\n\nWren AI Service is responsible for LLM-related tasks like converting natural language questions into SQL queries and providing step-by-step SQL breakdowns.\n\nTo contribute to Wren AI Service, please refer to the [Wren AI Service Contributing Guide](https://github.com/Canner/WrenAI/blob/main/wren-ai-service/CONTRIBUTING.md)\n\n\n### Wren UI Service\n\nWren UI is the client service of WrenAI. It is built with Next.js and TypeScript. \nTo contribute to Wren UI, you can refer to the [WrenAI/wren-ui/README.md](https://github.com/Canner/WrenAI/blob/main/wren-ui/README.md) file for instructions on how to set up the development environment and run the development server.\n\n\n### Wren Engine Service\nWren Engine is the backbone of the Wren AI project. The semantic engine for LLMs, bringing business context to AI agents.\n\nTo contribute, please refer to [Wren Engine Contributing Guide](https://github.com/Canner/wren-engine/blob/main/ibis-server/docs/CONTRIBUTING.md)\n\n## Guide for Contributing to Multiple Services\nWe rely on docker-compose to start all services. If you are contributing to multiple services, you could just comment out the services you'd like to start from the source code and change the `env` variables to point to the services you started by yourself.\n\n### Example: Contributing to the [Wren UI Service](#wren-ui-service) and [Wren Engine Service](#wren-engine-service)\nIf you are contributing to both the [Wren UI Service](#wren-ui-service) and [Wren Engine Service](#wren-engine-service), you should comment out the `wren-engine` service in the `docker/docker-compose-dev.yml` file (note that the UI service is already excluded from `docker/docker-compose-dev.yml`). Then, adjust the environment variables in your `.env` file to point to the services you have started manually. This will ensure that your local development environment correctly interfaces with the services you are working on.\n\n1. Prepare your `.env` file: In the `WrenAI/docker` folder, use the `.env.example` file as a template. Copy this file to create a `.env.local` file.\n    ```sh\n    # assuming the current directory is wren-ui\n    cd ../docker\n    cp .env.example .env.local\n    ```\n2. Modify your `.env.local` file: Fill in the `OPENAI_API_KEY` with your OpenAI API keys before starting.\n3. In the `WrenAI/docker` folder, copy `config.example.yaml` to `config.yaml` for AI service configuration. Also change `http://wren-ui:3000` to `http://host.docker.internal:3000` in `config.yaml`.\n4. Start the UI and engine services from the source code.\n5. Update the `env` variables in the `.env.local` file to point to the services you started manually.\n6. Start the other services using docker-compose:\n    ```sh\n    # current directory is WrenAI/docker\n    docker-compose -f docker-compose-dev.yaml --env-file .env.example up\n\n    # you can add the -d flag to run the services in the background\n    docker-compose -f docker-compose-dev.yaml --env-file .env.example up -d\n    # to stop the services, use\n    docker-compose -f docker-compose-dev.yaml --env-file .env.example down\n    ```\n7. Happy coding!\n\n## :electric_plug: Creating a New Data Source Connector\n\nTo develop a new data source connector, you'll need to modify both the front-end and back-end of the Wren UI, in addition to the Wren Engine.\n\nBelow is a brief overview of a data source connector:\n\n<img src=\"./misc/data_source.png\" width=\"400\">\n\nThe UI is primarily responsible for storing database connection settings, providing an interface for users to input these settings, and submitting them to the Engine, which then connects to the database.\n\nThe UI must be aware of the connection details it needs to retain, as specified by the Engine. Therefore, the implementation sequence would be as follows:\n\n\n- Engine:\n  - Implement the new data source (you'll determine what connection information is needed and how it should be passed from the UI).\n  - Implement the metadata API for the UI to access.\n- UI:\n  - Back-End:\n    - Safely store the connection information.\n    - Provide the connection information to the Engine.\n  - Front-End:\n    - Prepare an icon for the data source.\n    - Set up the form template for users to input the connection information.\n    - Update the data source list.\n\n### Wren Engine\n\n- To implement a new data source, please refer to [How to Add a New Data Source](https://github.com/Canner/wren-engine/blob/main/ibis-server/docs/how-to-add-data-source.md).\n- After adding a new data source, you can proceed with implementing the metadata API for the UI.\n\n  Here are some previous PRs that introduced new data sources:\n    - [Add MSSQL data source](https://github.com/Canner/wren-engine/pull/631)\n    - [Add MySQL data source](https://github.com/Canner/wren-engine/pull/618)\n    - [Add ClickHouse data source](https://github.com/Canner/wren-engine/pull/648)\n\n### Wren UI Guide\n\nWe'll describe what should be done in the UI for each new data source. \n\nIf you prefer to learn by example, you can refer to this Trino [issue](https://github.com/Canner/WrenAI/issues/492) and [PR](https://github.com/Canner/WrenAI/pull/535).\n\n\n#### Backend\n1. Define the data source in `wren-ui/src/apollo/server/dataSource.ts`\n  - define the `toIbisConnectionInfo` and `sensitiveProps` methods\n\n2. Modify the ibis adaptor in `wren-ui/src/apollo/server/adaptors/ibisAdaptor.ts`\n  - define an ibis connection info type for the new data source\n  - set up the `dataSourceUrlMap` for the new data source\n\n3. Modify the repository in `wren-ui/src/apollo/server/repositories/projectRepository.ts`\n  - define the wren ui connection info type for the new data source \n\n4. Update the graphql schema in `wren-ui/src/apollo/server/schema.ts` so that the new data source can be used in the UI \n  - add the new data source to the `DataSource` enum\n\n5. Update the type definition in `wren-ui/src/apollo/server/types/dataSource.ts`\n  - add the new data source to the `DataSourceName` enum\n\n#### Frontend\n1. Prepare the data source's logo:\n   - Image size should be `40 x 40` px\n   - Preferably use SVG format\n   - Ensure the logo is centered within a `30px` container for consistent formatting\n\n   Example:\n\n   <img src=\"./misc/logo_template.jpg\" width=\"120\">\n\n2. Create the data source form template:\n   - In `wren-ui/src/components/pages/setup/dataSources`, add a new file named `${dataSource}Properties.tsx`\n   - Implement the data source form template in this file\n\n3. Set up the data source template:\n   - Navigate to `wren-ui/src/utils/dataSourceType.ts`\n   - Add new data source image, name, properties\n   - Update the necessary files to include the new data source template settings\n\n4. Update the data source list:\n   - Add the new data source to the `DATA_SOURCES` enum in `wren-ui/src/utils/enum/dataSources.ts`\n   - Update relevant files in `wren-ui/src/components/pages/setup/` to include the new data source\n   - Ensure `wren-ui/src/apollo/server/adaptors/ibisAdaptor.ts` handle the new data source\n\n5. Test the new connector:\n   - Ensure the new data source appears in the UI\n   - Verify that the form works correctly\n   - Test the connection to the new data source\n\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU AFFERO GENERAL PUBLIC LICENSE\n                       Version 3, 19 November 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU Affero General Public License is a free, copyleft license for\nsoftware and other kinds of works, specifically designed to ensure\ncooperation with the community in the case of network server software.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nour General Public Licenses are intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  Developers that use our General Public Licenses protect your rights\nwith two steps: (1) assert copyright on the software, and (2) offer\nyou this License which gives you legal permission to copy, distribute\nand/or modify the software.\n\n  A secondary benefit of defending all users' freedom is that\nimprovements made in alternate versions of the program, if they\nreceive widespread use, become available for other developers to\nincorporate.  Many developers of free software are heartened and\nencouraged by the resulting cooperation.  However, in the case of\nsoftware used on network servers, this result may fail to come about.\nThe GNU General Public License permits making a modified version and\nletting the public access it on a server without ever releasing its\nsource code to the public.\n\n  The GNU Affero General Public License is designed specifically to\nensure that, in such cases, the modified source code becomes available\nto the community.  It requires the operator of a network server to\nprovide the source code of the modified version running there to the\nusers of that server.  Therefore, public use of a modified version, on\na publicly accessible server, gives the public access to the source\ncode of the modified version.\n\n  An older license, called the Affero General Public License and\npublished by Affero, was designed to accomplish similar goals.  This is\na different license, not a version of the Affero GPL, but Affero has\nreleased a new version of the Affero GPL which permits relicensing under\nthis license.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU Affero General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Remote Network Interaction; Use with the GNU General Public License.\n\n  Notwithstanding any other provision of this License, if you modify the\nProgram, your modified version must prominently offer all users\ninteracting with it remotely through a computer network (if your version\nsupports such interaction) an opportunity to receive the Corresponding\nSource of your version by providing access to the Corresponding Source\nfrom a network server at no charge, through some standard or customary\nmeans of facilitating copying of software.  This Corresponding Source\nshall include the Corresponding Source for any work covered by version 3\nof the GNU General Public License that is incorporated pursuant to the\nfollowing paragraph.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the work with which it is combined will remain governed by version\n3 of the GNU General Public License.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU Affero General Public License from time to time.  Such new versions\nwill be similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU Affero General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU Affero General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU Affero General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    Wren AI is a Text-to-SQL solution for data teams to get results\n    and insights faster by asking business questions without writing SQL.\n    Copyright (C) 2024  Canner, Inc.\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Affero General Public License as published\n    by the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Affero General Public License for more details.\n\n    You should have received a copy of the GNU Affero General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If your software can interact with users remotely through a computer\nnetwork, you should also make sure that it provides a way for users to\nget its source.  For example, if your program is a web application, its\ninterface could display a \"Source\" link that leads users to an archive\nof the code.  There are many ways you could offer source, and different\nsolutions will be better for different programs; see section 13 for the\nspecific requirements.\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU AGPL, see\n<https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "README.md",
    "content": "\n<p align=\"center\" id=\"top\">\n  <a href=\"https://getwren.ai/?utm_source=github&utm_medium=title&utm_campaign=readme\">\n    <picture>\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"./misc/wrenai_logo.png\">\n      <img src=\"./misc/wrenai_logo_white.png\" width=\"300px\">\n    </picture>\n    <h1 align=\"center\">Wren AI - Open-Source GenBI Agent</h1>\n  </a>\n</p>\n\n<p align=\"center\">\n  <a aria-label=\"Follow us on X\" href=\"https://x.com/getwrenai\">\n    <img alt=\"\" src=\"https://img.shields.io/badge/-@getwrenai-blue?style=for-the-badge&logo=x&logoColor=white&labelColor=gray&logoWidth=20\">\n  </a>\n  <a aria-label=\"Releases\" href=\"https://github.com/canner/WrenAI/releases\">\n    <img alt=\"\" src=\"https://img.shields.io/github/v/release/canner/WrenAI?logo=github&label=GitHub%20Release&color=blue&style=for-the-badge\">\n  </a>\n  <a aria-label=\"License\" href=\"https://github.com/Canner/WrenAI/blob/main/LICENSE\">\n    <img alt=\"\" src=\"https://img.shields.io/github/license/canner/WrenAI?color=blue&style=for-the-badge\">\n  </a>\n  <a href=\"https://docs.getwren.ai\">\n    <img src=\"https://img.shields.io/badge/docs-online-brightgreen?style=for-the-badge\" alt=\"Docs\">\n  </a>\n  <a aria-label=\"Join the community on GitHub\" href=\"https://discord.gg/5DvshJqG8Z\">\n    <img alt=\"\" src=\"https://img.shields.io/badge/-JOIN%20THE%20COMMUNITY-blue?style=for-the-badge&logo=discord&logoColor=white&labelColor=grey&logoWidth=20\">\n  </a>\n  <a aria-label=\"Canner\" href=\"https://cannerdata.com/?utm_source=github&utm_medium=badge&utm_campaign=readme\">\n    <img src=\"https://img.shields.io/badge/%F0%9F%A7%A1-Made%20by%20Canner-blue?style=for-the-badge\">\n  </a>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://trendshift.io/repositories/9263\" target=\"_blank\"><img src=\"https://trendshift.io/api/badge/repositories/9263\" alt=\"Canner%2FWrenAI | Trendshift\" style=\"width: 250px; height: 55px;\" width=\"250\" height=\"55\"/></a>\n</p>\n\n> ⚡ GenBI (Generative BI) queries any database in natural language, generates accurate SQL (Text-to-SQL), charts (Text-to-Chart), and AI-powered business intelligence in seconds. ️\n\n<p align=\"center\">\n  <img width=\"1920\" height=\"1080\" alt=\"1\" src=\"https://github.com/user-attachments/assets/bba9d37a-33e3-49ab-b7cb-32fd6dddc8d1\" />\n</p>\n \n## 😍 Demos\n\nhttps://github.com/user-attachments/assets/f9c1cb34-5a95-4580-8890-ec9644da4160\n\n[Watch GenBI Demo](https://github.com/user-attachments/assets/90ad1d35-bb1e-490b-9676-b29863ff090b)\n\n## 🤖 Features\n\n|                    | What you get | Why it matters |\n|--------------------|--------------|----------------|\n| **Talk to Your Data** | Ask in any language → precise SQL & answers | Slash the SQL learning curve﻿ |\n| **GenBI Insights** | AI-written summaries, charts & reports | Decision-ready context in one click﻿ |\n| **Semantic Layer** | MDL models encode schema, metrics, joins | Keeps LLM outputs accurate & governed﻿ |\n| **Embed via API**  | Generate queries & charts inside your apps ([API Docs](https://wrenai.readme.io/reference/cloud-getting-started)) | Build custom agents, SaaS features, chatbots﻿ ([Streamlit Live Demo](https://huggingface.co/spaces/getWrenAI/wrenai-cloud-api-demo)) |\n\n🤩 [Learn more about GenBI](https://getwren.ai/genbi?utm_source=github&utm_medium=content&utm_campaign=readme)\n\n## 🚀 Getting Started\n\nUsing Wren AI is super simple, you can set it up within 3 minutes, and start to interact with your data!\n\n<p align=\"center\">\n  <img width=\"1920\" height=\"1080\" alt=\"2\" src=\"https://github.com/user-attachments/assets/6555f539-9ef2-485d-9135-0071741fda96\" />\n</p>\n\n- Visit our [Install in your local environment](http://docs.getwren.ai/oss/installation?utm_source=github&utm_medium=content&utm_campaign=readme).\n- Visit the [Usage Guides](https://docs.getwren.ai/oss/guide/connect/overview?utm_source=github&utm_medium=content&utm_campaign=readme) to learn more about how to use Wren AI.\n- Or just start with [Wren AI Cloud](https://getwren.ai/?utm_source=github&utm_medium=content&utm_campaign=readme) our Managed Cloud Service. ([OSS vs. Commercial Plans](https://docs.getwren.ai/oss/overview/cloud_vs_self_host)).\n\n## 🏗️ Architecture\n\n<p align=\"center\">\n  <img width=\"1011\" height=\"682\" alt=\"wrenai-architecture\" src=\"https://github.com/user-attachments/assets/e99b999f-9912-4fa7-921a-9c86b6b83354\" />\n</p>\n\n👉 [Learn more about our Design](https://getwren.ai/post/how-we-design-our-semantic-engine-for-llms-the-backbone-of-the-semantic-layer-for-llm-architecture?utm_source=github&utm_medium=content&utm_campaign=readme)\n\n\n\n## 🔌 Data Sources\n\nIf your data source is not listed here, vote for it in our [GitHub discussion thread](https://github.com/Canner/WrenAI/discussions/327). It will be a valuable input for us to decide on the next supported data sources.\n- Athena (Trino)\n- Redshift\n- BigQuery\n- DuckDB\n- Databricks\n- PostgreSQL\n- MySQL\n- Microsoft SQL Server\n- ClickHouse\n- Oracle\n- Trino\n- Snowflake\n\n## 🤖 LLM Models\n\nWren AI supports integration with various Large Language Models (LLMs), including but not limited to:\n- OpenAI Models\n- Azure OpenAI Models\n- DeepSeek Models\n- Google AI Studio – Gemini Models\n- Vertex AI Models (Gemini + Anthropic)\n- Bedrock Models\n- Anthropic API Models\n- Groq Models\n- Ollama Models\n- Databricks Models\n\nCheck [configuration examples here](https://github.com/Canner/WrenAI/tree/main/wren-ai-service/docs/config_examples)!\n\n> [!CAUTION]\n> The performance of Wren AI depends significantly on the capabilities of the LLM you choose. We strongly recommend using the most powerful model available for optimal results. Using less capable models may lead to reduced performance, slower response times, or inaccurate outputs.\n\n## 📚 Documentation\n\nVisit [Wren AI documentation](https://docs.getwren.ai/oss/overview/introduction?utm_source=github&utm_medium=content&utm_campaign=readme) to view the full documentation.\n\n## 📪 Keep Posted?\n\n[Subscribe our blog](https://www.getwren.ai/blog/?utm_source=github&utm_medium=content&utm_campaign=readme) and [Follow our LinkedIn](https://www.linkedin.com/company/wrenai)\n\n## 🛠️ Contribution\n\n1.\tStar ⭐ the repo to show support (it really helps).\n2.\tOpen an issue for bugs, ideas, or discussions.\n3.\tRead [Contribution Guidelines](https://github.com/Canner/WrenAI/blob/main/CONTRIBUTING.md) for setup & PR guidelines.\n\n## ⭐️ Community\n\n- Join 1.3k+ developers in our [Discord](https://discord.gg/5DvshJqG8Z) for real-time help and roadmap previews.\n- If there are any issues, please visit [GitHub Issues](https://github.com/Canner/WrenAI/issues).\n- Explore our [public roadmap](https://wrenai.notion.site/) to stay updated on upcoming features and improvements!\n\nPlease note that our [Code of Conduct](./CODE_OF_CONDUCT.md) applies to all Wren AI community channels. Users are **highly encouraged** to read and adhere to them to avoid repercussions.\n\n## 🎉 Our Contributors\n<a href=\"https://github.com/canner/wrenAI/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=Canner/WrenAI\" />\n</a>\n\n<p align=\"right\">\n  <a href=\"#top\">⬆️ Back to Top</a>\n</p>\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n## Reporting a Vulnerability\n\nIf you believe you have found a security vulnerability in any Canner-owned repository, please report it to us through coordinated disclosure.\n\n**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.**\n\nInstead, please send an email to contact[@]cannerdata.com.\n\nPlease include as much of the information listed below as you can to help us better understand and resolve the issue:\n\n  * The type of issue (e.g., buffer overflow, SQL injection, or cross-site scripting)\n  * Full paths of source file(s) related to the manifestation of the issue\n  * The location of the affected source code (tag/branch/commit or direct URL)\n  * Any special configuration required to reproduce the issue\n  * Step-by-step instructions to reproduce the issue\n  * Proof-of-concept or exploit code (if possible)\n  * Impact of the issue, including how an attacker might exploit the issue\n\nThis information will help us triage your report more quickly.\n"
  },
  {
    "path": "deployment/README.md",
    "content": "# Various deployemnt starategies of the app\n\n- [x] [Docker](../docker/)\n- [x] [Kubernetes: Kustomizations](./kustomizations/)"
  },
  {
    "path": "deployment/kustomizations/.gitignore",
    "content": "*.kustomized.yaml\ncharts/*"
  },
  {
    "path": "deployment/kustomizations/README.md",
    "content": "# Deployment of Wren AI to Kubernetes with Kustomization\n1. Ensure you satisfy the dependencies required to deploy Wren AI.\n2. Adjust the values and manifests accordingly to fit your Kubernetes environment.\n3. Deploy Secrets separately.\n4. Deploy the inflated kustomized app.\nNote: Without authentication, once you publish this on the internet, anyone can access your app, see your data, and modify your settings!\n\n## Dependencies used in this kustomization:\n- nginx.ingress\n- external-dns\n- cert-manager\n- kubectl kustomize\n- helm (for minikube)\n\n## Steps to deploy:\n\n`Suggestion`: Before deploying, check out the manifests in the `deployment/kustomizations ` folder and modify them for your Kubernetes environment.\nThe `deployment/kustomizations` folder contains a `kustomization.yaml` file that will inflate the manifests into a `deployment/kustomizations/wrenai.kustomized.yaml` file used to deploy the app to your Kubernetes cluster.\n\n```shell\n# Clone the repository with the kustomization\ngit clone https://github.com/Canner/WrenAI.git\ncd WrenAI\n\n# Inflate the manifest with kustomization\nkubectl kustomize deployment/kustomizations --enable-helm > deployment/kustomizations/wrenai.kustomized.yaml\n\n# Create namespace\nkubectl create namespace wren\n\n# !!!!!!!!!!!!\n# MODIFY secret-wren_example.yaml manifest file FIRST\n# OPENAI_API_KEY is REQUIRED: without a valid key the wren-ai-service-deployment pod will not start\n# You must update PG_URL, otherwise wren-ui will not work\n#vi deployment/kustomizations/examples/secret-wren_example.yaml\nkubectl apply -f deployment/kustomizations/examples/secret-wren_example.yaml -n wren\n\n# Deploy the app:\nkubectl apply -f deployment/kustomizations/wrenai.kustomized.yaml\n\nkubectl get pods -n wren\n```\n\n### Notes on kustomization:\n- `deployment/kustomizations/kustomization.yaml` is the main file responsible for versions of other apps such as Qdrant and PostgreSQL, version of your Wren AI app. It also combines resourses from the manifest such as ConfigMaps, Deployments, and Services. And example Ingress, Certificates and Secrets.\n- `deployment/kustomizations/base` is the base folder that contains the core Wren AI manifests, its less likely you need to modify them, but check just in case\n- `deployment/kustomizations/examples` is a place with examples of manifests must take a look and adjust to your k8s environment and your needs.\n- `deployment/kustomizations/examples/secret-wren_example.yaml` is the file you would not normally include in the kustomization file as its not a best practice and especially not a good idea to include in your GitOps repo as it contains cleartext passwords. We recommend to deploy it separately. Thant's why its commented in the `kustomization.yaml` file.\n- `deployment/kustomizations/examples/wrenai-ingress-example.yaml` is an example of how to deploy Ingress. You can use this as a template for your own Ingress. It contains dependancy of extarnal-dns to add your dns name to your DNS records automatically, otherwise you'll need to add it manually. Also it assumes you are using nginx.ingress, it increases timeouts, disables the owasp and modsecurity that might be enabled globaly and prevent your UI from working properly. Comment the TLS section if you do not wish to use `https` encryption. Note: without authentication, enyone can acess your app, see your data and modify your settings!\n- `deployment/kustomizations/examples/certificate-wren_example.yaml` is an example of how to deploy certificates for your ingress for the Wren-UI. You can use this as a template for your own certificate. It contains dependancy of cert-manager to add your certificates automatically, otherwise you'll need to add it manually. The certificate will be used by your Ingress.\n- `deployment/kustomizations/examples/certificate-qdrant_example.yaml` is an example of how to deploy certificates for your ingress for Qdrant. This is included just in case and is not required, usually you would not be publishing your Vector Database publically in internet. That's why it's commented in the `kustomization.yaml` file. You can use this as a template for your own certificate. It contains dependancy of cert-manager to add your certificates automatically, otherwise you'll need to add it manually.\n- `deployment/kustomizations/patches` folder is empty, feel free to add your own patches & overlays there.\n\n#### Wren-UI Database\nStarting with wren-ui version 0.6.0 by default the postgres database is used for wren-ui in this kubernetes kustomization and will be installed in the same namespace as wren-ai.\n- `postgres`: Database that will be installed in the same namespace as wren-ai. You *must* update `PG_URL` in the Secret manifest `deployment/kustomizations/examples/secret-wren_example.yaml`.\n\nExample: `PG_URL: \"postgres://postgres:postgres@wrenai-postgresql:5432/admin_ui\"`\n- `postgres://`        This is the protocol. It tells the system that you’re connecting to a PostgreSQL database.\n- `postgres:postgres`  These are the username(first) and password(second) for the database respectively, separated by a colon. In this case, both the username and password are “postgres”.\n- `@wren-postgresql`   This is the hostname of the database server. \"wren-postgresql\" means the database server is running in a Kubernetes cluster and it is named \"wren-postgresql\" in the *same* namespace. If you are using another namespace you must provide the full hostname, example: `wren-postgresql.wrenai.svc.cluster.local`, \"wrenai\" is the namespace name, \"svc.cluster.local\" is the default domain name for Kubernetes services no need to change it.\n- `:5432`              This is the port number. PostgreSQL servers listen on port 5432 by default.\n- `/admin_ui`          This is the name of the database you’re connecting to. In this case, the database name is `admin_ui`. It can be found in the helm values file in the auth.database parameter `deployment/kustomizations/helm-values_postgresql_15.yaml`\n\n# Minikube\nPrepare your k8s environment. Then use the `Steps to deploy` section to deploy Wren AI app into your k8s.\n```shell\nminikube start\nminikube addons enable ingress\nminikube addons enable metallb\nminikube kubectl -- get nodes\nminikube kubectl -- get pods -A\n\nminikube update-context\nhelm repo add bitnami https://charts.bitnami.com/bitnami\nhelm repo update\nhelm install external-dns bitnami/external-dns\nhelm install \\\n  external-dns bitnami/external-dns \\\n  --namespace external-dns \\\n  --version 7.5.2 \\\n  --create-namespace \\\n  --set installCRDs=true\nkubectl get pods -n external-dns\n\nhelm repo add jetstack https://charts.jetstack.io\nhelm repo update\nhelm install \\\n  cert-manager jetstack/cert-manager \\\n  --namespace cert-manager \\\n  --version v1.13.6 \\\n  --create-namespace \\\n  --set installCRDs=true\nkubectl get pods -n cert-manager\n\n##########\n# Use the `Steps to deploy` section to continue as you would on a production k8s cluster.\n```\n\n# GitOps Patches\nIn the [patches](./patches) folder you can find usefull kustomization examples files if you wish to use existing official kustomization directly from this repo as a base kustomization layer and only customize some values. It can be usefull for you GitOps workflow and can be used in conjunction with FlexCD or ArgoCD.\n"
  },
  {
    "path": "deployment/kustomizations/base/cm.yaml",
    "content": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: wren-config\ndata:\n  # Wren Engine Service Port\n  WREN_ENGINE_PORT: \"8080\"\n  # Wren AI Service Port\n  WREN_AI_SERVICE_PORT: \"5555\"\n\n  WREN_UI_ENDPOINT: http://wren-ui-svc:3000\n\n  #Release version used by wren ui https://github.com/Canner/WrenAI/blob/main/docker/docker-compose.yaml#L85-L88\n  WREN_PRODUCT_VERSION: \"0.12.0\"\n  WREN_ENGINE_VERSION: \"0.12.3\"\n  WREN_AI_SERVICE_VERSION: \"0.12.1\"\n  WREN_UI_VERSION: \"0.17.6\"\n\n  # Document store related\n  QDRANT_HOST: \"wren-qdrant\"\n\n  # Telemetry\n  POSTHOG_HOST: \"https://app.posthog.com\"\n  TELEMETRY_ENABLED: \"false\"\n  # this is for telemetry to know the model, i think ai-service might be able to provide a endpoint to get the information\n  GENERATION_MODEL: \"gpt-4o-mini-2024-07-18\"\n\n  # service endpoints of AI service & engine service\n  WREN_ENGINE_ENDPOINT: \"http://wren-engine-svc:8080\"\n  WREN_AI_ENDPOINT: \"http://wren-ai-service-svc:5555\"\n  #WREN_AI_ENDPOINT: \"http://wren-ai-service-svc.ai-system.svc.cluster.local:5555\"\n\n  # \"pg\" for postgres as UI application database\n  WREN_UI_DB_TYPE: pg\n\n  #For bootstrap\n  WREN_ENGINE_DATA_PATH: \"/app/data\"\n\n  ### if DB_TYPE = \"postgres\" you must provide PG_URL string in the *Secret* manifest file (deployment/kustomizations/examples/secret-wren_example.yaml) to connect to postgres\n\n  #DEBUG, INFO\n  LOGGING_LEVEL: INFO\n\n  IBIS_SERVER_ENDPOINT: http://wren-ibis-server-svc:8000\n---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: wren-ai-service-config\ndata:\n  config.yaml: |\n    type: llm\n    provider: litellm_llm\n    timeout: 120\n    models:\n    - alias: default\n      model: gpt-4.1-nano-2025-04-14\n      context_window_size: 1000000\n      kwargs:\n        max_tokens: 4096\n        n: 1\n        seed: 0\n        temperature: 0\n    - model: gpt-4.1-mini-2025-04-14\n      context_window_size: 1000000\n      kwargs:\n        max_tokens: 4096\n        n: 1\n        seed: 0\n        temperature: 0\n    - model: gpt-4.1-2025-04-14\n      context_window_size: 1000000\n      kwargs:\n        max_tokens: 4096\n        n: 1\n        seed: 0\n        temperature: 0\n    - model: gpt-5-nano-2025-08-07\n      context_window_size: 380000\n      kwargs:\n        max_completion_tokens: 4096\n        n: 1\n        seed: 0\n        reasoning_effort: minimal\n    - model: gpt-5-mini-2025-08-07\n      context_window_size: 380000\n      kwargs:\n        max_completion_tokens: 4096\n        n: 1\n        seed: 0\n        reasoning_effort: minimal\n    - model: gpt-5-2025-08-07\n      context_window_size: 380000\n      kwargs:\n        max_completion_tokens: 4096\n        n: 1\n        seed: 0\n        reasoning_effort: minimal\n    ---\n    type: embedder\n    provider: litellm_embedder\n    models:\n    - model: text-embedding-3-large\n      alias: default\n      timeout: 120\n\n    ---\n    type: engine\n    provider: wren_ui\n    endpoint: http://wren-ui-svc:3000\n\n    ---\n    type: engine\n    provider: wren_ibis\n    endpoint: http://wren-ibis-server-svc:8000\n\n    ---\n    type: document_store\n    provider: qdrant\n    location: http://wren-qdrant:6333\n    embedding_model_dim: 3072\n    timeout: 120\n\n    ---\n    type: pipeline\n    pipes:\n      - name: db_schema_indexing\n        embedder: litellm_embedder.default\n        document_store: qdrant\n      - name: historical_question_indexing\n        embedder: litellm_embedder.default\n        document_store: qdrant\n      - name: table_description_indexing\n        embedder: litellm_embedder.default\n        document_store: qdrant\n      - name: db_schema_retrieval\n        llm: litellm_llm.default\n        embedder: litellm_embedder.default\n        document_store: qdrant\n      - name: historical_question_retrieval\n        embedder: litellm_embedder.default\n        document_store: qdrant\n      - name: sql_generation\n        llm: litellm_llm.default\n        engine: wren_ui\n        document_store: qdrant\n      - name: sql_correction\n        llm: litellm_llm.default\n        engine: wren_ui\n        document_store: qdrant\n      - name: followup_sql_generation\n        llm: litellm_llm.default\n        engine: wren_ui\n        document_store: qdrant\n      - name: sql_answer\n        llm: litellm_llm.default\n      - name: semantics_description\n        llm: litellm_llm.default\n      - name: relationship_recommendation\n        llm: litellm_llm.default\n      - name: question_recommendation\n        llm: litellm_llm.default\n      - name: question_recommendation_sql_generation\n        llm: litellm_llm.default\n        engine: wren_ui\n        document_store: qdrant\n      - name: intent_classification\n        llm: litellm_llm.default\n        embedder: litellm_embedder.default\n        document_store: qdrant\n      - name: misleading_assistance\n        llm: litellm_llm.default\n      - name: data_assistance\n        llm: litellm_llm.default\n      - name: sql_pairs_indexing\n        document_store: qdrant\n        embedder: litellm_embedder.default\n      - name: sql_pairs_retrieval\n        document_store: qdrant\n        embedder: litellm_embedder.default\n        llm: litellm_llm.default\n      - name: preprocess_sql_data\n        llm: litellm_llm.default\n      - name: sql_executor\n        engine: wren_ui\n      - name: chart_generation\n        llm: litellm_llm.default\n      - name: chart_adjustment\n        llm: litellm_llm.default\n      - name: user_guide_assistance\n        llm: litellm_llm.default\n      - name: sql_question_generation\n        llm: litellm_llm.default\n      - name: sql_generation_reasoning\n        llm: litellm_llm.default\n      - name: followup_sql_generation_reasoning\n        llm: litellm_llm.default\n      - name: sql_regeneration\n        llm: litellm_llm.default\n        engine: wren_ui\n      - name: instructions_indexing\n        embedder: litellm_embedder.default\n        document_store: qdrant\n      - name: instructions_retrieval\n        embedder: litellm_embedder.default\n        document_store: qdrant\n      - name: sql_functions_retrieval\n        engine: wren_ibis\n        document_store: qdrant\n      - name: project_meta_indexing\n        document_store: qdrant\n      - name: sql_tables_extraction\n        llm: litellm_llm.default\n      - name: sql_diagnosis\n        llm: litellm_llm.default\n\n    ---\n    settings:\n      doc_endpoint: https://docs.getwren.ai\n      is_oss: true\n      engine_timeout: 30\n      column_indexing_batch_size: 50\n      table_retrieval_size: 10\n      table_column_retrieval_size: 100\n      allow_intent_classification: true\n      allow_sql_generation_reasoning: true\n      allow_sql_functions_retrieval: true\n      enable_column_pruning: false\n      max_sql_correction_retries: 3\n      query_cache_maxsize: 1000\n      query_cache_ttl: 3600\n      langfuse_host: https://cloud.langfuse.com\n      langfuse_enable: true\n      logging_level: DEBUG\n      development: false\n      historical_question_retrieval_similarity_threshold: 0.9\n      sql_pairs_similarity_threshold: 0.7\n      sql_pairs_retrieval_max_size: 10\n      instructions_similarity_threshold: 0.7\n      instructions_top_k: 10\n"
  },
  {
    "path": "deployment/kustomizations/base/deploy-wren-ai-service.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: wren-ai-service-deployment\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: wren-ai-service\n  template:\n    metadata:\n      labels:\n        app: wren-ai-service\n    spec:\n      containers:\n        - name: wren-ai-service\n          image: ghcr.io/canner/wren-ai-service:latest\n          volumeMounts:\n            - name: config-volume\n              mountPath: /app/data\n          env:\n            - name: WREN_AI_SERVICE_PORT\n              valueFrom:\n                configMapKeyRef:\n                  name: wren-config\n                  key: WREN_AI_SERVICE_PORT\n            - name: OPENAI_API_KEY\n              valueFrom:\n                secretKeyRef:\n                  name: wrenai-secrets\n                  key: OPENAI_API_KEY\n            - name: QDRANT_HOST\n              valueFrom:\n                configMapKeyRef:\n                  name: wren-config\n                  key: QDRANT_HOST\n            - name: LOGGING_LEVEL\n              valueFrom:\n                configMapKeyRef:\n                  name: wren-config\n                  key: LOGGING_LEVEL\n            - name: WREN_UI_ENDPOINT\n              valueFrom:\n                configMapKeyRef:\n                  name: wren-config\n                  key: WREN_UI_ENDPOINT\n            - name: PYTHONUNBUFFERED\n              value: \"1\"\n            - name: LANGFUSE_PUBLIC_KEY\n              valueFrom:\n                secretKeyRef:\n                  name: wrenai-secrets\n                  key: LANGFUSE_PUBLIC_KEY\n            - name: LANGFUSE_SECRET_KEY\n              valueFrom:\n                secretKeyRef:\n                  name: wrenai-secrets\n                  key: LANGFUSE_SECRET_KEY\n            - name: CONFIG_PATH\n              value: /app/data/config.yaml\n          ports:\n            - containerPort: 5555\n      volumes:\n        - name: config-volume\n          configMap:\n            name: wren-ai-service-config\n            items:\n              - key: config.yaml\n                path: config.yaml\n"
  },
  {
    "path": "deployment/kustomizations/base/deploy-wren-engine.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: wren-engine-deployment\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: wren-engine\n  template:\n    metadata:\n      labels:\n        app: wren-engine\n    spec:\n      volumes:\n        - name: wren-data\n          persistentVolumeClaim:\n            claimName: wren-data-pvc\n      initContainers:\n        - name: bootstrap\n          image: ghcr.io/canner/wren-bootstrap:0.1.4\n          env:\n            - name: DATA_PATH\n              valueFrom:\n                configMapKeyRef:\n                  name: wren-config\n                  key: WREN_ENGINE_DATA_PATH\n            - name: PG_PASSWORD\n              valueFrom:\n                secretKeyRef:\n                  name: wrenai-postgresql\n                  key: postgres-password\n            - name: PG_USERNAME\n              valueFrom:\n                secretKeyRef:\n                  name: wrenai-secrets\n                  key: PG_USERNAME\n          volumeMounts:\n            - name: wren-data\n              mountPath: /app/data\n          command: [\"/bin/sh\", \"/app/init.sh\"]\n      containers:\n        - name: wren-engine\n          image: ghcr.io/canner/wren-engine:0.4.4\n          ports:\n            - containerPort: 8080\n            - containerPort: 7432\n          volumeMounts:\n            - name: wren-data\n              mountPath: /usr/src/app/etc"
  },
  {
    "path": "deployment/kustomizations/base/deploy-wren-ibis-server.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: wren-ibis-server\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: wren-ibis\n  template:\n    metadata:\n      labels:\n        app: wren-ibis\n    spec:\n      containers:\n        - name: wren-ibis\n          image: ghcr.io/canner/wren-engine-ibis:0.5.0\n          env:\n            - name: WREN_ENGINE_ENDPOINT\n              valueFrom:\n                configMapKeyRef:\n                  name: wren-config\n                  key: WREN_ENGINE_ENDPOINT\n            - name: LOGGING_LEVEL\n              valueFrom:\n                configMapKeyRef:\n                  name: wren-config\n                  key: LOGGING_LEVEL\n          ports:\n            - containerPort: 8000\n"
  },
  {
    "path": "deployment/kustomizations/base/deploy-wren-ui.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: wren-ui-deployment\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: wren-ui\n  template:\n    metadata:\n      labels:\n        app: wren-ui\n    spec:\n      containers:\n\n        - name: wren-ui\n          image: ghcr.io/canner/wren-ui:0.5.6\n          env:\n            - name: DB_TYPE\n              valueFrom:\n                configMapKeyRef:\n                  name: wren-config\n                  key: WREN_UI_DB_TYPE\n            - name: WREN_ENGINE_ENDPOINT\n              valueFrom:\n                configMapKeyRef:\n                  name: wren-config\n                  key: WREN_ENGINE_ENDPOINT\n            - name: WREN_AI_ENDPOINT\n              valueFrom:\n                configMapKeyRef:\n                  name: wren-config\n                  key: WREN_AI_ENDPOINT\n            - name: GENERATION_MODEL\n              valueFrom:\n                configMapKeyRef:\n                  name: wren-config\n                  key: GENERATION_MODEL\n            - name: PG_URL\n              valueFrom:\n                secretKeyRef:\n                  name: wrenai-secrets\n                  key: PG_URL\n            # telemetry\n            - name: WREN_ENGINE_PORT\n              valueFrom:\n                configMapKeyRef:\n                  name: wren-config\n                  key: WREN_ENGINE_PORT\n            - name: WREN_AI_SERVICE_VERSION\n              valueFrom:\n                configMapKeyRef:\n                  name: wren-config\n                  key: WREN_AI_SERVICE_VERSION\n            - name: WREN_UI_VERSION\n              valueFrom:\n                configMapKeyRef:\n                  name: wren-config\n                  key: WREN_UI_VERSION\n            - name: WREN_ENGINE_VERSION\n              valueFrom:\n                configMapKeyRef:\n                  name: wren-config\n                  key: WREN_ENGINE_VERSION\n            - name: USER_UUID\n              valueFrom:\n                secretKeyRef:\n                  name: wrenai-secrets\n                  key: USER_UUID\n            - name: POSTHOG_API_KEY\n              valueFrom:\n                secretKeyRef:\n                  name: wrenai-secrets\n                  key: POSTHOG_API_KEY\n            - name: POSTHOG_HOST\n              valueFrom:\n                secretKeyRef:\n                  name: wrenai-secrets\n                  key: POSTHOG_HOST\n            - name: TELEMETRY_ENABLED\n              valueFrom: \n                configMapKeyRef:\n                  name: wren-config\n                  key: TELEMETRY_ENABLED\n            # client side\n            - name: NEXT_PUBLIC_USER_UUID\n              valueFrom:\n                secretKeyRef:\n                  name: wrenai-secrets\n                  key: USER_UUID\n            - name: NEXT_PUBLIC_POSTHOG_API_KEY\n              valueFrom:\n                secretKeyRef:\n                  name: wrenai-secrets\n                  key: POSTHOG_API_KEY\n            - name: NEXT_PUBLIC_POSTHOG_HOST\n              valueFrom:\n                secretKeyRef:\n                  name: wrenai-secrets\n                  key: POSTHOG_HOST\n            - name: NEXT_PUBLIC_TELEMETRY_ENABLED\n              valueFrom: \n                configMapKeyRef:\n                  name: wren-config\n                  key: TELEMETRY_ENABLED\n            # configs\n            - name: WREN_PRODUCT_VERSION\n              valueFrom:\n                configMapKeyRef:\n                  name: wren-config\n                  key: WREN_PRODUCT_VERSION\n            - name: IBIS_SERVER_ENDPOINT\n              valueFrom:\n                configMapKeyRef:\n                  name: wren-config\n                  key: IBIS_SERVER_ENDPOINT\n          ports:\n            - containerPort: 3000\n"
  },
  {
    "path": "deployment/kustomizations/base/pvc.yaml",
    "content": "apiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  name: wren-data-pvc\nspec:\n  accessModes:\n  - ReadWriteOnce\n  resources:\n    requests:\n      storage: 8Gi\n#  storageClassName: vsphere-retain\n"
  },
  {
    "path": "deployment/kustomizations/base/svc.yaml",
    "content": "# Dependancy https://external-dns.io\n# You may want to add a DNS record for wren-ui.myhost.net host for your k8s Service instead of Ingress. \n# Note: without authentication, enyone can acess your app, see your data and modify your settings!\n# If this is the case, make sure to comment the ingress-wren_example.yaml manifest in the `kustomization.yaml` file to exclude it\n# And uncomment external-dns in the Service manifest here below:\n\napiVersion: v1\nkind: Service\nmetadata:\n  name: wren-ui-svc\n  #annotations:\n    ### Dependancy external-dns\n    #external-dns.alpha.kubernetes.io/filter: 'include'\n    #external-dns.alpha.kubernetes.io/cloudflare-proxied: 'false'\n    #external-dns.alpha.kubernetes.io/target: wren-ui.myhost.net\nspec:\n  selector:\n    app: wren-ui\n  ports:\n    - protocol: TCP\n      port: 3000\n      targetPort: 3000\n      name: http-ui\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: wren-engine-svc\nspec:\n  selector:\n    app: wren-engine\n  ports:\n    - protocol: TCP\n      port: 8080\n      targetPort: 8080\n      name: wren-engine\n    - protocol: TCP\n      port: 7432\n      targetPort: 7432\n      name: wren-engine-sql\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: wren-ai-service-svc\nspec:\n  selector:\n    app: wren-ai-service\n  ports:\n    - protocol: TCP\n      port: 5555\n      targetPort: 5555\n      name: wren-ai-service\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: wren-ibis-server-svc\nspec:\n  selector:\n    app: wren-ibis\n  ports:\n    - protocol: TCP\n      port: 8000\n      targetPort: 8000\n      name: wren-ibis"
  },
  {
    "path": "deployment/kustomizations/examples/.gitignore",
    "content": "secret.yaml"
  },
  {
    "path": "deployment/kustomizations/examples/certificate-qdrant_example.yaml",
    "content": "# To generate valid certificates into qdrant-ai.myhost.net-tls\n# Dependancy: install https://cert-manager.io\napiVersion: cert-manager.io/v1\nkind: Certificate\nmetadata:\n  name: qdrant-ai.myhost.net\nspec:\n  dnsNames:\n    - qdrant-ai.myhost.net\n  issuerRef:\n    group: cert-manager.io\n    kind: ClusterIssuer\n    #### Replace with the name of your issuer\n    name: myhost.net-prod\n  secretName: qdrant-ai.myhost.net-tls\n"
  },
  {
    "path": "deployment/kustomizations/examples/certificate-wren_example.yaml",
    "content": "# To generate valid certificates into wren-ui.myhost.net-tls\n# Dependancy: install https://cert-manager.io\napiVersion: cert-manager.io/v1\nkind: Certificate\nmetadata:\n  name: wren-ui.myhost.net\nspec:\n  dnsNames:\n    - wren-ui.myhost.net\n  issuerRef:\n    group: cert-manager.io\n    kind: ClusterIssuer\n    ### Replace with the name of your issuer, otherwise the secret will be produce randoom name and the ingress will not work.\n    name: myhost.net-prod\n  ### Your ingress will be looking for this exact name:\n  secretName: wren-ui.myhost.net-tls\n"
  },
  {
    "path": "deployment/kustomizations/examples/ingress-wren_example.yaml",
    "content": "# Dependancy https://external-dns.io\n# To add a DNS record for wren-ui.myhost.net host\n# Note: without authentication, enyone can acess your app, see your data and modify your settings!\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n  name: wren-ui-ingress\n  annotations:\n    ### Dependancy external-dns\n    #external-dns.alpha.kubernetes.io/filter: 'include'\n    #external-dns.alpha.kubernetes.io/cloudflare-proxied: 'false'\n    ##external-dns.alpha.kubernetes.io/cloudflare-proxied: 'true'\n    external-dns.alpha.kubernetes.io/target: ingress1.myhost.net\n    #external-dns.alpha.kubernetes.io/target: ingress2.myhost.net\n    \n    ### Dependancy nginx-ingress-controller\n    nginx.ingress.kubernetes.io/disable-lua: 'true'\n    nginx.ingress.kubernetes.io/enable-lua: 'false'\n    nginx.ingress.kubernetes.io/enable-vts-status: 'false'\n    nginx.ingress.kubernetes.io/enable-modsecurity: 'false'\n    #nginx.ingress.kubernetes.io/modsecurity-snippet: |\n    #  SecRuleEngine Off\n    nginx.ingress.kubernetes.io/enable-owasp-modsecurity-crs: 'false'\n    nginx.ingress.kubernetes.io/proxy-connect-timeout: '360'\n    nginx.ingress.kubernetes.io/proxy-read-timeout: '360'\n    nginx.ingress.kubernetes.io/proxy-send-timeout: '360'\n\nspec:\n  #instead you may use other ingressClassName such as AWS alb. If other than nginx ingress is used, don't forget to comment unsupported annotations above\n  #\"nginx\" or \"alb\"\n  ingressClassName: nginx\n  rules:\n    - host: wren-ui.myhost.net\n      http:\n        paths:\n          - path: /\n            pathType: Prefix\n            backend:\n              service:\n                name: wren-ui-svc\n                port:\n                  number: 3000\n### Comment TLS section if you are not going to use https\n  tls:\n    - hosts:\n      - wren-ui.myhost.net\n      secretName: wren-ui.myhost.net-tls\n"
  },
  {
    "path": "deployment/kustomizations/examples/secret-wren_example.yaml",
    "content": "---\napiVersion: v1\nkind: Secret\nmetadata:\n  name: wrenai-secrets\ntype: Opaque\ndata:\n  # OPENAI_API_KEY is REQUIRED: without a valid key the wren-ai-service-deployment pod will not start\n  OPENAI_API_KEY: UkVRVUlSRUQ6IHNrLXByb2otYWxsLWFjY2Vzcy1wbGFjZWhvbGRlci00LXdyZW4tYWktc2VydmljZS1kZXBsb3ltZW50\n\n  # Azure openai env\n  AZURE_CHAT_BASE: bi9h\n  AZURE_CHAT_KEY: bi9h\n  AZURE_CHAT_VERSION: bi9h\n\n  AZURE_EMBED_BASE: bi9h\n  AZURE_EMBED_KEY: bi9h\n  AZURE_EMBED_VERSION: bi9h\n\n  # Langfuse: for LLM tracing\n  LANGFUSE_PUBLIC_KEY: xxxx\n  LANGFUSE_SECRET_KEY: xxxx\n\n  ### postgres://        This is the protocol. It tells the system that you’re connecting to a PostgreSQL database.\n  ### postgres:postgres  These are the username and password for the database, separated by a colon. In this case, both the username and password are “postgres”.\n  ### @wren-postgresql   This is the hostname of the database server. \"wren-postgresql\" means the database server is running in a Kubernetes cluster and it is named \"wren-postgresql\" in the *same* namespace. If you are using another namespace you must provide the full hostname, example: `wren-postgresql.wrenai.svc.cluster.local`, \"wrenai\" is the namespace name, \"svc.cluster.local\" is the default domain name for Kubernetes services no need to change it.\n  ### :5432              This is the port number. PostgreSQL servers listen on port 5432 by default.\n  ### /admin_ui          This is the name of the database you’re connecting to. In this case, the database name is “admin_ui”. It can be found in the helm values file in the auth.database parameter (deployment/kustomizations/helm-values_postgresql_14.yaml)\n  ### PG_URL: \"postgres://postgres:postgres@wren-postgresql:5432/admin_ui\"\n  #Fix\n  PG_URL: cG9zdGdyZXM6Ly9wb3N0Z3Jlczpwb3N0Z3Jlc0B3cmVuLXBvc3RncmVzcWw6NTQzMi9hZG1pbl91aQo=\n  PG_USERNAME: cG9zdGdyZXM=\n\n  POSTHOG_API_KEY: cGhjX2tleS1wbGFjZWhvbGRlcg==\n  POSTHOG_HOST: aHR0cHM6Ly9hcHAucG9zdGhvZy5jb20=\n  USER_UUID: MDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAw\n---\napiVersion: v1\nkind: Secret\nmetadata:\n  name: wrenai-postgresql\ndata:\n  postgres-password: cG9zdGdyZXM=\ntype: Opaque\n"
  },
  {
    "path": "deployment/kustomizations/helm-values-qdrant_1.11.0.yaml",
    "content": "replicaCount: 1\n\nimage:\n  repository: docker.io/qdrant/qdrant\n  pullPolicy: IfNotPresent\n  tag: \"v1.11.0\"\n  useUnprivilegedImage: false\n\nimagePullSecrets: []\nnameOverride: \"\"\nfullnameOverride: \"\"\nargs: [\"./config/initialize.sh\"]\nenv: {}\n  # - name: QDRANT_ALLOW_RECOVERY_MODE\n  #   value: true\n\n# checks - Readiness and liveness checks can only be enabled for either http (REST) or grpc (multiple checks not supported)\n# grpc checks are only available from k8s 1.24+ so as of per default we check http\nservice:\n  type: ClusterIP\n  additionalLabels: {}\n  annotations: {}\n  loadBalancerIP: \"\"\n  ports:\n    - name: http\n      port: 6333\n      targetPort: 6333\n      protocol: TCP\n      checksEnabled: true\n    - name: grpc\n      port: 6334\n      targetPort: 6334\n      protocol: TCP\n      checksEnabled: false\n    - name: p2p\n      port: 6335\n      targetPort: 6335\n      protocol: TCP\n      checksEnabled: false\n\ningress:\n  enabled: false\n  ingressClassName: \"nginx\"\n  additionalLabels: {}\n  annotations:\n    # Dependancy: https://kubernetes-sigs.github.io/external-dns\n    #external-dns.alpha.kubernetes.io/filter: 'include'\n    #external-dns.alpha.kubernetes.io/cloudflare-proxied: 'true'\n    external-dns.alpha.kubernetes.io/target: ingress1.myhost.net\n  hosts:\n    - host: qdrant-ai.myhost.net\n      paths:\n        - path: /\n          pathType: Prefix\n          servicePort: 6333\n  tls:\n    - hosts:\n       - qdrant-ai.myhost.net\n      secretName: qdrant-ai.myhost.net-tls\n\nlivenessProbe:\n  enabled: false\n  initialDelaySeconds: 5\n  periodSeconds: 5\n  timeoutSeconds: 1\n  failureThreshold: 6\n  successThreshold: 1\n\nreadinessProbe:\n  enabled: true\n  initialDelaySeconds: 5\n  periodSeconds: 5\n  timeoutSeconds: 1\n  failureThreshold: 6\n  successThreshold: 1\n\nstartupProbe:\n  enabled: false\n  initialDelaySeconds: 10\n  periodSeconds: 5\n  timeoutSeconds: 1\n  failureThreshold: 30\n  successThreshold: 1\n\nadditionalLabels: {}\npodAnnotations: {}\npodLabels: {}\n\nresources: {}\n  # limits:\n  #   cpu: 100m\n  #   memory: 128Mi\n  # requests:\n  #   cpu: 100m\n  #   memory: 128Mi\n\ncontainerSecurityContext:\n  runAsNonRoot: true\n  runAsUser: 1000\n  runAsGroup: 2000\n  allowPrivilegeEscalation: false\n  privileged: false\n  readOnlyRootFilesystem: true\n\npodSecurityContext:\n  fsGroup: 3000\n  fsGroupChangePolicy: Always\n\nlifecycle:\n  preStop:\n    exec:\n      # Sleeping before shutdown allows Qdrant to process requests that were\n      # in-flight before the node is removed from load-balancing.\n      # If using an external load balancer, you may need to increase this\n      # duration to be greater than the LB's health check interval.\n      command: [\"sleep\", \"3\"]\n\n# If true ensures that the pre-existing files on the storage and snapshot volume are owned by the container's\n# user and fsGroup\nupdateVolumeFsOwnership: true\n\nnodeSelector: {}\n\ntolerations: []\n\naffinity: {}\n\ntopologySpreadConstraints: []\n\npersistence:\n  accessModes: [\"ReadWriteOnce\"]\n  size: 20Gi\n  annotations: {}\n#  storageClassName: vsphere-retain\n\n# If you use snapshots or the snapshot shard transfer mechanism, we recommend\n# creating a separate volume of the same size as your main volume so that your\n# cluster won't crash if the snapshot is too big.\nsnapshotPersistence:\n  enabled: false\n  accessModes: [\"ReadWriteOnce\"]\n  size: 20Gi\n  annotations: {}\n  # You can change the storageClassName to ensure snapshots are saved to cold storage.\n  # storageClassName: local-path\n\nsnapshotRestoration:\n  enabled: false\n  # Set pvcName if you want to restore from a separately-created PVC. Only supported for single-node clusters unless the PVC is ReadWriteMany.\n  # If you set snapshotPersistence.enabled and want to restore a snapshot from there, you can leave this blank to skip mounting an external volume.\n  pvcName: snapshots-pvc\n  # Must not conflict with /qdrant/snapshots or /qdrant/storage\n  mountPath: /qdrant/snapshot-restoration\n  snapshots:\n  #  - /qdrant/snapshot-restoration/test_collection/test_collection-2022-10-24-13-56-50.snapshot:test_collection\n\n# modification example for configuration to overwrite defaults\nconfig:\n  cluster:\n    enabled: true\n    p2p:\n      port: 6335\n    consensus:\n      tick_period_ms: 100\n\nsidecarContainers: []\n# sidecarContainers:\n#   - name: my-sidecar\n#     image: qdrant/my-sidecar-image\n#     imagePullPolicy: Always\n#     ports:\n#     - name: my-port\n#       containerPort: 5000\n#       protocol: TCP\n#     resources:\n#       requests:\n#         memory: 10Mi\n#         cpu: 10m\n#       limits:\n#         memory: 100Mi\n#         cpu: 100m\n\nmetrics:\n  serviceMonitor:\n    enabled: false\n    additionalLabels: {}\n    scrapeInterval: 30s\n    scrapeTimeout: 10s\n    targetPort: http\n    targetPath: \"/metrics\"\n    ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion.\n    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig\n    ##\n    metricRelabelings: []\n    ## RelabelConfigs to apply to samples before scraping\n    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig\n    ##\n    relabelings: []\n\nserviceAccount:\n  annotations: {}\n\npriorityClassName: \"\"\n\n# We disourage changing this setting. Using the \"OrderedReady\" policy in a\n# multi-node cluster will cause a deadlock where nodes refuse to become\n# \"Ready\" until all nodes are running.\npodManagementPolicy: Parallel\n\npodDisruptionBudget:\n  enabled: false\n  maxUnavailable: 1\n  # do not enable if you are using not in 1.27\n  unhealthyPodEvictionPolicy: \"\"\n  # minAvailable: 1\n\n# api key for authentication at qdrant\n# false: no api key will be configured\n# true: an api key will be auto-generated\n# string: the given string will be set as an apikey\napiKey: false\n# read-only api key for authentication at qdrant\n# false: no read-only api key will be configured\n# true: an read-only api key will be auto-generated\n# string: the given string will be set as a read-only apikey\nreadOnlyApiKey: false\n\nadditionalVolumes: []\n# - name: volumeName\n#   emptyDir: {}\n\nadditionalVolumeMounts: []\n# - name: volumeName\n#   mountPath: \"/mount/path\"\n"
  },
  {
    "path": "deployment/kustomizations/helm-values_postgresql_15.yaml",
    "content": "auth:\n  secretKeys:\n    adminPasswordKey: postgres-password\n  existingSecret: wrenai-postgresql\n#creates admin_ui database\nglobal:\n  postgresql:\n    auth:\n      database: admin_ui"
  },
  {
    "path": "deployment/kustomizations/kustomization.yaml",
    "content": "##### Dependancies used in this kustomization:\n# nginx.ingress\n# external-dns\n# cert-manager\n# kubectl kustomize\n\n#test output like this:\n#kubectl kustomize deployment/kustomizations --enable-helm > deployment/kustomizations/wrenai.kustimized.yaml\n#kubectl create namespace wren\n#kubectl apply -f deployment/kustomizations/wrenai.kustimized.yaml\napiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\n\n# Namespace for all resources here and in the Helm charts\nnamespace: wren\nhelmCharts:\n\n### Uncomment if you are planing to use postgresql\n  - name: postgresql\n    repo: https://repo.vmware.com/bitnami-files\n    version: 15.5.5\n    releaseName: wren-postgresql\n    valuesFile: helm-values_postgresql_15.yaml\n    includeCRDs: true\n    # the Same Namespace\n    namespace: wren\n\n  - name: qdrant\n    repo: https://qdrant.github.io/qdrant-helm\n    version: 1.11.0\n    releaseName: wren-qdrant\n    valuesFile: helm-values-qdrant_1.11.0.yaml\n    includeCRDs: true\n    # The Same Namespace\n    namespace: wren\n\n\nimages:\n  # for the latest versions, please check here: https://github.com/Canner/WrenAI/blob/main/docker/.env.example#L23\n  - name: ghcr.io/canner/wren-bootstrap\n    newTag: 0.1.5 # WREN_BOOTSTRAP_VERSION\n  - name: ghcr.io/canner/wren-engine\n    newTag: 0.14.8 # WREN_ENGINE_VERSION\n  - name: ghcr.io/canner/wren-ui\n    newTag: 0.24.1 # WREN_UI_VERSION\n  - name: ghcr.io/canner/wren-ai-service\n    newTag: 0.19.7 # WREN_AI_SERVICE_VERSION\n  - name: ghcr.io/canner/wren-engine-ibis\n    newTag: 0.14.8 # IBIS_SERVER_VERSION\n\nresources:\n  - base/cm.yaml\n  - base/deploy-wren-ui.yaml\n  - base/deploy-wren-engine.yaml\n  - base/deploy-wren-ibis-server.yaml\n  - base/deploy-wren-ai-service.yaml\n  - base/pvc.yaml\n  - base/svc.yaml\n### Modify these examples first and uncomment them:\n  # - examples/ingress-wren_example.yaml\n  # - examples/certificate-wren_example.yaml\n### Usually you do not need to generate a certificate for Qdrant\n#  - examples/certificate-qdrant_example.yaml\n### Best practice is to create and deploy Secrets manually, not as part of kustomization or GitOps!\n#  - examples/secret-wren_example.yaml"
  },
  {
    "path": "deployment/kustomizations/patches/README.md",
    "content": "# Example of usefull Patches for Kustomization\n\nPatches from this folder allows to utilize the official unmodified deployment/kustomization dirrectly from the repo as a base layer for your kustomization. And then add patches to update some values. This is usefull for your GitOps and can be combined with tools such as ArgoCD and FluxCD.\n\nPatch ConfigMap, and Service if needed.\nRemove Certificate and Ingress if not needed."
  },
  {
    "path": "deployment/kustomizations/patches/cm.yaml",
    "content": "- op: replace\n  path: /data\n  value:\n    # Wren Engine Service Port\n    WREN_ENGINE_PORT: \"8080\"\n    # Wren AI Service Port\n    WREN_AI_SERVICE_PORT: \"5555\"\n\n    #Release version used by wren ui https://github.com/Canner/WrenAI/blob/main/docker/docker-compose.yaml#L85-L88\n    WREN_PRODUCT_VERSION: \"0.12.0\"\n    #fix:\n    WREN_ENGINE_VERSION: \"0.12.3\"\n    WREN_AI_SERVICE_VERSION: \"0.12.1\"\n    #fix:\n    WREN_UI_VERSION: \"0.17.6\"\n\n    # OpenAI\n    GENERATION_MODEL: \"gpt-4o-mini\"\n\n    # Telemetry\n    POSTHOG_HOST: \"https://app.posthog.com\"\n    TELEMETRY_ENABLED: \"false\"\n\n    # service endpoints of AI service & engine service\n    WREN_ENGINE_ENDPOINT: \"http://wren-engine-svc:8080\"\n    #fix:\n    WREN_AI_ENDPOINT: \"http://wren-ai-service:5555\"\n\n    # \"pg\" for postgres as application database.\n    #fix\n    DB_TYPE: pg\n\n    DATA_PATH: \"/app/data\"\n\n    ### if DB_TYPE = \"postgres\" you must provide PG_URL string in the *Secret* manifest file (deployment/kustomizations/examples/secret-wren_example.yaml) to connect to postgres\n"
  },
  {
    "path": "deployment/kustomizations/patches/rm-certificate.yaml",
    "content": "$patch: delete\napiVersion: v1\nkind: Certificate\nmetadata:\n  name: wren-ui.myhost.net"
  },
  {
    "path": "deployment/kustomizations/patches/rm-ingress.yaml",
    "content": "$patch: delete\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n  name: wren-ui-ingress\n  annotations:\n    external-dns.alpha.kubernetes.io/target: ingress1.myhost.net"
  },
  {
    "path": "deployment/kustomizations/patches/service.yaml",
    "content": "- op: replace\n  path: /spec/ipFamilies\n  value:\n    - IPv6\n    - IPv4\n\n- op: replace\n  path: /spec/type\n  value:\n    LoadBalancer\n\n- op: replace\n  path: /spec/ipFamilyPolicy\n  value:\n#    SingleStack\n    PreferDualStack"
  },
  {
    "path": "docker/README.md",
    "content": "## Service\n\n- `wren-engine`: the engine service. check out example here: [wren-engine\n  /example](https://github.com/Canner/wren-engine/tree/main/example)\n- `wren-ai-service`: the AI service.\n- `qdrant`: the vector store ai service is using.\n- `wren-ui`: the UI service.\n- `bootstrap`: put required files to volume for engine service.\n\n## Volume\n\nShared data using `data` volume.\n\nPath structure as following:\n\n- `/mdl`\n  - `*.json` (will put `sample.json` during bootstrap)\n- `accounts`\n- `config.properties`\n\n## Network\n\n- Check out [Network drivers overview](https://docs.docker.com/engine/network/drivers/) to learn more about `bridge` network driver.\n\n## How to start with OpenAI\n\n1. copy `.env.example` to `.env` and modify the OpenAI API key.\n2. copy `config.example.yaml` to `config.yaml` for AI service configuration.\n3. start all services: `docker-compose --env-file .env up -d`.\n4. stop all services: `docker-compose --env-file .env down`.\n\n### Optional\n\n- If your port 3000 is occupied, you can modify the `HOST_PORT` in `.env`.\n\n## How to start with custom LLM\n\nTo start with a custom LLM, the process is similar to starting with OpenAI. The main difference is that you need to modify the `config.yaml` file\nthat we created on the previous step. After modifying the file, you can restart the services by running `docker-compose --env-file .env up -d --force-recreate wren-ai-service`.\n\nFor detailed information on how to modify the configuration for different LLM providers and models, please refer to the [AI Service Configuration](../wren-ai-service/docs/configuration.md).\nThis guide provides comprehensive instructions on setting up various LLM providers, embedders, and other components of the AI service.\n"
  },
  {
    "path": "docker/bootstrap/Dockerfile",
    "content": "FROM busybox\n\nWORKDIR /app\nCOPY init.sh ./"
  },
  {
    "path": "docker/bootstrap/init.sh",
    "content": "#!/bin/sh\n# declare a variable from the environment variable: DATA_PATH\ndata_path=${DATA_PATH:-\"./\"}\n\n# touch a empty config.properties if not exists\n# put a content into config.properties if not exists\nif [ ! -f ${data_path}/config.properties ]; then\n  echo \"init config.properties\"\n  echo \"node.environment=production\" >${data_path}/config.properties\nfi\n\n# after the config.properties is created, check if config properties properly set\n# if not, then append default values to the config.properties\n# check if wren.experimental-enable-dynamic-fields is set, otherwise append it with true\nif ! grep -q \"wren.experimental-enable-dynamic-fields\" ${data_path}/config.properties; then\n  echo \"wren.experimental-enable-dynamic-fields is not set, set it to true\"\n  echo \"wren.experimental-enable-dynamic-fields=true\" >>${data_path}/config.properties\nfi\n\n# create a folder mdl if not exists\nif [ ! -d ${data_path}/mdl ]; then\n  echo \"create mdl folder\"\n  mkdir ${data_path}/mdl\nfi\n\n# put an emtpy sample.json if not exists\nif [ ! -f ${data_path}/mdl/sample.json ]; then\n  echo \"init mdl/sample.json\"\n  echo \"{\\\"catalog\\\": \\\"test_catalog\\\", \\\"schema\\\": \\\"test_schema\\\", \\\"models\\\": []}\" >${data_path}/mdl/sample.json\nfi\n"
  },
  {
    "path": "docker/config.example.yaml",
    "content": "type: llm\nprovider: litellm_llm\ntimeout: 120\nmodels:\n  - alias: default\n    model: gpt-4.1-nano-2025-04-14\n    context_window_size: 1000000\n    kwargs:\n      max_tokens: 4096\n      n: 1\n      seed: 0\n      temperature: 0\n  - model: gpt-4.1-mini-2025-04-14\n    context_window_size: 1000000\n    kwargs:\n      max_tokens: 4096\n      n: 1\n      seed: 0\n      temperature: 0\n  - model: gpt-4.1-2025-04-14\n    context_window_size: 1000000\n    kwargs:\n      max_tokens: 4096\n      n: 1\n      seed: 0\n      temperature: 0\n  - model: gpt-5-nano-2025-08-07\n    context_window_size: 380000\n    kwargs:\n      max_completion_tokens: 4096\n      n: 1\n      seed: 0\n      reasoning_effort: minimal\n  - model: gpt-5-mini-2025-08-07\n    context_window_size: 380000\n    kwargs:\n      max_completion_tokens: 4096\n      n: 1\n      seed: 0\n      reasoning_effort: minimal\n  - model: gpt-5-2025-08-07\n    context_window_size: 380000\n    kwargs:\n      max_completion_tokens: 4096\n      n: 1\n      seed: 0\n      reasoning_effort: minimal\n---\ntype: embedder\nprovider: litellm_embedder\nmodels:\n  - model: text-embedding-3-large\n    alias: default\n    timeout: 120\n\n---\ntype: engine\nprovider: wren_ui\nendpoint: http://wren-ui:3000\n\n---\ntype: engine\nprovider: wren_ibis\nendpoint: http://ibis-server:8000\n\n---\ntype: document_store\nprovider: qdrant\nlocation: http://qdrant:6333\nembedding_model_dim: 3072\ntimeout: 120\nrecreate_index: true\n\n---\ntype: pipeline\npipes:\n  - name: db_schema_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: table_description_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_correction\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: followup_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_answer\n    llm: litellm_llm.default\n  - name: semantics_description\n    llm: litellm_llm.default\n  - name: relationship_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: intent_classification\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: misleading_assistance\n    llm: litellm_llm.default\n  - name: data_assistance\n    llm: litellm_llm.default\n  - name: sql_pairs_indexing\n    document_store: qdrant\n    embedder: litellm_embedder.default\n  - name: sql_pairs_retrieval\n    document_store: qdrant\n    embedder: litellm_embedder.default\n    llm: litellm_llm.default\n  - name: preprocess_sql_data\n    llm: litellm_llm.default\n  - name: sql_executor\n    engine: wren_ui\n  - name: chart_generation\n    llm: litellm_llm.default\n  - name: chart_adjustment\n    llm: litellm_llm.default\n  - name: user_guide_assistance\n    llm: litellm_llm.default\n  - name: sql_question_generation\n    llm: litellm_llm.default\n  - name: sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: followup_sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: sql_regeneration\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: instructions_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: instructions_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_functions_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n  - name: project_meta_indexing\n    document_store: qdrant\n  - name: sql_tables_extraction\n    llm: litellm_llm.default\n  - name: sql_diagnosis\n    llm: litellm_llm.default\n  - name: sql_knowledge_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n\n---\nsettings:\n  doc_endpoint: https://docs.getwren.ai\n  is_oss: true\n  engine_timeout: 30\n  column_indexing_batch_size: 50\n  table_retrieval_size: 10\n  table_column_retrieval_size: 100\n  allow_intent_classification: true\n  allow_sql_generation_reasoning: true\n  allow_sql_functions_retrieval: true\n  enable_column_pruning: false\n  max_sql_correction_retries: 3\n  query_cache_maxsize: 1000\n  query_cache_ttl: 3600\n  langfuse_host: https://cloud.langfuse.com\n  langfuse_enable: true\n  logging_level: DEBUG\n  development: false\n  historical_question_retrieval_similarity_threshold: 0.9\n  sql_pairs_similarity_threshold: 0.7\n  sql_pairs_retrieval_max_size: 10\n  instructions_similarity_threshold: 0.7\n  instructions_top_k: 10"
  },
  {
    "path": "docker/docker-compose-dev.yaml",
    "content": "version: \"3\"\n\nvolumes:\n  data:\n\nnetworks:\n  wren:\n    driver: bridge\n\nservices:\n  bootstrap:\n    image: ghcr.io/canner/wren-bootstrap:${WREN_BOOTSTRAP_VERSION}\n    pull_policy: always\n    platform: ${PLATFORM}\n    environment:\n      DATA_PATH: /app/data\n    volumes:\n      - data:/app/data\n    command: /bin/sh /app/init.sh\n\n  wren-engine:\n    image: ghcr.io/canner/wren-engine:${WREN_ENGINE_VERSION}\n    pull_policy: always\n    platform: ${PLATFORM}\n    expose:\n      - ${WREN_ENGINE_SQL_PORT}\n    ports:\n      - ${WREN_ENGINE_PORT}:${WREN_ENGINE_PORT}\n    volumes:\n      - data:/usr/src/app/etc\n    networks:\n      - wren\n    depends_on:\n      - bootstrap\n\n  wren-ai-service:\n    image: ghcr.io/canner/wren-ai-service:${WREN_AI_SERVICE_VERSION}\n    pull_policy: always\n    platform: ${PLATFORM}\n    ports:\n      - ${AI_SERVICE_FORWARD_PORT}:${WREN_AI_SERVICE_PORT}\n    environment:\n      WREN_UI_ENDPOINT: http://host.docker.internal:${WREN_UI_PORT}\n      # sometimes the console won't show print messages,\n      # using PYTHONUNBUFFERED: 1 can fix this\n      PYTHONUNBUFFERED: 1\n      CONFIG_PATH: /app/config.yaml\n    env_file:\n      - ${PROJECT_DIR}/.env\n    volumes:\n      - ${PROJECT_DIR}/config.yaml:/app/config.yaml:ro\n      - ${PROJECT_DIR}/data:/app/data:ro\n    networks:\n      - wren\n    depends_on:\n      - qdrant\n\n  ibis-server:\n    image: ghcr.io/canner/wren-engine-ibis:${IBIS_SERVER_VERSION}\n    pull_policy: always\n    platform: ${PLATFORM}\n    expose:\n      - 8000\n    ports:\n      - ${IBIS_SERVER_PORT}:8000\n    environment:\n      WREN_ENGINE_ENDPOINT: http://wren-engine:${WREN_ENGINE_PORT}\n      LOG_LEVEL: DEBUG\n    networks:\n      - wren\n\n  qdrant:\n    image: qdrant/qdrant:v1.11.0\n    pull_policy: always\n    ports:\n      - 6333:6333\n      - 6334:6334\n    networks:\n      - wren\n\n  # If you want to use postgres for testing purpose, uncomment the following block\n  # postgres:\n  #   image: postgres:14-alpine\n  #   platform: ${PLATFORM}\n  #   ports:\n  #     - 9432:5432\n  #   volumes:\n  #     - data:/var/lib/postgresql/data\n  #   environment:\n  #     - POSTGRES_PASSWORD=secret\n  #     - POSTGRES_USER=test\n  #     - POSTGRES_DB=test\n  #     - PGDATA=/var/lib/postgresql/data/pgdata\n  #   networks:\n  #     - wren\n"
  },
  {
    "path": "docker/docker-compose.yaml",
    "content": "version: \"3\"\n\nvolumes:\n  data:\n\nnetworks:\n  wren:\n    driver: bridge\n\nservices:\n  bootstrap:\n    image: ghcr.io/canner/wren-bootstrap:${WREN_BOOTSTRAP_VERSION}\n    restart: on-failure\n    platform: ${PLATFORM}\n    environment:\n      DATA_PATH: /app/data\n    volumes:\n      - data:/app/data\n    command: /bin/sh /app/init.sh\n\n  wren-engine:\n    image: ghcr.io/canner/wren-engine:${WREN_ENGINE_VERSION}\n    restart: on-failure\n    platform: ${PLATFORM}\n    expose:\n      - ${WREN_ENGINE_PORT}\n      - ${WREN_ENGINE_SQL_PORT}\n    volumes:\n      - data:/usr/src/app/etc\n      - ${PROJECT_DIR}/data:/usr/src/app/data\n    networks:\n      - wren\n    depends_on:\n      - bootstrap\n\n  ibis-server:\n    image: ghcr.io/canner/wren-engine-ibis:${IBIS_SERVER_VERSION}\n    restart: on-failure\n    platform: ${PLATFORM}\n    expose:\n      - ${IBIS_SERVER_PORT}\n    environment:\n      WREN_ENGINE_ENDPOINT: http://wren-engine:${WREN_ENGINE_PORT}\n    volumes:\n      - ${LOCAL_STORAGE:-.}:/usr/src/app/data\n    networks:\n      - wren\n\n  wren-ai-service:\n    image: ghcr.io/canner/wren-ai-service:${WREN_AI_SERVICE_VERSION}\n    restart: on-failure\n    platform: ${PLATFORM}\n    expose:\n      - ${WREN_AI_SERVICE_PORT}\n    ports:\n      - ${AI_SERVICE_FORWARD_PORT}:${WREN_AI_SERVICE_PORT}\n    environment:\n      # sometimes the console won't show print messages,\n      # using PYTHONUNBUFFERED: 1 can fix this\n      PYTHONUNBUFFERED: 1\n      CONFIG_PATH: /app/config.yaml\n    env_file:\n      - ${PROJECT_DIR}/.env\n    volumes:\n      - ${PROJECT_DIR}/config.yaml:/app/config.yaml:ro\n      - ${PROJECT_DIR}/data:/app/data:ro\n    networks:\n      - wren\n    depends_on:\n      - qdrant\n\n  qdrant:\n    image: qdrant/qdrant:v1.11.0\n    restart: on-failure\n    expose:\n      - 6333\n      - 6334\n    volumes:\n      - data:/qdrant/storage\n    networks:\n      - wren\n\n  wren-ui:\n    image: ghcr.io/canner/wren-ui:${WREN_UI_VERSION}\n    restart: on-failure\n    platform: ${PLATFORM}\n    environment:\n      DB_TYPE: sqlite\n      # /app is the working directory in the container\n      SQLITE_FILE: /app/data/db.sqlite3\n      WREN_ENGINE_ENDPOINT: http://wren-engine:${WREN_ENGINE_PORT}\n      WREN_AI_ENDPOINT: http://wren-ai-service:${WREN_AI_SERVICE_PORT}\n      IBIS_SERVER_ENDPOINT: http://ibis-server:${IBIS_SERVER_PORT}\n      # this is for telemetry to know the model, i think ai-service might be able to provide a endpoint to get the information\n      GENERATION_MODEL: ${GENERATION_MODEL}\n      # telemetry\n      WREN_ENGINE_PORT: ${WREN_ENGINE_PORT}\n      WREN_AI_SERVICE_VERSION: ${WREN_AI_SERVICE_VERSION}\n      WREN_UI_VERSION: ${WREN_UI_VERSION}\n      WREN_ENGINE_VERSION: ${WREN_ENGINE_VERSION}\n      USER_UUID: ${USER_UUID}\n      POSTHOG_API_KEY: ${POSTHOG_API_KEY}\n      POSTHOG_HOST: ${POSTHOG_HOST}\n      TELEMETRY_ENABLED: ${TELEMETRY_ENABLED}\n      # client side\n      NEXT_PUBLIC_USER_UUID: ${USER_UUID}\n      NEXT_PUBLIC_POSTHOG_API_KEY: ${POSTHOG_API_KEY}\n      NEXT_PUBLIC_POSTHOG_HOST: ${POSTHOG_HOST}\n      NEXT_PUBLIC_TELEMETRY_ENABLED: ${TELEMETRY_ENABLED}\n      EXPERIMENTAL_ENGINE_RUST_VERSION: ${EXPERIMENTAL_ENGINE_RUST_VERSION}\n      # configs\n      WREN_PRODUCT_VERSION: ${WREN_PRODUCT_VERSION}\n    ports:\n      # HOST_PORT is the port you want to expose to the host machine\n      - ${HOST_PORT}:3000\n    volumes:\n      - data:/app/data\n    networks:\n      - wren\n    depends_on:\n      - wren-ai-service\n      - wren-engine\n"
  },
  {
    "path": "wren-ai-service/.dockerignore",
    "content": "*\n!src\n!entrypoint.sh\n!pyproject.toml\nsrc/eval"
  },
  {
    "path": "wren-ai-service/.pre-commit-config.yaml",
    "content": "repos:\n- repo: https://github.com/astral-sh/ruff-pre-commit\n  # Ruff version.\n  rev: v0.2.2\n  hooks:\n    # Run the linter.\n    - id: ruff\n      args: [ --fix ]\n    # Run the formatter.\n    - id: ruff-format\n"
  },
  {
    "path": "wren-ai-service/CONTRIBUTING.md",
    "content": "# Welcome to Wren AI Service contributing guide\n\nThank you for investing your time in contributing to our project! This document provides guidelines for contributing to the Wren AI service.\n\n## New contributor guide\n\n- To get an overview of the project, please read the [concepts](https://docs.getwren.ai/oss/concept/wren_ai_service).\n- To set up the project for local development, please read [Environment Setup](README.md#environment-setup) and [Start the service for development](README.md#start-the-service-for-development)\n- To understand the codebase more quickly, we've prepared [a codebase introduciton](docs/code_design.md) for you.\n\n## Getting started\n\n### Issues\n\n#### Create a new issue\n\nIf you spot a problem, search if an issue already exists. If a related issue doesn't exist, you can open a new [issue](https://github.com/Canner/WrenAI/issues/new/choose).\n\n#### Solve an issue\n\nScan through our [existing issues](https://github.com/Canner/WrenAI/issues?q=is%3Aopen+is%3Aissue+label%3Amodule%2Fai-service) to find one that interests you. As a general rule, we don't assign issues to anyone. If you find an issue to work on, you are welcome to open a PR with a fix.\n\n### Pull Request\n\nWhen you've finished with the changes, create a pull request, also known as a PR.\n- Fill the description so that we can review your PR.\n- Don't forget to [link PR to issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) if you are solving one.\n- Add the `module/ai-service` label to your PR.\n- Enable the checkbox to [allow maintainer edits](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/allowing-changes-to-a-pull-request-branch-created-from-a-fork) so the branch can be updated for a merge.\n  Once you submit your PR, a Canner team member will review your proposal. We may ask questions or request additional information.\n- We may ask for changes to be made before a PR can be merged, either using [suggested changes](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/incorporating-feedback-in-your-pull-request) or pull request comments. You can apply suggested changes directly through the UI. You can make any other changes in your fork, then commit them to your branch.\n- As you update your PR and apply changes, mark each conversation as [resolved](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request#resolving-conversations).\n- Be sure to add one of the prefixes to the PR title, so that our CI could automatically capture the changelog of this PR.\n  - `feat(wren-ai-service)`: for new features\n  - `chore(wren-ai-service)`: for maintenance work\n  - `fix(wren-ai-service)`: for bug fixes\n- If you run into any merge issues, checkout this [git tutorial](https://github.com/skills/resolve-merge-conflicts) to help you resolve merge conflicts and other issues.\n\n### Your PR is merged!\n\nCongratulations :tada::tada: The Canner team thanks you :sparkles:.\n\nOnce your PR is merged, your contributions will be worked on the next release.\n\nNow that you are part of the Canner community.\n\n## How to add your preferred LLM, Embedder or Document Store\n\n- Please read [this documentation for further details](https://docs.getwren.ai/oss/ai_service/guide/custom_llm#adding-a-custom-llm-embedder-or-document-store-to-wren-ai).\n"
  },
  {
    "path": "wren-ai-service/Justfile",
    "content": "GREEN := \"\\u{001b}[32m\"\nYELLOW := \"\\u{001b}[33m\"\nRESET := \"\\u{001b}[0m\"\n\n## todo: consider to support --override flag to override existing files\ninit dev='--dev':\n\t@if [ ! -f config.yaml ]; then \\\n\t\techo \"{{GREEN}}config.yaml does not exist. Creating from example...{{RESET}}\"; \\\n\t\tcp tools/config/config.example.yaml config.yaml; \\\n\telse \\\n\t\techo \"{{YELLOW}}config.yaml already exists. Skipping creation.{{RESET}}\"; \\\n\tfi \n\n\t@if [ {{dev}} = \"--dev\" ] || [ {{dev}} != \"--non-dev\" ]; then \\\n\t\tif [ ! -f .env.dev ]; then \\\n\t\t\t\techo \"{{GREEN}}.env.dev does not exist. Creating from example...{{RESET}}\"; \\\n\t\t\t\tcp tools/config/.env.dev.example .env.dev; \\\n\t\telse \\\n\t\t\techo \"{{YELLOW}}.env.dev already exists. Skipping creation.{{RESET}}\"; \\\n\t\tfi \\\n\tfi\n\nup: prepare-files\n\tdocker compose -f ./tools/dev/docker-compose-dev.yaml --env-file ./tools/dev/.env up -d\n\ndown:\n\tdocker compose -f ./tools/dev/docker-compose-dev.yaml --env-file ./tools/dev/.env down\n\nstart: force_update_config\n\tpoetry run python -m src.__main__\n\ncurate_eval_data:\n\tpoetry run streamlit run eval/data_curation/app.py\n\nprep dataset='spider1.0':\n\tpoetry run python -m eval.preparation --dataset {{dataset}}\n\npredict dataset pipeline='ask':\n    poetry run python -u eval/prediction.py --file {{dataset}} --pipeline {{pipeline}}\n\neval prediction_result semantics='--no-semantics':\n    poetry run python -u eval/evaluation.py --file {{prediction_result}} {{semantics}}\n\ntest test_args='': up && down\n\tpoetry run pytest -s {{test_args}} --ignore tests/pytest/test_usecases.py\n\ntest-usecases usecases='all' lang='en':\n\tpoetry run python -m tests.pytest.test_usecases --usecases {{usecases}} --lang {{lang}}\n\nload-test:\n\tpoetry run python -m tests.locust.locust_script\n\nprepare-files:\n\t# only remove files related to engine and ui\n\trm -rf tools/dev/etc/duckdb tools/dev/etc/mdl tools/dev/etc/config.properties tools/dev/etc/db.sqlite3 tools/dev/etc/archived\n\tmkdir -p tools/dev/etc\n\tcp tools/dev/config.properties.example tools/dev/etc/config.properties\n\tmkdir -p tools/dev/etc/mdl\n\techo \"{\\\"catalog\\\": \\\"test_catalog\\\", \\\"schema\\\": \\\"test_schema\\\", \\\"models\\\": []}\" \\\\\n\t\t> tools/dev/etc/mdl/sample.json\n\nforce_update_config:\n\tpoetry run python -m src.force_update_config\n\nrun-sql mdl_path=\"\" data_source=\"\" sample_dataset=\"\":\n\tpoetry run python tools/run_sql.py --mdl-path \"{{mdl_path}}\" --data-source \"{{data_source}}\" --sample-dataset \"{{sample_dataset}}\"\n\nmdl-to-str mdl_path=\"\":\n\tpoetry run python tools/mdl_to_str.py -p {{mdl_path}}\n"
  },
  {
    "path": "wren-ai-service/README.md",
    "content": "# AI Service of Wren AI\n\n## Concepts\n\nPlease read the [documentation](https://docs.getwren.ai/oss/concept/wren_ai_service) here to understand the concepts of Wren AI Service.\n\n## Setup for Local Development\n\n### Prerequisites\n\n1. **Python**: Install Python 3.12.\\*\n\n   - Recommended: Use [`pyenv`](https://github.com/pyenv/pyenv?tab=readme-ov-file#installation) to manage Python versions\n\n2. **Poetry**: Install Poetry 1.8.3\n\n   ```bash\n   curl -sSL https://install.python-poetry.org | python3 - --version 1.8.3\n   ```\n\n3. **Just**: Install [Just](https://github.com/casey/just?tab=readme-ov-file#packages) command runner (version 1.36 or higher)\n\n### Step-by-Step Setup\n\n1. **Install Dependencies**:\n\n   ```bash\n   poetry install\n   ```\n\n2. **Generate Configuration Files**:\n\n   ```bash\n   just init\n   ```\n\n   This creates both `.env.dev` and `config.yaml`. Use `just init --non-dev` to generate only `config.yaml`.\n\n    > For Windows, add the line `set shell:= [\"bash\", \"-cu\"]` at the start of the Justfile.\n\n4. **Configure Environment**:\n\n   - Edit `.env.dev` to set environment variables\n   - Modify `config.yaml` to configure components, pipelines, and other settings\n   - Refer to [AI Service Configuration](./docs/configuration.md) for detailed setup instructions\n\n5. **Set Up Development Environment** (optional):\n\n   - Install pre-commit hooks:\n\n     ```bash\n     poetry run pre-commit install\n     ```\n\n   - Run initial pre-commit checks:\n\n     ```bash\n     poetry run pre-commit run --all-files\n     ```\n\n6. **Run Tests** (optional):\n\n   ```bash\n   just test\n   ```\n\n### Starting the Service\n\n1. **Start Required Containers**:\n\n   ```bash\n   just up\n   ```\n\n2. **Launch the AI Service**:\n\n   ```bash\n   just start\n   ```\n\n3. **Access the Service**:\n\n   - API Documentation: `http://WREN_AI_SERVICE_HOST:WREN_AI_SERVICE_PORT` (default: <http://localhost:5556>)\n   - User Interface: `http://WREN_UI_HOST:WREN_UI_PORT` (default: <http://localhost:3000>)\n\n4. **Stop the Service**:\n   When finished, stop the containers:\n\n   ```bash\n   just down\n   ```\n\nThis setup ensures a consistent development environment and helps maintain code quality through pre-commit hooks and tests. Follow these steps to get started with local development of the Wren AI Service.\n\n## Others\n\n### Pipeline Evaluation\n\nFor a comprehensive understanding of how to evaluate the pipelines, please refer to the [evaluation framework](./eval/README.md). This document provides detailed guidelines on the evaluation process, including how to set up and run evaluations, interpret results, and utilize the evaluation metrics effectively. It is a valuable resource for ensuring that the evaluation is conducted accurately and that the results are meaningful.\n\n### Estimate the Speed of the Pipeline(may be outdated)\n\n- to run the load test\n  - setup `DATASET_NAME` in `.env.dev`\n  - adjust test config if needed\n    - adjust user count in `tests/locust/config_users.json`\n  - in wren-ai-service folder, run `just up` to start the docker containers\n  - in wren-ai-service folder, run `just start` to start the ai service\n  - run `just load-test`\n  - check reports in /outputs/locust folder, there are 3 files with filename **locust*report*{test_timestamp}**:\n    - .json: test report in json format, including info like llm provider, version\n    - .html: test report in html format, showing tables and charts\n    - .log: test log\n\n## Contributing\n\nThank you for investing your time in contributing to our project! Please [read this for more information](CONTRIBUTING.md)!\n"
  },
  {
    "path": "wren-ai-service/docker/Dockerfile",
    "content": "# reference: https://medium.com/@albertazzir/blazing-fast-python-docker-builds-with-poetry-a78a66f5aed0\nFROM python:3.12.0-bookworm as builder\n\nRUN pip install poetry==1.8.3\n\nENV POETRY_NO_INTERACTION=1 \\\n    POETRY_VIRTUALENVS_IN_PROJECT=1 \\\n    POETRY_VIRTUALENVS_CREATE=1 \\\n    POETRY_CACHE_DIR=/tmp/poetry_cache\n\nWORKDIR /app\n\nCOPY pyproject.toml ./\n\nRUN poetry install --without dev,eval,test --no-root && rm -rf $POETRY_CACHE_DIR\n\nFROM python:3.12.0-slim-bookworm as runtime\n\nRUN apt-get update && apt install -y netcat-traditional\n\nENV VIRTUAL_ENV=/app/.venv \\\n    PATH=\"/app/.venv/bin:$PATH\"\n\nCOPY --from=builder ${VIRTUAL_ENV} ${VIRTUAL_ENV}\n\nCOPY src src\nCOPY entrypoint.sh /app/entrypoint.sh\nCOPY pyproject.toml pyproject.toml\nRUN chmod +x /app/entrypoint.sh\n\nENTRYPOINT [ \"/app/entrypoint.sh\" ]"
  },
  {
    "path": "wren-ai-service/docs/code_design.md",
    "content": "# Introduction to the codebase of wren-ai-service\n\n## Table of Contents\n\n- [Purpose](#purpose)\n- [Environment Setup and Start wren-ai-service Locally](#environment-setup-and-start-wren-ai-service-locally)\n- [Codebase Introduction](#codebase-introduction)\n    - [Entrypoint](#entrypoint)\n    - [Globals](#globals)\n    - [API endpoints](#api-endpoints)\n    - [Services](#services)\n    - [Pipelines](#pipelines)\n    - [Providers](#providers)\n    - [Others](#others)\n\n## Purpose\n\nThis document aims to dive deep to the implementation details of wren-ai-service. We have two goals in mind while writing the document:\n1. You will be more knowledgeable about how wren-ai-service works under the hood.\n2. You will be more confident on what part of codebase is needed for adjustment if you would like to be Wren AI's contributor.\n\n## Environment Setup and Start wren-ai-service Locally\n\nIf you haven't setup the environment or don't know how to run wren-ai-service locally, please refer to the [document](../README.md#setup-for-local-development) here first.\n\n## Codebase Introduction\n\nwren-ai-service is basically an AI service which provides REST api endpoints for access. There are 4 main concepts to wren-ai-service: `API endpoints`, `Services`, `Pipelines` and `Providers`.\n1. `API endpoints`: They are entry points for users to access several kinds of RAG(retrieval-augmented-generation) systems; you can also see API endpoints as encapsulation of Services. For example, when users need to ask a question in order to get SQL, they need to call `/ask` and there is AskService under the hood for background computation.\n2. `Services`: They are abstraction of business-logic concepts, such as AskService for users asking questions to get SQL results back, AskDetailsService for users to get SQL breakdown as several sub-steps in order to understand the logic behind the original SQL. Every service is composed of a series of pipelines.\n3. `Pipelines`: Basically RAG systems are actually implemented here. However, not all pipelines have complete indexing, retrieval and generation components; it depends on what's the purpose of the pipeline. Also, every pipeline contains some providers such as LLM provider, which represents an LLM.\n4. `Providers`: Now there are 4 kinds of providers:\n    - llm: representing large language models, and now we support OpenAI, Azure OpenAI, OpenAI api-compatible and Ollama models\n    - embedder: representing embedding models, and now we support OpenAI, Azure OpenAI, OpenAI api-compatible and Ollama models\n    - document store: representing vector database, and now we use Qdrant\n    - engine: representing data engine, which is responsible for validating generated SQL's syntax.\n\n### Entrypoint\n\n- The entry point of wren-ai-service is located at [`wren-ai-service/src/__main__.py`](../src/__main__.py)\n- The main point of the entry point is the `lifespan` method, which is FastAPI's feature for defining startup and shutdown logic.\n\n```python\n# https://fastapi.tiangolo.com/advanced/events/#lifespan\n@asynccontextmanager\nasync def lifespan(app: FastAPI):\n    # startup events\n\n    pipe_components = generate_components()\n    app.state.service_container = create_service_container(\n        pipe_components,\n        column_indexing_batch_size=(\n            int(os.getenv(\"COLUMN_INDEXING_BATCH_SIZE\"))\n            if os.getenv(\"COLUMN_INDEXING_BATCH_SIZE\")\n            else 50\n        ),\n        table_retrieval_size=(\n            int(os.getenv(\"TABLE_RETRIEVAL_SIZE\"))\n            if os.getenv(\"TABLE_RETRIEVAL_SIZE\")\n            else 10\n        ),\n        table_column_retrieval_size=(\n            int(os.getenv(\"TABLE_COLUMN_RETRIEVAL_SIZE\"))\n            if os.getenv(\"TABLE_COLUMN_RETRIEVAL_SIZE\")\n            else 1000\n        ),\n        query_cache={\n            # the maxsize is a necessary parameter to init cache, but we don't want to expose it to the user\n            # so we set it to 1_000_000, which is a large number\n            \"maxsize\": 1_000_000,\n            \"ttl\": int(os.getenv(\"QUERY_CACHE_TTL\") or 120),\n        },\n    )\n    app.state.service_metadata = create_service_metadata(pipe_components)\n    init_langfuse()\n\n    yield\n\n    # shutdown events\n    langfuse_context.flush()\n```\n\n- For startup logic, we initialize pipeline components, service containers(which include all services), service metadata(which is some metadata logged for traces inside [Langfuse, an open-source LLM engineering platform](https://langfuse.com/)) and Langfuse.\n- For initializing pipeline components, we are in the progress of supporting multiple LLMs, namely users can choose which LLM is responsible for each pipeline.\n    - You still need to have `.env.dev` locally, then you can prepare `config.yaml` and run `just start`.\n- For shutdown logic, we make sure all Langfuse events are transmitted successfully\n\n### Globals\n\n- The file is located at [`wren-ai-service/src/globals.py`](../src/globals.py)\n- You can understand the details of service containers and service metadata here\n    - service containers(Other services are not supported in UI yet)\n        - SemanticsPreparationService: this is responsible for indexing [MDL](https://docs.getwren.ai/oss/engine/concept/what_is_mdl) to Qdarnt\n        - AskService: this is responsible for answering users' questions with SQLs, namely text-to-sql\n        - AskDetailsService: this is responsible for SQL breakdown to several sub-steps\n    - service metadata\n        - We will record llm's and embedding model's metadata, wren-ai-service version, etc.\n\n### API endpoints\n\n- All business related API endpoints are located at [`wren-ai-service/src/web/v1/routers`](../src/web/v1/routers)\n- Since computation for each kind of API endpoint(ex. ask, etc.) takes several seconds, so we use FastAPI's `background_tasks`. For example, after the `ask` api is invoked, the response is immediately returned, then users need to conduct polling in order to get the latest task status; and once the status is `finished`, the result is returned correspondingly\n- Each kind of API endpoint corresponds to one kind of business related task, for example, AskService, AskDetailsService\n\n### Services\n\n- All services are located at [`wren-ai-service/src/web/v1/services`](../src/web/v1/services)\n\n### Pipelines\n\n- All pipelines are located at [`wren-ai-service/src/pipelines`](../src/pipelines)\n- Since all pipelines are actually RAG systems, so we classify the role of each pipeline as indexing, retrieval or generation\n- The abstract class is defined at [`wren-ai-service/src/core/pipeline.py`](../src/core/pipeline.py)\n\n### Providers\n\n- All providers are located at [`wren-ai-service/src/providers`](../src/providers)\n- The abstract classes for providers(LLM, embedding model and document store) are defined at [`wren-ai-service/src/core/provider.py`](../src/core/provider.py)\n- The abstract class for engine is defined at [`wren-ai-service/src/core/engine.py`](../src/core/engine.py)\n"
  },
  {
    "path": "wren-ai-service/docs/config_examples/README.md",
    "content": "# MUST READ!!!\n\nSince these config files are examples, so **please carefully read the file and comments inside**. Try to understand the purpose of each section and parameter, **don't simply copy and paste the content of these config files into your own config file. It will not work.** For more detailed information to the configurations, please [read this file](../configuration.md).\n\nWe also definitely welcome your contribution to add config files for other LLM providers.\n\n## Qwen3 Think and No_Think Configuration\n\nThe `config.qwen3.yaml` file provides an example configuration for using Qwen3 models with their unique thinking and non-thinking capabilities. Qwen3 models support two modes:\n\n### Thinking Mode\n- Use `/think` in your prompts to enable step-by-step reasoning\n- Optimized with `temperature=0.6`, `top_p=0.95`, `top_k=20`\n- Best for complex problems requiring detailed reasoning\n- Uses the `qwen3-thinking` alias in the pipeline configuration\n\n### Non-Thinking Mode  \n- Use `/no_think` in your prompts for direct, fast responses\n- Optimized with `temperature=0.7`, `top_p=0.8`, `top_k=20`\n- Best for simple queries and general conversation\n- Uses the `qwen3-fast` alias in the pipeline configuration\n\n### Available Models\n- `qwen/qwen3-30b-a3b`: 30B parameter MoE model (3.3B activated)\n- `qwen/qwen3-32b`: 32B parameter dense model\n- `qwen/qwen3-8b`: 8B parameter dense model\n- `qwen/qwen3-14b`: 14B parameter dense model\n\n### Usage Examples\n```\n# Enable thinking for complex reasoning\n\"Explain the mathematical proof for the Pythagorean theorem /think\"\n\n# Use fast mode for simple queries  \n\"What is the capital of France? /no_think\"\n```\n\n**Note**: You need to set `OPENROUTER_API_KEY` in your `~/.wrenai/.env` file to use OpenRouter as the provider for Qwen3 models.\n"
  },
  {
    "path": "wren-ai-service/docs/config_examples/config.anthropic.yaml",
    "content": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting with # and adjust the config accordingly, 3 steps basically:\n# 1. you need to use your own llm and embedding models\n# 2. fill in embedding model dimension in the document_store section\n# 3. you need to use the correct pipe definitions based on https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\n# 4. you need to fill in correct llm and embedding models in the pipe definitions\n\ntype: llm\nprovider: litellm_llm\ntimeout: 120\nmodels:\n  # put ANTHROPIC_API_KEY=<your_api_key> in ~/.wrenai/.env\n  - api_base: https://api.anthropic.com\n    model: anthropic/claude-3-7-sonnet-20250219\n    alias: default\n    timeout: 600\n    kwargs:\n      n: 1\n      temperature: 0\n\n---\ntype: embedder\nprovider: litellm_embedder\nmodels:\n  # anthropic embedding model is not supported yet, so we use openai embedding model as a workaround\n  - model: text-embedding-3-large\n    alias: default\n    timeout: 120\n\n---\ntype: engine\nprovider: wren_ui\nendpoint: http://wren-ui:3000\n\n---\ntype: engine\nprovider: wren_ibis\nendpoint: http://ibis-server:8000\n\n---\ntype: document_store\nprovider: qdrant\nlocation: http://qdrant:6333\nembedding_model_dim: 3072  # put your embedding model dimension here\ntimeout: 120\nrecreate_index: true\n\n---\ntype: pipeline\npipes:\n  - name: db_schema_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: table_description_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_correction\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: followup_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_answer\n    llm: litellm_llm.default\n  - name: semantics_description\n    llm: litellm_llm.default\n  - name: relationship_recommendation\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: question_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation_db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: question_recommendation_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: intent_classification\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: misleading_assistance\n    llm: litellm_llm.default\n  - name: data_assistance\n    llm: litellm_llm.default\n  - name: sql_pairs_indexing\n    document_store: qdrant\n    embedder: litellm_embedder.default\n  - name: sql_pairs_retrieval\n    document_store: qdrant\n    embedder: litellm_embedder.default\n    llm: litellm_llm.default\n  - name: preprocess_sql_data\n    llm: litellm_llm.default\n  - name: sql_executor\n    engine: wren_ui\n  - name: user_guide_assistance\n    llm: litellm_llm.default\n  - name: chart_generation\n    llm: litellm_llm.default\n  - name: chart_adjustment\n    llm: litellm_llm.default\n  - name: sql_question_generation\n    llm: litellm_llm.default\n  - name: sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: followup_sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: sql_regeneration\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: instructions_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: instructions_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_functions_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n  - name: project_meta_indexing\n    document_store: qdrant\n  - name: sql_tables_extraction\n    llm: litellm_llm.default\n  - name: sql_diagnosis\n    llm: litellm_llm.default\n  - name: sql_knowledge_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n---\nsettings:\n  engine_timeout: 30\n  column_indexing_batch_size: 50\n  table_retrieval_size: 10\n  table_column_retrieval_size: 100\n  allow_intent_classification: true\n  allow_sql_generation_reasoning: true\n  allow_sql_functions_retrieval: true\n  enable_column_pruning: false\n  max_sql_correction_retries: 3\n  query_cache_maxsize: 1000\n  query_cache_ttl: 3600\n  langfuse_host: https://cloud.langfuse.com\n  langfuse_enable: true\n  logging_level: DEBUG\n  development: false\n  historical_question_retrieval_similarity_threshold: 0.9\n  sql_pairs_similarity_threshold: 0.7\n  sql_pairs_retrieval_max_size: 10\n  instructions_similarity_threshold: 0.7\n  instructions_top_k: 10"
  },
  {
    "path": "wren-ai-service/docs/config_examples/config.azure.yaml",
    "content": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting with # and adjust the config accordingly, 3 steps basically:\n# 1. you need to use your own llm and embedding models\n# 2. fill in embedding model dimension in the document_store section\n# 3. you need to use the correct pipe definitions based on https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\n# 4. you need to fill in correct llm and embedding models in the pipe definitions\n\n\ntype: llm\nprovider: litellm_llm\nmodels:\n  # put AZURE_OPENAI_API_KEY=<your_api_key> in ~/.wrenai/.env\n  - model: azure/gpt-4  # Your Azure deployment name, put 'azure/' before deployment name\n    alias: default\n    api_base: https://endpoint.openai.azure.com  # Replace with your custom Azure endpoint\n    api_version: 2024-02-15-preview\n    timeout: 120\n    kwargs:\n      temperature: 0\n      n: 1\n      seed: 0\n      max_tokens: 4096\n\n---\ntype: embedder\nprovider: litellm_embedder\nmodels:\n  # put AZURE_OPENAI_API_KEY=<your_api_key> in ~/.wrenai/.env\n  - model: azure/text-embedding-ada-002  # Your Azure deployment name, put 'azure/' before deployment name\n    alias: default\n    api_base: https://endpoint.openai.azure.com  # Replace with your custom Azure endpoint\n    api_version: 2023-05-15\n    timeout: 300\n\n---\ntype: engine\nprovider: wren_ui\nendpoint: http://wren-ui:3000\n\n---\ntype: engine\nprovider: wren_ibis\nendpoint: http://ibis-server:8000\n\n---\ntype: document_store\nprovider: qdrant\nlocation: http://qdrant:6333\nembedding_model_dim: 1536  # put your embedding model dimension here\ntimeout: 120\nrecreate_index: true\n\n---\n# please change the llm and embedder names to the ones you want to use\n# the format of llm and embedder should be <provider>.<model_name> such as litellm_llm.gpt-4o-2024-08-06\n# the pipes may be not the latest version, please refer to the latest version: https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\ntype: pipeline\npipes:\n  - name: db_schema_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant # Match document_store name\n    llm: litellm_llm.default\n  - name: historical_question_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: table_description_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_correction\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: followup_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_answer\n    llm: litellm_llm.default\n  - name: semantics_description\n    llm: litellm_llm.default\n  - name: relationship_recommendation\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: question_recommendation\n    llm: litellm_llm.default\n  - name: intent_classification\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: misleading_assistance\n    llm: litellm_llm.default\n  - name: data_assistance\n    llm: litellm_llm.default\n  - name: sql_pairs_preparation\n    document_store: qdrant\n    embedder: litellm_embedder.default\n    llm: litellm_llm.default\n  - name: sql_pairs_retrieval\n    document_store: qdrant\n    embedder: litellm_embedder.default\n    llm: litellm_llm.default\n  - name: preprocess_sql_data\n    llm: litellm_llm.default\n  - name: sql_executor\n    engine: wren_ui\n  - name: user_guide_assistance\n    llm: litellm_llm.default\n  - name: chart_generation\n    llm: litellm_llm.default\n  - name: chart_adjustment\n    llm: litellm_llm.default\n  - name: sql_pairs_indexing\n    document_store: qdrant\n    embedder: litellm_embedder.default\n  - name: sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: followup_sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: question_recommendation_db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: question_recommendation_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_question_generation\n    llm: litellm_llm.default\n  - name: sql_regeneration\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: instructions_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: instructions_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_functions_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n  - name: project_meta_indexing\n    document_store: qdrant\n  - name: sql_tables_extraction\n    llm: litellm_llm.default\n  - name: sql_diagnosis\n    llm: litellm_llm.default\n  - name: sql_knowledge_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n---\nsettings:\n  engine_timeout: 30\n  column_indexing_batch_size: 50\n  table_retrieval_size: 10\n  table_column_retrieval_size: 100\n  allow_intent_classification: true\n  allow_sql_generation_reasoning: true\n  allow_sql_functions_retrieval: true\n  enable_column_pruning: false\n  max_sql_correction_retries: 3\n  query_cache_maxsize: 1000\n  query_cache_ttl: 3600\n  langfuse_host: https://cloud.langfuse.com\n  langfuse_enable: true\n  logging_level: DEBUG\n  development: false\n  historical_question_retrieval_similarity_threshold: 0.9\n  sql_pairs_similarity_threshold: 0.7\n  sql_pairs_retrieval_max_size: 10\n  instructions_similarity_threshold: 0.7\n  instructions_top_k: 10\n"
  },
  {
    "path": "wren-ai-service/docs/config_examples/config.bedrock.yaml",
    "content": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting with # and adjust the config accordingly, 3 steps basically:\n# 1. you need to use your own llm and embedding models\n# 2. fill in embedding model dimension in the document_store section\n# 3. you need to use the correct pipe definitions based on https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\n# 4. you need to fill in correct llm and embedding models in the pipe definitions\n\ntype: llm\nprovider: litellm_llm\ntimeout: 120\nmodels:\n  - model: bedrock/us.anthropic.claude-3-7-sonnet-20250219-v1:0  # Inference profile ID, us. -> us-east-1, You can get it from \"Cross-region inference\" section\n    api_base: https://bedrock-runtime.<region-name>.amazonaws.com\n    alias: default\n    kwargs:\n      temperature: 0.1\n      aws_region_name: <region-name>\n      aws_bedrock_runtime_endpoint: https://bedrock-runtime.<region-name>.amazonaws.com\n\n      # to authenticate via iam role\n      aws_role_name: <iam-role-arn>\n\n      ##  other available configs\n      # aws_access_key_id: <access-key-id>\n      # aws_secret_access_key: <secret-access-key>\n      # aws_session_token: <session-token>\n      # aws_session_name: <session-name>\n      # aws_profile_name: <profile-name>\n      # aws_web_identity_token: <web-identity-token>\n      # aws_sts_endpoint: <sts-endpoint>\n\n---\ntype: embedder\nprovider: litellm_embedder\nmodels:\n  - model: bedrock/amazon.titan-embed-text-v2:0\n    api_base: https://bedrock-runtime.<region-name>.amazonaws.com\n    timeout: 600\n    alias: default\n    kwargs:\n      temperature: 0.1\n      aws_region_name: <region-name>\n      aws_role_name: <iam-role-arn>\n      aws_bedrock_runtime_endpoint: https://bedrock-runtime.<region-name>.amazonaws.com\n\n---\ntype: engine\nprovider: wren_ui\nendpoint: http://wren-ui:3000\n\n---\ntype: engine\nprovider: wren_ibis\nendpoint: http://ibis-server:8000\n\n---\ntype: document_store\nprovider: qdrant\nlocation: http://qdrant:6333\nembedding_model_dim: 1024  # put your embedding model dimension here, 1024 for amazon-titan\ntimeout: 120\nrecreate_index: true\n\n---\ntype: pipeline\npipes:\n  - name: db_schema_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: table_description_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_correction\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: followup_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_answer\n    llm: litellm_llm.default\n  - name: semantics_description\n    llm: litellm_llm.default\n  - name: relationship_recommendation\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: question_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation_db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: question_recommendation_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: intent_classification\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: misleading_assistance\n    llm: litellm_llm.default\n  - name: data_assistance\n    llm: litellm_llm.default\n  - name: sql_pairs_indexing\n    document_store: qdrant\n    embedder: litellm_embedder.default\n  - name: sql_pairs_retrieval\n    document_store: qdrant\n    embedder: litellm_embedder.default\n    llm: litellm_llm.default\n  - name: preprocess_sql_data\n    llm: litellm_llm.default\n  - name: sql_executor\n    engine: wren_ui\n  - name: user_guide_assistance\n    llm: litellm_llm.default\n  - name: chart_generation\n    llm: litellm_llm.default\n  - name: chart_adjustment\n    llm: litellm_llm.default\n  - name: sql_question_generation\n    llm: litellm_llm.default\n  - name: sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: followup_sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: sql_regeneration\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: instructions_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: instructions_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_functions_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n  - name: project_meta_indexing\n    document_store: qdrant\n  - name: sql_tables_extraction\n    llm: litellm_llm.default\n  - name: sql_diagnosis\n    llm: litellm_llm.default\n  - name: sql_knowledge_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n---\nsettings:\n  engine_timeout: 30\n  column_indexing_batch_size: 50\n  table_retrieval_size: 10\n  table_column_retrieval_size: 100\n  allow_intent_classification: true\n  allow_sql_generation_reasoning: true\n  allow_sql_functions_retrieval: true\n  enable_column_pruning: false\n  max_sql_correction_retries: 3\n  query_cache_maxsize: 1000\n  query_cache_ttl: 3600\n  langfuse_host: https://cloud.langfuse.com\n  langfuse_enable: true\n  logging_level: DEBUG\n  development: false\n  historical_question_retrieval_similarity_threshold: 0.9\n  sql_pairs_similarity_threshold: 0.7\n  sql_pairs_retrieval_max_size: 10\n  instructions_similarity_threshold: 0.7\n  instructions_top_k: 10\n"
  },
  {
    "path": "wren-ai-service/docs/config_examples/config.deepseek.yaml",
    "content": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting with # and adjust the config accordingly, 3 steps basically:\n# 1. you need to use your own llm and embedding models\n# 2. fill in embedding model dimension in the document_store section\n# 3. you need to use the correct pipe definitions based on https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\n# 4. you need to fill in correct llm and embedding models in the pipe definitions\n\n\ntype: llm\nprovider: litellm_llm\nmodels:\n  # put DEEPSEEK_API_KEY=<your_api_key> in ~/.wrenai/.env\n  - api_base: https://api.deepseek.com/v1\n    model: deepseek/deepseek-reasoner\n    timeout: 120\n    kwargs:\n      n: 1\n      temperature: 0\n      response_format:\n        type: text\n  - api_base: https://api.deepseek.com/v1\n    model: deepseek/deepseek-chat\n    timeout: 120\n    kwargs:\n      n: 1\n      temperature: 0\n      response_format:\n        type: text\n  - api_base: https://api.deepseek.com/v1\n    model: deepseek/deepseek-coder\n    alias: default\n    timeout: 120\n    kwargs:\n      n: 1\n      temperature: 0\n      response_format:\n        type: json_object\n\n---\ntype: embedder\nprovider: litellm_embedder\nmodels:\n  # define OPENAI_API_KEY=<api_key> in ~/.wrenai/.env if you are using openai embedding model\n  # please refer to LiteLLM documentation for more details: https://docs.litellm.ai/docs/providers\n  - model: text-embedding-3-large  # put your embedding model name here, if it is not openai embedding model, should be <provider>/<model_name>\n    alias: default\n    api_base: https://api.openai.com/v1  # change this according to your embedding model\n    timeout: 120\n\n---\ntype: engine\nprovider: wren_ui\nendpoint: http://wren-ui:3000\n\n---\ntype: engine\nprovider: wren_ibis\nendpoint: http://ibis-server:8000\n\n---\ntype: document_store\nprovider: qdrant\nlocation: http://qdrant:6333\nembedding_model_dim: 3072 # put your embedding model dimension here\ntimeout: 120\nrecreate_index: true\n\n---\n# please change the llm and embedder names to the ones you want to use\n# the format of llm and embedder should be <provider>.<model_name> such as litellm_llm.gpt-4o-2024-08-06\n# the pipes may be not the latest version, please refer to the latest version: https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\ntype: pipeline\npipes:\n  - name: db_schema_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: table_description_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_correction\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: followup_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_answer\n    llm: litellm_llm.deepseek/deepseek-chat\n  - name: semantics_description\n    llm: litellm_llm.default\n  - name: relationship_recommendation\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: question_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation_db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: question_recommendation_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: chart_generation\n    llm: litellm_llm.default\n  - name: chart_adjustment\n    llm: litellm_llm.default\n  - name: intent_classification\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: misleading_assistance\n    llm: litellm_llm.default\n  - name: data_assistance\n    llm: litellm_llm.deepseek/deepseek-chat\n  - name: sql_pairs_indexing\n    document_store: qdrant\n    embedder: litellm_embedder.default\n  - name: sql_pairs_retrieval\n    document_store: qdrant\n    embedder: litellm_embedder.default\n    llm: litellm_llm.default\n  - name: preprocess_sql_data\n    llm: litellm_llm.default\n  - name: sql_executor\n    engine: wren_ui\n  - name: user_guide_assistance\n    llm: litellm_llm.default\n  - name: sql_question_generation\n    llm: litellm_llm.default\n  - name: sql_generation_reasoning\n    llm: litellm_llm.deepseek/deepseek-reasoner\n  - name: followup_sql_generation_reasoning\n    llm: litellm_llm.deepseek/deepseek-reasoner\n  - name: sql_regeneration\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: instructions_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: instructions_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_functions_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n  - name: project_meta_indexing\n    document_store: qdrant\n  - name: sql_tables_extraction\n    llm: litellm_llm.default\n  - name: sql_diagnosis\n    llm: litellm_llm.default\n  - name: sql_knowledge_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n---\nsettings:\n  engine_timeout: 30\n  column_indexing_batch_size: 50\n  table_retrieval_size: 10\n  table_column_retrieval_size: 100\n  allow_intent_classification: true\n  allow_sql_generation_reasoning: true\n  allow_sql_functions_retrieval: true\n  enable_column_pruning: false\n  max_sql_correction_retries: 3\n  query_cache_maxsize: 1000\n  query_cache_ttl: 3600\n  langfuse_host: https://cloud.langfuse.com\n  langfuse_enable: true\n  logging_level: DEBUG\n  development: true\n  historical_question_retrieval_similarity_threshold: 0.9\n  sql_pairs_similarity_threshold: 0.7\n  sql_pairs_retrieval_max_size: 10\n  instructions_similarity_threshold: 0.7\n  instructions_top_k: 10\n"
  },
  {
    "path": "wren-ai-service/docs/config_examples/config.google_ai_studio.yaml",
    "content": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting with # and adjust the config accordingly, 3 steps basically:\n# 1. you need to use your own llm and embedding models\n# 2. fill in embedding model dimension in the document_store section\n# 3. you need to use the correct pipe definitions based on https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\n# 4. you need to fill in correct llm and embedding models in the pipe definitions\n\ntype: llm\nprovider: litellm_llm\nmodels:\n  # put GEMINI_API_KEY=<your_api_key> in ~/.wrenai/.env\n  - model: gemini/gemini-2.0-flash # gemini/<gemini_model_name>\n    alias: default\n    timeout: 120\n    kwargs:\n      n: 1\n      temperature: 0\n  - model: gemini/gemini-2.0-flash # gemini/<gemini_model_name>\n    alias: gemini-llm-for-chart\n    timeout: 120\n    kwargs:\n      n: 1\n      temperature: 0\n      response_format:\n        type: json_object\n\n---\ntype: embedder\nprovider: litellm_embedder\nmodels:\n  # put GEMINI_API_KEY=<your_api_key> in ~/.wrenai/.env\n  - model: gemini/text-embedding-004 # gemini/<gemini_model_name>\n    alias: default\n    timeout: 120\n\n---\ntype: engine\nprovider: wren_ui\nendpoint: http://wren-ui:3000\n\n---\ntype: engine\nprovider: wren_ibis\nendpoint: http://ibis-server:8000\n\n---\ntype: document_store\nprovider: qdrant\nlocation: http://qdrant:6333\nembedding_model_dim: 768 # put your embedding model dimension here\ntimeout: 120\nrecreate_index: true\n\n---\n# please change the llm and embedder names to the ones you want to use\n# the format of llm and embedder should be <provider>.<model_name> such as litellm_llm.gpt-4o-2024-08-06 or <provider>.<alias> such as litellm_llm.gemini-llm-for-chart\n# the pipes may be not the latest version, please refer to the latest version: https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\ntype: pipeline\npipes:\n  - name: db_schema_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: table_description_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_correction\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: followup_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_answer\n    llm: litellm_llm.default\n  - name: semantics_description\n    llm: litellm_llm.default\n  - name: relationship_recommendation\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: question_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation_db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: question_recommendation_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: chart_generation\n    llm: litellm_llm.gemini-llm-for-chart\n  - name: chart_adjustment\n    llm: litellm_llm.gemini-llm-for-chart\n  - name: intent_classification\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: misleading_assistance\n    llm: litellm_llm.default\n  - name: data_assistance\n    llm: litellm_llm.default\n  - name: sql_pairs_indexing\n    document_store: qdrant\n    embedder: litellm_embedder.default\n  - name: sql_pairs_retrieval\n    document_store: qdrant\n    embedder: litellm_embedder.default\n    llm: litellm_llm.default\n  - name: preprocess_sql_data\n    llm: litellm_llm.default\n  - name: sql_executor\n    engine: wren_ui\n  - name: user_guide_assistance\n    llm: litellm_llm.default\n  - name: sql_question_generation\n    llm: litellm_llm.default\n  - name: sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: followup_sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: sql_regeneration\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: instructions_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: instructions_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_functions_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n  - name: project_meta_indexing\n    document_store: qdrant\n  - name: sql_tables_extraction\n    llm: litellm_llm.default\n  - name: sql_diagnosis\n    llm: litellm_llm.default\n  - name: sql_knowledge_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n---\nsettings:\n  engine_timeout: 30\n  column_indexing_batch_size: 50\n  table_retrieval_size: 10\n  table_column_retrieval_size: 100\n  allow_intent_classification: true\n  allow_sql_generation_reasoning: true\n  allow_sql_functions_retrieval: true\n  enable_column_pruning: false\n  max_sql_correction_retries: 3\n  query_cache_maxsize: 1000\n  query_cache_ttl: 3600\n  langfuse_host: https://cloud.langfuse.com\n  langfuse_enable: true\n  logging_level: DEBUG\n  development: true\n  historical_question_retrieval_similarity_threshold: 0.9\n  sql_pairs_similarity_threshold: 0.7\n  sql_pairs_retrieval_max_size: 10\n  instructions_similarity_threshold: 0.7\n  instructions_top_k: 10\n"
  },
  {
    "path": "wren-ai-service/docs/config_examples/config.google_vertexai.yaml",
    "content": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting with # and adjust the config accordingly, 3 steps basically:\n# 1. you need to use your own llm and embedding models\n# 2. fill in embedding model dimension in the document_store section\n# 3. you need to use the correct pipe definitions based on https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\n# 4. you need to fill in correct llm and embedding models in the pipe definitions\n\ntype: llm\nprovider: litellm_llm\nmodels:\n  # put VERTEXAI_LOCATION=<your project location> in ~/.wrenai/.env\n  # put VERTEXAI_PROJECT=<your project id> in ~/.wrenai/.env\n  # put GOOGLE_APPLICATION_CREDENTIALS=/app/data/<json_file_name> in ~/.wrenai.env\n  - model: vertex_ai/gemini-2.5-flash # vertex_ai/<gemini_model_name>\n    alias: default\n    timeout: 120\n    kwargs:\n      n: 1\n      temperature: 0\n      seed: 0\n      max_tokens: 4096\n  - model: vertex_ai/gemini-2.5-flash # vertex_ai/<gemini_model_name>\n    alias: gemini-llm-for-chart\n    timeout: 120\n    kwargs:\n      n: 1\n      temperature: 0\n      seed: 0\n      max_tokens: 4096\n      response_format:\n        type: json_object\n\n---\ntype: embedder\nprovider: litellm_embedder\nmodels:\n  # put VERTEXAI_LOCATION=<your project location> in ~/.wrenai/.env\n  # put VERTEXAI_PROJECT=<your project id> in ~/.wrenai/.env\n  # put GOOGLE_APPLICATION_CREDENTIALS=/app/data/<json_file_name> in ~/.wrenai.env\n  - model: vertex_ai/text-embedding-004 # vertex_ai/<gemini_model_name>\n    alias: default\n    timeout: 120\n\n---\ntype: engine\nprovider: wren_ui\nendpoint: http://wren-ui:3000\n\n---\ntype: engine\nprovider: wren_ibis\nendpoint: http://ibis-server:8000\n\n---\ntype: document_store\nprovider: qdrant\nlocation: http://qdrant:6333\nembedding_model_dim: 768 # put your embedding model dimension here\ntimeout: 120\nrecreate_index: true\n\n---\n# please change the llm and embedder names to the ones you want to use\n# the format of llm and embedder should be <provider>.<model_name> such as litellm_llm.gpt-4o-2024-08-06 or <provider>.<alias> such as litellm_llm.gemini-llm-for-chart\n# the pipes may be not the latest version, please refer to the latest version: https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\ntype: pipeline\npipes:\n  - name: db_schema_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: table_description_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_correction\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: followup_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_answer\n    llm: litellm_llm.default\n  - name: semantics_description\n    llm: litellm_llm.default\n  - name: relationship_recommendation\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: question_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation_db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: question_recommendation_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: chart_generation\n    llm: litellm_llm.gemini-llm-for-chart\n  - name: chart_adjustment\n    llm: litellm_llm.gemini-llm-for-chart\n  - name: intent_classification\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: misleading_assistance\n    llm: litellm_llm.default\n  - name: data_assistance\n    llm: litellm_llm.default\n  - name: sql_pairs_indexing\n    document_store: qdrant\n    embedder: litellm_embedder.default\n  - name: sql_pairs_retrieval\n    document_store: qdrant\n    embedder: litellm_embedder.default\n    llm: litellm_llm.default\n  - name: preprocess_sql_data\n    llm: litellm_llm.default\n  - name: sql_executor\n    engine: wren_ui\n  - name: user_guide_assistance\n    llm: litellm_llm.default\n  - name: sql_question_generation\n    llm: litellm_llm.default\n  - name: sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: followup_sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: sql_regeneration\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: instructions_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: instructions_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_functions_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n  - name: project_meta_indexing\n    document_store: qdrant\n  - name: sql_tables_extraction\n    llm: litellm_llm.default\n  - name: sql_diagnosis\n    llm: litellm_llm.default\n  - name: sql_knowledge_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n---\nsettings:\n  engine_timeout: 30\n  column_indexing_batch_size: 50\n  table_retrieval_size: 10\n  table_column_retrieval_size: 100\n  allow_intent_classification: true\n  allow_sql_generation_reasoning: true\n  allow_sql_functions_retrieval: true\n  enable_column_pruning: false\n  max_sql_correction_retries: 3\n  query_cache_maxsize: 1000\n  query_cache_ttl: 3600\n  langfuse_host: https://cloud.langfuse.com\n  langfuse_enable: true\n  logging_level: DEBUG\n  development: true\n  historical_question_retrieval_similarity_threshold: 0.9\n  sql_pairs_similarity_threshold: 0.7\n  sql_pairs_retrieval_max_size: 10\n  instructions_similarity_threshold: 0.7\n  instructions_top_k: 10\n"
  },
  {
    "path": "wren-ai-service/docs/config_examples/config.grok.yaml",
    "content": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting with # and adjust the config accordingly, 3 steps basically:\n# 1. you need to use your own llm and embedding models\n# 2. fill in embedding model dimension in the document_store section\n# 3. you need to use the correct pipe definitions based on https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\n# 4. you need to fill in correct llm and embedding models in the pipe definitions\n\ntype: llm\nprovider: litellm_llm\nmodels:\n  # put XAI_API_KEY=<your_api_key> in ~/.wrenai/.env\n  - api_base: https://api.x.ai/v1\n    model: xai/grok-3-latest \n    alias: default\n    timeout: 120\n    kwargs:\n      temperature: 0\n      max_tokens: 4096\n      n: 1\n\n---\ntype: embedder\nprovider: litellm_embedder\nmodels:\n  # define OPENAI_API_KEY=<api_key> in ~/.wrenai/.env if you are using openai embedding model\n  # please refer to LiteLLM documentation for more details: https://docs.litellm.ai/docs/providers\n  - model: text-embedding-3-large # put your embedding model name here, if it is not openai embedding model, should be <provider>/<model_name>\n    alias: default\n    api_base: https://api.openai.com/v1 # change this according to your embedding model\n    timeout: 120\n\n---\ntype: engine\nprovider: wren_ui\nendpoint: http://wren-ui:3000\n\n---\ntype: engine\nprovider: wren_ibis\nendpoint: http://ibis-server:8000\n\n---\ntype: document_store\nprovider: qdrant\nlocation: http://qdrant:6333\nembedding_model_dim: 3072 # put your embedding model dimension here\ntimeout: 120\nrecreate_index: true\n\n---\n# please change the llm and embedder names to the ones you want to use\n# the format of llm and embedder should be <provider>.<model_name> such as litellm_llm.gpt-4o-2024-08-06\n# the pipes may be not the latest version, please refer to the latest version: https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\ntype: pipeline\npipes:\n  - name: db_schema_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: table_description_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_correction\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: followup_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_answer\n    llm: litellm_llm.default\n  - name: semantics_description\n    llm: litellm_llm.default\n  - name: relationship_recommendation\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: question_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation_db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: question_recommendation_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: chart_generation\n    llm: litellm_llm.default\n  - name: chart_adjustment\n    llm: litellm_llm.default\n  - name: intent_classification\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: misleading_assistance\n    llm: litellm_llm.default\n  - name: data_assistance\n    llm: litellm_llm.default\n  - name: sql_pairs_indexing\n    document_store: qdrant\n    embedder: litellm_embedder.default\n  - name: sql_pairs_retrieval\n    document_store: qdrant\n    embedder: litellm_embedder.default\n    llm: litellm_llm.default\n  - name: preprocess_sql_data\n    llm: litellm_llm.default\n  - name: sql_executor\n    engine: wren_ui\n  - name: user_guide_assistance\n    llm: litellm_llm.default\n  - name: sql_question_generation\n    llm: litellm_llm.default\n  - name: sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: followup_sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: sql_regeneration\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: instructions_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: instructions_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_functions_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n  - name: project_meta_indexing\n    document_store: qdrant\n  - name: sql_tables_extraction\n    llm: litellm_llm.default\n  - name: sql_diagnosis\n    llm: litellm_llm.default\n  - name: sql_knowledge_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n---\nsettings:\n  engine_timeout: 30\n  column_indexing_batch_size: 50\n  table_retrieval_size: 10\n  table_column_retrieval_size: 100\n  allow_intent_classification: true\n  allow_sql_generation_reasoning: true\n  allow_sql_functions_retrieval: true\n  enable_column_pruning: false\n  max_sql_correction_retries: 3\n  query_cache_maxsize: 1000\n  query_cache_ttl: 3600\n  langfuse_host: https://cloud.langfuse.com\n  langfuse_enable: true\n  logging_level: DEBUG\n  development: true\n  historical_question_retrieval_similarity_threshold: 0.9\n  sql_pairs_similarity_threshold: 0.7\n  sql_pairs_retrieval_max_size: 10\n  instructions_similarity_threshold: 0.7\n  instructions_top_k: 10\n"
  },
  {
    "path": "wren-ai-service/docs/config_examples/config.groq.yaml",
    "content": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting with # and adjust the config accordingly, 3 steps basically:\n# 1. you need to use your own llm and embedding models\n# 2. fill in embedding model dimension in the document_store section\n# 3. you need to use the correct pipe definitions based on https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\n# 4. you need to fill in correct llm and embedding models in the pipe definitions\n\ntype: llm\nprovider: litellm_llm\nmodels:\n  # put GROQ_API_KEY=<your_api_key> in ~/.wrenai/.env\n  - api_base: https://api.groq.com/openai/v1\n    model: groq/llama-3.3-70b-specdec # groq/<ollama_model_name>\n    alias: default\n    timeout: 120\n    kwargs:\n      n: 1\n      temperature: 0\n\n---\ntype: embedder\nprovider: litellm_embedder\nmodels:\n  # define OPENAI_API_KEY=<api_key> in ~/.wrenai/.env if you are using openai embedding model\n  # please refer to LiteLLM documentation for more details: https://docs.litellm.ai/docs/providers\n  - model: text-embedding-3-large # put your embedding model name here, if it is not openai embedding model, should be <provider>/<model_name>\n    alias: default\n    api_base: https://api.openai.com/v1 # change this according to your embedding model\n    timeout: 120\n\n---\ntype: engine\nprovider: wren_ui\nendpoint: http://wren-ui:3000\n\n---\ntype: engine\nprovider: wren_ibis\nendpoint: http://ibis-server:8000\n\n---\ntype: document_store\nprovider: qdrant\nlocation: http://qdrant:6333\nembedding_model_dim: 3072 # put your embedding model dimension here\ntimeout: 120\nrecreate_index: true\n\n---\n# please change the llm and embedder names to the ones you want to use\n# the format of llm and embedder should be <provider>.<model_name> such as litellm_llm.gpt-4o-2024-08-06\n# the pipes may be not the latest version, please refer to the latest version: https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\ntype: pipeline\npipes:\n  - name: db_schema_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: table_description_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_correction\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: followup_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_answer\n    llm: litellm_llm.default\n  - name: semantics_description\n    llm: litellm_llm.default\n  - name: relationship_recommendation\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: question_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation_db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: question_recommendation_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: chart_generation\n    llm: litellm_llm.default\n  - name: chart_adjustment\n    llm: litellm_llm.default\n  - name: intent_classification\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: misleading_assistance\n    llm: litellm_llm.default\n  - name: data_assistance\n    llm: litellm_llm.default\n  - name: sql_pairs_indexing\n    document_store: qdrant\n    embedder: litellm_embedder.default\n  - name: sql_pairs_retrieval\n    document_store: qdrant\n    embedder: litellm_embedder.default\n    llm: litellm_llm.default\n  - name: preprocess_sql_data\n    llm: litellm_llm.default\n  - name: sql_executor\n    engine: wren_ui\n  - name: user_guide_assistance\n    llm: litellm_llm.default\n  - name: sql_question_generation\n    llm: litellm_llm.default\n  - name: sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: followup_sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: sql_regeneration\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: instructions_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: instructions_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_functions_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n  - name: project_meta_indexing\n    document_store: qdrant\n  - name: sql_tables_extraction\n    llm: litellm_llm.default\n  - name: sql_diagnosis\n    llm: litellm_llm.default\n  - name: sql_knowledge_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n---\nsettings:\n  engine_timeout: 30\n  column_indexing_batch_size: 50\n  table_retrieval_size: 10\n  table_column_retrieval_size: 100\n  allow_intent_classification: true\n  allow_sql_generation_reasoning: true\n  allow_sql_functions_retrieval: true\n  enable_column_pruning: false\n  max_sql_correction_retries: 3\n  query_cache_maxsize: 1000\n  query_cache_ttl: 3600\n  langfuse_host: https://cloud.langfuse.com\n  langfuse_enable: true\n  logging_level: DEBUG\n  development: true\n  historical_question_retrieval_similarity_threshold: 0.9\n  sql_pairs_similarity_threshold: 0.7\n  sql_pairs_retrieval_max_size: 10\n  instructions_similarity_threshold: 0.7\n  instructions_top_k: 10\n"
  },
  {
    "path": "wren-ai-service/docs/config_examples/config.lm_studio.yaml",
    "content": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting with # and adjust the config accordingly, 3 steps basically:\n# 1. you need to use your own llm and embedding models\n# 2. fill in embedding model dimension in the document_store section\n# 3. you need to use the correct pipe definitions based on https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\n# 4. you need to fill in correct llm and embedding models in the pipe definitions\n\ntype: llm\nprovider: litellm_llm\nmodels:\n  # put LM_STUDIO_API_KEY=<random_string> in ~/.wrenai/.env\n  - api_base: http://host.docker.internal:1234/v1\n    model: openai/phi-4 # openai/<lm_studio_model_name>\n    alias: default\n    timeout: 600\n    kwargs:\n      n: 1\n      temperature: 0\n\n---\ntype: embedder\nprovider: litellm_embedder\nmodels:\n  # put LM_STUDIO_API_KEY=<random_string> in ~/.wrenai/.env\n  - model: openai/text-embedding-nomic-embed-text-v1.5 # put your lm_studio embedder model name here, openai/<lm_studio_model_name>\n    alias: default\n    api_base: http://host.docker.internal:1234/v1\n    timeout: 600\n\n---\ntype: engine\nprovider: wren_ui\nendpoint: http://wren-ui:3000\n\n---\ntype: engine\nprovider: wren_ibis\nendpoint: http://ibis-server:8000\n\n---\ntype: document_store\nprovider: qdrant\nlocation: http://qdrant:6333\nembedding_model_dim: 768 # put your embedding model dimension here\ntimeout: 120\nrecreate_index: true\n\n---\n# please change the llm and embedder names to the ones you want to use\n# the format of llm and embedder should be <provider>.<model_name> such as litellm_llm.gpt-4o-2024-08-06\n# the pipes may be not the latest version, please refer to the latest version: https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\ntype: pipeline\npipes:\n  - name: db_schema_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: table_description_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_correction\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: followup_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_answer\n    llm: litellm_llm.default\n  - name: semantics_description\n    llm: litellm_llm.default\n  - name: relationship_recommendation\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: question_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation_db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: question_recommendation_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: chart_generation\n    llm: litellm_llm.default\n  - name: chart_adjustment\n    llm: litellm_llm.default\n  - name: intent_classification\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: misleading_assistance\n    llm: litellm_llm.default\n  - name: data_assistance\n    llm: litellm_llm.default\n  - name: sql_pairs_indexing\n    document_store: qdrant\n    embedder: litellm_embedder.default\n  - name: sql_pairs_retrieval\n    document_store: qdrant\n    embedder: litellm_embedder.default\n    llm: litellm_llm.default\n  - name: preprocess_sql_data\n    llm: litellm_llm.default\n  - name: sql_executor\n    engine: wren_ui\n  - name: user_guide_assistance\n    llm: litellm_llm.default\n  - name: sql_question_generation\n    llm: litellm_llm.default\n  - name: sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: followup_sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: sql_regeneration\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: instructions_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: instructions_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_functions_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n  - name: project_meta_indexing\n    document_store: qdrant\n  - name: sql_tables_extraction\n    llm: litellm_llm.default\n  - name: sql_diagnosis\n    llm: litellm_llm.default\n  - name: sql_knowledge_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n---\nsettings:\n  engine_timeout: 30\n  column_indexing_batch_size: 50\n  table_retrieval_size: 10\n  table_column_retrieval_size: 100\n  allow_intent_classification: true\n  allow_sql_generation_reasoning: true\n  allow_sql_functions_retrieval: true\n  enable_column_pruning: false\n  max_sql_correction_retries: 3\n  query_cache_maxsize: 1000\n  query_cache_ttl: 3600\n  langfuse_host: https://cloud.langfuse.com\n  langfuse_enable: true\n  logging_level: DEBUG\n  development: true\n  historical_question_retrieval_similarity_threshold: 0.9\n  sql_pairs_similarity_threshold: 0.7\n  sql_pairs_retrieval_max_size: 10\n  instructions_similarity_threshold: 0.7\n  instructions_top_k: 10\n"
  },
  {
    "path": "wren-ai-service/docs/config_examples/config.ollama.yaml",
    "content": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting with # and adjust the config accordingly, 3 steps basically:\n# 1. you need to use your own llm and embedding models\n# 2. fill in embedding model dimension in the document_store section\n# 3. you need to use the correct pipe definitions based on https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\n# 4. you need to fill in correct llm and embedding models in the pipe definitions\n\ntype: llm\nprovider: litellm_llm\nmodels:\n  - api_base: http://host.docker.internal:11434 # if you are using mac/windows, don't change this; if you are using linux, please search \"Run Ollama in docker container\" in this page: https://docs.getwren.ai/oss/ai_service/guide/custom_llm#running-wren-ai-with-your-custom-llm-embedder\n    model: ollama_chat/phi4:14b # ollama_chat/<ollama_model_name>\n    alias: default\n    timeout: 600\n    kwargs:\n      n: 1\n      temperature: 0\n\n---\ntype: embedder\nprovider: litellm_embedder\nmodels:\n  # at the moment, we are invoking ollama embedding model through ollama's openai compatible endpoint\n  # since there is issue invoking ollama embedding model through ollama/<ollama_model_name> using litellm: https://github.com/BerriAI/litellm/issues/7572\n  - model: openai/nomic-embed-text # put your ollama embedder model name here, openai/<ollama_model_name>\n    alias: default\n    api_base: http://host.docker.internal:11434/v1 # if you are using mac/windows, don't change this; if you are using linux, please search \"Run Ollama in docker container\" in this page: https://docs.getwren.ai/oss/ai_service/guide/custom_llm#running-wren-ai-with-your-custom-llm-embedder\n    timeout: 600\n\n---\ntype: engine\nprovider: wren_ui\nendpoint: http://wren-ui:3000\n\n---\ntype: engine\nprovider: wren_ibis\nendpoint: http://ibis-server:8000\n\n---\ntype: document_store\nprovider: qdrant\nlocation: http://qdrant:6333\nembedding_model_dim: 768 # put your embedding model dimension here\ntimeout: 120\nrecreate_index: true\n\n---\n# please change the llm and embedder names to the ones you want to use\n# the format of llm and embedder should be <provider>.<model_name> such as litellm_llm.gpt-4o-2024-08-06\n# the pipes may be not the latest version, please refer to the latest version: https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\ntype: pipeline\npipes:\n  - name: db_schema_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: table_description_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_correction\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: followup_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_answer\n    llm: litellm_llm.default\n  - name: semantics_description\n    llm: litellm_llm.default\n  - name: relationship_recommendation\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: question_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation_db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: question_recommendation_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: chart_generation\n    llm: litellm_llm.default\n  - name: chart_adjustment\n    llm: litellm_llm.default\n  - name: intent_classification\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: misleading_assistance\n    llm: litellm_llm.default\n  - name: data_assistance\n    llm: litellm_llm.default\n  - name: sql_pairs_indexing\n    document_store: qdrant\n    embedder: litellm_embedder.default\n  - name: sql_pairs_retrieval\n    document_store: qdrant\n    embedder: litellm_embedder.default\n    llm: litellm_llm.default\n  - name: preprocess_sql_data\n    llm: litellm_llm.default\n  - name: sql_executor\n    engine: wren_ui\n  - name: user_guide_assistance\n    llm: litellm_llm.default\n  - name: sql_question_generation\n    llm: litellm_llm.default\n  - name: sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: followup_sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: sql_regeneration\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: instructions_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: instructions_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_functions_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n  - name: project_meta_indexing\n    document_store: qdrant\n  - name: sql_tables_extraction\n    llm: litellm_llm.default\n  - name: sql_diagnosis\n    llm: litellm_llm.default\n  - name: sql_knowledge_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n---\nsettings:\n  engine_timeout: 30\n  column_indexing_batch_size: 50\n  table_retrieval_size: 10\n  table_column_retrieval_size: 100\n  allow_intent_classification: true\n  allow_sql_generation_reasoning: true\n  allow_sql_functions_retrieval: true\n  enable_column_pruning: false\n  max_sql_correction_retries: 3\n  query_cache_maxsize: 1000\n  query_cache_ttl: 3600\n  langfuse_host: https://cloud.langfuse.com\n  langfuse_enable: true\n  logging_level: DEBUG\n  development: true\n  historical_question_retrieval_similarity_threshold: 0.9\n  sql_pairs_similarity_threshold: 0.7\n  sql_pairs_retrieval_max_size: 10\n  instructions_similarity_threshold: 0.7\n  instructions_top_k: 10\n"
  },
  {
    "path": "wren-ai-service/docs/config_examples/config.open_router.yaml",
    "content": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting with # and adjust the config accordingly, 3 steps basically:\n# 1. you need to use your own llm and embedding models\n# 2. fill in embedding model dimension in the document_store section\n# 3. you need to use the correct pipe definitions based on https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\n# 4. you need to fill in correct llm and embedding models in the pipe definitions\n\ntype: llm\nprovider: litellm_llm\ntimeout: 120\nmodels:\n  # put OPENROUTER_API_KEY=<your_api_key> in ~/.wrenai/.env\n  - api_base: https://openrouter.ai/api/v1\n    model: openrouter/anthropic/claude-3.7-sonnet\n    alias: default\n    timeout: 600\n    kwargs:\n      n: 1\n      temperature: 0\n\n---\ntype: embedder\nprovider: litellm_embedder\nmodels:\n  # put GEMINI_API_KEY=<your_api_key> in ~/.wrenai/.env\n  # openrouter embedding model is not supported yet, so you can use gemini embedding model as a workaround\n  - model: gemini/text-embedding-004\n    alias: default\n    timeout: 120\n\n---\ntype: engine\nprovider: wren_ui\nendpoint: http://wren-ui:3000\n\n---\ntype: engine\nprovider: wren_ibis\nendpoint: http://ibis-server:8000\n\n---\ntype: document_store\nprovider: qdrant\nlocation: http://qdrant:6333\nembedding_model_dim: 768  # put your embedding model dimension here\ntimeout: 120\nrecreate_index: true\n\n---\ntype: pipeline\npipes:\n  - name: db_schema_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: table_description_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_correction\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: followup_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_answer\n    llm: litellm_llm.default\n  - name: semantics_description\n    llm: litellm_llm.default\n  - name: relationship_recommendation\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: question_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation_db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: question_recommendation_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: intent_classification\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: misleading_assistance\n    llm: litellm_llm.default\n  - name: data_assistance\n    llm: litellm_llm.default\n  - name: sql_pairs_indexing\n    document_store: qdrant\n    embedder: litellm_embedder.default\n  - name: sql_pairs_retrieval\n    document_store: qdrant\n    embedder: litellm_embedder.default\n    llm: litellm_llm.default\n  - name: preprocess_sql_data\n    llm: litellm_llm.default\n  - name: sql_executor\n    engine: wren_ui\n  - name: user_guide_assistance\n    llm: litellm_llm.default\n  - name: chart_generation\n    llm: litellm_llm.default\n  - name: chart_adjustment\n    llm: litellm_llm.default\n  - name: sql_question_generation\n    llm: litellm_llm.default\n  - name: sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: followup_sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: sql_regeneration\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: instructions_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: instructions_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_functions_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n  - name: project_meta_indexing\n    document_store: qdrant\n  - name: sql_tables_extraction\n    llm: litellm_llm.default\n  - name: sql_diagnosis\n    llm: litellm_llm.default\n  - name: sql_knowledge_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n---\nsettings:\n  engine_timeout: 30\n  column_indexing_batch_size: 50\n  table_retrieval_size: 10\n  table_column_retrieval_size: 100\n  allow_intent_classification: true\n  allow_sql_generation_reasoning: true\n  allow_sql_functions_retrieval: true\n  enable_column_pruning: false\n  max_sql_correction_retries: 3\n  query_cache_maxsize: 1000\n  query_cache_ttl: 3600\n  langfuse_host: https://cloud.langfuse.com\n  langfuse_enable: true\n  logging_level: DEBUG\n  development: false\n  historical_question_retrieval_similarity_threshold: 0.9\n  sql_pairs_similarity_threshold: 0.7\n  sql_pairs_retrieval_max_size: 10\n  instructions_similarity_threshold: 0.7\n  instructions_top_k: 10"
  },
  {
    "path": "wren-ai-service/docs/config_examples/config.qwen3.yaml",
    "content": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting with # and adjust the config accordingly, 3 steps basically:\n# 1. you need to use your own llm and embedding models\n# 2. fill in embedding model dimension in the document_store section\n# 3. you need to use the correct pipe definitions based on https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\n# 4. you need to fill in correct llm and embedding models in the pipe definitions\n\ntype: llm\nprovider: litellm_llm\nmodels:\n  # put OPENROUTER_API_KEY=<your_api_key> in ~/.wrenai/.env\n  # Qwen3 models support thinking and non-thinking modes\n  # Use /think and /no_think in prompts to control reasoning behavior\n  - api_base: https://openrouter.ai/api/v1\n    model: openrouter/qwen/qwen3-30b-a3b\n    alias: default\n    timeout: 600\n    kwargs:\n      n: 1\n      temperature: 0.6  # Recommended for thinking mode\n      top_p: 0.95\n      top_k: 20\n      response_format:\n        type: text\n  - api_base: https://openrouter.ai/api/v1\n    model: openrouter/qwen/qwen3-30b-a3b\n    alias: qwen3-thinking\n    timeout: 600\n    kwargs:\n      n: 1\n      temperature: 0.6  # Optimized for thinking mode\n      top_p: 0.95\n      top_k: 20\n      response_format:\n        type: text\n  - api_base: https://openrouter.ai/api/v1\n    model: openrouter/qwen/qwen3-30b-a3b\n    alias: qwen3-fast\n    timeout: 600\n    kwargs:\n      n: 1\n      temperature: 0.7  # Optimized for non-thinking mode\n      top_p: 0.8\n      top_k: 20\n      response_format:\n        type: text\n  - api_base: https://openrouter.ai/api/v1\n    model: openrouter/qwen/qwen3-32b\n    alias: qwen3-32b\n    timeout: 600\n    kwargs:\n      n: 1\n      temperature: 0.6\n      top_p: 0.95\n      top_k: 20\n      response_format:\n        type: json_object\n\n---\ntype: embedder\nprovider: litellm_embedder\nmodels:\n  # define OPENAI_API_KEY=<api_key> in ~/.wrenai/.env if you are using openai embedding model\n  # please refer to LiteLLM documentation for more details: https://docs.litellm.ai/docs/providers\n  - model: text-embedding-3-large  # put your embedding model name here, if it is not openai embedding model, should be <provider>/<model_name>\n    alias: default\n    api_base: https://api.openai.com/v1  # change this according to your embedding model\n    timeout: 120\n\n---\ntype: engine\nprovider: wren_ui\nendpoint: http://wren-ui:3000\n\n---\ntype: engine\nprovider: wren_ibis\nendpoint: http://ibis-server:8000\n\n---\ntype: document_store\nprovider: qdrant\nlocation: http://qdrant:6333\nembedding_model_dim: 3072 # put your embedding model dimension here\ntimeout: 120\nrecreate_index: true\n\n---\n# please change the llm and embedder names to the ones you want to use\n# the format of llm and embedder should be <provider>.<model_name> such as litellm_llm.gpt-4o-2024-08-06\n# the pipes may be not the latest version, please refer to the latest version: https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\ntype: pipeline\npipes:\n  - name: db_schema_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: table_description_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_correction\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: followup_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_answer\n    llm: litellm_llm.qwen3-fast\n  - name: semantics_description\n    llm: litellm_llm.default\n  - name: relationship_recommendation\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: question_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation_db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: question_recommendation_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: chart_generation\n    llm: litellm_llm.default\n  - name: chart_adjustment\n    llm: litellm_llm.default\n  - name: intent_classification\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: misleading_assistance\n    llm: litellm_llm.default\n  - name: data_assistance\n    llm: litellm_llm.qwen3-fast\n  - name: sql_pairs_indexing\n    document_store: qdrant\n    embedder: litellm_embedder.default\n  - name: sql_pairs_retrieval\n    document_store: qdrant\n    embedder: litellm_embedder.default\n    llm: litellm_llm.default\n  - name: preprocess_sql_data\n    llm: litellm_llm.default\n  - name: sql_executor\n    engine: wren_ui\n  - name: user_guide_assistance\n    llm: litellm_llm.default\n  - name: sql_question_generation\n    llm: litellm_llm.default\n  - name: sql_generation_reasoning\n    llm: litellm_llm.qwen3-thinking\n  - name: followup_sql_generation_reasoning\n    llm: litellm_llm.qwen3-thinking\n  - name: sql_regeneration\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: instructions_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: instructions_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_functions_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n  - name: project_meta_indexing\n    document_store: qdrant\n  - name: sql_tables_extraction\n    llm: litellm_llm.default\n  - name: sql_diagnosis\n    llm: litellm_llm.default\n  - name: sql_knowledge_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n---\nsettings:\n  engine_timeout: 30\n  column_indexing_batch_size: 50\n  table_retrieval_size: 10\n  table_column_retrieval_size: 100\n  allow_intent_classification: true\n  allow_sql_generation_reasoning: true\n  allow_sql_functions_retrieval: true\n  enable_column_pruning: false\n  max_sql_correction_retries: 3\n  query_cache_maxsize: 1000\n  query_cache_ttl: 3600\n  langfuse_host: https://cloud.langfuse.com\n  langfuse_enable: true\n  logging_level: DEBUG\n  development: true\n  historical_question_retrieval_similarity_threshold: 0.9\n  sql_pairs_similarity_threshold: 0.7\n  sql_pairs_retrieval_max_size: 10\n  instructions_similarity_threshold: 0.7\n  instructions_top_k: 10\n"
  },
  {
    "path": "wren-ai-service/docs/config_examples/config.zhipu.yaml",
    "content": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting with # and adjust the config accordingly, steps:\n# 1. you need to get your Zhipu AI API key from https://open.bigmodel.cn/\n# 2. set your API key in environment variable\n# 3. fill in embedding model dimension in the document_store section\n# 4. you need to use the correct pipe definitions based on https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\n# 5. you need to fill in correct llm and embedding models in the pipe definitions\n\ntype: llm\nprovider: litellm_llm\nmodels:\n  # GLM-4.5 with thinking disabled - Method 1: Using allowed_openai_params\n  - api_base: https://open.bigmodel.cn/api/paas/v4/\n    model: openai/glm-4.5\n    alias: default\n    timeout: 900\n    kwargs:\n      n: 1\n      temperature: 0.1\n      top_p: 0.8\n      extra_body:\n        chat_template_kwargs:\n          enable_thinking: false\n      allowed_openai_params: [\"extra_body\"]  # Force LiteLLM to allow extra_body\n  # GLM-4.5 fast mode\n  - api_base: https://open.bigmodel.cn/api/paas/v4/\n    model: openai/glm-4.5\n    alias: glm45-fast\n    timeout: 900\n    kwargs:\n      n: 1\n      temperature: 0.1\n      top_p: 0.8\n      extra_body:\n        chat_template_kwargs:\n          enable_thinking: false\n      allowed_openai_params: [\"extra_body\"]\n  # GLM-4.5 with thinking enabled for complex tasks\n  - api_base: https://open.bigmodel.cn/api/paas/v4/\n    model: openai/glm-4.5\n    alias: glm45-thinking\n    timeout: 1200  # Longer timeout for thinking mode\n    kwargs:\n      n: 1\n      temperature: 0.3\n      top_p: 0.9\n      extra_body:\n        chat_template_kwargs:\n          enable_thinking: true\n      allowed_openai_params: [\"extra_body\"]\n  # GLM-4.5 for JSON responses with thinking disabled\n  - api_base: https://open.bigmodel.cn/api/paas/v4/\n    model: openai/glm-4.5\n    alias: glm45-json\n    timeout: 900\n    kwargs:\n      n: 1\n      temperature: 0.05\n      top_p: 0.7\n      response_format:\n        type: json_object\n      extra_body:\n        chat_template_kwargs:\n          enable_thinking: false\n      allowed_openai_params: [\"extra_body\"]\n\n---\ntype: embedder\nprovider: litellm_embedder\nmodels:\n  # define OPENAI_API_KEY=<api_key> in ~/.wrenai/.env if you are using openai embedding model\n  # GLM series doesn't have dedicated embedding models yet, so we use OpenAI embedding\n  # please refer to LiteLLM documentation for more details: https://docs.litellm.ai/docs/providers\n  - model: text-embedding-3-large\n    alias: default\n    timeout: 120\n\n---\ntype: engine\nprovider: wren_ui\nendpoint: http://wren-ui:3000\n\n---\ntype: engine\nprovider: wren_ibis\nendpoint: http://ibis-server:8000\n\n---\ntype: document_store\nprovider: qdrant\nlocation: http://qdrant:6333\nembedding_model_dim: 3072  # text-embedding-3-large dimension\ntimeout: 120\nrecreate_index: true\n\n---\n# please change the llm and embedder names to the ones you want to use\n# the format of llm and embedder should be <provider>.<model_name> such as litellm_llm.glm45-fast\n# the pipes may be not the latest version, please refer to the latest version: https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml\ntype: pipeline\npipes:\n  - name: db_schema_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: table_description_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_correction\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: followup_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_answer\n    llm: litellm_llm.glm45-fast\n  - name: semantics_description\n    llm: litellm_llm.default\n  - name: relationship_recommendation\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: question_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation_db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: question_recommendation_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: chart_generation\n    llm: litellm_llm.default\n  - name: chart_adjustment\n    llm: litellm_llm.default\n  - name: intent_classification\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: misleading_assistance\n    llm: litellm_llm.default\n  - name: data_assistance\n    llm: litellm_llm.glm45-fast\n  - name: sql_pairs_indexing\n    document_store: qdrant\n    embedder: litellm_embedder.default\n  - name: sql_pairs_retrieval\n    document_store: qdrant\n    embedder: litellm_embedder.default\n    llm: litellm_llm.default\n  - name: preprocess_sql_data\n    llm: litellm_llm.default\n  - name: sql_executor\n    engine: wren_ui\n  - name: user_guide_assistance\n    llm: litellm_llm.default\n  - name: sql_question_generation\n    llm: litellm_llm.default\n  - name: sql_generation_reasoning\n    llm: litellm_llm.glm45-thinking\n  - name: followup_sql_generation_reasoning\n    llm: litellm_llm.glm45-thinking\n  - name: sql_regeneration\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: instructions_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: instructions_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_functions_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n  - name: project_meta_indexing\n    document_store: qdrant\n  - name: sql_tables_extraction\n    llm: litellm_llm.default\n  - name: sql_diagnosis\n    llm: litellm_llm.default\n  - name: sql_knowledge_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n---\nsettings:\n  engine_timeout: 30\n  column_indexing_batch_size: 50\n  table_retrieval_size: 10\n  table_column_retrieval_size: 100\n  allow_intent_classification: true\n  allow_sql_generation_reasoning: true\n  allow_sql_functions_retrieval: true\n  enable_column_pruning: false\n  max_sql_correction_retries: 3\n  query_cache_maxsize: 1000\n  query_cache_ttl: 3600\n  langfuse_host: https://cloud.langfuse.com\n  langfuse_enable: true\n  logging_level: DEBUG\n  development: true\n  historical_question_retrieval_similarity_threshold: 0.9\n  sql_pairs_similarity_threshold: 0.7\n  sql_pairs_retrieval_max_size: 10\n  instructions_similarity_threshold: 0.7\n  instructions_top_k: 10\n"
  },
  {
    "path": "wren-ai-service/docs/configuration.md",
    "content": "# AI Service Configuration\n\nThe AI service configuration is managed through a combination of environment variables and a configuration file, providing a flexible and secure approach to setting up the service.\n\n1. **Environment Variables**:\n\n   - Used for configuring sensitive information such as vendor API keys\n   - Specify the configuration file to use\n   - Allow for partial settings to be configured directly, see [Settings Loading Mechanism](#settings-loading-mechanism) for more details\n   - Provide a way to override settings in different environments\n\n2. **Configuration File**:\n   - Used for detailed configuration of components, pipelines, and other service settings\n   - Allows for more complex and structured configuration options\n\nThis dual approach ensures that sensitive data can be kept secure (using environment variables) while allowing for more detailed and shareable configuration through the configuration file. It also provides flexibility in deployment across different environments.\n\n## Settings Loading Mechanism\n\nThe AI service uses a hierarchical approach to load settings, ensuring flexibility across different environments and deployment scenarios. The settings are loaded in the following order of precedence:\n\n1. **Default Values**: These are defined as class attributes in the `Settings` class within [`config.py`](../src/config.py). They serve as the base configuration.\n\n2. **Environment Variables**: Using [pydantic-settings](https://fastapi.tiangolo.com/advanced/settings/#pydantic-settings), the service checks for environment variables that match the setting names. If found, these override the default values. For example, `WREN_AI_SERVICE_HOST` can override the default `host` value.\n\n3. **.env.dev File**: The service loads additional settings or overrides existing ones from a `.env.dev` file if present. This is particularly useful for development environments.\n\n4. **config.yaml File**: This file provides the highest priority configuration. It can override all previous settings and is used to configure components, pipelines, and other detailed settings. See [Configuration File](#configuration-file) for more details.\n\nThis mechanism allows for easy configuration management across different environments, from development to production, while maintaining security for sensitive information like API keys.\n\n## Configuration File\n\nThe configuration file (`config.yaml`) is structured into several sections, each defining different aspects of the AI service. Here's a breakdown of its main components:\n\n1. **LLM Configuration**:\n\n   ```yaml\n   type: llm\n   provider: <provider_name>\n   models:\n     - model: <model_name>\n       kwargs: {}\n   api_base: <api_endpoint>\n   ```\n\n   This component initializes the LLM provider at runtime. You can specify multiple models with different parameters. The `kwargs` field allows for model-specific configurations. For example:\n\n   ```yaml\n   type: llm\n   provider: openai_llm\n   models:\n     - model: gpt-4\n       kwargs:\n         temperature: 0\n         n: 1\n         max_tokens: 4096\n         response_format:\n           type: \"json_object\"\n     - model: gpt-4o-mini\n       kwargs: {}\n   api_base: https://api.openai.com/v1\n   ```\n\n   For detailed parameter options, refer to the implementation of the specific LLM provider.\n\n2. **Embedder Configuration**:\n\n   ```yaml\n   type: embedder\n   provider: <provider_name>\n   models:\n     - model: <model_name>\n       dimension: <embedding_size>\n   api_base: <api_endpoint>\n   timeout: <timeout_in_seconds>\n   ```\n\n   This component configures the embedder, which converts text into numerical vectors. The `provider` specifies the embedder service (e.g., OpenAI, Ollama). You can define multiple `models` with their parameters. The `dimension` parameter indicates the size of the embedding vector.\n\n3. **Engine Configuration**:\n\n   ```yaml\n   type: engine\n   provider: <provider_name>\n   endpoint: <engine_endpoint>\n   ```\n\n   This component configures the engine responsible for generating SQL queries. The `provider` specifies the engine service (e.g., Wren UI).\n\n4. **Document Store Configuration**:\n\n   ```yaml\n   type: document_store\n   provider: <provider_name>\n   ```\n\n   This component configures the document store, which is responsible for storing and retrieving embeddings. The `provider` specifies the document store service (e.g., Qdrant).\n\n5. **Pipeline Configuration**:\n\n   ```yaml\n   type: pipeline\n   pipes:\n     - name: <pipe_name>\n       llm: <provider>.<model_name>\n       embedder: <provider>.<model_name>\n       engine: <provider_name>\n       document_store: <provider_name>\n   ```\n\n   This component configures each pipeline, specifying different LLM, embedder, engine, and document store combinations. For LLM and embedder, use `<provider>.<model_name>`. For engine and document store, use `<provider_name>`.\n\n   Example:\n\n   ```yaml\n   type: pipeline\n   pipes:\n     - name: sql_generation\n       llm: openai_llm.gpt-4o-mini\n       engine: wren_ui\n   ```\n\n6. **Settings**:\n\n   ```yaml\n   settings:\n     host: <host_address>\n     port: <port_number>\n     column_indexing_batch_size: <batch_size>\n     table_retrieval_size: <retrieval_size>\n     table_column_retrieval_size: <column_retrieval_size>\n     query_cache_maxsize: <cache_size>\n     query_cache_ttl: <cache_ttl_in_seconds>\n     langfuse_host: <langfuse_endpoint>\n     langfuse_enable: <true/false>\n     logging_level: <log_level>\n     development: <true/false>\n   ```\n\n   This section defines various service settings including host, port, indexing and retrieval parameters, cache settings, Langfuse configuration, logging level, and development mode.\n\nThis configuration file allows for detailed customization of the AI service components, pipelines, and overall behavior. It provides a centralized place to manage complex configurations while keeping sensitive information separate (managed through environment variables). See [Full Configuration File](../tools/config/config.full.yaml) for a complete example.\n"
  },
  {
    "path": "wren-ai-service/entrypoint.sh",
    "content": "#!/bin/bash\nset -e\n\nINTERVAL=1\nTIMEOUT=60\n\n# Wait for qdrant to be responsive\necho \"Waiting for qdrant to start...\"\ncurrent=0\n\nwhile ! nc -z $QDRANT_HOST 6333; do\n    sleep $INTERVAL\n    current=$((current + INTERVAL))\n    if [ $current -eq $TIMEOUT ]; then\n        echo \"Timeout: qdrant did not start within $TIMEOUT seconds\"\n        exit 1\n    fi\ndone\necho \"qdrant has started.\"\n\n# Start wren-ai-service in the background\nuvicorn src.__main__:app --host 0.0.0.0 --port $WREN_AI_SERVICE_PORT --loop uvloop --http httptools &\n\nif [[ -n \"$SHOULD_FORCE_DEPLOY\" ]]; then\n\n    # Wait for the server to be responsive\n    echo \"Waiting for wren-ai-service to start...\"\n    current=0\n\n    while ! nc -z localhost $WREN_AI_SERVICE_PORT; do\n        sleep $INTERVAL\n        current=$((current + INTERVAL))\n        if [ $current -eq $TIMEOUT ]; then\n            echo \"Timeout: wren-ai-service did not start within $TIMEOUT seconds\"\n            exit 1\n        fi\n    done\n    echo \"wren-ai-service has started.\"\n\n    # Wait for wren-ui to be responsive\n    echo \"Waiting for wren-ui to start...\"\n    current=0\n\n    while ! nc -z wren-ui $WREN_UI_PORT && ! nc -z host.docker.internal $WREN_UI_PORT; do\n        sleep $INTERVAL\n        current=$((current + INTERVAL))\n        if [ $current -eq $TIMEOUT ]; then\n            echo \"Timeout: wren-ui did not start within $TIMEOUT seconds\"\n            exit 1\n        fi\n    done\n    echo \"wren-ui has started.\"\n\n    echo \"Forcing deployment...\"\n    python -m src.force_deploy\nfi\n\n# Bring wren-ai-service to the foreground\nwait\n"
  },
  {
    "path": "wren-ai-service/eval/.gitignore",
    "content": ".env\nconfig.yaml"
  },
  {
    "path": "wren-ai-service/eval/README.md",
    "content": "# Evaluation Framework\n\nThis document describes the evaluation framework for the Wren AI service. The evaluation framework is designed to assess the performance of the Wren AI service based on the following components:\n\n## Requirements\n\n1. **Install Just**: Download and install [Just](https://github.com/casey/just?tab=readme-ov-file#packages) to run the evaluation framework commands.\n2. **Set up Langfuse**: Create an account on [Langfuse](https://cloud.langfuse.com) and obtain the API key and secret. Populate the `.env.dev` file with these credentials.\n3. **Start Development Services**: Run `just up` to initiate the necessary development services.\n4. **Configuration File**: Ensure you have a copy of `config.yaml` located in the `wren-ai-service/eval/` directory.\n\n## Dataset Curation\n\nThe dataset curation process is used to prepare the evaluation dataset for the Wren AI service on evaluation purpose. You can follow the steps below to start the curation app:\n\n- copy `.env.example` to `.env` and fill in the environment variables\n- execute the command under the `wren-ai-service` folder: `just curate_eval_data`\n\n## Eval Dataset Preparation(If using Spider 1.0 dataset, or Bird dataset)\n\n```cli\njust prep <dataset-name>\n```\n\nCurrently, we support two datasets for evaluation:\n\n- `spider1.0`: The Spider dataset (default if no dataset specified)\n- `bird`: The Bird dataset\n\nThe command performs two main steps:\n\n1. Downloads the specified dataset to:\n\n   ```txt\n   wren-ai-service/tools/dev/etc/<dataset-name>\n   ```\n\n2. Prepares and saves evaluation datasets to:\n\n   ```txt\n   wren-ai-service/eval/dataset\n   ```\n\n   The output files follow these naming conventions:\n\n   - Spider dataset: `spider_<db_name>_eval_dataset.toml`\n   - Bird dataset: `bird_<db_name>_eval_dataset.toml`\n\nEach evaluation dataset contains questions, SQL queries, and relevant context needed for testing the system's text-to-SQL capabilities.\n\n## Evaluation Dataset Schema\n\n- dataset_id(UUID)\n- date\n- mdl\n- eval dataset\n\n## Configure the datasource for prediction and evaluation\n\nBefore starting the prediction and evaluation process, you need to configure the datasource correctly. This ensures that the system can access the necessary data for making predictions and evaluations.\n\n### For Spider or Bird Datasets\n\nFor the Spider or Bird datasets, a built-in datasource is used. This means that the data is stored locally and accessed through a specific path. You need to specify the `eval_data_db_path` in the `config.yaml` file. This path tells the system where to find the database files.\n\nHere's an example of how to set this up in the `config.yaml` file:\n\n```yaml\neval_data_db_path: \"etc/bird/minidev/MINIDEV/dev_databases\"\n```\n\n### Configuring BigQuery as a Datasource for Other custom MDLs\n\nWhen working with custom MDLs that utilize BigQuery as their datasource, it's crucial to properly configure your system to access the necessary datasets. This involves setting specific parameters in the `config.yaml` file or the `.env.dev` file. Both methods are effective, but using the `.env.dev` file is particularly beneficial for keeping sensitive credentials secure.\n\n#### Encoding the credentials\n\nYou can use the following command to encode the credentials:\n\n```cli\ncat <path/to/credentials.json> | base64\n```\n\n#### Configuration in `config.yaml`\n\nTo enable access to your BigQuery dataset, add the following parameters to your `config.yaml` file. This configuration will guide the system in locating and authenticating with your BigQuery resources:\n\n```yaml\nbigquery_project_id: \"your_project_id\"\nbigquery_dataset_id: \"your_dataset_id\"\nbigquery_credentials: \"your_credentials\" # this is a base64 encoded string of the credentials\n```\n\n#### Configuration in `.env.dev`\n\nFor the `.env.dev` file, you can use the following parameters:\n\n```env\nBIGQUERY_PROJECT_ID=\"your_project_id\"\nBIGQUERY_DATASET_ID=\"your_dataset_id\"\nBIGQUERY_CREDENTIALS=\"your_credentials\" # this is a base64 encoded string of the credentials\n```\n\n## Prediction Process\n\nThe prediction process is used to produce the results of the evaluation data using the Wren AI service. It will create traces and a session on Langfuse to make the results available to the user. You can use the following command to predict the evaluation dataset under the `eval/dataset` directory:\n\n```cli\njust predict <evaluation-dataset>\n```\n\nAlso, sub-pipeline predictions are supported by specifying the pipeline name:\n\n```cli\njust predict <evaluation-dataset> <pipeline-name>\n```\n\nCurrently, we support the following pipelines: 'ask', 'generation', and 'retrieval'. If no pipeline name is specified, the default is the 'ask' pipeline.\n\n## Evaluation Process\n\nThe evaluation process is used to assess the prediction results of the Wren AI service. It compares the prediction results with the ground truth and calculates the evaluation metrics. This process will also add a trace in the same session on Langfuse to make the evaluation results available to the user. You can use the following command to evaluate the prediction results under the `outputs/predictions` directory:\n\n```cli\njust eval <prediction-result>\n```\n\nNote: If you would like to enable semantics comparison between SQLs by LLM in order to improve the accuracy metric, please fill in Open AI API key in `.env` file in `wren-ai-service/eval` and add `--semantics` to the end of the command like following:\n\n```cli\njust eval <prediction-result> --semantics\n```\n\nThe evaluation results will be presented on Langfuse as follows:\n\n![shallow_trace_example](../docs/imgs/shallow_trace_example.png)\n\n## Terms\n\nThis section describes the terms used in the evaluation framework:\n\n- **input**: The user query used as input to the Wren AI service (e.g., \"What is the total number of COVID-19 cases in the US?\").\n- **actual_output**: The actual SQL query generated to retrieve the answer to the user query (e.g., \"SELECT SUM(cases) FROM covid19 WHERE country='US'\").\n- **expected_output**: The expected SQL query that should retrieve the answer to the user query (e.g., \"SELECT SUM(cases) FROM covid19 WHERE country='US'\").\n- **retrieval_context**: The relevant context that helps the LLM generate the SQL query (e.g., \"covid19.country\", \"covid19.cases\").\n- **context**: The relevant context that aligns with human expectations to generate the SQL query (e.g., \"covid19.country\", \"covid19.cases\").\n\n## Metrics\n\nThis section describes the evaluation metrics used in the evaluation framework:\n\n- **Accuracy**: This metrics is defined as the proportion of the correct SQL output generated by the model compared to the expected SQL output. It checks if the generated SQL query produces the correct results.\n- **Answer Relevancy**: This metric helps determine how well your LLM generates relevant information based on the input it receives. It ensures the efficiency and accuracy of the model's output.\n- **Faithfulness**: This metric helps determine how well your LLM generates information that is factually correct and aligned with the retrieval context, minimizing hallucinations and contradictions.\n- **Contextual Relevancy**: This metric helps determine how well your retriever minimizes irrelevant information while maximizing the retrieval of relevant information. It ensures the efficiency and accuracy of the retrieval process.\n- **Contextual Recall**: This metric helps determine how well the embedding model identifies and retrieves relevant information based on the given context.\n- **Contextual Precision**: This metric helps determine how well the reranker places relevant nodes higher in the ranking, ensuring that users get the most pertinent results quickly.\n- **QuestionToReasoningJudge**: This metric helps determine how well the LLM generates reasoning that is aligned with the question.\n- **ReasoningToSqlJudge**: This metric helps determine how well the LLM generates SQL that is aligned with the reasoning.\n- **SqlSemanticsJudge**: This metric helps determine how well the LLM generates SQL that is semantically equivalent to the expected SQL.\n"
  },
  {
    "path": "wren-ai-service/eval/__init__.py",
    "content": "from pathlib import Path\n\nfrom pydantic import Field, SecretStr\n\nfrom src.config import Settings\n\nSPIDER_DESTINATION_PATH = Path(\"./tools/dev/etc/spider1.0\")\nBIRD_DESTINATION_PATH = Path(\"./tools/dev/etc/bird\")\nWREN_ENGINE_API_URL = \"http://localhost:8080\"\nEVAL_DATASET_DESTINATION_PATH = Path(\"./eval/dataset\")\n\n\nclass EvalSettings(Settings):\n    langfuse_project_id: str = \"\"\n    batch_size: int = 4\n    batch_interval: int = 1\n    datasource: str = \"bigquery\"\n    config_path: str = \"eval/config.yaml\"\n    openai_api_key: SecretStr = Field(alias=\"OPENAI_API_KEY\")\n    allow_sql_samples: bool = True\n    allow_instructions: bool = True\n    allow_sql_functions: bool = True\n    eval_data_db_path: str = \"\"\n\n    # BigQuery\n    bigquery_project_id: str = Field(default=\"\")\n    bigquery_dataset_id: str = Field(default=\"\")\n    bigquery_credentials: SecretStr = Field(default=\"\")\n\n    # Postgres\n    postgres_host: str = Field(default=\"postgres\")\n    postgres_port: str = Field(default=\"5432\")\n    postgres_user: str = Field(default=\"postgres\")\n    postgres_password: SecretStr = Field(default=\"postgres\")\n    postgres_database: str = Field(default=\"test\")\n\n    @property\n    def langfuse_url(self) -> str:\n        if not self.langfuse_project_id:\n            return \"\"\n        return f\"{self.langfuse_host.rstrip('/')}/project/{self.langfuse_project_id}\"\n\n    def get_openai_api_key(self) -> str:\n        return self.openai_api_key.get_secret_value()\n\n    @property\n    def bigquery_info(self) -> dict:\n        return {\n            \"project_id\": self.bigquery_project_id,\n            \"dataset_id\": self.bigquery_dataset_id,\n            \"credentials\": self.bigquery_credentials.get_secret_value(),\n        }\n\n    @property\n    def postgres_info(self) -> dict:\n        return {\n            \"host\": self.postgres_host,\n            \"port\": self.postgres_port,\n            \"user\": self.postgres_user,\n            \"password\": self.postgres_password.get_secret_value(),\n            \"database\": self.postgres_database,\n        }\n"
  },
  {
    "path": "wren-ai-service/eval/add_samples_to_toml.py",
    "content": "import argparse\n\nimport tomlkit\n\nfrom eval.utils import (\n    get_next_few_items_circular,\n)\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"--toml\", type=str, help=\"The toml file name\", required=True)\n    args = parser.parse_args()\n\n    if args.toml:\n        # read toml\n        with open(f\"eval/dataset/{args.toml}\", \"r\") as f:\n            doc = tomlkit.parse(f.read())\n\n        # get the list of question-sql pairs for generating sample values\n        ground_truth_list = [\n            {\"question\": element[\"question\"], \"sql\": element[\"sql\"]}\n            for element in doc[\"eval_dataset\"]\n        ]\n\n        # utilize utils.get_next_few_items_circular, put n samples in the eval dataset\n        new_dataset = []\n        for i, element in enumerate(doc[\"eval_dataset\"]):\n            samples = get_next_few_items_circular(ground_truth_list, i)\n            element[\"samples\"] = samples\n            new_dataset.append(element)\n\n        # write toml\n        doc[\"eval_dataset\"] = new_dataset\n\n        with open(f\"eval/dataset/added_samples_{args.toml}\", \"w\") as f:\n            f.write(tomlkit.dumps(doc, sort_keys=True))\n"
  },
  {
    "path": "wren-ai-service/eval/data_curation/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/eval/data_curation/app.py",
    "content": "import asyncio\nimport re\nimport sys\nimport uuid\nfrom datetime import datetime\nfrom pathlib import Path\n\nimport orjson\nimport pandas as pd\nimport streamlit as st\nimport tomlkit\nfrom openai import AsyncClient\nfrom streamlit_tags import st_tags\n\nsys.path.append(f\"{Path().parent.resolve()}\")\nfrom utils import (\n    DATA_SOURCES,\n    WREN_ENGINE_ENDPOINT,\n    WREN_IBIS_ENDPOINT,\n    get_contexts_from_sqls,\n    get_data_from_wren_engine_with_sqls,\n    get_question_sql_pairs,\n    is_sql_valid,\n    prettify_sql,\n)\n\nfrom eval import EvalSettings\nfrom eval.utils import (\n    get_documents_given_contexts,\n    get_eval_dataset_in_toml_string,\n    get_openai_client,\n    prepare_duckdb_init_sql,\n    prepare_duckdb_session_sql,\n)\n\nst.set_page_config(layout=\"wide\")\nst.title(\"WrenAI Data Curation App\")\n\n\nLLM_OPTIONS = [\"gpt-4o-mini\", \"gpt-4o\"]\n\nsettings = EvalSettings()\nllm_client = get_openai_client(api_key=settings.get_openai_api_key())\n\n# session states\nif \"llm_model\" not in st.session_state:\n    st.session_state[\"llm_model\"] = LLM_OPTIONS[0]\nif \"deployment_id\" not in st.session_state:\n    st.session_state[\"deployment_id\"] = str(uuid.uuid4())\nif \"mdl_json\" not in st.session_state:\n    st.session_state[\"mdl_json\"] = None\nif \"custom_instructions_for_llm\" not in st.session_state:\n    st.session_state[\"custom_instructions_for_llm\"] = \"\"\nif \"llm_question_sql_pairs\" not in st.session_state:\n    st.session_state[\"llm_question_sql_pairs\"] = []\nif \"user_question_sql_pair\" not in st.session_state:\n    st.session_state[\"user_question_sql_pair\"] = {}\nif \"candidate_dataset\" not in st.session_state:\n    st.session_state[\"candidate_dataset\"] = []\nif \"data_source\" not in st.session_state:\n    st.session_state[\"data_source\"] = None\nif \"connection_info\" not in st.session_state:\n    st.session_state[\"connection_info\"] = None\n\n\n# widget callbacks\ndef on_change_upload_eval_dataset():\n    doc = tomlkit.parse(st.session_state.uploaded_eval_file.getvalue().decode(\"utf-8\"))\n\n    assert (\n        doc[\"mdl\"] == st.session_state[\"mdl_json\"]\n    ), \"The model in the uploaded dataset is different from the deployed model\"\n    st.session_state[\"candidate_dataset\"] = doc[\"eval_dataset\"]\n\n\ndef on_change_custom_instructions_for_llm():\n    st.session_state[\"custom_instructions_for_llm\"] = st.session_state[\n        \"custom_instructions_text_area\"\n    ]\n\n\ndef on_click_generate_question_sql_pairs(llm_client: AsyncClient):\n    st.toast(\"Generating question-sql-pairs...\")\n    st.session_state[\"llm_question_sql_pairs\"] = asyncio.run(\n        get_question_sql_pairs(\n            llm_client,\n            st.session_state[\"llm_model\"],\n            st.session_state[\"mdl_json\"],\n            st.session_state[\"custom_instructions_for_llm\"],\n            st.session_state[\"data_source\"],\n            st.session_state[\"connection_info\"],\n        )\n    )\n\n\ndef on_click_setup_uploaded_file():\n    uploaded_file = st.session_state.get(\"uploaded_mdl_file\")\n    if uploaded_file:\n        match = re.match(\n            r\".+_(\" + \"|\".join(DATA_SOURCES) + r\")(_.+)?_mdl\\.json$\",\n            uploaded_file.name,\n        )\n        if not match:\n            st.error(\n                f\"the file name must be [xxx]_[datasource]_mdl.json, now we support these datasources: {DATA_SOURCES}\"\n            )\n            st.stop()\n\n        data_source = match.group(1)\n        st.session_state[\"data_source\"] = data_source\n        st.session_state[\"mdl_json\"] = orjson.loads(\n            uploaded_file.getvalue().decode(\"utf-8\")\n        )\n\n        if data_source == \"bigquery\":\n            st.session_state[\"connection_info\"] = settings.bigquery_info\n        elif data_source == \"duckdb\":\n            prepare_duckdb_session_sql(WREN_ENGINE_ENDPOINT)\n            prepare_duckdb_init_sql(\n                WREN_ENGINE_ENDPOINT,\n                st.session_state[\"mdl_json\"][\"catalog\"],\n                \"etc/spider1.0/database\",\n            )\n    else:\n        st.session_state[\"data_source\"] = None\n        st.session_state[\"mdl_json\"] = None\n        st.session_state[\"connection_info\"] = None\n\n\ndef on_change_llm_model():\n    st.toast(f\"Switching LLM model to {st.session_state['select_llm_model']}\")\n    st.session_state[\"llm_model\"] = st.session_state[\"select_llm_model\"]\n\n\ndef on_change_sql(i: int, key: str):\n    sql = st.session_state[key]\n\n    valid, error = asyncio.run(\n        is_sql_valid(\n            sql,\n            st.session_state[\"data_source\"],\n            st.session_state[\"mdl_json\"],\n            st.session_state[\"connection_info\"],\n            WREN_ENGINE_ENDPOINT\n            if st.session_state[\"data_source\"] == \"duckdb\"\n            else WREN_IBIS_ENDPOINT,\n        )\n    )\n    if valid:\n        new_context = asyncio.run(\n            get_contexts_from_sqls([sql], st.session_state[\"mdl_json\"])\n        )[0]\n        document = get_documents_given_contexts(\n            [new_context], st.session_state[\"mdl_json\"]\n        )\n    if i != -1:\n        st.session_state[\"llm_question_sql_pairs\"][i][\"sql\"] = sql\n        st.session_state[\"llm_question_sql_pairs\"][i][\"is_valid\"] = valid\n        st.session_state[\"llm_question_sql_pairs\"][i][\"error\"] = error\n        if valid:\n            st.session_state[\"llm_question_sql_pairs\"][i][\"context\"] = new_context\n            st.session_state[\"llm_question_sql_pairs\"][i][\"document\"] = document\n    else:\n        st.session_state[\"user_question_sql_pair\"][\"sql\"] = sql\n        st.session_state[\"user_question_sql_pair\"][\"is_valid\"] = valid\n        st.session_state[\"user_question_sql_pair\"][\"error\"] = error\n        if valid:\n            st.session_state[\"user_question_sql_pair\"][\"context\"] = new_context\n            st.session_state[\"user_question_sql_pair\"][\"document\"] = document\n\n\ndef on_click_add_candidate_dataset(i: int, categories: list):\n    if i != -1:\n        dataset_to_add = {\n            \"categories\": categories,\n            \"question\": st.session_state[\"llm_question_sql_pairs\"][i][\"question\"],\n            \"context\": st.session_state[\"llm_question_sql_pairs\"][i][\"context\"],\n            \"sql\": st.session_state[\"llm_question_sql_pairs\"][i][\"sql\"],\n            \"document\": st.session_state[\"llm_question_sql_pairs\"][i][\"document\"],\n        }\n    else:\n        dataset_to_add = {\n            \"categories\": categories,\n            \"question\": st.session_state[\"user_question_sql_pair\"][\"question\"],\n            \"context\": st.session_state[\"user_question_sql_pair\"][\"context\"],\n            \"sql\": st.session_state[\"user_question_sql_pair\"][\"sql\"],\n            \"document\": st.session_state[\"user_question_sql_pair\"][\"document\"],\n        }\n\n        # reset input for user question sql pair\n        st.session_state[\"user_question_sql_pair\"] = {}\n        st.session_state[\"user_question\"] = \"\"\n        st.session_state[\"user_sql\"] = \"\"\n\n    should_add = True\n    for dataset in st.session_state[\"candidate_dataset\"]:\n        if dataset == dataset_to_add:\n            should_add = False\n            break\n\n    if should_add:\n        st.session_state[\"candidate_dataset\"].append(dataset_to_add)\n\n\ndef on_change_user_question():\n    if not st.session_state[\"user_question_sql_pair\"]:\n        st.session_state[\"user_question_sql_pair\"] = {\n            \"question\": st.session_state[\"user_question\"],\n            \"context\": [],\n            \"document\": [],\n            \"sql\": \"\",\n            \"is_valid\": False,\n            \"error\": \"\",\n        }\n    else:\n        st.session_state[\"user_question_sql_pair\"] = {\n            **st.session_state[\"user_question_sql_pair\"],\n            \"question\": st.session_state[\"user_question\"],\n        }\n\n\ndef on_click_remove_candidate_dataset_button(i: int):\n    st.session_state[\"candidate_dataset\"].pop(i)\n\n\nst.file_uploader(\n    f\"Upload an MDL json file, and the file name must be [xxx]_[datasource]_mdl.json, now we support these datasources: {DATA_SOURCES}\",\n    type=\"json\",\n    key=\"uploaded_mdl_file\",\n    on_change=on_click_setup_uploaded_file,\n)\n\nst.selectbox(\n    label=\"Select which LLM model you want to use\",\n    options=LLM_OPTIONS,\n    index=0,\n    key=\"select_llm_model\",\n    on_change=on_change_llm_model,\n)\n\ntab_create_dataset, tab_modify_dataset = st.tabs(\n    [\"Create New Evaluation Dataset\", \"Modify Saved Evaluation Dataset\"]\n)\nwith tab_create_dataset:\n    st.markdown(\n        \"\"\"\n        ### Usage Guide\n        1. Upload an MDL json file first\n        2. Get question-sql-pairs given by LLM or you manually enter question and corresponding sql\n        3. Do validation on each group of question, context and SQL, and move it to the candidate dataset if you think it's valid\n        3. Save the candidate dataset by clicking the \"Save as Evaluation Dataset\" button.\n        \"\"\"\n    )\n\nwith tab_modify_dataset:\n    st.markdown(\n        \"\"\"\n        ### Usage Guide\n        1. Upload an MDL json file first\n        2. Upload the evaluation dataset(`.toml` file) you want to modify, and please make sure the model in the dataset is the same as the deployed model\n        3. Modify the evaluation dataset the same as you create a new one\n        4. Save the candidate dataset by clicking the \"Save as Evaluation Dataset\" button.\n        \"\"\"\n    )\n\n    st.warning(\n        \"WARNING: Uploading the evaluation dataset will overwrite the current candidate dataset\"\n    )\n    st.file_uploader(\n        \"Upload Evaluation Dataset\",\n        type=\"toml\",\n        key=\"uploaded_eval_file\",\n        on_change=on_change_upload_eval_dataset,\n        disabled=st.session_state[\"mdl_json\"] is None,\n    )\n\nif st.session_state[\"mdl_json\"] is not None:\n    col1, col2 = st.columns(2)\n    with col1:\n        st.markdown(\"### Question SQL Pairs\")\n        tab_generated_by_llm, tab_generated_by_user = st.tabs(\n            [\"Generated by LLM\", \"Generated by User\"]\n        )\n\n        with tab_generated_by_llm:\n            st.text_area(\n                \"Custom Instructions for generating question-sql-pairs (Optional)\",\n                key=\"custom_instructions_text_area\",\n                value=st.session_state[\"custom_instructions_for_llm\"],\n                placeholder=\"You can specify the custom instructions on how LLM should generate question-sql-pairs here, for example: what type of questions you want to generate.\",\n                on_change=on_change_custom_instructions_for_llm,\n            )\n\n            st.button(\n                \"Generate 10 question-sql-pairs\",\n                key=\"generate_question_sql_pairs\",\n                on_click=on_click_generate_question_sql_pairs,\n                args=(llm_client,),\n            )\n\n            with st.container(border=True, height=550):\n                for i, question_sql_pair in enumerate(\n                    st.session_state[\"llm_question_sql_pairs\"]\n                ):\n                    st.text_input(\n                        f\"Question {i}\",\n                        question_sql_pair[\"question\"],\n                        disabled=True,\n                        key=f\"question_{i}\",\n                    )\n                    categories = st_tags(\n                        label=f\"Categories {i}\",\n                        text=\"Press enter to add more\",\n                        value=[],\n                        key=f\"categories_{i}\",\n                    )\n                    st.multiselect(\n                        label=f\"Context {i}\",\n                        options=question_sql_pair[\"context\"],\n                        default=question_sql_pair[\"context\"],\n                        key=f\"context_{i}\",\n                        help=\"Contexts are automatically generated based on the SQL once you save the changes of the it(ctrl+enter or command+enter)\",\n                        disabled=True,\n                    )\n                    st.text_area(\n                        f\"SQL {i}\",\n                        prettify_sql(question_sql_pair[\"sql\"]),\n                        key=f\"sql_{i}\",\n                        height=250,\n                        on_change=on_change_sql,\n                        args=(i, f\"sql_{i}\"),\n                    )\n                    if st.session_state[\"llm_question_sql_pairs\"][i][\"is_valid\"]:\n                        st.success(\"SQL is valid\")\n                        st.dataframe(\n                            pd.DataFrame(\n                                question_sql_pair[\"data\"][\"data\"],\n                                columns=question_sql_pair[\"data\"][\"columns\"],\n                            )\n                        )\n                    else:\n                        st.error(\n                            f\"SQL is invalid: {st.session_state['llm_question_sql_pairs'][i]['error']}\"\n                        )\n\n                    st.button(\n                        \"Move it to the candidate dataset\",\n                        key=f\"move_to_dataset_{i}\",\n                        disabled=(\n                            not st.session_state[\"llm_question_sql_pairs\"][i][\n                                \"is_valid\"\n                            ]\n                            or not st.session_state[f\"context_{i}\"]\n                            or not categories\n                        ),\n                        on_click=on_click_add_candidate_dataset,\n                        args=(\n                            i,\n                            categories,\n                        ),\n                    )\n\n                    st.markdown(\"---\")\n\n        with tab_generated_by_user:\n            with st.container(border=True, height=550):\n                st.text_input(\n                    \"Question\",\n                    disabled=False,\n                    key=\"user_question\",\n                    on_change=on_change_user_question,\n                )\n                categories = st_tags(\n                    label=\"Categories\",\n                    text=\"Press enter to add more\",\n                    value=[],\n                    key=\"user_categories\",\n                )\n                st.multiselect(\n                    label=\"Context\",\n                    options=st.session_state.get(\"user_question_sql_pair\", {}).get(\n                        \"context\", []\n                    ),\n                    default=st.session_state.get(\"user_question_sql_pair\", {}).get(\n                        \"context\", []\n                    ),\n                    key=\"user_context\",\n                    help=\"Contexts are automatically generated based on the SQL once you save the changes of the it(ctrl+enter or command+enter)\",\n                    disabled=True,\n                )\n                st.text_area(\n                    \"SQL\",\n                    key=\"user_sql\",\n                    height=250,\n                    on_change=on_change_sql,\n                    args=(-1, \"user_sql\"),\n                )\n\n                if st.session_state.get(\"user_question_sql_pair\", {}).get(\n                    \"is_valid\", False\n                ):\n                    st.success(\"SQL is valid\")\n                    data = asyncio.run(\n                        get_data_from_wren_engine_with_sqls(\n                            [st.session_state[\"user_question_sql_pair\"][\"sql\"]],\n                            st.session_state[\"data_source\"],\n                            st.session_state[\"mdl_json\"],\n                            st.session_state[\"connection_info\"],\n                            WREN_ENGINE_ENDPOINT\n                            if st.session_state[\"data_source\"] == \"duckdb\"\n                            else WREN_IBIS_ENDPOINT,\n                        )\n                    )[0]\n                    st.dataframe(\n                        pd.DataFrame(\n                            data[\"data\"],\n                            columns=data[\"columns\"],\n                        )\n                    )\n                else:\n                    st.error(\n                        f\"SQL is invalid: {st.session_state.get('user_question_sql_pair', {}).get('error', '')}\"\n                    )\n\n                st.button(\n                    \"Move it to the candidate dataset\",\n                    key=\"move_to_dataset\",\n                    disabled=(\n                        not st.session_state.get(\"user_question_sql_pair\", {}).get(\n                            \"is_valid\", False\n                        )\n                        or not st.session_state[\"user_context\"]\n                        or not st.session_state[\"user_question\"]\n                        or not categories\n                    ),\n                    on_click=on_click_add_candidate_dataset,\n                    args=(\n                        -1,\n                        categories,\n                    ),\n                )\n    with col2:\n        st.markdown(\"### Candidate Dataset\")\n\n        with st.container(border=True, height=600):\n            for i, dataset in enumerate(st.session_state[\"candidate_dataset\"]):\n                st.text_input(\n                    f\"Question {i}\",\n                    dataset[\"question\"],\n                    disabled=True,\n                    key=f\"candidate_dataset_question_{i}\",\n                )\n                st.multiselect(\n                    f\"Categories {i}\",\n                    options=dataset[\"categories\"],\n                    default=dataset[\"categories\"],\n                    disabled=True,\n                    key=f\"candidate_dataset_categories_{i}\",\n                )\n                st.multiselect(\n                    f\"Context {i}\",\n                    options=dataset[\"context\"],\n                    default=dataset[\"context\"],\n                    disabled=True,\n                    key=f\"candidate_dataset_context_{i}\",\n                )\n                st.markdown(f\"SQL {i}\")\n                st.code(prettify_sql(dataset[\"sql\"]), language=\"sql\", line_numbers=True)\n                st.button(\n                    \"Remove\",\n                    key=f\"remove_{i}\",\n                    on_click=on_click_remove_candidate_dataset_button,\n                    args=(i,),\n                )\n                st.markdown(\"---\")\n\n        with st.popover(\"Save as Evaluation Dataset\", use_container_width=True):\n            file_name = st.text_input(\n                \"File Name\",\n                f\"eval_dataset_{datetime.today().strftime('%Y_%m_%d')}.toml\",\n                key=\"eval_dataset_file_name\",\n            )\n            download_btn = st.download_button(\n                \"Download\",\n                get_eval_dataset_in_toml_string(\n                    st.session_state[\"mdl_json\"],\n                    st.session_state[\"candidate_dataset\"],\n                ),\n                file_name=file_name,\n                key=\"download_eval_dataset_confirmed\",\n                disabled=not st.session_state[\"candidate_dataset\"],\n            )\n            if download_btn:\n                st.toast(\"Downloading the evaluation dataset...\")\n"
  },
  {
    "path": "wren-ai-service/eval/data_curation/utils.py",
    "content": "import asyncio\nimport base64\nimport logging\nimport os\nimport re\nimport sys\nfrom pathlib import Path\nfrom typing import List, Tuple\n\nimport aiohttp\nimport orjson\nimport sqlparse\nimport streamlit as st\nfrom dotenv import load_dotenv\nfrom openai import AsyncClient\n\n# add wren-ai-service to sys.path\nsys.path.append(f\"{Path().parent.parent.resolve()}\")\nfrom eval.utils import (\n    get_contexts_from_sql,\n    get_data_from_wren_engine,\n    get_ddl_commands,\n    get_documents_given_contexts,\n)\nfrom src.pipelines.indexing.db_schema import DDLChunker\n\nload_dotenv()\n\nWREN_IBIS_ENDPOINT = os.getenv(\"WREN_IBIS_ENDPOINT\", \"http://localhost:8000\")\nWREN_ENGINE_ENDPOINT = os.getenv(\"WREN_ENGINE_ENDPOINT\", \"http://localhost:8080\")\nDATA_SOURCES = [\"bigquery\", \"duckdb\"]\nTIMEOUT_SECONDS = 60\nddl_converter = DDLChunker()\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nasync def is_sql_valid(\n    sql: str,\n    data_source: str,\n    mdl_json: dict,\n    connection_info: dict,\n    api_endpoint: str,\n    timeout: float = TIMEOUT_SECONDS,\n) -> Tuple[bool, str]:\n    sql = sql.rstrip(\";\") if sql.endswith(\";\") else sql\n\n    if data_source == \"duckdb\":\n        async with aiohttp.request(\n            \"GET\",\n            f\"{api_endpoint}/v1/mdl/dry-run\",\n            json={\n                \"sql\": remove_limit_statement(sql),\n                \"manifest\": mdl_json,\n                \"limit\": 1,\n            },\n            timeout=aiohttp.ClientTimeout(total=timeout),\n        ) as response:\n            if response.status == 200:\n                return True, None\n\n            res = await response.json()\n            return False, res\n    else:\n        async with aiohttp.request(\n            \"POST\",\n            f\"{api_endpoint}/v3/connector/{data_source}/query?dryRun=true\",\n            json={\n                \"sql\": remove_limit_statement(sql),\n                \"manifestStr\": base64.b64encode(orjson.dumps(mdl_json)).decode(),\n                \"connectionInfo\": connection_info,\n            },\n            timeout=aiohttp.ClientTimeout(total=timeout),\n        ) as response:\n            if response.status == 204:\n                return True, None\n            res = await response.text()\n\n            return False, res\n\n\nasync def get_validated_question_sql_pairs(\n    question_sql_pairs: list[dict],\n    data_source: str,\n    mdl_json: dict,\n    connection_info: dict,\n) -> list[dict]:\n    tasks = []\n\n    async with aiohttp.ClientSession():\n        for question_sql_pair in question_sql_pairs:\n            task = asyncio.ensure_future(\n                is_sql_valid(\n                    question_sql_pair[\"sql\"],\n                    data_source,\n                    mdl_json,\n                    connection_info,\n                    WREN_ENGINE_ENDPOINT\n                    if data_source == \"duckdb\"\n                    else WREN_IBIS_ENDPOINT,\n                )\n            )\n            tasks.append(task)\n\n        results = await asyncio.gather(*tasks)\n        return [\n            {\n                **question_sql_pairs[i],\n                \"context\": [],\n                \"is_valid\": valid,\n                \"error\": error,\n            }\n            for i, (valid, error) in enumerate(results)\n        ]\n\n\nasync def get_contexts_from_sqls(\n    sqls: list[str],\n    mdl_json: dict,\n    api_endpoint: str = WREN_ENGINE_ENDPOINT,\n    timeout: float = TIMEOUT_SECONDS,\n) -> list[list[str]]:\n    async with aiohttp.ClientSession():\n        tasks = []\n        for sql in sqls:\n            task = asyncio.ensure_future(\n                get_contexts_from_sql(\n                    sql,\n                    mdl_json,\n                    api_endpoint,\n                    timeout,\n                )\n            )\n            tasks.append(task)\n\n        results = await asyncio.gather(*tasks)\n\n        return results\n\n\nasync def get_question_sql_pairs(\n    llm_client: AsyncClient,\n    llm_model: str,\n    mdl_json: dict,\n    custom_instructions: str,\n    data_source: str,\n    connection_info: dict,\n    num_pairs: int = 10,\n) -> list[dict]:\n    messages = [\n        {\n            \"role\": \"system\",\n            \"content\": \"\",\n        },\n        {\n            \"role\": \"user\",\n            \"content\": f\"\"\"\n### TASK ###\nGiven the database DDL, generate {num_pairs} of the questions and corresponding SQL queries.\n\n### Output Format ###\n{{\n    \"results\": [\n        {{\n            \"question\": <question_string>,\n            \"sql\": <sql_query_string>\n        }},\n        {{\n            \"question\": <question_string>,\n            \"sql\": <sql_query_string>\n        }},\n        ...\n    ]\n}}\n\n### Custom Instructions ###\n\n{custom_instructions}\n\n### Input ###\nData Model: {\"\\n\\n\".join(get_ddl_commands(mdl_json))}\n\nGenerate {num_pairs} of the questions and corresponding SQL queries according to the Output Format in JSON\nThink step by step\n\"\"\",\n        },\n    ]\n\n    try:\n        response = await llm_client.chat.completions.create(\n            model=llm_model,\n            messages=messages,\n            response_format={\"type\": \"json_object\"},\n            max_tokens=4096,\n            temperature=0,\n        )\n\n        results = orjson.loads(response.choices[0].message.content)[\"results\"]\n        question_sql_pairs = await get_validated_question_sql_pairs(\n            results,\n            data_source=data_source,\n            mdl_json=mdl_json,\n            connection_info=connection_info,\n        )\n        sqls = [question_sql_pair[\"sql\"] for question_sql_pair in question_sql_pairs]\n        contexts = await get_contexts_from_sqls(sqls, mdl_json)\n        documents = get_documents_given_contexts(contexts, mdl_json)\n        sqls_data = await get_data_from_wren_engine_with_sqls(\n            sqls,\n            data_source,\n            mdl_json,\n            connection_info,\n            WREN_ENGINE_ENDPOINT\n            if st.session_state[\"data_source\"] == \"duckdb\"\n            else WREN_IBIS_ENDPOINT,\n        )\n        return [\n            {\n                **quesiton_sql_pair,\n                \"context\": context,\n                \"data\": sql_data,\n                \"document\": document,\n            }\n            for quesiton_sql_pair, context, sql_data, document in zip(\n                question_sql_pairs, contexts, sqls_data, documents\n            )\n        ]\n    except Exception as e:\n        logger.error(e)\n        st.error(f\"Error generating question-sql-pairs: {e}\")\n        return []\n\n\ndef prettify_sql(sql: str) -> str:\n    return sqlparse.format(\n        sql,\n        reindent=True,\n        keyword_case=\"upper\",\n    )\n\n\nasync def get_data_from_wren_engine_with_sqls(\n    sqls: List[str],\n    data_source: str,\n    mdl_json: dict,\n    connection_info: dict,\n    api_endpoint: str,\n    timeout: float = TIMEOUT_SECONDS,\n) -> List[dict]:\n    assert data_source in DATA_SOURCES, f\"Invalid data source: {data_source}\"\n\n    async with aiohttp.ClientSession():\n        tasks = []\n        for sql in sqls:\n            task = asyncio.ensure_future(\n                get_data_from_wren_engine(\n                    sql=sql,\n                    mdl_json=mdl_json,\n                    api_endpoint=api_endpoint,\n                    data_source=data_source,\n                    connection_info=connection_info,\n                    timeout=timeout,\n                    limit=50,\n                )\n            )\n            tasks.append(task)\n\n        return await asyncio.gather(*tasks)\n\n\ndef remove_limit_statement(sql: str) -> str:\n    pattern = r\"\\s*LIMIT\\s+\\d+(\\s*;?\\s*--.*|\\s*;?\\s*)$\"\n    modified_sql = re.sub(pattern, \"\", sql, flags=re.IGNORECASE)\n\n    return modified_sql\n"
  },
  {
    "path": "wren-ai-service/eval/dataset/.gitignore",
    "content": "*\n!.gitignore"
  },
  {
    "path": "wren-ai-service/eval/dspy_modules/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/eval/dspy_modules/ask_generation.py",
    "content": "import dspy\n\n\nclass AskGenerationSignatureV1(dspy.Signature):\n    \"\"\"Given a user query that is ambiguous in nature, your task is to interpret the query in various plausible ways and \\\ngenerate three SQL statements that could potentially answer each interpreted version of the queries and within-10-words summary. \\\nProvide three different interpretations and corresponding SQL queries that reflect these interpretations. \\\nEnsure that your SQL queries are diverse, covering a range of possible meanings behind the ambiguous query. \\\n\nThe output should be in the following JSON format:\n\n{\n    \"results\": [\n        {\"sql\": <SQL_QUERY_STRING_1>, \"summary\": <SUMMARY_STRING_1>},\n        {\"sql\": <SQL_QUERY_STRING2>, \"summary\": <SUMMARY_STRING_2>},\n        {\"sql\": <SQL_QUERY_STRING3>, \"summary\": <SUMMARY_STRING_3>}\n    ]\n}\n\"\"\"\n\n    question = dspy.InputField()\n    context = dspy.InputField(description=\"List of database schema documents\")\n    answer = dspy.OutputField()\n\n\nclass AskGenerationV1(dspy.Module):\n    def __init__(self):\n        super().__init__()\n        self.generate_answer = dspy.ChainOfThought(AskGenerationSignatureV1)\n\n    def forward(self, question, context):\n        prediction = self.generate_answer(question=question, context=context)\n        return dspy.Prediction(context=context, answer=prediction.answer)\n"
  },
  {
    "path": "wren-ai-service/eval/dspy_modules/prompt_optimizer.py",
    "content": "import argparse\nimport os\nimport re\nimport sys\nfrom datetime import datetime\nfrom pathlib import Path\nfrom typing import Callable, Tuple\n\nimport dotenv\nimport dspy\nimport dspy.evaluate\nimport dspy.teleprompt\n\nsys.path.append(f\"{Path().parent.resolve()}\")\nimport src.utils as utils\nfrom eval.dspy_modules.ask_generation import AskGenerationV1\nfrom eval.utils import parse_toml\n\n\ndef parse_args() -> Tuple[str]:\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\n        \"--file\",\n        \"-F\",\n        type=str,\n        required=True,\n        help=\"Eval dataset file name in the eval/dataset folder\",\n    )\n    parser.add_argument(\n        \"--program_file\",\n        \"-P\",\n        type=str,\n        help=\"Optimized program file name in the eval/optimized folder\",\n    )\n    parser.add_argument(\n        \"--optimize\",\n        action=argparse.BooleanOptionalAction,\n        help=\"Whether to optimize the program or not\",\n    )\n    parser.add_argument(\n        \"--eval\",\n        action=argparse.BooleanOptionalAction,\n        help=\"Whether to evaluate the program or not based on the devset of eval dataset\",\n    )\n\n    return parser.parse_args()\n\n\noptimizer_parameters = {\n    \"evaluator\": None,\n    \"metrics\": None,\n    \"meta\": None,\n    \"predictions\": None,\n}\n\n\ndef configure_llm_provider(llm: str, api_key: str):\n    dspy.settings.configure(lm=dspy.LM(model=llm, api_key=api_key))\n\n\ndef clean_sql(sql: str) -> str:\n    return re.sub(\"[ \\t\\n]+\", \" \", sql)\n\n\ndef prepare_dataset(path: str, train_ratio: float = 0.5):\n    eval_dataset = parse_toml(f\"eval/dataset/{path}\")[\"eval_dataset\"]\n\n    dspy_dataset = []\n    for data in eval_dataset:\n        dspy_dataset.append(\n            dspy.Example(\n                context=[str(doc[\"content\"]) for doc in data[\"document\"]],\n                question=str(data[\"question\"]),\n                answer=clean_sql(str(data[\"sql\"])),\n            ).with_inputs(\"question\", \"context\")\n        )\n\n    train_size = int(len(dspy_dataset) * train_ratio)\n    _train = dspy_dataset[:train_size]\n    _dev = dspy_dataset[train_size:]\n    return _train, _dev\n\n\n# Validation logic: check that the predicted answer is correct.\n# Also check that the retrieved context does actually contain that answer.\ndef validate_context_and_answer(example, pred, trace=None):\n    if optimizer_parameters[\"predictions\"] is None:\n        # if we don't have metric from eval module, we use the default metric\n        answer_EM = dspy.evaluate.answer_exact_match(example, pred)\n        answer_PM = dspy.evaluate.answer_passage_match(example, pred)\n        return answer_EM and answer_PM\n    else:\n        prediction = optimizer_parameters[\"predictions\"][0]\n        prediction.input = example.question\n        prediction.expected_output = example.answer\n        prediction.context = example.context\n        prediction[\"type\"] = \"execution\"\n        prediction.actual_output = pred.answer\n        # reuse the first predict result to optimize the dspy module\n        optimizer_parameters[\"evaluator\"].eval(\n            optimizer_parameters[\"meta\"], [prediction]\n        )\n        sum_score = 0\n        for metric in optimizer_parameters[\"metrics\"].get(\"metrics\"):\n            sum_score += metric.score\n        return sum_score\n\n\ndef optimize(\n    module: dspy.Module,\n    optimizer: dspy.teleprompt.Teleprompter,\n    trainset: list,\n    metric: Callable,\n):\n    optimizer = optimizer(metric=metric)\n    return optimizer.compile(module(), trainset=trainset)\n\n\ndef build_optimizing_module(trainset):\n    module = optimize(\n        AskGenerationV1,\n        dspy.teleprompt.BootstrapFewShot,\n        trainset=trainset,\n        metric=validate_context_and_answer,\n    )\n    path = f\"eval/optimized/{AskGenerationV1.__name__}_optimized_{datetime.now().strftime(\"%Y_%m_%d_%H%M%S\")}.json\"\n    directory = os.path.dirname(path)\n    if directory and not os.path.exists(directory):\n        os.makedirs(directory)\n    module.save(path)\n    return module\n\n\nif __name__ == \"__main__\":\n    args = parse_args()\n    path = f\"eval/dataset/{args.file}\"\n    optimized_program_file = args.program_file\n    should_optimize = args.optimize\n    should_eval = args.eval\n\n    dotenv.load_dotenv()\n    utils.load_env_vars()\n\n    configure_llm_provider(os.getenv(\"GENERATION_MODEL\"), os.getenv(\"OPENAI_API_KEY\"))\n\n    trainset, devset = prepare_dataset(path)\n\n    if optimized_program_file:\n        module = AskGenerationV1()\n        module.load(f\"eval/optimized/{optimized_program_file}\")\n    elif should_optimize:\n        module = build_optimizing_module(trainset)\n    else:\n        module = AskGenerationV1()\n\n    if should_eval:\n        evaluator = dspy.evaluate.Evaluate(\n            devset=devset,\n            metric=validate_context_and_answer,\n            display_progress=True,\n            display_table=True,\n            return_outputs=True,\n        )\n\n        results = evaluator(\n            module,\n            metric=validate_context_and_answer,\n            display_progress=True,\n            display_table=True,\n            return_all_scores=True,\n            return_outputs=True,\n        )\n        for result in results:\n            if isinstance(result, list):\n                for item in result:\n                    if isinstance(item, tuple):\n                        if len(item) == 3:\n                            print(item[0])\n                            print(f\"Question: {item[0].get('question')}\")\n                            print(f\"Context: {item[0].get('context')}\")\n                            print(item[1])\n                            print(f\"Answer: {item[1].get('answer')}\")\n                            print(f\"Context: {item[1].get('context')}\")\n"
  },
  {
    "path": "wren-ai-service/eval/evaluation.py",
    "content": "import argparse\nimport sys\nfrom pathlib import Path\nfrom typing import Tuple\n\nfrom deepeval import evaluate\nfrom deepeval.evaluate import TestResult\nfrom deepeval.test_case import LLMTestCase\nfrom langfuse import Langfuse\nfrom langfuse.decorators import langfuse_context, observe\n\nsys.path.append(f\"{Path().parent.resolve()}\")\nimport traceback\n\nimport eval.pipelines as pipelines\nimport src.providers as provider\nfrom eval import EvalSettings\nfrom eval.utils import parse_toml, trace_metadata\nfrom src import utils\n\n\ndef formatter(prediction: dict, meta: dict) -> dict:\n    \"\"\"\n    Formats the prediction result to be used as evaluation input.\n\n    This function takes a prediction dictionary and a meta dictionary,\n    processes them to extract relevant information, and returns a formatted\n    dictionary that serves as input for evaluation. It includes details such\n    as input, actual and expected outputs, context, and additional metadata.\n\n    Args:\n        prediction (dict): A dictionary containing prediction details.\n        meta (dict): A dictionary containing metadata information.\n\n    Returns:\n        dict: A formatted dictionary containing evaluation input data.\n    \"\"\"\n    retrieval_context = [str(context) for context in prediction[\"retrieval_context\"]]\n    context = [str(context) for context in prediction[\"context\"]]\n    enable_spider_metrics = \"spider\" in meta.get(\"evaluation_dataset\", \"\").lower()\n    enable_rewrite = any(\n        dataset in meta.get(\"evaluation_dataset\", \"\").lower() for dataset in [\"spider\"]\n    )\n\n    return {\n        \"input\": prediction[\"input\"],\n        \"actual_output\": (\n            prediction.get(\"actual_output\", {})\n            .get(\"post_process\", {})\n            .get(\"valid_generation_result\", {})\n            .get(\"sql\", \"\")\n        ),\n        \"expected_output\": prediction[\"expected_output\"],\n        \"retrieval_context\": retrieval_context,\n        \"context\": context,\n        \"reasoning\": prediction.get(\"reasoning\", \"\"),\n        \"additional_metadata\": {\n            \"trace_id\": prediction[\"trace_id\"],\n            \"trace_url\": prediction[\"trace_url\"],\n            \"catalog\": meta.get(\"catalog\", None),\n            \"enable_spider_metrics\": enable_spider_metrics,\n            \"enable_rewrite\": enable_rewrite,\n        },\n    }\n\n\ndef parse_args() -> Tuple[str]:\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\n        \"--file\",\n        \"-F\",\n        type=str,\n        help=\"Eval the prediction result in the outputs/predictions directory\",\n    )\n    parser.add_argument(\n        \"--semantics\",\n        \"-S\",\n        default=False,\n        action=argparse.BooleanOptionalAction,\n        help=\"Whether use the LLM(OpenAI's gpt-4o-mini) to help check semantics of sqls to improve accuracy metrics\",\n    )\n    parser.add_argument(\n        \"--training-dataset\",\n        \"-T\",\n        default=None,\n        help=\"Use the training dataset to build a dspy optimized module\",\n    )\n    return parser.parse_args()\n\n\nclass Evaluator:\n    def __init__(self, metrics: list, **kwargs):\n        self._score_collector = {}\n        self._langfuse = Langfuse()\n        self._metrics = metrics\n        self._failed_count = 0\n        self._post_metrics = kwargs.get(\"post_metrics\", [])\n\n    def eval(self, meta: dict, predictions: list) -> None:\n        for prediction in predictions:\n            try:\n                test_case = LLMTestCase(**formatter(prediction, meta))\n                result = evaluate(\n                    [test_case], self._metrics, ignore_errors=True\n                ).test_results[0]\n                self._score_metrics(test_case, result)\n                [metric.collect(test_case, result) for metric in self._post_metrics]\n            except Exception:\n                self._failed_count += 1\n                traceback.print_exc()\n\n        self._average_score(meta)\n\n    def _score_metrics(self, test_case: LLMTestCase, result: TestResult) -> None:\n        for metric in result.metrics_data:\n            name = metric.name\n            score = metric.score or 0\n\n            self._langfuse.score(\n                trace_id=test_case.additional_metadata[\"trace_id\"],\n                name=name,\n                value=score,\n                comment=metric.reason or metric.error,\n                source=\"EVAL\",\n            )\n\n            if name not in self._score_collector:\n                self._score_collector[name] = []\n\n            self._score_collector[name].append(score)\n\n    @observe(name=\"Summary Trace\", capture_input=False, capture_output=False)\n    def _average_score(self, meta: dict) -> None:\n        langfuse_context.update_current_trace(\n            session_id=meta.get(\"session_id\"),\n            user_id=meta.get(\"user_id\"),\n            metadata=trace_metadata(meta, type=\"summary\"),\n        )\n\n        summary = {\n            \"query_count\": meta[\"query_count\"],\n            \"expected_batch_size\": meta[\"expected_batch_size\"],\n            \"actual_batch_size\": meta[\"actual_batch_size\"],\n            \"valid_eval_count\": meta[\"actual_batch_size\"] - self._failed_count,\n        }\n        langfuse_context.update_current_observation(output=summary)\n\n        for name, scores in self._score_collector.items():\n            langfuse_context.score_current_trace(\n                name=name,\n                value=sum(scores) / len(scores),\n                comment=f\"Average score for {name}\",\n            )\n\n        for metric in self._post_metrics:\n            langfuse_context.score_current_trace(\n                name=metric.__name__,\n                value=metric.measure(),\n                comment=f\"Average score for {metric.__name__}\",\n            )\n\n\nif __name__ == \"__main__\":\n    args = parse_args()\n\n    settings = EvalSettings()\n    pipe_components = provider.generate_components(settings.components)\n    utils.init_langfuse(settings)\n\n    predicted_file = parse_toml(f\"outputs/predictions/{args.file}\")\n    meta = predicted_file[\"meta\"]\n    predictions = predicted_file[\"predictions\"]\n\n    dataset = parse_toml(meta[\"evaluation_dataset\"])\n    metrics = pipelines.metrics_initiator(\n        meta[\"pipeline\"], dataset, pipe_components, args.semantics, settings\n    )\n\n    evaluator = Evaluator(**metrics)\n    evaluator.eval(meta, predictions)\n    # if args.training_dataset:\n    #     # todo: for now comment dspy related code\n    #     optimizer_parameters[\"evaluator\"] = evaluator\n    #     optimizer_parameters[\"metrics\"] = metrics\n    #     optimizer_parameters[\"meta\"] = meta\n    #     optimizer_parameters[\"predictions\"] = predictions\n    #     configure_llm_provider(\n    #         os.getenv(\"GENERATION_MODEL\"), os.getenv(\"OPENAI_API_KEY\")\n    #     )\n    #     trainset, devset = prepare_dataset(args.training_dataset)\n    #     build_optimizing_module(trainset)\n    # else:\n    #     evaluator.eval(meta, predictions)\n\n    langfuse_context.flush()\n\n    if meta[\"langfuse_url\"]:\n        print(\n            f\"\\n\\nYou can view the evaluation result in Langfuse at {meta['langfuse_url']}/sessions/{meta['session_id']}\"\n        )\n"
  },
  {
    "path": "wren-ai-service/eval/mdl_to_csv.py",
    "content": "import argparse\nimport csv\nfrom pathlib import Path\n\nimport orjson\n\n\ndef gen_eval_preparation_data_from_json_to_csv(mdl_path: str):\n    assert Path(mdl_path).exists(), f\"File not found: {mdl_path}\"\n\n    with open(mdl_path) as file:\n        mdl = orjson.loads(file.read())\n\n    csv_data = [\n        [\n            \"table\",\n            \"table alias\",\n            \"table description\",\n            \"column\",\n            \"column alias\",\n            \"column description\",\n        ]\n    ]\n    for model in mdl[\"models\"]:\n        for column in model[\"columns\"]:\n            csv_data.append(\n                [\n                    model[\"name\"],\n                    model.get(\"properties\", {}).get(\"displayName\", \"\"),\n                    model.get(\"properties\", {}).get(\"description\", \"\"),\n                    column[\"name\"],\n                    column.get(\"properties\", {}).get(\"displayName\", \"\"),\n                    column.get(\"properties\", {}).get(\"description\", \"\"),\n                ]\n            )\n\n    with open(f\"{Path(mdl_path).stem}.csv\", \"w\", newline=\"\\n\") as file:\n        writer = csv.writer(file, quoting=csv.QUOTE_MINIMAL)\n\n        for row in csv_data:\n            writer.writerow(row)\n\n\ndef gen_new_mdl_from_csv(mdl_path: str, csv_path: str):\n    assert Path(mdl_path).exists(), f\"File not found: {mdl_path}\"\n    assert Path(csv_path).exists(), f\"File not found: {csv_path}\"\n\n    with open(mdl_path) as file:\n        mdl = orjson.loads(file.read())\n\n    csv_data_by_table = {}\n\n    with open(csv_path, newline=\"\\n\") as file:\n        csv_data = csv.reader(file)\n\n        for row in csv_data:\n            model_name = row[0]\n            if model_name not in csv_data_by_table:\n                csv_data_by_table[model_name] = {\n                    \"model\": {\n                        \"displayName\": row[1],\n                        \"description\": row[2],\n                    },\n                    \"columns\": {},\n                }\n\n            csv_data_by_table[model_name][\"columns\"][row[3]] = {\n                \"displayName\": row[4],\n                \"description\": row[5],\n            }\n\n        new_models = []\n        for model in mdl[\"models\"]:\n            if model[\"name\"] in csv_data_by_table:\n                if \"properties\" not in model:\n                    model[\"properties\"] = {}\n                if csv_data_by_table[model[\"name\"]][\"model\"][\"displayName\"]:\n                    model[\"properties\"][\"displayName\"] = csv_data_by_table[\n                        model[\"name\"]\n                    ][\"model\"][\"displayName\"]\n                if csv_data_by_table[model[\"name\"]][\"model\"][\"description\"]:\n                    model[\"properties\"][\"description\"] = csv_data_by_table[\n                        model[\"name\"]\n                    ][\"model\"][\"description\"]\n\n                new_columns = []\n                for column in model[\"columns\"]:\n                    if column[\"name\"] in csv_data_by_table[model[\"name\"]][\"columns\"]:\n                        if \"properties\" not in column:\n                            column[\"properties\"] = {}\n                        if csv_data_by_table[model[\"name\"]][\"columns\"][column[\"name\"]][\n                            \"displayName\"\n                        ]:\n                            column[\"properties\"][\"displayName\"] = csv_data_by_table[\n                                model[\"name\"]\n                            ][\"columns\"][column[\"name\"]][\"displayName\"]\n                        if csv_data_by_table[model[\"name\"]][\"columns\"][column[\"name\"]][\n                            \"description\"\n                        ]:\n                            column[\"properties\"][\"description\"] = csv_data_by_table[\n                                model[\"name\"]\n                            ][\"columns\"][column[\"name\"]][\"description\"]\n                        new_columns.append(column)\n\n                model[\"columns\"] = new_columns\n                new_models.append(model)\n\n        mdl[\"models\"] = new_models\n\n    with open(f\"{Path(mdl_path).stem}_new.json\", \"w\") as file:\n        file.write(orjson.dumps(mdl).decode())\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\n        \"--mdl-path\", type=str, help=\"Path to the MDL JSON file\", required=True\n    )\n    parser.add_argument(\"--csv-path\", type=str, help=\"Path to the input CSV file\")\n    args = parser.parse_args()\n\n    if args.mdl_path and not args.csv_path:\n        gen_eval_preparation_data_from_json_to_csv(args.mdl_path)\n    elif args.mdl_path and args.csv_path:\n        gen_new_mdl_from_csv(args.mdl_path, args.csv_path)\n"
  },
  {
    "path": "wren-ai-service/eval/metrics/__init__.py",
    "content": "from .accuracy import AccuracyMetric, AccuracyMultiCandidateMetric\nfrom .answer_relevancy import AnswerRelevancyMetric\nfrom .context_precision import ContextualPrecisionMetric\nfrom .context_recall import ContextualRecallMetric\nfrom .context_relevancy import ContextualRelevancyMetric\nfrom .faithfulness import FaithfulnessMetric\nfrom .llm import (\n    QuestionToReasoningJudge,\n    ReasoningToSqlJudge,\n    SqlSemanticsJudge,\n)\nfrom .spider.exact_match import ExactMatchAccuracy\nfrom .spider.exec_match import ExecutionAccuracy\n\n__all__ = [\n    \"AccuracyMetric\",\n    \"AccuracyMultiCandidateMetric\",\n    \"AnswerRelevancyMetric\",\n    \"ContextualPrecisionMetric\",\n    \"ContextualRecallMetric\",\n    \"ContextualRelevancyMetric\",\n    \"FaithfulnessMetric\",\n    \"ExactMatchAccuracy\",\n    \"ExecutionAccuracy\",\n    \"QuestionToReasoningJudge\",\n    \"ReasoningToSqlJudge\",\n    \"SqlSemanticsJudge\",\n]\n"
  },
  {
    "path": "wren-ai-service/eval/metrics/accuracy.py",
    "content": "import asyncio\nimport re\nimport traceback\n\nimport orjson\nimport pandas as pd\nfrom deepeval.evaluate import TestResult\nfrom deepeval.metrics import BaseMetric\nfrom deepeval.test_case import LLMTestCase\nfrom deprecated import deprecated\n\nfrom eval.utils import get_data_from_wren_engine, get_openai_client\n\n\nclass AccuracyMetric(BaseMetric):\n    def __init__(self, engine_info: dict, enable_semantics_comparison: bool = False):\n        self.threshold = 0\n        self.score = 0\n        self.engine_info = engine_info\n        self.enable_semantics_comparison = enable_semantics_comparison\n        if self.enable_semantics_comparison:\n            self._openai_client = get_openai_client()\n\n    def measure(self, test_case: LLMTestCase):\n        return asyncio.run(self.a_measure(test_case))\n\n    def _is_subset(self, expected: pd.DataFrame, actual: pd.DataFrame) -> bool:\n        if not set(expected.columns).issubset(set(actual.columns)):\n            return False\n\n        common_columns = sorted(expected.columns)\n\n        expected_sorted = expected[common_columns]\n        actual_sorted = actual[common_columns]\n        # Ensure that the data types are the same\n        actual_sorted = actual_sorted.astype(expected_sorted.dtypes.to_dict())\n\n        merged = pd.merge(\n            actual_sorted,\n            expected_sorted,\n            on=common_columns,\n            how=\"left\",\n            indicator=True,\n        )\n        return all(merged[\"_merge\"] == \"both\")\n\n    def _count_partial_matches(\n        self, expected: pd.DataFrame, actual: pd.DataFrame\n    ) -> int:\n        intersection = set(expected.columns).intersection(set(actual.columns))\n        common_columns = sorted(intersection)\n        if not common_columns:\n            return 0\n\n        expected_sorted = expected[common_columns]\n        actual_sorted = actual[common_columns]\n        # Ensure that the data types are the same\n        actual_sorted = actual_sorted.astype(expected_sorted.dtypes.to_dict())\n\n        merged = pd.merge(\n            actual_sorted,\n            expected_sorted,\n            on=common_columns,\n            how=\"left\",\n            indicator=True,\n        )\n        if all(merged[\"_merge\"] == \"both\"):\n            return len(intersection) / len(expected.columns)\n        else:\n            return 0\n\n    def _rewrite_sql(self, sql: str) -> str:\n        # Pattern to match double quotes after WHERE clause, including multiple occurrences\n        pattern = r'(WHERE\\s+.*?)(\")(.+?)(\")(.*)$'\n        replacement = r\"\\1'\\3'\\5\"\n\n        # Apply the replacement repeatedly until no more changes\n        new_sql = re.sub(pattern, replacement, sql, flags=re.IGNORECASE | re.DOTALL)\n        while new_sql != sql:\n            sql = new_sql\n            new_sql = re.sub(pattern, replacement, sql, flags=re.IGNORECASE | re.DOTALL)\n\n        return sql\n\n    async def _retrieve_data(self, sql: str) -> pd.DataFrame:\n        response = await get_data_from_wren_engine(sql=sql, **self.engine_info)\n\n        df = pd.DataFrame(**response)\n        sorted_columns = sorted(df.columns)\n        return df[sorted_columns].sort_values(by=sorted_columns)\n\n    async def _check_sql_semantics(self, expected_sql: str, actual_sql: str):\n        _system_prompt = (\n            \"### TASK ### \\n\"\n            + \"You are a great data anlyst, please carefully check the semantics of two given SQLs if they are the same. \\n\"\n            + \"The output should be a JSON format with the following schema: \\n\"\n            + \"{ \\n\"\n            + '   \"reasoning\": <REASONING_STRING> \\n'\n            + '   \"same\": <BOOL> \\n'\n            + \"}\"\n        )\n\n        _user_prompt = (\n            \"### QUESTION ### \\n\"\n            + f\"Expected SQL: {expected_sql} \\n\"\n            + f\"Actual SQL: {actual_sql} \\n\"\n            + \"\\n\"\n            + \"Please think step by step\"\n        )\n\n        response = await self._openai_client.chat.completions.create(\n            model=\"gpt-4o-mini\",\n            messages=[\n                {\"role\": \"system\", \"content\": _system_prompt},\n                {\"role\": \"user\", \"content\": _user_prompt},\n            ],\n            response_format={\"type\": \"json_object\"},\n        )\n\n        print(\n            f\"response of _check_sql_semantics: {response.choices[0].message.content}\"\n        )\n\n        return 1 if orjson.loads(response.choices[0].message.content)[\"same\"] else 0\n\n    async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):\n        try:\n            enable_rewrite = test_case.additional_metadata.get(\"enable_rewrite\", False)\n            rewritten_expected_output = test_case.expected_output\n\n            if enable_rewrite:\n                rewritten_expected_output = self._rewrite_sql(test_case.expected_output)\n\n            expected_dataset = await self._retrieve_data(rewritten_expected_output)\n            actual_dataset = await self._retrieve_data(test_case.actual_output)\n\n            print(f\"expected columns: {set(expected_dataset.columns)}\")\n            print(f\"actual columns: {set(actual_dataset.columns)}\")\n\n            if expected_dataset.equals(actual_dataset) or self._is_subset(\n                expected_dataset, actual_dataset\n            ):\n                self.success = True\n                self.score = 1\n                return self.score\n\n            self.score = self._count_partial_matches(expected_dataset, actual_dataset)\n            # use llm to check sql semantics\n            if self.score == 0 and self.enable_semantics_comparison:\n                # TODO: we may need to upload the sql semantics result to langfuse\n                print(f\"before _check_sql_semantics: {self.score}\")\n                print(f\"expected sql: {rewritten_expected_output}\")\n                print(f\"actual sql: {test_case.actual_output}\")\n                self.score = await self._check_sql_semantics(\n                    rewritten_expected_output, test_case.actual_output\n                )\n                print(f\"after _check_sql_semantics: {self.score}\")\n        except Exception as e:\n            self.error = f\"Error occurred while evaluating the metric: {e}\"\n            traceback.print_exc()\n\n        # if didn't pass any of the above checks\n        self.success = False\n        return self.score\n\n    def is_successful(self):\n        return self.success\n\n    @property\n    def __name__(self):\n        return \"Accuracy(column-based)\"\n\n\n@deprecated(\n    reason=\"We don't generate multiple candidates for Text to SQL task, so don't need this metric\"\n)\nclass AccuracyMultiCandidateMetric(BaseMetric):\n    def __init__(self):\n        self.threshold = 0\n        self.score = 0\n        self._questions = {}\n\n    def collect(self, test_case: LLMTestCase, result: TestResult):\n        for metric in result.metrics_data:\n            if metric.name != \"Accuracy(column-based)\":\n                continue\n\n            # or 0 to avoid when metric.error is exist\n            self._questions[test_case.input] = (\n                self._questions.get(test_case.input, 0) or metric.score or 0\n            )\n\n    def measure(self):\n        if not self._questions:\n            return 0\n        self.score = sum(self._questions.values()) / len(self._questions)\n        self.success = self.score >= self.threshold\n        return self.score\n\n    def is_successful(self):\n        return self.success\n\n    @property\n    def __name__(self):\n        return \"Accuracy(question-based)\"\n"
  },
  {
    "path": "wren-ai-service/eval/metrics/answer_relevancy.py",
    "content": "import asyncio\n\nfrom deepeval.metrics import BaseMetric\nfrom deepeval.test_case import LLMTestCase\n\nfrom eval.utils import get_contexts_from_sql\n\n\nclass AnswerRelevancyMetric(BaseMetric):\n    def __init__(self, engine_info: dict):\n        self.threshold = 0\n        self.score = 0\n        self.engine_info = engine_info\n\n    def measure(self, test_case: LLMTestCase):\n        return asyncio.run(self.a_measure(test_case))\n\n    async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):\n        actual_units = await get_contexts_from_sql(\n            sql=test_case.actual_output, **self.engine_info\n        )\n\n        expected_units = await get_contexts_from_sql(\n            sql=test_case.expected_output, **self.engine_info\n        )\n\n        intersection = set(actual_units) & set(expected_units)\n        self.score = len(intersection) / len(actual_units)\n\n        self.success = self.score >= self.threshold\n        return self.score\n\n    def is_successful(self):\n        return self.success\n\n    @property\n    def __name__(self):\n        return \"AnswerRelevancy(column-based)\"\n"
  },
  {
    "path": "wren-ai-service/eval/metrics/context_precision.py",
    "content": "import asyncio\n\nfrom deepeval.metrics import BaseMetric\nfrom deepeval.test_case import LLMTestCase\n\n\nclass ContextualPrecisionMetric(BaseMetric):\n    def __init__(self):\n        self.threshold = 0\n        self.score = 0\n\n    def measure(self, test_case: LLMTestCase):\n        return asyncio.run(self.a_measure(test_case))\n\n    async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):\n        context = test_case.context\n        retrieval_context = test_case.retrieval_context\n\n        intersection = set(context) & set(retrieval_context)\n        intersection_count = len(intersection)\n\n        if intersection_count == 0:\n            self.success = False\n            return self.score\n\n        n = len(retrieval_context)\n        summation = 0\n        for k in range(1, n + 1):\n            intersection_up_to_k = len(set(context[:k]) & set(retrieval_context[:k]))\n            rk = len(set(context[:k]) & set(retrieval_context[k - 1 : k])) > 0\n            summation += (intersection_up_to_k / k) * rk\n\n        self.score = (1 / intersection_count) * summation\n\n        self.success = self.score >= self.threshold\n        return self.score\n\n    def is_successful(self):\n        return self.success\n\n    @property\n    def __name__(self):\n        return \"ContextualPrecision(column-based)\"\n"
  },
  {
    "path": "wren-ai-service/eval/metrics/context_recall.py",
    "content": "import asyncio\n\nfrom deepeval.metrics import BaseMetric\nfrom deepeval.test_case import LLMTestCase\n\nfrom eval.utils import get_contexts_from_sql\n\n\nclass ContextualRecallMetric(BaseMetric):\n    def __init__(self, engine_info: dict):\n        self.threshold = 0\n        self.score = 0\n        self.engine_info = engine_info\n\n    def measure(self, test_case: LLMTestCase):\n        return asyncio.run(self.a_measure(test_case))\n\n    async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):\n        expected_units = await get_contexts_from_sql(\n            sql=test_case.expected_output, **self.engine_info\n        )\n\n        intersection = set(test_case.retrieval_context) & set(expected_units)\n        self.score = len(intersection) / len(expected_units)\n\n        self.success = self.score >= self.threshold\n        return self.score\n\n    def is_successful(self):\n        return self.success\n\n    @property\n    def __name__(self):\n        return \"ContextualRecall(column-based)\"\n"
  },
  {
    "path": "wren-ai-service/eval/metrics/context_relevancy.py",
    "content": "import asyncio\n\nfrom deepeval.metrics import BaseMetric\nfrom deepeval.test_case import LLMTestCase\n\n\nclass ContextualRelevancyMetric(BaseMetric):\n    def __init__(self):\n        self.threshold = 0\n        self.score = 0\n\n    def measure(self, test_case: LLMTestCase):\n        return asyncio.run(self.a_measure(test_case))\n\n    async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):\n        intersection = set(test_case.retrieval_context) & set(test_case.context)\n        self.score = len(intersection) / len(test_case.retrieval_context)\n\n        self.success = self.score >= self.threshold\n        return self.score\n\n    def is_successful(self):\n        return self.success\n\n    @property\n    def __name__(self):\n        return \"ContextualRelevancy(column-based)\"\n"
  },
  {
    "path": "wren-ai-service/eval/metrics/faithfulness.py",
    "content": "import asyncio\n\nfrom deepeval.metrics import BaseMetric\nfrom deepeval.test_case import LLMTestCase\n\nfrom eval.utils import get_contexts_from_sql\n\n\nclass FaithfulnessMetric(BaseMetric):\n    def __init__(self, engine_info: dict):\n        self.threshold = 0\n        self.score = 0\n        self.engine_info = engine_info\n\n    def measure(self, test_case: LLMTestCase):\n        return asyncio.run(self.a_measure(test_case))\n\n    async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):\n        actual_units = await get_contexts_from_sql(\n            sql=test_case.actual_output, **self.engine_info\n        )\n        intersection = set(actual_units) & set(test_case.retrieval_context)\n        self.score = len(intersection) / len(actual_units)\n\n        self.success = self.score >= self.threshold\n        return self.score\n\n    def is_successful(self):\n        return self.success\n\n    @property\n    def __name__(self):\n        return \"Faithfulness(column-based)\"\n"
  },
  {
    "path": "wren-ai-service/eval/metrics/llm/__init__.py",
    "content": "import asyncio\n\nfrom deepeval.metrics import BaseMetric\nfrom deepeval.test_case import LLMTestCase\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom pydantic import BaseModel\n\nfrom src.providers import LLMProvider\n\n\nclass EvalResult(BaseModel):\n    score: float\n    reason: str\n\n\n_MODEL_KWARGS = {\n    \"response_format\": {\n        \"type\": \"json_schema\",\n        \"json_schema\": {\n            \"name\": \"eval_result\",\n            \"schema\": EvalResult.model_json_schema(),\n        },\n    }\n}\n\n\ndef format(response: dict) -> EvalResult:\n    reply = response.get(\"replies\", [])[0]\n    return EvalResult.model_validate_json(reply)\n\n\nclass QuestionToReasoningJudge(BaseMetric):\n    _system_prompt = \"\"\"\n    You are an expert evaluator. Your task is to analyze the reasoning provided for a given question and determine if it makes sense. \n    Provide a score in the range 0.0~1.0 and a detailed explanation for your evaluation.\n    \"\"\"\n    _test_case_prompt = \"\"\"\n    Question: \n    {{ question }}\n    \n    Reasoning:\n    {{ reasoning }}\n    \"\"\"\n\n    def __init__(self, llm_provider: LLMProvider, **_):\n        self.threshold = 0\n        self.score = 0\n        self.llm_provider = llm_provider\n        self.llm = llm_provider.get_generator(\n            system_prompt=self._system_prompt,\n            generation_kwargs=_MODEL_KWARGS,\n        )\n        self.prompt_builder = PromptBuilder(template=self._test_case_prompt)\n\n    def measure(self, test_case: LLMTestCase):\n        return asyncio.run(self.a_measure(test_case))\n\n    async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):\n        prompt = self.prompt_builder.run(\n            question=test_case.input,\n            reasoning=test_case.reasoning,\n        )\n        response = await self.llm(prompt.get(\"prompt\"))\n        result = format(response)\n\n        self.score = result.score\n        self.reason = result.reason\n\n        self.success = self.score >= self.threshold\n        return self.score\n\n    def is_successful(self):\n        return self.success\n\n    @property\n    def __name__(self):\n        return \"QuestionToReasoningJudge\"\n\n\nclass ReasoningToSqlJudge(BaseMetric):\n    _system_prompt = \"\"\"\n    You are an expert evaluator. Your task is to analyze the reasoning provided for a given SQL query and determine if it makes sense. \n    Provide a score in the range 0.0~1.0 and a detailed explanation for your evaluation.\n    \"\"\"\n    _test_case_prompt = \"\"\"\n    Actual Output: \n    {{ actual_output }}\n\n    Reasoning:\n    {{ reasoning }}\n    \"\"\"\n\n    def __init__(self, llm_provider: LLMProvider, **_):\n        self.threshold = 0\n        self.score = 0\n        self.llm_provider = llm_provider\n        self.llm = llm_provider.get_generator(\n            system_prompt=self._system_prompt,\n            generation_kwargs=_MODEL_KWARGS,\n        )\n        self.prompt_builder = PromptBuilder(template=self._test_case_prompt)\n\n    def measure(self, test_case: LLMTestCase):\n        return asyncio.run(self.a_measure(test_case))\n\n    async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):\n        prompt = self.prompt_builder.run(\n            actual_output=test_case.actual_output,\n            reasoning=test_case.reasoning,\n        )\n        response = await self.llm(prompt.get(\"prompt\"))\n        result = format(response)\n\n        self.score = result.score\n        self.reason = result.reason\n\n        self.success = self.score >= self.threshold\n        return self.score\n\n    def is_successful(self):\n        return self.success\n\n    @property\n    def __name__(self):\n        return \"ReasoningToSqlJudge\"\n\n\nclass SqlSemanticsJudge(BaseMetric):\n    _system_prompt = \"\"\"\n    You are an expert evaluator. Your task is to analyze the actual SQL query and the expected SQL query and determine if they are semantically equivalent. \n    Provide a score in the range 0.0~1.0 and a detailed explanation for your evaluation.\n    \"\"\"\n    _test_case_prompt = \"\"\"\n    Actual SQL: \n    {{ actual_sql }}\n\n    Expected SQL: \n    {{ expected_sql }}\n    \"\"\"\n\n    def __init__(self, llm_provider: LLMProvider, **_):\n        self.threshold = 0\n        self.score = 0\n        self.llm_provider = llm_provider\n        self.llm = llm_provider.get_generator(\n            system_prompt=self._system_prompt,\n            generation_kwargs=_MODEL_KWARGS,\n        )\n        self.prompt_builder = PromptBuilder(template=self._test_case_prompt)\n\n    def measure(self, test_case: LLMTestCase):\n        return asyncio.run(self.a_measure(test_case))\n\n    async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):\n        prompt = self.prompt_builder.run(\n            actual_sql=test_case.actual_output,\n            expected_sql=test_case.expected_output,\n        )\n        response = await self.llm(prompt.get(\"prompt\"))\n        result = format(response)\n\n        self.score = result.score\n        self.reason = result.reason\n\n        self.success = self.score >= self.threshold\n        return self.score\n\n    def is_successful(self):\n        return self.success\n\n    @property\n    def __name__(self):\n        return \"SqlSemanticsJudge\"\n"
  },
  {
    "path": "wren-ai-service/eval/metrics/spider/__init__.py",
    "content": "import asyncio\nimport itertools\nimport os\nimport random\nimport re\nimport sqlite3\nfrom collections import defaultdict\nfrom itertools import chain, product\nfrom typing import Any, Iterator, List, Set, Tuple\n\nimport sqlparse\nimport tqdm\n\nfrom eval.metrics.spider.process_sql import get_sql\n\n# Flag to disable value evaluation\nDISABLE_VALUE = True\n# Flag to disable distinct in select evaluation\nDISABLE_DISTINCT = True\n\nTABLE_TYPE = {\n    \"sql\": \"sql\",\n    \"table_unit\": \"table_unit\",\n}\n\n\nWHERE_OPS = (\n    \"not\",\n    \"between\",\n    \"=\",\n    \">\",\n    \"<\",\n    \">=\",\n    \"<=\",\n    \"!=\",\n    \"in\",\n    \"like\",\n    \"is\",\n    \"exists\",\n)\n\n\ndef get_scores(count, pred_total, label_total):\n    if pred_total != label_total:\n        return 0, 0, 0\n    elif count == pred_total:\n        return 1, 1, 1\n    return 0, 0, 0\n\n\ndef eval_sel(pred, label):\n    pred_sel = pred[\"select\"][1]\n    label_sel = label[\"select\"][1]\n    label_wo_agg = [unit[1] for unit in label_sel]\n    pred_total = len(pred_sel)\n    label_total = len(label_sel)\n    cnt = 0\n    cnt_wo_agg = 0\n\n    for unit in pred_sel:\n        if unit in label_sel:\n            cnt += 1\n            label_sel.remove(unit)\n        if unit[1] in label_wo_agg:\n            cnt_wo_agg += 1\n            label_wo_agg.remove(unit[1])\n\n    return label_total, pred_total, cnt, cnt_wo_agg\n\n\ndef eval_where(pred, label):\n    pred_conds = [unit for unit in pred[\"where\"][::2]]\n    label_conds = [unit for unit in label[\"where\"][::2]]\n    label_wo_agg = [unit[2] for unit in label_conds]\n    pred_total = len(pred_conds)\n    label_total = len(label_conds)\n    cnt = 0\n    cnt_wo_agg = 0\n\n    for unit in pred_conds:\n        if unit in label_conds:\n            cnt += 1\n            label_conds.remove(unit)\n        if unit[2] in label_wo_agg:\n            cnt_wo_agg += 1\n            label_wo_agg.remove(unit[2])\n\n    return label_total, pred_total, cnt, cnt_wo_agg\n\n\ndef eval_group(pred, label):\n    pred_cols = [unit[1] for unit in pred[\"groupBy\"]]\n    label_cols = [unit[1] for unit in label[\"groupBy\"]]\n    pred_total = len(pred_cols)\n    label_total = len(label_cols)\n    cnt = 0\n    pred_cols = [pred.split(\".\")[1] if \".\" in pred else pred for pred in pred_cols]\n    label_cols = [\n        label.split(\".\")[1] if \".\" in label else label for label in label_cols\n    ]\n    for col in pred_cols:\n        if col in label_cols:\n            cnt += 1\n            label_cols.remove(col)\n    return label_total, pred_total, cnt\n\n\ndef eval_having(pred, label):\n    pred_total = label_total = cnt = 0\n    if len(pred[\"groupBy\"]) > 0:\n        pred_total = 1\n    if len(label[\"groupBy\"]) > 0:\n        label_total = 1\n\n    pred_cols = [unit[1] for unit in pred[\"groupBy\"]]\n    label_cols = [unit[1] for unit in label[\"groupBy\"]]\n    if (\n        pred_total == label_total == 1\n        and pred_cols == label_cols\n        and pred[\"having\"] == label[\"having\"]\n    ):\n        cnt = 1\n\n    return label_total, pred_total, cnt\n\n\ndef eval_order(pred, label):\n    pred_total = label_total = cnt = 0\n    if len(pred[\"orderBy\"]) > 0:\n        pred_total = 1\n    if len(label[\"orderBy\"]) > 0:\n        label_total = 1\n    if (\n        len(label[\"orderBy\"]) > 0\n        and pred[\"orderBy\"] == label[\"orderBy\"]\n        and (\n            (pred[\"limit\"] is None and label[\"limit\"] is None)\n            or (pred[\"limit\"] is not None and label[\"limit\"] is not None)\n        )\n    ):\n        cnt = 1\n    return label_total, pred_total, cnt\n\n\ndef eval_and_or(pred, label):\n    pred_ao = pred[\"where\"][1::2]\n    label_ao = label[\"where\"][1::2]\n    pred_ao = set(pred_ao)\n    label_ao = set(label_ao)\n\n    if pred_ao == label_ao:\n        return 1, 1, 1\n    return len(pred_ao), len(label_ao), 0\n\n\ndef get_nestedSQL(sql):\n    nested = []\n    for cond_unit in sql[\"from\"][\"conds\"][::2] + sql[\"where\"][::2] + sql[\"having\"][::2]:\n        if isinstance(cond_unit[3], dict):\n            nested.append(cond_unit[3])\n        if isinstance(cond_unit[4], dict):\n            nested.append(cond_unit[4])\n    if sql[\"intersect\"] is not None:\n        nested.append(sql[\"intersect\"])\n    if sql[\"except\"] is not None:\n        nested.append(sql[\"except\"])\n    if sql[\"union\"] is not None:\n        nested.append(sql[\"union\"])\n    return nested\n\n\ndef eval_nested(pred, label):\n    label_total = 0\n    pred_total = 0\n    cnt = 0\n    if pred is not None:\n        pred_total += 1\n    if label is not None:\n        label_total += 1\n    if pred is not None and label is not None:\n        cnt += Evaluator().eval_exact_match(pred, label)\n    return label_total, pred_total, cnt\n\n\ndef eval_IUEN(pred, label):\n    lt1, pt1, cnt1 = eval_nested(pred[\"intersect\"], label[\"intersect\"])\n    lt2, pt2, cnt2 = eval_nested(pred[\"except\"], label[\"except\"])\n    lt3, pt3, cnt3 = eval_nested(pred[\"union\"], label[\"union\"])\n    label_total = lt1 + lt2 + lt3\n    pred_total = pt1 + pt2 + pt3\n    cnt = cnt1 + cnt2 + cnt3\n    return label_total, pred_total, cnt\n\n\ndef get_keywords(sql):\n    res = set()\n    if len(sql[\"where\"]) > 0:\n        res.add(\"where\")\n    if len(sql[\"groupBy\"]) > 0:\n        res.add(\"group\")\n    if len(sql[\"having\"]) > 0:\n        res.add(\"having\")\n    if len(sql[\"orderBy\"]) > 0:\n        res.add(sql[\"orderBy\"][0])\n        res.add(\"order\")\n    if sql[\"limit\"] is not None:\n        res.add(\"limit\")\n    if sql[\"except\"] is not None:\n        res.add(\"except\")\n    if sql[\"union\"] is not None:\n        res.add(\"union\")\n    if sql[\"intersect\"] is not None:\n        res.add(\"intersect\")\n\n    # or keyword\n    ao = sql[\"from\"][\"conds\"][1::2] + sql[\"where\"][1::2] + sql[\"having\"][1::2]\n    if len([token for token in ao if token == \"or\"]) > 0:\n        res.add(\"or\")\n\n    cond_units = sql[\"from\"][\"conds\"][::2] + sql[\"where\"][::2] + sql[\"having\"][::2]\n    # not keyword\n    if len([cond_unit for cond_unit in cond_units if cond_unit[0]]) > 0:\n        res.add(\"not\")\n\n    # in keyword\n    if (\n        len(\n            [\n                cond_unit\n                for cond_unit in cond_units\n                if cond_unit[1] == WHERE_OPS.index(\"in\")\n            ]\n        )\n        > 0\n    ):\n        res.add(\"in\")\n\n    # like keyword\n    if (\n        len(\n            [\n                cond_unit\n                for cond_unit in cond_units\n                if cond_unit[1] == WHERE_OPS.index(\"like\")\n            ]\n        )\n        > 0\n    ):\n        res.add(\"like\")\n\n    return res\n\n\ndef eval_keywords(pred, label):\n    pred_keywords = get_keywords(pred)\n    label_keywords = get_keywords(label)\n    pred_total = len(pred_keywords)\n    label_total = len(label_keywords)\n    cnt = 0\n\n    for k in pred_keywords:\n        if k in label_keywords:\n            cnt += 1\n    return label_total, pred_total, cnt\n\n\nclass Evaluator:\n    def eval_exact_match(self, pred: dict, label: dict):\n        partial_scores = self.eval_partial_match(pred, label)\n\n        for key, score in partial_scores.items():\n            if score[\"f1\"] != 1:\n                return 0\n\n        if len(label[\"from\"][\"table_units\"]) > 0:\n            label_tables = sorted(label[\"from\"][\"table_units\"])\n            pred_tables = sorted(pred[\"from\"][\"table_units\"])\n            return label_tables == pred_tables\n        return 1\n\n    def eval_partial_match(self, pred, label):\n        res = {}\n\n        label_total, pred_total, cnt, cnt_wo_agg = eval_sel(pred, label)\n        acc, rec, f1 = get_scores(cnt, pred_total, label_total)\n        res[\"select\"] = {\n            \"acc\": acc,\n            \"rec\": rec,\n            \"f1\": f1,\n            \"label_total\": label_total,\n            \"pred_total\": pred_total,\n        }\n        acc, rec, f1 = get_scores(cnt_wo_agg, pred_total, label_total)\n        res[\"select(no AGG)\"] = {\n            \"acc\": acc,\n            \"rec\": rec,\n            \"f1\": f1,\n            \"label_total\": label_total,\n            \"pred_total\": pred_total,\n        }\n\n        label_total, pred_total, cnt, cnt_wo_agg = eval_where(pred, label)\n        acc, rec, f1 = get_scores(cnt, pred_total, label_total)\n        res[\"where\"] = {\n            \"acc\": acc,\n            \"rec\": rec,\n            \"f1\": f1,\n            \"label_total\": label_total,\n            \"pred_total\": pred_total,\n        }\n        acc, rec, f1 = get_scores(cnt_wo_agg, pred_total, label_total)\n        res[\"where(no OP)\"] = {\n            \"acc\": acc,\n            \"rec\": rec,\n            \"f1\": f1,\n            \"label_total\": label_total,\n            \"pred_total\": pred_total,\n        }\n\n        label_total, pred_total, cnt = eval_group(pred, label)\n        acc, rec, f1 = get_scores(cnt, pred_total, label_total)\n        res[\"group(no Having)\"] = {\n            \"acc\": acc,\n            \"rec\": rec,\n            \"f1\": f1,\n            \"label_total\": label_total,\n            \"pred_total\": pred_total,\n        }\n\n        label_total, pred_total, cnt = eval_having(pred, label)\n        acc, rec, f1 = get_scores(cnt, pred_total, label_total)\n        res[\"group\"] = {\n            \"acc\": acc,\n            \"rec\": rec,\n            \"f1\": f1,\n            \"label_total\": label_total,\n            \"pred_total\": pred_total,\n        }\n\n        label_total, pred_total, cnt = eval_order(pred, label)\n        acc, rec, f1 = get_scores(cnt, pred_total, label_total)\n        res[\"order\"] = {\n            \"acc\": acc,\n            \"rec\": rec,\n            \"f1\": f1,\n            \"label_total\": label_total,\n            \"pred_total\": pred_total,\n        }\n\n        label_total, pred_total, cnt = eval_and_or(pred, label)\n        acc, rec, f1 = get_scores(cnt, pred_total, label_total)\n        res[\"and/or\"] = {\n            \"acc\": acc,\n            \"rec\": rec,\n            \"f1\": f1,\n            \"label_total\": label_total,\n            \"pred_total\": pred_total,\n        }\n\n        label_total, pred_total, cnt = eval_IUEN(pred, label)\n        acc, rec, f1 = get_scores(cnt, pred_total, label_total)\n        res[\"IUEN\"] = {\n            \"acc\": acc,\n            \"rec\": rec,\n            \"f1\": f1,\n            \"label_total\": label_total,\n            \"pred_total\": pred_total,\n        }\n\n        label_total, pred_total, cnt = eval_keywords(pred, label)\n        acc, rec, f1 = get_scores(cnt, pred_total, label_total)\n        res[\"keywords\"] = {\n            \"acc\": acc,\n            \"rec\": rec,\n            \"f1\": f1,\n            \"label_total\": label_total,\n            \"pred_total\": pred_total,\n        }\n\n        return res\n\n\ndef rebuild_col_unit_col(valid_col_units, col_unit, kmap):\n    if col_unit is None:\n        return col_unit\n\n    agg_id, col_id, distinct = col_unit\n    if col_id in kmap and col_id in valid_col_units:\n        col_id = kmap[col_id]\n    if DISABLE_DISTINCT:\n        distinct = None\n    return agg_id, col_id, distinct\n\n\ndef rebuild_val_unit_col(valid_col_units, val_unit, kmap):\n    if val_unit is None:\n        return val_unit\n\n    unit_op, col_unit1, col_unit2 = val_unit\n    col_unit1 = rebuild_col_unit_col(valid_col_units, col_unit1, kmap)\n    col_unit2 = rebuild_col_unit_col(valid_col_units, col_unit2, kmap)\n    return unit_op, col_unit1, col_unit2\n\n\ndef rebuild_table_unit_col(valid_col_units, table_unit, kmap):\n    if table_unit is None:\n        return table_unit\n\n    table_type, col_unit_or_sql = table_unit\n    if isinstance(col_unit_or_sql, tuple):\n        col_unit_or_sql = rebuild_col_unit_col(valid_col_units, col_unit_or_sql, kmap)\n    return table_type, col_unit_or_sql\n\n\ndef rebuild_cond_unit_col(valid_col_units, cond_unit, kmap):\n    if cond_unit is None:\n        return cond_unit\n\n    not_op, op_id, val_unit, val1, val2 = cond_unit\n    val_unit = rebuild_val_unit_col(valid_col_units, val_unit, kmap)\n    return not_op, op_id, val_unit, val1, val2\n\n\ndef rebuild_condition_col(valid_col_units, condition, kmap):\n    for idx in range(len(condition)):\n        if idx % 2 == 0:\n            condition[idx] = rebuild_cond_unit_col(\n                valid_col_units, condition[idx], kmap\n            )\n    return condition\n\n\ndef rebuild_select_col(valid_col_units, sel, kmap):\n    if sel is None:\n        return sel\n    distinct, _list = sel\n    new_list = []\n    for it in _list:\n        agg_id, val_unit = it\n        new_list.append((agg_id, rebuild_val_unit_col(valid_col_units, val_unit, kmap)))\n    if DISABLE_DISTINCT:\n        distinct = None\n    return distinct, new_list\n\n\ndef rebuild_from_col(valid_col_units, from_, kmap):\n    if from_ is None:\n        return from_\n\n    from_[\"table_units\"] = [\n        rebuild_table_unit_col(valid_col_units, table_unit, kmap)\n        for table_unit in from_[\"table_units\"]\n    ]\n    from_[\"conds\"] = rebuild_condition_col(valid_col_units, from_[\"conds\"], kmap)\n    return from_\n\n\ndef rebuild_group_by_col(valid_col_units, group_by, kmap):\n    if group_by is None:\n        return group_by\n\n    return [\n        rebuild_col_unit_col(valid_col_units, col_unit, kmap) for col_unit in group_by\n    ]\n\n\ndef rebuild_order_by_col(valid_col_units, order_by, kmap):\n    if order_by is None or len(order_by) == 0:\n        return order_by\n\n    direction, val_units = order_by\n    new_val_units = [\n        rebuild_val_unit_col(valid_col_units, val_unit, kmap) for val_unit in val_units\n    ]\n    return direction, new_val_units\n\n\ndef rebuild_sql_col(valid_col_units, sql, kmap):\n    if sql is None:\n        return sql\n\n    sql[\"select\"] = rebuild_select_col(valid_col_units, sql[\"select\"], kmap)\n    sql[\"from\"] = rebuild_from_col(valid_col_units, sql[\"from\"], kmap)\n    sql[\"where\"] = rebuild_condition_col(valid_col_units, sql[\"where\"], kmap)\n    sql[\"groupBy\"] = rebuild_group_by_col(valid_col_units, sql[\"groupBy\"], kmap)\n    sql[\"orderBy\"] = rebuild_order_by_col(valid_col_units, sql[\"orderBy\"], kmap)\n    sql[\"having\"] = rebuild_condition_col(valid_col_units, sql[\"having\"], kmap)\n    sql[\"intersect\"] = rebuild_sql_col(valid_col_units, sql[\"intersect\"], kmap)\n    sql[\"except\"] = rebuild_sql_col(valid_col_units, sql[\"except\"], kmap)\n    sql[\"union\"] = rebuild_sql_col(valid_col_units, sql[\"union\"], kmap)\n\n    return sql\n\n\n# Rebuild SQL functions for value evaluation\ndef rebuild_cond_unit_val(cond_unit):\n    if cond_unit is None or not DISABLE_VALUE:\n        return cond_unit\n\n    not_op, op_id, val_unit, val1, val2 = cond_unit\n    if not isinstance(val1, dict):\n        val1 = None\n    else:\n        val1 = rebuild_sql_val(val1)\n    if not isinstance(val2, dict):\n        val2 = None\n    else:\n        val2 = rebuild_sql_val(val2)\n    return not_op, op_id, val_unit, val1, val2\n\n\ndef rebuild_condition_val(condition):\n    if condition is None or not DISABLE_VALUE:\n        return condition\n\n    res = []\n    for idx, it in enumerate(condition):\n        if idx % 2 == 0:\n            res.append(rebuild_cond_unit_val(it))\n        else:\n            res.append(it)\n    return res\n\n\ndef rebuild_sql_val(sql):\n    if sql is None or not DISABLE_VALUE:\n        return sql\n\n    sql[\"from\"][\"conds\"] = rebuild_condition_val(sql[\"from\"][\"conds\"])\n    sql[\"having\"] = rebuild_condition_val(sql[\"having\"])\n    sql[\"where\"] = rebuild_condition_val(sql[\"where\"])\n    sql[\"intersect\"] = rebuild_sql_val(sql[\"intersect\"])\n    sql[\"except\"] = rebuild_sql_val(sql[\"except\"])\n    sql[\"union\"] = rebuild_sql_val(sql[\"union\"])\n\n    return sql\n\n\n# Rebuild SQL functions for foreign key evaluation\ndef build_valid_col_units(table_units, schema):\n    col_ids = [\n        table_unit[1]\n        for table_unit in table_units\n        if table_unit[0] == TABLE_TYPE[\"table_unit\"]\n    ]\n    prefixs = [col_id[:-2] for col_id in col_ids]\n    valid_col_units = []\n    for value in schema.idMap.values():\n        if \".\" in value and value[: value.index(\".\")] in prefixs:\n            valid_col_units.append(value)\n    return valid_col_units\n\n\ndef rewrite_sql(sql: str) -> str:\n    sql = re.sub(r'\"([^\"]*)\"', r\"\\1\", sql)\n    sql = re.sub(r\"\\s+AS\\s+\\w+\", \"\", sql, flags=re.IGNORECASE)\n    sql = re.sub(r\"\\s+\", \" \", sql).strip()\n\n    return sql\n\n\ndef tokenize(sql: str, schema: dict, kmap: dict) -> dict:\n    rewritten_sql = rewrite_sql(sql)\n\n    try:\n        struct = get_sql(schema, rewritten_sql)\n    except Exception:\n        struct = {\n            \"except\": None,\n            \"from\": {\"conds\": [], \"table_units\": []},\n            \"groupBy\": [],\n            \"having\": [],\n            \"intersect\": None,\n            \"limit\": None,\n            \"orderBy\": [],\n            \"select\": [False, []],\n            \"union\": None,\n            \"where\": [],\n        }\n\n    g_valid_col_units = build_valid_col_units(struct[\"from\"][\"table_units\"], schema)\n    struct = rebuild_sql_val(struct)\n    struct = rebuild_sql_col(g_valid_col_units, struct, kmap)\n    return struct\n\n\ndef build_foreign_key_map(entry):\n    cols_orig = entry[\"column_names_original\"]\n    tables_orig = entry[\"table_names_original\"]\n\n    # rebuild cols corresponding to idmap in Schema\n    cols = []\n    for col_orig in cols_orig:\n        if col_orig[0] >= 0:\n            t = tables_orig[col_orig[0]]\n            c = col_orig[1]\n            cols.append(\"__\" + t.lower() + \".\" + c.lower() + \"__\")\n        else:\n            cols.append(\"__all__\")\n\n    def keyset_in_list(k1, k2, k_list):\n        for k_set in k_list:\n            if k1 in k_set or k2 in k_set:\n                return k_set\n        new_k_set = set()\n        k_list.append(new_k_set)\n        return new_k_set\n\n    foreign_key_list = []\n    foreign_keys = entry[\"foreign_keys\"]\n    for fkey in foreign_keys:\n        key1, key2 = fkey\n        key_set = keyset_in_list(key1, key2, foreign_key_list)\n        key_set.add(key1)\n        key_set.add(key2)\n\n    foreign_key_map = {}\n    for key_set in foreign_key_list:\n        sorted_list = sorted(list(key_set))\n        midx = sorted_list[0]\n        for idx in sorted_list:\n            foreign_key_map[cols[idx]] = cols[midx]\n\n    return foreign_key_map\n\n\ndef build_foreign_key_map_from_json(table):\n    try:\n        import json\n\n        with open(table) as f:\n            data = json.load(f)\n        tables = {}\n        for entry in data:\n            tables[entry[\"db_id\"]] = build_foreign_key_map(entry)\n        return tables\n    except Exception as e:\n        print(f\"Error building foreign key map from JSON: {e}\")\n        return {}\n\n\nVALUE_NUM_SYMBOL = \"VALUERARE\"\n\n\n# plug in the values into query with value slots\ndef plugin(query_value_replaced: List[str], values_in_order: List[str]) -> str:\n    q_length = len(query_value_replaced)\n    query_w_values = query_value_replaced[:]\n    value_idx = [\n        idx\n        for idx in range(q_length)\n        if query_value_replaced[idx] == VALUE_NUM_SYMBOL.lower()\n    ]\n    assert len(value_idx) == len(values_in_order)\n\n    for idx, value in zip(value_idx, values_in_order):\n        query_w_values[idx] = value\n    return \" \".join(query_w_values)\n\n\n# a generator generating all possible ways of\n# filling values into predicted query\ndef plugin_all_permutations(\n    query_value_replaced: List[str], values: Set[str]\n) -> Iterator[str]:\n    num_slots = len([v for v in query_value_replaced if v == VALUE_NUM_SYMBOL.lower()])\n    for values in itertools.product(*[list(values) for _ in range(num_slots)]):\n        yield plugin(query_value_replaced, list(values))\n\n\n# strip_query, reformat_query and replace values\n# were implemented by Yu Tao for processing CoSQL\ndef strip_query(query: str) -> Tuple[List[str], List[str]]:\n    query_keywords, all_values = [], []\n\n    # then replace all stuff enclosed by \"\" with a numerical value to get it marked as {VALUE}\n\n    # Tao's implementation is commented out here.\n    \"\"\"\n    str_1 = re.findall(\"\\\"[^\\\"]*\\\"\", query)\n    str_2 = re.findall(\"\\'[^\\']*\\'\", query)\n    values = str_1 + str_2\n        \"\"\"\n\n    toks = sqlparse.parse(query)[0].flatten()\n    values = [\n        t.value\n        for t in toks\n        if t.ttype == sqlparse.tokens.Literal.String.Single\n        or t.ttype == sqlparse.tokens.Literal.String.Symbol\n    ]\n\n    for val in values:\n        all_values.append(val)\n        query = query.replace(val.strip(), VALUE_NUM_SYMBOL)\n\n    query_tokenized = query.split()\n    float_nums = re.findall(\"[-+]?\\d*\\.\\d+\", query)\n    all_values += [qt for qt in query_tokenized if qt in float_nums]\n    query_tokenized = [\n        VALUE_NUM_SYMBOL if qt in float_nums else qt for qt in query_tokenized\n    ]\n\n    query = \" \".join(query_tokenized)\n    int_nums = [i.strip() for i in re.findall(\"[^tT]\\d+\", query)]\n\n    all_values += [qt for qt in query_tokenized if qt in int_nums]\n    query_tokenized = [\n        VALUE_NUM_SYMBOL if qt in int_nums else qt for qt in query_tokenized\n    ]\n    # print int_nums, query, query_tokenized\n\n    for tok in query_tokenized:\n        if \".\" in tok:\n            table = re.findall(\"[Tt]\\d+\\.\", tok)\n            if len(table) > 0:\n                to = tok.replace(\".\", \" . \").split()\n                to = [t.lower() for t in to if len(t) > 0]\n                query_keywords.extend(to)\n            else:\n                query_keywords.append(tok.lower())\n\n        elif len(tok) > 0:\n            query_keywords.append(tok.lower())\n    return query_keywords, all_values\n\n\ndef reformat_query(query: str) -> str:\n    query = query.strip().replace(\";\", \"\").replace(\"\\t\", \"\")\n    query = \" \".join(\n        [t.value for t in tokenize(query) if t.ttype != sqlparse.tokens.Whitespace]\n    )\n    t_stars = [\"t1.*\", \"t2.*\", \"t3.*\", \"T1.*\", \"T2.*\", \"T3.*\"]\n    for ts in t_stars:\n        query = query.replace(ts, \"*\")\n    return query\n\n\ndef replace_values(sql: str) -> Tuple[List[str], Set[str]]:\n    sql = sqlparse.format(sql, reindent=False, keyword_case=\"upper\")\n    # sql = re.sub(r\"(<=|>=|!=|=|<|>|,)\", r\" \\1 \", sql)\n    sql = re.sub(r\"(T\\d+\\.)\\s\", r\"\\1\", sql)\n    query_toks_no_value, values = strip_query(sql)\n    return query_toks_no_value, set(values)\n\n\n# extract the non-value tokens and the set of values\n# from a sql query\ndef extract_query_values(sql: str) -> Tuple[List[str], Set[str]]:\n    reformated = reformat_query(query=sql)\n    query_value_replaced, values = replace_values(reformated)\n    return query_value_replaced, values\n\n\n# given the gold query and the model prediction\n# extract values from the gold, extract predicted sql with value slots\n# return 1) number of possible ways to plug in gold values and 2) an iterator of predictions with value plugged in\ndef get_all_preds_for_execution(gold: str, pred: str) -> Tuple[int, Iterator[str]]:\n    _, gold_values = extract_query_values(gold)\n    pred_query_value_replaced, _ = extract_query_values(pred)\n    num_slots = len(\n        [v for v in pred_query_value_replaced if v == VALUE_NUM_SYMBOL.lower()]\n    )\n    num_alternatives = len(gold_values) ** num_slots\n    return num_alternatives, plugin_all_permutations(\n        pred_query_value_replaced, gold_values\n    )\n\n\ndef remove_distinct(s):\n    toks = [t.value for t in list(sqlparse.parse(s)[0].flatten())]\n    return \"\".join([t for t in toks if t.lower() != \"distinct\"])\n\n\n# postprocess the model predictions to avoid execution errors\n# e.g. removing spaces between \">\" and \"=\"\ndef postprocess(query: str) -> str:\n    query = query.replace(\"> =\", \">=\").replace(\"< =\", \"<=\").replace(\"! =\", \"!=\")\n    return query\n\n\ndef replace_cur_year(query: str) -> str:\n    return re.sub(\n        \"YEAR\\s*\\(\\s*CURDATE\\s*\\(\\s*\\)\\s*\\)\\s*\", \"2020\", query, flags=re.IGNORECASE\n    )\n\n\n# get the database cursor for a sqlite database path\ndef get_cursor_from_path(sqlite_path: str):\n    try:\n        if not os.path.exists(sqlite_path):\n            print(\"Openning a new connection %s\" % sqlite_path)\n        connection = sqlite3.connect(sqlite_path)\n    except Exception as e:\n        print(sqlite_path)\n        raise e\n    connection.text_factory = lambda b: b.decode(errors=\"ignore\")\n    cursor = connection.cursor()\n    return cursor\n\n\nasync def exec_on_db_(sqlite_path: str, query: str) -> Tuple[str, Any]:\n    query = replace_cur_year(query)\n    cursor = get_cursor_from_path(sqlite_path)\n    try:\n        cursor.execute(query)\n        result = cursor.fetchall()\n        cursor.close()\n        cursor.connection.close()\n        return \"result\", result\n    except Exception as e:\n        cursor.close()\n        cursor.connection.close()\n        return \"exception\", e\n\n\nTIMEOUT = 60\n\n\nasync def exec_on_db(\n    sqlite_path: str, query: str, process_id: str = \"\", timeout: int = TIMEOUT\n) -> Tuple[str, Any]:\n    try:\n        return await asyncio.wait_for(exec_on_db_(sqlite_path, query), timeout)\n    except asyncio.TimeoutError:\n        return (\"exception\", TimeoutError)\n    except Exception as e:\n        return (\"exception\", e)\n\n\ndef permute_tuple(element: Tuple, perm: Tuple) -> Tuple:\n    assert len(element) == len(perm)\n    return tuple([element[i] for i in perm])\n\n\ndef unorder_row(row: Tuple) -> Tuple:\n    return tuple(sorted(row, key=lambda x: str(x) + str(type(x))))\n\n\n# unorder each row in the table\n# [result_1 and result_2 has the same bag of unordered row]\n# is a necessary condition of\n# [result_1 and result_2 are equivalent in denotation]\ndef quick_rej(result1: List[Tuple], result2: List[Tuple], order_matters: bool) -> bool:\n    s1 = [unorder_row(row) for row in result1]\n    s2 = [unorder_row(row) for row in result2]\n    if order_matters:\n        return s1 == s2\n    else:\n        return set(s1) == set(s2)\n\n\ndef get_constraint_permutation(tab1_sets_by_columns: List[Set], result2: List[Tuple]):\n    num_cols = len(result2[0])\n    perm_constraints = [{i for i in range(num_cols)} for _ in range(num_cols)]\n    if num_cols <= 3:\n        return product(*perm_constraints)\n\n    # we sample 20 rows and constrain the space of permutations\n    for _ in range(20):\n        random_tab2_row = random.choice(result2)\n\n        for tab1_col in range(num_cols):\n            for tab2_col in set(perm_constraints[tab1_col]):\n                if random_tab2_row[tab2_col] not in tab1_sets_by_columns[tab1_col]:\n                    perm_constraints[tab1_col].remove(tab2_col)\n    return product(*perm_constraints)\n\n\n# return whether two bag of relations are equivalent\ndef multiset_eq(l1: List, l2: List) -> bool:\n    if len(l1) != len(l2):\n        return False\n    d = defaultdict(int)\n    for e in l1:\n        d[e] = d[e] + 1\n    for e in l2:\n        d[e] = d[e] - 1\n        if d[e] < 0:\n            return False\n    return True\n\n\n# check whether two denotations are correct\ndef result_eq(result1: List[Tuple], result2: List[Tuple], order_matters: bool) -> bool:\n    if len(result1) == 0 and len(result2) == 0:\n        return True\n\n    # if length is not the same, then they are definitely different bag of rows\n    if len(result1) != len(result2):\n        return False\n\n    num_cols = len(result1[0])\n\n    # if the results do not have the same number of columns, they are different\n    if len(result2[0]) != num_cols:\n        return False\n\n    # unorder each row and compare whether the denotation is the same\n    # this can already find most pair of denotations that are different\n    if not quick_rej(result1, result2, order_matters):\n        return False\n\n    # the rest of the problem is in fact more complicated than one might think\n    # we want to find a permutation of column order and a permutation of row order,\n    # s.t. result_1 is the same as result_2\n    # we return true if we can find such column & row permutations\n    # and false if we cannot\n    tab1_sets_by_columns = [{row[i] for row in result1} for i in range(num_cols)]\n\n    # on a high level, we enumerate all possible column permutations that might make result_1 == result_2\n    # we decrease the size of the column permutation space by the function get_constraint_permutation\n    # if one of the permutation make result_1, result_2 equivalent, then they are equivalent\n    for perm in get_constraint_permutation(tab1_sets_by_columns, result2):\n        if len(perm) != len(set(perm)):\n            continue\n        if num_cols == 1:\n            result2_perm = result2\n        else:\n            result2_perm = [permute_tuple(element, perm) for element in result2]\n        if order_matters:\n            if result1 == result2_perm:\n                return True\n        else:\n            # in fact the first condition must hold if the second condition holds\n            # but the first is way more efficient implementation-wise\n            # and we use it to quickly reject impossible candidates\n            if set(result1) == set(result2_perm) and multiset_eq(result1, result2_perm):\n                return True\n    return False\n\n\n# approximate whether p_str and g_str are semantically equivalent\n# db is the database path\n# we are going to evaluate whether they are equivalent in all the databases\n# that are in the same directory as db\n# 0 if denotationally equivalent\n# 1 otherwise\n# the meaning of each auxillary argument can be seen in the parser definition in evaluation.py\nasync def eval_exec_match(\n    db: str,\n    p_str: str,\n    g_str: str,\n    plug_value: bool = False,\n    keep_distinct: bool = False,\n    progress_bar_for_each_datapoint: bool = False,\n) -> int:\n    # post-process the prediction.\n    # e.g. removing spaces between \">\" and \"=\"\n    p_str, g_str = postprocess(p_str), postprocess(g_str)\n    if not keep_distinct:\n        p_str = remove_distinct(p_str)\n        g_str = remove_distinct(g_str)\n\n    # we decide whether two denotations are equivalent based on \"bag semantics\"\n    # https://courses.cs.washington.edu/courses/cse444/10sp/lectures/lecture16.pdf\n    # if there is order by in query, then we assume order of the rows matter\n    # order by might also be used to find the max/min instead of sorting,\n    # but in that case the result mostly only contains one row and hence order_matters does not make a difference\n    order_matters = \"order by\" in g_str.lower()\n\n    # find all databases in the same directory\n    db_dir = os.path.dirname(db)\n    db_paths = [\n        os.path.join(db_dir, basename)\n        for basename in os.listdir(db_dir)\n        if \".sqlite\" in basename\n    ]\n\n    preds = [p_str]\n    # if plug in value (i.e. we do not consider value prediction correctness)\n    # enumerate all ways to plug in values in the gold query to the model predictions\n    # otherwise, we only evaluate the predicted query with its own value prediction\n    if plug_value:\n        _, preds = get_all_preds_for_execution(g_str, p_str)\n        # we did not add this line in our EMNLP work\n        # this reduces \"false negatives\" when value is substituted\n        preds = chain([p_str], preds)\n\n    for pred in preds:\n        pred_passes = 1\n        # compare the gold and predicted denotations on each database in the directory\n        # wrap with progress bar if required\n        if progress_bar_for_each_datapoint:\n            ranger = tqdm.tqdm(db_paths)\n        else:\n            ranger = db_paths\n\n        for db_path in ranger:\n            g_flag, g_denotation = await exec_on_db(db_path, g_str)\n            p_flag, p_denotation = await exec_on_db(db_path, pred)\n\n            # we should expect the gold to be succesfully executed on the database\n            assert g_flag != \"exception\", (\n                \"gold query %s has error on database file %s\" % (g_str, db_path)\n            )\n\n            # wrong if execution fails\n            if p_flag == \"exception\":\n                pred_passes = 0\n\n            # if denotations are not equivalent, the prediction must be wrong\n            elif not result_eq(g_denotation, p_denotation, order_matters=order_matters):\n                pred_passes = 0\n            if pred_passes == 0:\n                break\n\n        # the model prediction has the same denotation as the gold for all databases\n        if pred_passes == 1:\n            return 1\n\n    # none of the predictions passed\n    return 0\n"
  },
  {
    "path": "wren-ai-service/eval/metrics/spider/exact_match.py",
    "content": "import asyncio\nimport os\n\nfrom deepeval.metrics import BaseMetric\nfrom deepeval.test_case import LLMTestCase\n\nfrom eval.metrics.spider import Evaluator, build_foreign_key_map_from_json, tokenize\nfrom eval.metrics.spider.process_sql import Schema, get_schema\n\n\nclass ExactMatchAccuracy(BaseMetric):\n    def __init__(\n        self,\n        kmap_path: str = \"./tools/dev/etc/spider1.0/spider_data/tables.json\",\n        db_dir: str = \"./tools/dev/etc/spider1.0/database\",\n    ):\n        self.threshold = 0\n        self.score = 0\n        self.kmaps = build_foreign_key_map_from_json(kmap_path)\n\n        self.db_dir = db_dir\n\n    def measure(self, test_case: LLMTestCase):\n        return asyncio.run(self.a_measure(test_case))\n\n    async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):\n        if not test_case.additional_metadata[\"enable_spider_metrics\"]:\n            self.success = True\n            return 0\n\n        db_name = test_case.additional_metadata[\"catalog\"]\n        db = os.path.join(self.db_dir, db_name, db_name + \".sqlite\")\n        schema = Schema(get_schema(db))\n        gold_sql = tokenize(test_case.expected_output, schema, self.kmaps[db_name])\n        pred_sql = tokenize(test_case.actual_output, schema, self.kmaps[db_name])\n\n        evaluator = Evaluator()\n        self.score = evaluator.eval_exact_match(pred_sql, gold_sql)\n        self.success = self.score >= self.threshold\n\n        return self.score\n\n    def is_successful(self):\n        return self.success\n\n    @property\n    def __name__(self):\n        return \"ExactMatchAccuracy\"\n\n\nif __name__ == \"__main__\":\n    metric = ExactMatchAccuracy()\n    test_case = LLMTestCase(\n        input=\"\",\n        expected_output=\"SELECT COUNT(DISTINCT Nationality) FROM people\",\n        actual_output='SELECT COUNT(DISTINCT \"Nationality\") AS \"nationality_count\" FROM \"people\"',\n        additional_metadata={\"catalog\": \"poker_player\"},\n    )\n    print(metric.measure(test_case))\n"
  },
  {
    "path": "wren-ai-service/eval/metrics/spider/exec_match.py",
    "content": "import asyncio\nimport os\n\nfrom deepeval.metrics import BaseMetric\nfrom deepeval.test_case import LLMTestCase\n\nfrom eval.metrics.spider import eval_exec_match\n\n\nclass ExecutionAccuracy(BaseMetric):\n    def __init__(\n        self,\n        db_dir: str = \"./tools/dev/etc/spider1.0/database\",\n    ):\n        self.threshold = 0\n        self.score = 0\n\n        self.db_dir = db_dir\n\n    def measure(self, test_case: LLMTestCase):\n        return asyncio.run(self.a_measure(test_case))\n\n    async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):\n        if not test_case.additional_metadata[\"enable_spider_metrics\"]:\n            self.success = True\n            return 0\n\n        db_name = test_case.additional_metadata[\"catalog\"]\n        db = os.path.join(self.db_dir, db_name, db_name + \".sqlite\")\n\n        self.score = await eval_exec_match(\n            db=db,\n            p_str=test_case.actual_output,\n            g_str=test_case.expected_output,\n        )\n\n        self.success = self.score >= self.threshold\n\n        return self.score\n\n    def is_successful(self):\n        return self.success\n\n    @property\n    def __name__(self):\n        return \"ExecutionAccuracy\"\n\n\nif __name__ == \"__main__\":\n    metric = ExecutionAccuracy()\n    test_case = LLMTestCase(\n        input=\"\",\n        expected_output=\"SELECT COUNT(DISTINCT Nationality) FROM people\",\n        actual_output='SELECT COUNT(DISTINCT \"Nationality\") AS \"nationality_count\" FROM \"people\"',\n        additional_metadata={\"catalog\": \"poker_player\"},\n    )\n    print(metric.measure(test_case))\n"
  },
  {
    "path": "wren-ai-service/eval/metrics/spider/process_sql.py",
    "content": "################################\n# Assumptions:\n#   1. sql is correct\n#   2. only table name has alias\n#   3. only one intersect/union/except\n#\n# val: number(float)/string(str)/sql(dict)\n# col_unit: (agg_id, col_id, isDistinct(bool))\n# val_unit: (unit_op, col_unit1, col_unit2)\n# table_unit: (table_type, col_unit/sql)\n# cond_unit: (not_op, op_id, val_unit, val1, val2)\n# condition: [cond_unit1, 'and'/'or', cond_unit2, ...]\n# sql {\n#   'select': (isDistinct(bool), [(agg_id, val_unit), (agg_id, val_unit), ...])\n#   'from': {'table_units': [table_unit1, table_unit2, ...], 'conds': condition}\n#   'where': condition\n#   'groupBy': [col_unit1, col_unit2, ...]\n#   'orderBy': ('asc'/'desc', [val_unit1, val_unit2, ...])\n#   'having': condition\n#   'limit': None/limit value\n#   'intersect': None/sql\n#   'except': None/sql\n#   'union': None/sql\n# }\n################################\n\nimport json\nimport sqlite3\n\nimport nltk\n\nnltk.download(\"punkt_tab\")\n\nCLAUSE_KEYWORDS = (\n    \"select\",\n    \"from\",\n    \"where\",\n    \"group\",\n    \"order\",\n    \"limit\",\n    \"intersect\",\n    \"union\",\n    \"except\",\n)\nJOIN_KEYWORDS = (\"join\", \"on\", \"as\")\n\nWHERE_OPS = (\n    \"not\",\n    \"between\",\n    \"=\",\n    \">\",\n    \"<\",\n    \">=\",\n    \"<=\",\n    \"!=\",\n    \"in\",\n    \"like\",\n    \"is\",\n    \"exists\",\n)\nUNIT_OPS = (\"none\", \"-\", \"+\", \"*\", \"/\")\nAGG_OPS = (\"none\", \"max\", \"min\", \"count\", \"sum\", \"avg\")\nTABLE_TYPE = {\n    \"sql\": \"sql\",\n    \"table_unit\": \"table_unit\",\n}\n\nCOND_OPS = (\"and\", \"or\")\nSQL_OPS = (\"intersect\", \"union\", \"except\")\nORDER_OPS = (\"desc\", \"asc\")\n\n\nclass Schema:\n    \"\"\"\n    Simple schema which maps table&column to a unique identifier\n    \"\"\"\n\n    def __init__(self, schema):\n        self._schema = schema\n        self._idMap = self._map(self._schema)\n\n    @property\n    def schema(self):\n        return self._schema\n\n    @property\n    def idMap(self):\n        return self._idMap\n\n    def _map(self, schema):\n        idMap = {\"*\": \"__all__\"}\n        id = 1\n        for key, vals in schema.items():\n            for val in vals:\n                idMap[key.lower() + \".\" + val.lower()] = (\n                    \"__\" + key.lower() + \".\" + val.lower() + \"__\"\n                )\n                id += 1\n\n        for key in schema:\n            idMap[key.lower()] = \"__\" + key.lower() + \"__\"\n            id += 1\n\n        return idMap\n\n\ndef get_schema(db):\n    \"\"\"\n    Get database's schema, which is a dict with table name as key\n    and list of column names as value\n    :param db: database path\n    :return: schema dict\n    \"\"\"\n\n    schema = {}\n    conn = sqlite3.connect(db)\n    cursor = conn.cursor()\n\n    # fetch table names\n    cursor.execute(\"SELECT name FROM sqlite_master WHERE type='table';\")\n    tables = [str(table[0].lower()) for table in cursor.fetchall()]\n\n    # fetch table info\n    for table in tables:\n        cursor.execute(\"PRAGMA table_info({})\".format(table))\n        schema[table] = [str(col[1].lower()) for col in cursor.fetchall()]\n\n    return schema\n\n\ndef get_schema_from_json(fpath):\n    with open(fpath) as f:\n        data = json.load(f)\n\n    schema = {}\n    for entry in data:\n        table = str(entry[\"table\"].lower())\n        cols = [str(col[\"column_name\"].lower()) for col in entry[\"col_data\"]]\n        schema[table] = cols\n\n    return schema\n\n\ndef tokenize(string):\n    string = str(string)\n    string = string.replace(\n        \"'\", '\"'\n    )  # ensures all string values wrapped by \"\" problem??\n    quote_idxs = [idx for idx, char in enumerate(string) if char == '\"']\n    assert len(quote_idxs) % 2 == 0, \"Unexpected quote\"\n\n    # keep string value as token\n    vals = {}\n    for i in range(len(quote_idxs) - 1, -1, -2):\n        qidx1 = quote_idxs[i - 1]\n        qidx2 = quote_idxs[i]\n        val = string[qidx1 : qidx2 + 1]\n        key = \"__val_{}_{}__\".format(qidx1, qidx2)\n        string = string[:qidx1] + key + string[qidx2 + 1 :]\n        vals[key] = val\n\n    toks = [word.lower() for word in nltk.word_tokenize(string)]\n    # replace with string value token\n    for i in range(len(toks)):\n        if toks[i] in vals:\n            toks[i] = vals[toks[i]]\n\n    # find if there exists !=, >=, <=\n    eq_idxs = [idx for idx, tok in enumerate(toks) if tok == \"=\"]\n    eq_idxs.reverse()\n    prefix = (\"!\", \">\", \"<\")\n    for eq_idx in eq_idxs:\n        pre_tok = toks[eq_idx - 1]\n        if pre_tok in prefix:\n            toks = toks[: eq_idx - 1] + [pre_tok + \"=\"] + toks[eq_idx + 1 :]\n\n    return toks\n\n\ndef scan_alias(toks):\n    \"\"\"Scan the index of 'as' and build the map for all alias\"\"\"\n    as_idxs = [idx for idx, tok in enumerate(toks) if tok == \"as\"]\n    alias = {}\n    for idx in as_idxs:\n        alias[toks[idx + 1]] = toks[idx - 1]\n    return alias\n\n\ndef get_tables_with_alias(schema, toks):\n    tables = scan_alias(toks)\n    for key in schema:\n        assert key not in tables, \"Alias {} has the same name in table\".format(key)\n        tables[key] = key\n    return tables\n\n\ndef parse_col(toks, start_idx, tables_with_alias, schema, default_tables=None):\n    \"\"\"\n    :returns next idx, column id\n    \"\"\"\n    tok = toks[start_idx]\n    if tok == \"*\":\n        return start_idx + 1, schema.idMap[tok]\n\n    if \".\" in tok:  # if token is a composite\n        alias, col = tok.split(\".\")\n        key = tables_with_alias[alias] + \".\" + col\n        return start_idx + 1, schema.idMap[key]\n\n    assert (\n        default_tables is not None and len(default_tables) > 0\n    ), \"Default tables should not be None or empty\"\n\n    for alias in default_tables:\n        table = tables_with_alias[alias]\n        if tok in schema.schema[table]:\n            key = table + \".\" + tok\n            return start_idx + 1, schema.idMap[key]\n\n    assert False, \"Error col: {}\".format(tok)\n\n\ndef parse_col_unit(toks, start_idx, tables_with_alias, schema, default_tables=None):\n    \"\"\"\n    :returns next idx, (agg_op id, col_id)\n    \"\"\"\n    idx = start_idx\n    len_ = len(toks)\n    isBlock = False\n    isDistinct = False\n    if toks[idx] == \"(\":\n        isBlock = True\n        idx += 1\n\n    if toks[idx] in AGG_OPS:\n        agg_id = AGG_OPS.index(toks[idx])\n        idx += 1\n        assert idx < len_ and toks[idx] == \"(\"\n        idx += 1\n        if toks[idx] == \"distinct\":\n            idx += 1\n            isDistinct = True\n        idx, col_id = parse_col(toks, idx, tables_with_alias, schema, default_tables)\n        assert idx < len_ and toks[idx] == \")\"\n        idx += 1\n        return idx, (agg_id, col_id, isDistinct)\n\n    if toks[idx] == \"distinct\":\n        idx += 1\n        isDistinct = True\n    agg_id = AGG_OPS.index(\"none\")\n    idx, col_id = parse_col(toks, idx, tables_with_alias, schema, default_tables)\n\n    if isBlock:\n        assert toks[idx] == \")\"\n        idx += 1  # skip ')'\n\n    return idx, (agg_id, col_id, isDistinct)\n\n\ndef parse_val_unit(toks, start_idx, tables_with_alias, schema, default_tables=None):\n    idx = start_idx\n    len_ = len(toks)\n    isBlock = False\n    if toks[idx] == \"(\":\n        isBlock = True\n        idx += 1\n\n    col_unit1 = None\n    col_unit2 = None\n    unit_op = UNIT_OPS.index(\"none\")\n\n    idx, col_unit1 = parse_col_unit(\n        toks, idx, tables_with_alias, schema, default_tables\n    )\n    if idx < len_ and toks[idx] in UNIT_OPS:\n        unit_op = UNIT_OPS.index(toks[idx])\n        idx += 1\n        idx, col_unit2 = parse_col_unit(\n            toks, idx, tables_with_alias, schema, default_tables\n        )\n\n    if isBlock:\n        assert toks[idx] == \")\"\n        idx += 1  # skip ')'\n\n    return idx, (unit_op, col_unit1, col_unit2)\n\n\ndef parse_table_unit(toks, start_idx, tables_with_alias, schema):\n    \"\"\"\n    :returns next idx, table id, table name\n    \"\"\"\n    idx = start_idx\n    len_ = len(toks)\n    key = tables_with_alias[toks[idx]]\n\n    if idx + 1 < len_ and toks[idx + 1] == \"as\":\n        idx += 3\n    else:\n        idx += 1\n\n    return idx, schema.idMap[key], key\n\n\ndef parse_value(toks, start_idx, tables_with_alias, schema, default_tables=None):\n    idx = start_idx\n    len_ = len(toks)\n\n    isBlock = False\n    if toks[idx] == \"(\":\n        isBlock = True\n        idx += 1\n\n    if toks[idx] == \"select\":\n        idx, val = parse_sql(toks, idx, tables_with_alias, schema)\n    elif '\"' in toks[idx]:  # token is a string value\n        val = toks[idx]\n        idx += 1\n    else:\n        try:\n            val = float(toks[idx])\n            idx += 1\n        except ValueError:\n            end_idx = idx\n            while (\n                end_idx < len_\n                and toks[end_idx] != \",\"\n                and toks[end_idx] != \")\"\n                and toks[end_idx] != \"and\"\n                and toks[end_idx] not in CLAUSE_KEYWORDS\n                and toks[end_idx] not in JOIN_KEYWORDS\n            ):\n                end_idx += 1\n\n            idx, val = parse_col_unit(\n                toks[start_idx:end_idx], 0, tables_with_alias, schema, default_tables\n            )\n            idx = end_idx\n\n    if isBlock:\n        assert toks[idx] == \")\"\n        idx += 1\n\n    return idx, val\n\n\ndef parse_condition(toks, start_idx, tables_with_alias, schema, default_tables=None):\n    idx = start_idx\n    len_ = len(toks)\n    conds = []\n\n    while idx < len_:\n        idx, val_unit = parse_val_unit(\n            toks, idx, tables_with_alias, schema, default_tables\n        )\n        not_op = False\n        if toks[idx] == \"not\":\n            not_op = True\n            idx += 1\n\n        assert (\n            idx < len_ and toks[idx] in WHERE_OPS\n        ), \"Error condition: idx: {}, tok: {}\".format(idx, toks[idx])\n        op_id = WHERE_OPS.index(toks[idx])\n        idx += 1\n        val1 = val2 = None\n        if op_id == WHERE_OPS.index(\n            \"between\"\n        ):  # between..and... special case: dual values\n            idx, val1 = parse_value(\n                toks, idx, tables_with_alias, schema, default_tables\n            )\n            assert toks[idx] == \"and\"\n            idx += 1\n            idx, val2 = parse_value(\n                toks, idx, tables_with_alias, schema, default_tables\n            )\n        else:  # normal case: single value\n            idx, val1 = parse_value(\n                toks, idx, tables_with_alias, schema, default_tables\n            )\n            val2 = None\n\n        conds.append((not_op, op_id, val_unit, val1, val2))\n\n        if idx < len_ and (\n            toks[idx] in CLAUSE_KEYWORDS\n            or toks[idx] in (\")\", \";\")\n            or toks[idx] in JOIN_KEYWORDS\n        ):\n            break\n\n        if idx < len_ and toks[idx] in COND_OPS:\n            conds.append(toks[idx])\n            idx += 1  # skip and/or\n\n    return idx, conds\n\n\ndef parse_select(toks, start_idx, tables_with_alias, schema, default_tables=None):\n    idx = start_idx\n    len_ = len(toks)\n\n    assert toks[idx] == \"select\", \"'select' not found\"\n    idx += 1\n    isDistinct = False\n    if idx < len_ and toks[idx] == \"distinct\":\n        idx += 1\n        isDistinct = True\n    val_units = []\n\n    while idx < len_ and toks[idx] not in CLAUSE_KEYWORDS:\n        agg_id = AGG_OPS.index(\"none\")\n        if toks[idx] in AGG_OPS:\n            agg_id = AGG_OPS.index(toks[idx])\n            idx += 1\n        idx, val_unit = parse_val_unit(\n            toks, idx, tables_with_alias, schema, default_tables\n        )\n        val_units.append((agg_id, val_unit))\n        if idx < len_ and toks[idx] == \",\":\n            idx += 1  # skip ','\n\n    return idx, (isDistinct, val_units)\n\n\ndef parse_from(toks, start_idx, tables_with_alias, schema):\n    \"\"\"\n    Assume in the from clause, all table units are combined with join\n    \"\"\"\n    assert \"from\" in toks[start_idx:], \"'from' not found\"\n\n    len_ = len(toks)\n    idx = toks.index(\"from\", start_idx) + 1\n    default_tables = []\n    table_units = []\n    conds = []\n\n    while idx < len_:\n        isBlock = False\n        if toks[idx] == \"(\":\n            isBlock = True\n            idx += 1\n\n        if toks[idx] == \"select\":\n            idx, sql = parse_sql(toks, idx, tables_with_alias, schema)\n            table_units.append((TABLE_TYPE[\"sql\"], sql))\n        else:\n            if idx < len_ and toks[idx] == \"join\":\n                idx += 1  # skip join\n            idx, table_unit, table_name = parse_table_unit(\n                toks, idx, tables_with_alias, schema\n            )\n            table_units.append((TABLE_TYPE[\"table_unit\"], table_unit))\n            default_tables.append(table_name)\n        if idx < len_ and toks[idx] == \"on\":\n            idx += 1  # skip on\n            idx, this_conds = parse_condition(\n                toks, idx, tables_with_alias, schema, default_tables\n            )\n            if len(conds) > 0:\n                conds.append(\"and\")\n            conds.extend(this_conds)\n\n        if isBlock:\n            assert toks[idx] == \")\"\n            idx += 1\n        if idx < len_ and (toks[idx] in CLAUSE_KEYWORDS or toks[idx] in (\")\", \";\")):\n            break\n\n    return idx, table_units, conds, default_tables\n\n\ndef parse_where(toks, start_idx, tables_with_alias, schema, default_tables):\n    idx = start_idx\n    len_ = len(toks)\n\n    if idx >= len_ or toks[idx] != \"where\":\n        return idx, []\n\n    idx += 1\n    idx, conds = parse_condition(toks, idx, tables_with_alias, schema, default_tables)\n    return idx, conds\n\n\ndef parse_group_by(toks, start_idx, tables_with_alias, schema, default_tables):\n    idx = start_idx\n    len_ = len(toks)\n    col_units = []\n\n    if idx >= len_ or toks[idx] != \"group\":\n        return idx, col_units\n\n    idx += 1\n    assert toks[idx] == \"by\"\n    idx += 1\n\n    while idx < len_ and not (toks[idx] in CLAUSE_KEYWORDS or toks[idx] in (\")\", \";\")):\n        idx, col_unit = parse_col_unit(\n            toks, idx, tables_with_alias, schema, default_tables\n        )\n        col_units.append(col_unit)\n        if idx < len_ and toks[idx] == \",\":\n            idx += 1  # skip ','\n        else:\n            break\n\n    return idx, col_units\n\n\ndef parse_order_by(toks, start_idx, tables_with_alias, schema, default_tables):\n    idx = start_idx\n    len_ = len(toks)\n    val_units = []\n    order_type = \"asc\"  # default type is 'asc'\n\n    if idx >= len_ or toks[idx] != \"order\":\n        return idx, val_units\n\n    idx += 1\n    assert toks[idx] == \"by\"\n    idx += 1\n\n    while idx < len_ and not (toks[idx] in CLAUSE_KEYWORDS or toks[idx] in (\")\", \";\")):\n        idx, val_unit = parse_val_unit(\n            toks, idx, tables_with_alias, schema, default_tables\n        )\n        val_units.append(val_unit)\n        if idx < len_ and toks[idx] in ORDER_OPS:\n            order_type = toks[idx]\n            idx += 1\n        if idx < len_ and toks[idx] == \",\":\n            idx += 1  # skip ','\n        else:\n            break\n\n    return idx, (order_type, val_units)\n\n\ndef parse_having(toks, start_idx, tables_with_alias, schema, default_tables):\n    idx = start_idx\n    len_ = len(toks)\n\n    if idx >= len_ or toks[idx] != \"having\":\n        return idx, []\n\n    idx += 1\n    idx, conds = parse_condition(toks, idx, tables_with_alias, schema, default_tables)\n    return idx, conds\n\n\ndef parse_limit(toks, start_idx):\n    idx = start_idx\n    len_ = len(toks)\n\n    if idx < len_ and toks[idx] == \"limit\":\n        idx += 2\n        # make limit value can work, cannot assume put 1 as a fake limit number\n        limit_token = toks[idx - 1]\n        if not str(limit_token).isdigit():\n            # Preserve previous behaviour but make the intent explicit\n            return idx, 1\n\n        return idx, int(limit_token)\n\n    return idx, None\n\n\ndef parse_sql(toks, start_idx, tables_with_alias, schema):\n    isBlock = False  # indicate whether this is a block of sql/sub-sql\n    len_ = len(toks)\n    idx = start_idx\n\n    sql = {}\n    if toks[idx] == \"(\":\n        isBlock = True\n        idx += 1\n\n    # parse from clause in order to get default tables\n    from_end_idx, table_units, conds, default_tables = parse_from(\n        toks, start_idx, tables_with_alias, schema\n    )\n    sql[\"from\"] = {\"table_units\": table_units, \"conds\": conds}\n    # select clause\n    _, select_col_units = parse_select(\n        toks, idx, tables_with_alias, schema, default_tables\n    )\n    idx = from_end_idx\n    sql[\"select\"] = select_col_units\n    # where clause\n    idx, where_conds = parse_where(toks, idx, tables_with_alias, schema, default_tables)\n    sql[\"where\"] = where_conds\n    # group by clause\n    idx, group_col_units = parse_group_by(\n        toks, idx, tables_with_alias, schema, default_tables\n    )\n    sql[\"groupBy\"] = group_col_units\n    # having clause\n    idx, having_conds = parse_having(\n        toks, idx, tables_with_alias, schema, default_tables\n    )\n    sql[\"having\"] = having_conds\n    # order by clause\n    idx, order_col_units = parse_order_by(\n        toks, idx, tables_with_alias, schema, default_tables\n    )\n    sql[\"orderBy\"] = order_col_units\n    # limit clause\n    idx, limit_val = parse_limit(toks, idx)\n    sql[\"limit\"] = limit_val\n\n    idx = skip_semicolon(toks, idx)\n    if isBlock:\n        assert toks[idx] == \")\"\n        idx += 1  # skip ')'\n    idx = skip_semicolon(toks, idx)\n\n    # intersect/union/except clause\n    for op in SQL_OPS:  # initialize IUE\n        sql[op] = None\n    if idx < len_ and toks[idx] in SQL_OPS:\n        sql_op = toks[idx]\n        idx += 1\n        idx, IUE_sql = parse_sql(toks, idx, tables_with_alias, schema)\n        sql[sql_op] = IUE_sql\n    return idx, sql\n\n\ndef load_data(fpath):\n    with open(fpath) as f:\n        data = json.load(f)\n    return data\n\n\ndef get_sql(schema, query):\n    toks = tokenize(query)\n    tables_with_alias = get_tables_with_alias(schema.schema, toks)\n    _, sql = parse_sql(toks, 0, tables_with_alias, schema)\n\n    return sql\n\n\ndef skip_semicolon(toks, start_idx):\n    idx = start_idx\n    while idx < len(toks) and toks[idx] == \";\":\n        idx += 1\n    return idx\n"
  },
  {
    "path": "wren-ai-service/eval/optimized/.gitignore",
    "content": "*.json\n"
  },
  {
    "path": "wren-ai-service/eval/pipelines.py",
    "content": "import asyncio\nimport re\nimport sys\nfrom abc import abstractmethod\nfrom datetime import datetime\nfrom pathlib import Path\nfrom typing import Any, Dict, List, Literal\n\nimport orjson\nfrom haystack import Document\nfrom langfuse.decorators import langfuse_context, observe\nfrom tqdm.asyncio import tqdm_asyncio\n\nfrom src.core.pipeline import PipelineComponent\n\nsys.path.append(f\"{Path().parent.resolve()}\")\n\nfrom eval import WREN_ENGINE_API_URL, EvalSettings\nfrom eval.metrics import (\n    AccuracyMetric,\n    AnswerRelevancyMetric,\n    ContextualPrecisionMetric,\n    ContextualRecallMetric,\n    ContextualRelevancyMetric,\n    ExactMatchAccuracy,\n    ExecutionAccuracy,\n    FaithfulnessMetric,\n    QuestionToReasoningJudge,\n    ReasoningToSqlJudge,\n    SqlSemanticsJudge,\n)\nfrom eval.utils import (\n    engine_config,\n    trace_metadata,\n)\nfrom src.pipelines import generation, indexing, retrieval\n\n\ndef deploy_model(mdl: str, pipes: list) -> None:\n    async def wrapper():\n        tasks = [pipe.run(orjson.dumps(mdl).decode()) for pipe in pipes]\n        await asyncio.gather(*tasks)\n\n    asyncio.run(wrapper())\n\n\ndef extract_units(ddls: list[str]) -> list:\n    def parse_ddl(ddl: str) -> list:\n        \"\"\"\n        Parses a DDL statement and returns a list of column definitions in the format table_name.column_name, excluding foreign keys.\n\n        Args:\n            ddl (str): The DDL statement to parse.\n\n        Returns:\n            list: A list of column definitions in the format table_name.column_name.\n        \"\"\"\n        # Regex to extract table name\n        table_name_match = re.search(r\"CREATE TABLE (\\w+)\", ddl, re.IGNORECASE)\n        table_name = table_name_match.group(1) if table_name_match else None\n\n        # Split the DDL into lines\n        lines = ddl.splitlines()\n        # Define a regex pattern to match foreign key constraints and comments\n        foreign_key_pattern = re.compile(r\"^\\s*FOREIGN KEY\", re.IGNORECASE)\n        comment_pattern = re.compile(r\"^\\s*--|/\\*|\\*/\")\n\n        # Filter out lines that define foreign keys or are comments\n        columns = [\n            line.strip()\n            for line in lines\n            if not foreign_key_pattern.match(line)\n            and not comment_pattern.match(line)\n            and line.strip()\n        ]\n\n        # Extract column names and format with table name as prefix\n        if table_name:\n            columns = [\n                f\"{table_name}.{line.split()[0]}\"\n                for line in columns\n                if line and line.split()[0] != \"CREATE\" and line.split()[0] != \");\"\n            ]\n\n        return columns\n\n    columns = []\n\n    for ddl in ddls:\n        columns.extend(parse_ddl(ddl))\n\n    return columns\n\n\nclass Eval:\n    def __init__(self, meta: dict, candidate_size: int = 1, **_):\n        self._meta = meta\n        self._candidate_size = candidate_size\n        self._batch_size = int(meta[\"batch_size\"])\n        self._batch_interval = int(meta[\"batch_interval\"])\n\n    @property\n    def candidate_size(self):\n        return self._candidate_size\n\n    def predict(self, queries: list) -> List[Dict[str, Any]]:\n        def split(queries: list, batch_size: int) -> list[list]:\n            return [\n                queries[i : i + batch_size] for i in range(0, len(queries), batch_size)\n            ]\n\n        async def wrapper(batch: list):\n            tasks = [self(query) for query in batch]\n            results = await tqdm_asyncio.gather(*tasks, desc=\"Generating Predictions\")\n            await asyncio.sleep(self._batch_interval)\n            return [prediction for predictions in results for prediction in predictions]\n\n        batches = [\n            asyncio.run(wrapper(batch)) for batch in split(queries, self._batch_size)\n        ]\n        return [prediction for batch in batches for prediction in batch]\n\n    @abstractmethod\n    def _process(self, prediction: dict, **_) -> dict:\n        ...\n\n    @observe(name=\"Prediction Process\", capture_input=False)\n    async def process(self, params: dict) -> dict:\n        prediction = {\n            \"trace_id\": langfuse_context.get_current_trace_id(),\n            \"trace_url\": langfuse_context.get_current_trace_url(),\n            \"input\": params[\"question\"],\n            \"actual_output\": {},\n            \"expected_output\": params[\"sql\"],\n            \"retrieval_context\": [],\n            \"context\": params[\"context\"],\n            \"samples\": params.get(\"samples\", []),\n            \"instructions\": params.get(\"instructions\", []),\n            \"type\": \"execution\",\n            \"reasoning\": \"\",\n            \"elapsed_time\": 0,\n        }\n\n        langfuse_context.update_current_trace(\n            session_id=self._meta.get(\"session_id\"),\n            user_id=self._meta.get(\"user_id\"),\n            metadata=trace_metadata(self._meta, type=prediction[\"type\"]),\n        )\n\n        start_time = datetime.now()\n        returned = await self._process(prediction, **params)\n        returned[\"elapsed_time\"] = (datetime.now() - start_time).total_seconds()\n\n        return returned\n\n\nclass RetrievalPipeline(Eval):\n    def __init__(\n        self,\n        meta: dict,\n        mdl: dict,\n        pipe_components: dict,\n        settings: EvalSettings,\n        **kwargs,\n    ):\n        super().__init__(meta)\n\n        _db_schema_indexing = indexing.DBSchema(\n            **pipe_components[\"db_schema_indexing\"],\n            column_batch_size=settings.column_indexing_batch_size,\n        )\n        _table_description_indexing = indexing.TableDescription(\n            **pipe_components[\"table_description_indexing\"],\n        )\n        deploy_model(mdl, [_db_schema_indexing, _table_description_indexing])\n\n        self._retrieval = retrieval.DbSchemaRetrieval(\n            **pipe_components[\"db_schema_retrieval\"],\n            table_retrieval_size=settings.table_retrieval_size,\n            table_column_retrieval_size=settings.table_column_retrieval_size,\n        )\n\n    async def _process(self, params: dict, **_) -> dict:\n        result = await self._retrieval.run(query=params[\"input\"])\n        documents = result.get(\"construct_retrieval_results\", {}).get(\n            \"retrieval_results\", []\n        )\n        table_ddls = [document.get(\"table_ddl\") for document in documents]\n        params[\"retrieval_context\"] = extract_units(table_ddls)\n\n        return params\n\n    async def __call__(self, params: dict, **_):\n        prediction = await self.process(params)\n\n        return [prediction]\n\n    @staticmethod\n    def metrics(engine_info: dict) -> dict:\n        wren_engine_info = engine_info.copy()\n        wren_engine_info[\"api_endpoint\"] = WREN_ENGINE_API_URL\n\n        return {\n            \"metrics\": [\n                ContextualRecallMetric(engine_info=wren_engine_info),\n                ContextualRelevancyMetric(),\n                ContextualPrecisionMetric(),\n            ]\n        }\n\n\nclass GenerationPipeline(Eval):\n    def __init__(\n        self,\n        meta: dict,\n        mdl: dict,\n        pipe_components: dict,\n        settings: EvalSettings,\n        **kwargs,\n    ):\n        super().__init__(meta)\n        self._mdl = mdl\n        self._generation = generation.SQLGeneration(\n            **pipe_components[\"sql_generation\"],\n        )\n\n        self._sql_functions_retrieval = retrieval.SqlFunctions(\n            **pipe_components[\"sql_functions_retrieval\"],\n        )\n\n        self._allow_sql_samples = settings.allow_sql_samples\n        self._allow_instructions = settings.allow_instructions\n        self._allow_sql_functions = settings.allow_sql_functions\n        self._engine_info = engine_config(\n            mdl, pipe_components, settings.eval_data_db_path\n        )\n\n    def _get_instructions(self, params: dict) -> list:\n        if self._allow_instructions:\n            return [\n                {\"instruction\": instruction}\n                for instruction in params.get(\"instructions\", [])\n            ]\n        return []\n\n    def _get_samples(self, params: dict) -> list:\n        if self._allow_sql_samples:\n            return params.get(\"samples\", [])\n        return []\n\n    async def _process(self, params: dict, document: list, **_) -> dict:\n        documents = [Document.from_dict(doc).content for doc in document]\n        table_ddls = [document.get(\"table_ddl\") for document in documents]\n\n        instructions = self._get_instructions(params)\n        samples = self._get_samples(params)\n\n        if self._allow_sql_functions:\n            sql_functions = await self._sql_functions_retrieval.run()\n        else:\n            sql_functions = []\n\n        actual_output = await self._generation.run(\n            query=params[\"input\"],\n            contexts=table_ddls,\n            sql_samples=samples,\n            has_calculated_field=params.get(\"has_calculated_field\", False),\n            has_metric=params.get(\"has_metric\", False),\n            sql_generation_reasoning=params.get(\"reasoning\", \"\"),\n            instructions=instructions,\n            sql_functions=sql_functions,\n        )\n\n        params[\"actual_output\"] = actual_output\n        params[\"retrieval_context\"] = extract_units(table_ddls)\n\n        return params\n\n    async def __call__(self, params: dict, **_):\n        return [await self.process(params)]\n\n    @staticmethod\n    def metrics(\n        engine_info: dict,\n        enable_semantics_comparison: bool,\n        component: PipelineComponent,\n    ) -> dict:\n        wren_engine_info = engine_info.copy()\n        wren_engine_info[\"api_endpoint\"] = WREN_ENGINE_API_URL\n\n        return {\n            \"metrics\": [\n                AccuracyMetric(\n                    engine_info=engine_info,\n                    enable_semantics_comparison=enable_semantics_comparison,\n                ),\n                AnswerRelevancyMetric(engine_info=wren_engine_info),\n                FaithfulnessMetric(engine_info=wren_engine_info),\n                ExactMatchAccuracy(),\n                ExecutionAccuracy(),\n                QuestionToReasoningJudge(**component),\n                ReasoningToSqlJudge(**component),\n                SqlSemanticsJudge(**component),\n            ],\n            \"post_metrics\": [],\n        }\n\n\nclass AskPipeline(Eval):\n    def __init__(\n        self,\n        meta: dict,\n        mdl: dict,\n        pipe_components: dict,\n        settings: EvalSettings,\n        **kwargs,\n    ):\n        super().__init__(meta)\n\n        _db_schema_indexing = indexing.DBSchema(\n            **pipe_components[\"db_schema_indexing\"],\n            column_batch_size=settings.column_indexing_batch_size,\n        )\n        _table_description_indexing = indexing.TableDescription(\n            **pipe_components[\"table_description_indexing\"],\n        )\n        deploy_model(mdl, [_db_schema_indexing, _table_description_indexing])\n\n        self._retrieval = retrieval.DbSchemaRetrieval(\n            **pipe_components[\"db_schema_retrieval\"],\n            table_retrieval_size=settings.table_retrieval_size,\n            table_column_retrieval_size=settings.table_column_retrieval_size,\n        )\n        self._sql_reasoner = generation.SQLGenerationReasoning(\n            **pipe_components[\"sql_generation_reasoning\"],\n        )\n        self._sql_functions_retrieval = retrieval.SqlFunctions(\n            **pipe_components[\"sql_functions_retrieval\"],\n        )\n        self._generation = generation.SQLGeneration(\n            **pipe_components[\"sql_generation\"],\n        )\n        self._allow_sql_samples = settings.allow_sql_samples\n        self._allow_instructions = settings.allow_instructions\n        self._allow_sql_generation_reasoning = settings.allow_sql_generation_reasoning\n        self._allow_sql_functions = settings.allow_sql_functions\n        self._engine_info = engine_config(\n            mdl, pipe_components, settings.eval_data_db_path\n        )\n\n    def _get_instructions(self, params: dict) -> list:\n        if self._allow_instructions:\n            return [\n                {\"instruction\": instruction}\n                for instruction in params.get(\"instructions\", [])\n            ]\n        return []\n\n    def _get_samples(self, params: dict) -> list:\n        if self._allow_sql_samples:\n            return params.get(\"samples\", [])\n        return []\n\n    async def _process(self, params: dict, **_) -> dict:\n        result = await self._retrieval.run(query=params[\"input\"])\n        _retrieval_result = result.get(\"construct_retrieval_results\", {})\n\n        documents = _retrieval_result.get(\"retrieval_results\", [])\n        table_ddls = [document.get(\"table_ddl\") for document in documents]\n        has_calculated_field = _retrieval_result.get(\"has_calculated_field\", False)\n        has_metric = _retrieval_result.get(\"has_metric\", False)\n\n        instructions = self._get_instructions(params)\n        samples = self._get_samples(params)\n\n        if self._allow_sql_generation_reasoning:\n            _reasoning = await self._sql_reasoner.run(\n                query=params[\"input\"],\n                contexts=documents,\n                sql_samples=samples,\n            )\n            reasoning = _reasoning.get(\"post_process\", {})\n        else:\n            reasoning = \"\"\n\n        if self._allow_sql_functions:\n            sql_functions = await self._sql_functions_retrieval.run()\n        else:\n            sql_functions = []\n\n        actual_output = await self._generation.run(\n            query=params[\"input\"],\n            contexts=table_ddls,\n            sql_samples=samples,\n            has_calculated_field=has_calculated_field,\n            has_metric=has_metric,\n            sql_generation_reasoning=reasoning,\n            instructions=instructions,\n            sql_functions=sql_functions,\n        )\n\n        params[\"actual_output\"] = actual_output\n        params[\"retrieval_context\"] = extract_units(table_ddls)\n        params[\"has_calculated_field\"] = has_calculated_field\n        params[\"has_metric\"] = has_metric\n        params[\"reasoning\"] = reasoning\n\n        return params\n\n    async def __call__(self, params: dict, **_):\n        return [await self.process(params)]\n\n    @staticmethod\n    def metrics(\n        engine_info: dict,\n        enable_semantics_comparison: bool,\n        component: PipelineComponent,\n    ) -> dict:\n        wren_engine_info = engine_info.copy()\n        wren_engine_info[\"api_endpoint\"] = WREN_ENGINE_API_URL\n\n        return {\n            \"metrics\": [\n                AccuracyMetric(\n                    engine_info=engine_info,\n                    enable_semantics_comparison=enable_semantics_comparison,\n                ),\n                AnswerRelevancyMetric(engine_info=wren_engine_info),\n                FaithfulnessMetric(engine_info=wren_engine_info),\n                ContextualRecallMetric(engine_info=wren_engine_info),\n                ContextualRelevancyMetric(),\n                ContextualPrecisionMetric(),\n                ExactMatchAccuracy(),\n                ExecutionAccuracy(),\n                QuestionToReasoningJudge(**component),\n                ReasoningToSqlJudge(**component),\n                SqlSemanticsJudge(**component),\n            ],\n            \"post_metrics\": [],\n        }\n\n\ndef init(\n    name: Literal[\"retrieval\", \"generation\", \"ask\"],\n    meta: dict,\n    mdl: dict,\n    components: Dict[str, Any],\n    settings: EvalSettings,\n) -> Eval:\n    args = {\n        \"meta\": meta,\n        \"mdl\": mdl,\n        \"pipe_components\": components,\n        \"settings\": settings,\n    }\n\n    match name:\n        case \"retrieval\":\n            return RetrievalPipeline(**args)\n        case \"generation\":\n            return GenerationPipeline(**args)\n        case \"ask\":\n            return AskPipeline(**args)\n        case _:\n            raise ValueError(f\"Invalid pipeline name: {name}\")\n\n\ndef metrics_initiator(\n    pipeline: str,\n    dataset: dict,\n    pipe_components: dict[str, PipelineComponent],\n    enable_semantics_comparison: bool = True,\n    settings: EvalSettings = EvalSettings(),\n) -> dict:\n    engine_info = engine_config(\n        dataset[\"mdl\"],\n        pipe_components,\n        settings.eval_data_db_path,\n    )\n    component = pipe_components[\"evaluation\"]\n    match pipeline:\n        case \"retrieval\":\n            return RetrievalPipeline.metrics(engine_info)\n        case \"generation\":\n            return GenerationPipeline.metrics(\n                engine_info, enable_semantics_comparison, component\n            )\n        case \"ask\":\n            return AskPipeline.metrics(\n                engine_info, enable_semantics_comparison, component\n            )\n"
  },
  {
    "path": "wren-ai-service/eval/prediction.py",
    "content": "import argparse\nimport base64\nimport sys\nimport uuid\nfrom datetime import datetime\nfrom pathlib import Path\nfrom typing import Any, Dict, Tuple\n\nimport orjson\nfrom git import Repo\nfrom langfuse.decorators import langfuse_context\nfrom tomlkit import document, dumps\n\nsys.path.append(f\"{Path().parent.resolve()}\")\nimport eval.pipelines as pipelines\nimport src.providers as provider\nimport src.utils as utils\nfrom eval import EvalSettings\nfrom eval.utils import (\n    load_eval_data_db_to_postgres,\n    parse_db_name,\n    parse_toml,\n    replace_wren_engine_env_variables,\n)\n\n\ndef generate_meta(\n    path: str,\n    dataset: dict,\n    pipe: str,\n    settings: EvalSettings,\n    **kwargs,\n) -> Dict[str, Any]:\n    return {\n        \"langfuse_url\": settings.langfuse_url,\n        \"user_id\": \"wren-evaluator\",  # this property is using for langfuse\n        \"session_id\": f\"eval_{pipe}_{uuid.uuid4()}\",\n        \"date\": datetime.now(),\n        \"dataset_id\": dataset[\"dataset_id\"],\n        \"evaluation_dataset\": path,\n        \"query_count\": len(dataset[\"eval_dataset\"]),\n        \"commit\": obtain_commit_hash(),\n        \"column_indexing_batch_size\": settings.column_indexing_batch_size,\n        \"table_retrieval_size\": settings.table_retrieval_size,\n        \"table_column_retrieval_size\": settings.table_column_retrieval_size,\n        \"pipeline\": pipe,\n        \"batch_size\": settings.batch_size,\n        \"batch_interval\": settings.batch_interval,\n        \"catalog\": dataset[\"mdl\"][\"catalog\"],\n        \"datasource\": settings.datasource,\n    }\n\n\ndef write_prediction(\n    meta: dict, predictions: list[dict], dir_path: str = \"outputs/predictions\"\n) -> None:\n    if Path(dir_path).exists() is False:\n        Path(dir_path).mkdir(parents=True, exist_ok=True)\n\n    output_file = f\"prediction_{meta['session_id']}_{meta['date'].strftime('%Y_%m_%d_%H%M%S')}.toml\"\n    output_path = f\"{dir_path}/{output_file}\"\n\n    doc = document()\n    doc.add(\"meta\", meta)\n    doc.add(\"predictions\", predictions)\n\n    with open(output_path, \"w\") as file:\n        file.write(dumps(doc))\n\n    print(f\"\\n\\nPrediction result is saved at {output_path}\")\n    print(\n        f\"You can then evaluate the prediction result by running `just eval {output_file}`\"\n    )\n\n\ndef obtain_commit_hash() -> str:\n    repo = Repo(search_parent_directories=True)\n    branch = repo.active_branch\n    return f\"{repo.head.commit}@{branch.name}\"\n\n\ndef parse_args() -> Tuple[str, str]:\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\n        \"--file\",\n        \"-F\",\n        type=str,\n        help=\"Eval dataset file path\",\n    )\n    parser.add_argument(\n        \"--pipeline\",\n        \"-P\",\n        type=str,\n        choices=[\"ask\", \"generation\", \"retrieval\"],\n        help=\"Specify the pipeline that you want to evaluate\",\n    )\n    args = parser.parse_args()\n    return args.file, args.pipeline\n\n\nif __name__ == \"__main__\":\n    path, pipe_name = parse_args()\n    dataset = parse_toml(path)\n\n    settings = EvalSettings()\n    # todo: refactor this\n    _mdl = base64.b64encode(orjson.dumps(dataset[\"mdl\"])).decode(\"utf-8\")\n    if \"spider_\" in path or \"bird_\" in path:\n        db_name = parse_db_name(path)\n        if \"spider_\" in path:\n            settings.eval_data_db_path = \"etc/spider1.0/database\"\n            load_eval_data_db_to_postgres(db_name, settings.eval_data_db_path)\n        elif \"bird_\" in path:\n            settings.eval_data_db_path = \"etc/bird/minidev/MINIDEV/dev_databases\"\n            load_eval_data_db_to_postgres(db_name, settings.eval_data_db_path)\n\n        settings.datasource = \"postgres\"\n        _connection_info = base64.b64encode(\n            orjson.dumps(settings.postgres_info)\n        ).decode(\"utf-8\")\n        replace_wren_engine_env_variables(\n            \"wren_ibis\",\n            {\n                \"manifest\": _mdl,\n                \"source\": settings.datasource,\n                \"connection_info\": _connection_info,\n            },\n            settings.config_path,\n        )\n    else:\n        _connection_info = base64.b64encode(\n            orjson.dumps(settings.bigquery_info)\n        ).decode(\"utf-8\")\n        replace_wren_engine_env_variables(\n            \"wren_ibis\",\n            {\n                \"manifest\": _mdl,\n                \"source\": settings.datasource,\n                \"connection_info\": _connection_info,\n            },\n            settings.config_path,\n        )\n\n    pipe_components = provider.generate_components(settings.components)\n    utils.init_langfuse(settings)\n\n    meta = generate_meta(path=path, dataset=dataset, pipe=pipe_name, settings=settings)\n\n    pipe: pipelines.Eval = pipelines.init(\n        pipe_name,\n        meta,\n        mdl=dataset[\"mdl\"],\n        components=pipe_components,\n        settings=settings,\n    )\n\n    predictions = pipe.predict(dataset[\"eval_dataset\"])\n    meta[\"expected_batch_size\"] = meta[\"query_count\"] * pipe.candidate_size\n    meta[\"actual_batch_size\"] = len(predictions)\n\n    write_prediction(meta, predictions)\n    langfuse_context.flush()\n\n    if meta[\"langfuse_url\"]:\n        print(\n            f\"You can also view the prediction result in Langfuse at {meta['langfuse_url']}/sessions/{meta['session_id']}\"\n        )\n"
  },
  {
    "path": "wren-ai-service/eval/preparation.py",
    "content": "\"\"\"\nThis file aims to prepare spider 1.0 or bird eval dataset for text-to-sql eval purpose\n\"\"\"\n\nimport argparse\nimport asyncio\nimport os\nimport zipfile\nfrom collections import defaultdict\nfrom itertools import zip_longest\nfrom pathlib import Path\nfrom urllib.request import urlretrieve\n\nimport gdown\nimport orjson\nimport pandas as pd\n\nfrom eval import (\n    BIRD_DESTINATION_PATH,\n    EVAL_DATASET_DESTINATION_PATH,\n    SPIDER_DESTINATION_PATH,\n    WREN_ENGINE_API_URL,\n)\nfrom eval.utils import (\n    get_contexts_from_sql,\n    get_documents_given_contexts,\n    get_eval_dataset_in_toml_string,\n    get_next_few_items_circular,\n)\n\n\ndef download_spider_data(destination_path: Path):\n    def _download_and_extract(\n        destination_path: Path, path: Path, file_name: str, gdrive_id: str\n    ):\n        if not (destination_path / path).exists():\n            if Path(file_name).exists():\n                os.remove(file_name)\n\n            url = f\"https://drive.google.com/u/0/uc?id={gdrive_id}&export=download\"\n\n            gdown.download(url, file_name, quiet=False)\n\n            with zipfile.ZipFile(file_name, \"r\") as zip_ref:\n                zip_ref.extractall(destination_path)\n\n            os.remove(file_name)\n\n    _download_and_extract(\n        destination_path,\n        \"database\",\n        \"testsuitedatabases.zip\",\n        \"1mkCx2GOFIqNesD4y8TDAO1yX1QZORP5w\",\n    )\n\n    _download_and_extract(\n        destination_path,\n        \"spider_data\",\n        \"spider_data.zip\",\n        \"1403EGqzIDoHMdQF4c9Bkyl7dZLZ5Wt6J\",\n    )\n\n\ndef download_bird_data(destination_path: Path):\n    def _download_and_extract(destination_path: Path, path: Path, file_name: str):\n        if not (destination_path / path).exists():\n            if Path(file_name).exists():\n                os.remove(file_name)\n\n            url = \"https://bird-bench.oss-cn-beijing.aliyuncs.com/minidev.zip\"\n\n            print(f\"Downloading {file_name} from {url}...\")\n            urlretrieve(url, file_name)\n\n            with zipfile.ZipFile(file_name, \"r\") as zip_ref:\n                zip_ref.extractall(destination_path)\n\n            os.remove(file_name)\n\n    _download_and_extract(\n        destination_path,\n        \"minidev\",\n        \"minidev.zip\",\n    )\n\n\ndef get_database_names(path: Path):\n    return [folder.name for folder in path.iterdir() if folder.is_dir()]\n\n\ndef get_tables_by_db(path: Path, key: str):\n    with open(path, \"rb\") as f:\n        json_data = orjson.loads(f.read())\n\n    return {item[key]: item for item in json_data}\n\n\ndef build_mdl_models(database, tables_info, database_info={}):\n    def _build_mdl_columns(tables_info, table_index, table_info=None):\n        def _merge_column_info(column_names_original, column_types):\n            merged_info = []\n            for (table_index, column_name), column_type in zip(\n                column_names_original, column_types\n            ):\n                merged_info.append(\n                    {\n                        \"table_index\": table_index,\n                        \"column_name\": column_name,\n                        \"column_type\": column_type,\n                    }\n                )\n            return merged_info\n\n        def _get_columns_by_table_index(columns, table_index):\n            return list(filter(lambda col: col[\"table_index\"] == table_index, columns))\n\n        _columns = _get_columns_by_table_index(\n            _merge_column_info(\n                tables_info[\"column_names_original\"], tables_info[\"column_types\"]\n            ),\n            table_index,\n        )\n\n        columns_info = {}\n        if table_info:\n            for column_info in table_info:\n                original_col_key = next(\n                    key for key in column_info.keys() if \"original_column_name\" in key\n                )\n                if value_description := column_info.get(\"value_description\", \"\"):\n                    columns_info[column_info[original_col_key]] = (\n                        column_info.get(\"column_description\", \"\")\n                        + \", \"\n                        + value_description\n                    ).strip()\n                else:\n                    columns_info[column_info[original_col_key]] = column_info.get(\n                        \"column_description\", \"\"\n                    ).strip()\n\n        # dealing with some edge cases\n        return [\n            {\n                \"name\": column[\"column_name\"],\n                \"type\": column[\"column_type\"],\n                \"notNull\": False,\n                \"properties\": {\n                    \"description\": columns_info.get(column[\"column_name\"], \"\"),\n                }\n                if columns_info and columns_info.get(column[\"column_name\"], \"\")\n                else {},\n            }\n            for column in _columns\n        ]\n\n    return [\n        {\n            \"name\": table,\n            \"properties\": {},\n            \"tableReference\": {\n                \"catalog\": database,\n                \"schema\": \"main\",\n                \"table\": table,\n            },\n            \"primaryKey\": (\n                tables_info[\"column_names_original\"][primary_key_column_index][-1]\n                if primary_key_column_index\n                else \"\"\n            ),\n            \"columns\": _build_mdl_columns(\n                tables_info, i, database_info.get(table, None)\n            ),\n        }\n        for i, (table, primary_key_column_index) in enumerate(\n            zip_longest(\n                tables_info[\"table_names_original\"],\n                filter(\n                    lambda x: isinstance(x, int), tables_info[\"primary_keys\"]\n                ),  # filter out composite primary keys as of now\n            )\n        )\n    ]\n\n\ndef build_mdl_relationships(tables_info):\n    relationships = []\n    for first, second in tables_info[\"foreign_keys\"]:\n        first_table_index, first_column_name = tables_info[\"column_names_original\"][\n            first\n        ]\n        first_foreign_key_table = tables_info[\"table_names_original\"][first_table_index]\n\n        second_table_index, second_column_name = tables_info[\"column_names_original\"][\n            second\n        ]\n        second_foreign_key_table = tables_info[\"table_names_original\"][\n            second_table_index\n        ]\n\n        relationships.append(\n            {\n                \"name\": f\"{first_foreign_key_table}_{first_column_name}_{second_foreign_key_table}_{second_column_name}\",\n                \"models\": [first_foreign_key_table, second_foreign_key_table],\n                \"joinType\": \"MANY_TO_MANY\",\n                \"condition\": f\"{first_foreign_key_table}.{first_column_name} = {second_foreign_key_table}.{second_column_name}\",\n            }\n        )\n\n    return relationships\n\n\ndef get_ground_truths_by_db(path: Path, key: str):\n    with open(path, \"rb\") as f:\n        json_data = orjson.loads(f.read())\n\n    results = defaultdict(list)\n    for item in json_data:\n        results[item[key]].append(item)\n\n    return results\n\n\ndef build_mdl_by_db_using_spider(destination_path: Path):\n    # get all database names in the spider testsuite\n    database_names = get_database_names(destination_path / \"database\")\n\n    # read tables.json and transform it to be a dictionary with database name as key\n    tables_by_db = get_tables_by_db(\n        destination_path / \"spider_data/tables.json\", \"db_id\"\n    )\n\n    # build mdl for each database by checking the test_tables.json in spider_data\n    mdl_by_db = {}\n    for database in database_names:\n        if tables_info := tables_by_db.get(database):\n            mdl_by_db[database] = {\n                \"catalog\": database,\n                \"schema\": \"main\",\n                \"dataSource\": \"postgres\",\n                \"models\": build_mdl_models(database, tables_info),\n                \"relationships\": build_mdl_relationships(tables_info),\n                \"views\": [],\n                \"metrics\": [],\n            }\n\n    return mdl_by_db\n\n\ndef build_question_sql_pairs_by_db_using_spider(destination_path: Path):\n    # get all database names in the spider testsuite\n    database_names = get_database_names(destination_path / \"database\")\n\n    # get dev.json and transform it to be a dictionary with database name as key\n    ground_truths_by_db = get_ground_truths_by_db(\n        destination_path / \"spider_data/dev.json\", \"db_id\"\n    )\n\n    question_sql_pairs_by_db = defaultdict(list)\n    for database in database_names:\n        if ground_truths_info := ground_truths_by_db.get(database):\n            for ground_truth in ground_truths_info:\n                question_sql_pairs_by_db[database].append(\n                    {\n                        \"question\": ground_truth[\"question\"],\n                        \"sql\": ground_truth[\"query\"],\n                    }\n                )\n\n    return question_sql_pairs_by_db\n\n\ndef build_mdl_by_db_using_bird(destination_path: Path):\n    def _get_database_infos(path: Path):\n        database_infos = {}\n        for folder in path.iterdir():\n            if folder.is_dir():\n                path_to_database_description = (\n                    path / folder.name / \"database_description\"\n                )\n                if (\n                    path_to_database_description in folder.iterdir()\n                    and path_to_database_description.is_dir()\n                ):\n                    database_infos[folder.name] = {}\n                    for file in path_to_database_description.iterdir():\n                        if file.is_file() and file.suffix == \".csv\":\n                            df = pd.read_csv(\n                                file, encoding=\"ISO-8859-1\", keep_default_na=False\n                            )\n                            database_infos[folder.name][file.stem] = df.to_dict(\n                                orient=\"records\"\n                            )\n\n        return database_infos\n\n    database_names = get_database_names(\n        destination_path / \"minidev/MINIDEV/dev_databases\"\n    )\n    database_infos = _get_database_infos(\n        destination_path / \"minidev/MINIDEV/dev_databases\"\n    )\n    tables_by_db = get_tables_by_db(\n        destination_path / \"minidev/MINIDEV/dev_tables.json\", \"db_id\"\n    )\n\n    # build mdl for each database by checking the test_tables.json in spider_data\n    mdl_by_db = {}\n    for database in database_names:\n        if tables_info := tables_by_db.get(database):\n            mdl_by_db[database] = {\n                \"catalog\": database,\n                \"schema\": \"main\",\n                \"dataSource\": \"postgres\",\n                \"models\": build_mdl_models(\n                    database, tables_info, database_infos.get(database, {})\n                ),\n                \"relationships\": build_mdl_relationships(tables_info),\n                \"views\": [],\n                \"metrics\": [],\n            }\n\n    return mdl_by_db\n\n\ndef build_question_sql_pairs_by_db_using_bird(destination_path: Path):\n    database_names = get_database_names(\n        destination_path / \"minidev/MINIDEV/dev_databases\"\n    )\n\n    ground_truths_by_db = get_ground_truths_by_db(\n        destination_path / \"minidev/MINIDEV/mini_dev_sqlite.json\", \"db_id\"\n    )\n\n    question_sql_pairs_by_db = defaultdict(list)\n    for database in database_names:\n        if ground_truths_info := ground_truths_by_db.get(database):\n            for ground_truth in ground_truths_info:\n                question_sql_pairs_by_db[database].append(\n                    {\n                        \"question\": ground_truth[\"question\"],\n                        \"sql\": ground_truth[\"SQL\"],\n                        \"question_id\": ground_truth[\"question_id\"],\n                        \"evidence\": ground_truth[\"evidence\"],\n                        \"difficulty\": ground_truth[\"difficulty\"],\n                    }\n                )\n\n    return question_sql_pairs_by_db\n\n\ndef get_mdls_and_question_sql_pairs_by_common_db(mdl_by_db, question_sql_pairs_by_db):\n    common_dbs = set(mdl_by_db.keys()) & set(question_sql_pairs_by_db.keys())\n\n    return {\n        db: {\"mdl\": mdl_by_db[db], \"ground_truth\": question_sql_pairs_by_db[db]}\n        for db in common_dbs\n    }\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(\n        description=\"Prepare evaluation dataset for text-to-sql tasks.\"\n    )\n    parser.add_argument(\n        \"--dataset\",\n        choices=[\"spider1.0\", \"bird\"],\n        default=\"spider1.0\",\n        help=\"Choose which dataset to prepare (spider1.0 or bird)\",\n    )\n    args = parser.parse_args()\n\n    if args.dataset == \"spider1.0\":\n        destination_path = SPIDER_DESTINATION_PATH\n        print(\n            f\"Downloading {args.dataset} data if unavailable in {destination_path}...\"\n        )\n        download_spider_data(destination_path)\n    elif args.dataset == \"bird\":\n        destination_path = BIRD_DESTINATION_PATH\n        print(\n            f\"Downloading {args.dataset} data if unavailable in {destination_path}...\"\n        )\n        download_bird_data(destination_path)\n\n    print(f\"Building mdl and question sql pairs using {args.dataset} data...\")\n    # get mdl_by_db and question_sql_pairs_by_db whose dbs are present in both dictionaries\n    if args.dataset == \"spider1.0\":\n        mdl_and_ground_truths_by_db = get_mdls_and_question_sql_pairs_by_common_db(\n            build_mdl_by_db_using_spider(destination_path),\n            build_question_sql_pairs_by_db_using_spider(destination_path),\n        )\n    elif args.dataset == \"bird\":\n        mdl_and_ground_truths_by_db = get_mdls_and_question_sql_pairs_by_common_db(\n            build_mdl_by_db_using_bird(destination_path),\n            build_question_sql_pairs_by_db_using_bird(destination_path),\n        )\n\n    print(\"Creating eval dataset...\")\n    questions_size = 0\n    if args.dataset == \"spider1.0\":\n        eval_data_db_path = \"etc/spider1.0/database\"\n    elif args.dataset == \"bird\":\n        eval_data_db_path = \"etc/bird/minidev/MINIDEV/dev_databases\"\n    for db, values in sorted(mdl_and_ground_truths_by_db.items()):\n        candidate_eval_dataset = []\n\n        print(f\"Database: {db}\")\n        for i, ground_truth in enumerate(values[\"ground_truth\"]):\n            context = asyncio.run(\n                get_contexts_from_sql(\n                    ground_truth[\"sql\"],\n                    values[\"mdl\"],\n                    api_endpoint=WREN_ENGINE_API_URL,\n                )\n            )\n\n            # ignore empty context\n            if context:\n                previous_ground_truths = get_next_few_items_circular(\n                    values[\"ground_truth\"], i\n                )\n                sql_pairs = [\n                    {\n                        \"question\": ground_truth[\"question\"],\n                        \"sql\": ground_truth[\"sql\"],\n                    }\n                    for ground_truth in previous_ground_truths\n                ]\n\n                instructions = [ground_truth.get(\"evidence\", \"\")]\n\n                candidate_eval_dataset.append(\n                    {\n                        \"categories\": [],\n                        \"question\": ground_truth[\"question\"],\n                        \"sql\": ground_truth[\"sql\"],\n                        \"context\": context,\n                        \"document\": get_documents_given_contexts(\n                            [context], values[\"mdl\"]\n                        ),\n                        \"samples\": sql_pairs,\n                        \"instructions\": instructions,\n                    }\n                )\n\n        # save eval dataset\n        if candidate_eval_dataset:\n            if args.dataset == \"spider1.0\":\n                file_name = f\"spider_{db}_eval_dataset.toml\"\n            elif args.dataset == \"bird\":\n                file_name = f\"bird_{db}_eval_dataset.toml\"\n\n            with open(f\"{EVAL_DATASET_DESTINATION_PATH}/{file_name}\", \"w\") as f:\n                f.write(\n                    get_eval_dataset_in_toml_string(\n                        values[\"mdl\"], candidate_eval_dataset\n                    )\n                )\n            print(\n                f\"Successfully creating eval dataset of database {db}, which has {len(candidate_eval_dataset)} questions\"\n            )\n            questions_size += len(candidate_eval_dataset)\n            print()\n\n    print(f\"Total questions size: {questions_size}\")\n"
  },
  {
    "path": "wren-ai-service/eval/utils.py",
    "content": "import base64\nimport os\nimport re\nimport uuid\nfrom copy import deepcopy\nfrom datetime import datetime\nfrom typing import Any, Dict, List, Literal, Optional, get_args\n\nimport aiohttp\nimport orjson\nimport psycopg2\nimport requests\nimport tomlkit\nimport yaml\nfrom dotenv import load_dotenv\nfrom openai import AsyncClient\nfrom tomlkit import parse\n\nimport docker\nfrom eval import WREN_ENGINE_API_URL, EvalSettings\nfrom src.providers.engine.wren import WrenEngine\n\nload_dotenv(\".env\", override=True)\n\n\nasync def get_data_from_wren_engine(\n    sql: str,\n    mdl_json: dict,\n    api_endpoint: str,\n    data_source: Optional[str] = None,\n    connection_info: Optional[dict] = None,\n    timeout: float = 300,\n    limit: Optional[int] = None,\n):\n    if data_source == \"duckdb\":\n        async with aiohttp.request(\n            \"GET\",\n            f\"{api_endpoint}/v1/mdl/preview\",\n            json={\n                \"sql\": sql,\n                \"manifest\": mdl_json,\n                \"limit\": 500 if limit is None else limit,\n            },\n        ) as response:\n            data = await response.json()\n\n            if response.status != 200:\n                return {\"data\": [], \"columns\": []}\n\n            column_names = [col[\"name\"] for col in data[\"columns\"]]\n            return {\"data\": data[\"data\"], \"columns\": column_names}\n    else:\n        url = f\"{api_endpoint}/v3/connector/{data_source}/query\"\n        if limit is not None:\n            url += f\"?limit={limit}\"\n\n        async with aiohttp.request(\n            \"POST\",\n            url,\n            json={\n                \"sql\": sql,\n                \"manifestStr\": base64.b64encode(orjson.dumps(mdl_json)).decode(),\n                \"connectionInfo\": connection_info,\n            },\n            timeout=aiohttp.ClientTimeout(total=timeout),\n        ) as response:\n            if response.status != 200:\n                return {\"data\": [], \"columns\": []}\n\n            data = await response.json()\n            column_names = [col for col in data[\"columns\"]]\n\n            return {\"data\": data[\"data\"], \"columns\": column_names}\n\n\nasync def get_contexts_from_sql(\n    sql: str,\n    mdl_json: dict,\n    api_endpoint: str = WREN_ENGINE_API_URL,\n    timeout: float = 300,\n    **kwargs,\n) -> list[str]:\n    def _get_contexts_from_sql_analysis_results(sql_analysis_results: list[dict]):\n        def _compose_contexts_of_select_type(select_items: list[dict]):\n            return [\n                f\"{expr_source['sourceDataset']}.{expr_source['sourceColumn']}\"\n                for select_item in select_items\n                for expr_source in select_item[\"exprSources\"]\n            ]\n\n        def _compose_contexts_of_filter_type(filter: dict):\n            contexts = []\n            if filter[\"type\"] == \"EXPR\":\n                contexts += [\n                    f\"{expr_source['sourceDataset']}.{expr_source['sourceColumn']}\"\n                    for expr_source in filter[\"exprSources\"]\n                ]\n            elif filter[\"type\"] in (\"AND\", \"OR\"):\n                contexts += _compose_contexts_of_filter_type(filter[\"left\"])\n                contexts += _compose_contexts_of_filter_type(filter[\"right\"])\n\n            return contexts\n\n        def _compose_contexts_of_groupby_type(groupby_keys: list[list[dict]]):\n            contexts = []\n            for groupby_key_list in groupby_keys:\n                contexts += [\n                    f\"{expr_source['sourceDataset']}.{expr_source['sourceColumn']}\"\n                    for groupby_key in groupby_key_list\n                    for expr_source in groupby_key[\"exprSources\"]\n                ]\n            return contexts\n\n        def _compose_contexts_of_sorting_type(sortings: list[dict]):\n            return [\n                f\"{expr_source['sourceDataset']}.{expr_source['sourceColumn']}\"\n                for sorting in sortings\n                for expr_source in sorting[\"exprSources\"]\n            ]\n\n        def _compose_contexts_of_relation_type(relation: dict):\n            contexts = []\n            if relation[\"type\"] != \"TABLE\" and relation[\"type\"] != \"SUBQUERY\":\n                contexts += [\n                    f\"{expr_source['sourceDataset']}.{expr_source['sourceColumn']}\"\n                    for expr_source in relation[\"exprSources\"]\n                ]\n\n                contexts += _compose_contexts_of_relation_type(relation[\"left\"])\n                contexts += _compose_contexts_of_relation_type(relation[\"right\"])\n\n            return contexts\n\n        contexts = []\n        for result in sql_analysis_results:\n            if \"selectItems\" in result:\n                contexts += _compose_contexts_of_select_type(result[\"selectItems\"])\n            if \"filter\" in result:\n                contexts += _compose_contexts_of_filter_type(result[\"filter\"])\n            if \"groupByKeys\" in result:\n                contexts += _compose_contexts_of_groupby_type(result[\"groupByKeys\"])\n            if \"sortings\" in result:\n                contexts += _compose_contexts_of_sorting_type(result[\"sortings\"])\n            if \"relation\" in result:\n                contexts += _compose_contexts_of_relation_type(result[\"relation\"])\n\n        return sorted(set(contexts))\n\n    async def _get_sql_analysis(\n        sql: str,\n        mdl_json: dict,\n        api_endpoint: str,\n        timeout: float = 300,\n    ) -> List[dict]:\n        sql = sql.rstrip(\";\") if sql.endswith(\";\") else sql\n        manifest_str = base64.b64encode(orjson.dumps(mdl_json)).decode()\n\n        async with aiohttp.request(\n            \"GET\",\n            f\"{api_endpoint}/v2/analysis/sql\",\n            json={\n                \"sql\": sql,\n                \"manifestStr\": manifest_str,\n            },\n            timeout=aiohttp.ClientTimeout(total=timeout),\n        ) as response:\n            return await response.json()\n\n    sql_analysis_results = await _get_sql_analysis(\n        sql, mdl_json, api_endpoint, timeout=timeout\n    )\n    contexts = _get_contexts_from_sql_analysis_results(sql_analysis_results)\n    return contexts\n\n\ndef parse_toml(path: str) -> Dict[str, Any]:\n    with open(path) as file:\n        return parse(file.read())\n\n\ndef parse_db_name(path: str) -> str:\n    match = re.search(\n        r\"bird_(.+?)_eval_dataset\\.toml|spider_(.+?)_eval_dataset\\.toml\", path\n    )\n    if match:\n        return match.group(1) or match.group(2)\n    else:\n        raise ValueError(\n            f\"Invalid path format: {path}. Expected format: bird_<db_name>_eval_dataset.toml or spider_<db_name>_eval_dataset.toml\"\n        )\n\n\nTRACE_TYPES = Literal[\"execution\", \"shallow\", \"summary\"]\n\n\ndef trace_metadata(\n    meta: dict,\n    type: TRACE_TYPES,\n) -> dict:\n    if type not in get_args(TRACE_TYPES):\n        raise ValueError(\n            f\"Invalid type: {type}, should be one of {get_args(TRACE_TYPES)}\"\n        )\n    return {\n        \"commit\": meta[\"commit\"],\n        \"dataset_id\": meta[\"dataset_id\"],\n        \"column_indexing_batch_size\": meta[\"column_indexing_batch_size\"],\n        \"table_retrieval_size\": meta[\"table_retrieval_size\"],\n        \"table_column_retrieval_size\": meta[\"table_column_retrieval_size\"],\n        \"type\": type,\n        \"pipeline\": meta[\"pipeline\"],\n    }\n\n\ndef engine_config(\n    mdl: dict, pipe_components: dict[str, Any] = {}, path: str = \"\"\n) -> dict:\n    engine = pipe_components.get(\"sql_generation\", {}).get(\"engine\")\n\n    if engine is None:\n        raise ValueError(\n            \"SQL Generation engine not found in pipe_components. Ensure 'sql_generation' key exists and contains 'engine' configuration.\"\n        )\n\n    if isinstance(engine, WrenEngine):\n        print(\"datasource is duckdb\")\n        prepare_duckdb_session_sql(engine._endpoint)\n        prepare_duckdb_init_sql(engine._endpoint, mdl[\"catalog\"], path)\n        return {\n            \"mdl_json\": mdl,\n            \"api_endpoint\": engine._endpoint,\n            \"timeout\": 10,\n            \"data_source\": \"duckdb\",\n        }\n\n    return {\n        \"mdl_json\": mdl,\n        \"data_source\": engine._source,\n        \"api_endpoint\": engine._endpoint,\n        \"connection_info\": engine._connection_info,\n        \"timeout\": 10,\n    }\n\n\ndef get_ddl_commands(mdl: Dict[str, Any]) -> List[str]:\n    def _convert_models_and_relationships(\n        models: List[Dict[str, Any]], relationships: List[Dict[str, Any]]\n    ) -> List[str]:\n        ddl_commands = []\n\n        # A map to store model primary keys for foreign key relationships\n        primary_keys_map = {model[\"name\"]: model[\"primaryKey\"] for model in models}\n\n        for model in models:\n            table_name = model[\"name\"]\n            columns_ddl = []\n            for column in model[\"columns\"]:\n                if \"relationship\" not in column:\n                    if \"properties\" in column:\n                        column[\"properties\"][\"alias\"] = column[\"properties\"].pop(\n                            \"displayName\", \"\"\n                        )\n                        comment = f\"-- {orjson.dumps(column['properties']).decode('utf-8')}\\n  \"\n                    else:\n                        comment = \"\"\n                    if \"isCalculated\" in column and column[\"isCalculated\"]:\n                        comment = (\n                            comment\n                            + f\"-- This column is a Calculated Field\\n  -- column expression: {column['expression']}\\n  \"\n                        )\n                    column_name = column[\"name\"]\n                    column_type = column[\"type\"]\n                    column_ddl = f\"{comment}{column_name} {column_type}\"\n\n                    # If column is a primary key\n                    if column_name == model.get(\"primaryKey\", \"\"):\n                        column_ddl += \" PRIMARY KEY\"\n\n                    columns_ddl.append(column_ddl)\n\n            # Add foreign key constraints based on relationships\n            for relationship in relationships:\n                comment = f'-- {{\"condition\": {relationship[\"condition\"]}, \"joinType\": {relationship[\"joinType\"]}}}\\n  '\n                if (\n                    table_name == relationship[\"models\"][0]\n                    and relationship[\"joinType\"].upper() == \"MANY_TO_ONE\"\n                ):\n                    related_table = relationship[\"models\"][1]\n                    fk_column = relationship[\"condition\"].split(\" = \")[0].split(\".\")[1]\n                    fk_constraint = f\"FOREIGN KEY ({fk_column}) REFERENCES {related_table}({primary_keys_map[related_table]})\"\n                    columns_ddl.append(f\"{comment}{fk_constraint}\")\n                elif (\n                    table_name == relationship[\"models\"][1]\n                    and relationship[\"joinType\"].upper() == \"ONE_TO_MANY\"\n                ):\n                    related_table = relationship[\"models\"][0]\n                    fk_column = relationship[\"condition\"].split(\" = \")[1].split(\".\")[1]\n                    fk_constraint = f\"FOREIGN KEY ({fk_column}) REFERENCES {related_table}({primary_keys_map[related_table]})\"\n                    columns_ddl.append(f\"{comment}{fk_constraint}\")\n                elif (\n                    table_name in relationship[\"models\"]\n                    and relationship[\"joinType\"].upper() == \"ONE_TO_ONE\"\n                ):\n                    index = relationship[\"models\"].index(table_name)\n                    related_table = [\n                        m for m in relationship[\"models\"] if m != table_name\n                    ][0]\n                    fk_column = (\n                        relationship[\"condition\"].split(\" = \")[index].split(\".\")[1]\n                    )\n                    fk_constraint = f\"FOREIGN KEY ({fk_column}) REFERENCES {related_table}({primary_keys_map[related_table]})\"\n                    columns_ddl.append(f\"{comment}{fk_constraint}\")\n\n            if \"properties\" in model:\n                model[\"properties\"][\"alias\"] = model[\"properties\"].pop(\n                    \"displayName\", \"\"\n                )\n                comment = (\n                    f\"\\n/* {orjson.dumps(model['properties']).decode('utf-8')} */\\n\"\n                )\n            else:\n                comment = \"\"\n\n            create_table_ddl = (\n                f\"{comment}CREATE TABLE {table_name} (\\n  \"\n                + \",\\n  \".join(columns_ddl)\n                + \"\\n);\"\n            )\n            ddl_commands.append(create_table_ddl)\n\n        return ddl_commands\n\n    def _convert_views(views: List[Dict[str, Any]]) -> List[str]:\n        def _format(view: Dict[str, Any]) -> str:\n            properties = view[\"properties\"] if \"properties\" in view else \"\"\n            return f\"/* {properties} */\\nCREATE VIEW {view['name']}\\nAS ({view['statement']})\"\n\n        return [_format(view) for view in views]\n\n    def _convert_metrics(metrics: List[Dict[str, Any]]) -> List[str]:\n        ddl_commands = []\n\n        for metric in metrics:\n            table_name = metric[\"name\"]\n            columns_ddl = []\n            for dimension in metric[\"dimension\"]:\n                column_name = dimension[\"name\"]\n                column_type = dimension[\"type\"]\n                comment = \"-- This column is a dimension\\n  \"\n                column_ddl = f\"{comment}{column_name} {column_type}\"\n                columns_ddl.append(column_ddl)\n\n            for measure in metric[\"measure\"]:\n                column_name = measure[\"name\"]\n                column_type = measure[\"type\"]\n                comment = f\"-- This column is a measure\\n  -- expression: {measure['expression']}\\n  \"\n                column_ddl = f\"{comment}{column_name} {column_type}\"\n                columns_ddl.append(column_ddl)\n\n            comment = f\"\\n/* This table is a metric */\\n/* Metric Base Object: {metric['baseObject']} */\\n\"\n            create_table_ddl = (\n                f\"{comment}CREATE TABLE {table_name} (\\n  \"\n                + \",\\n  \".join(columns_ddl)\n                + \"\\n);\"\n            )\n\n            ddl_commands.append(create_table_ddl)\n\n        return ddl_commands\n\n    semantics = {\n        \"models\": [],\n        \"relationships\": mdl[\"relationships\"],\n        \"views\": mdl[\"views\"],\n        \"metrics\": mdl[\"metrics\"],\n    }\n\n    for model in mdl[\"models\"]:\n        columns = []\n        for column in model[\"columns\"]:\n            ddl_column = {\n                \"name\": column[\"name\"],\n                \"type\": column[\"type\"],\n            }\n            if \"properties\" in column:\n                ddl_column[\"properties\"] = column[\"properties\"]\n            if \"relationship\" in column:\n                ddl_column[\"relationship\"] = column[\"relationship\"]\n            if \"expression\" in column:\n                ddl_column[\"expression\"] = column[\"expression\"]\n            if \"isCalculated\" in column:\n                ddl_column[\"isCalculated\"] = column[\"isCalculated\"]\n\n            columns.append(ddl_column)\n\n        semantics[\"models\"].append(\n            {\n                \"type\": \"model\",\n                \"name\": model[\"name\"],\n                \"properties\": model[\"properties\"] if \"properties\" in model else {},\n                \"columns\": columns,\n                \"primaryKey\": model[\"primaryKey\"],\n            }\n        )\n\n    return (\n        _convert_models_and_relationships(\n            semantics[\"models\"], semantics[\"relationships\"]\n        )\n        + _convert_metrics(semantics[\"metrics\"])\n        + _convert_views(semantics[\"views\"])\n    )\n\n\ndef get_documents_given_contexts(\n    contexts_list: list[list[str]], mdl_json: dict\n) -> list[list[dict]]:\n    mdl_json_cloned = deepcopy(mdl_json)\n\n    def _build_partial_mdl_json(\n        contexts_list: list[list[str]], mdl_json: dict\n    ) -> list[dict]:\n        mdj_json_model_lookup_table = {\n            model[\"name\"]: {\n                **model,\n                \"column_lookup\": {\n                    column[\"name\"]: column\n                    for column in model[\"columns\"]\n                    if \"relationship\" not in column\n                },\n                \"relationship_lookup\": {\n                    column[\"relationship\"]: column\n                    for column in model[\"columns\"]\n                    if \"relationship\" in column\n                },\n            }\n            for model in mdl_json[\"models\"]\n        }\n\n        new_mdl_jsons = []\n        for contexts in contexts_list:\n            model_candidates = {}\n            relationship_candidates = []\n            for context in contexts:\n                table_name, column_name = context.split(\".\")\n                model = mdj_json_model_lookup_table.get(table_name)\n                if model:\n                    if table_name not in model_candidates:\n                        model_candidates[table_name] = {\n                            \"name\": model[\"name\"],\n                            \"properties\": model[\"properties\"],\n                            \"tableReference\": model[\"tableReference\"],\n                            \"primaryKey\": model[\"primaryKey\"],\n                            \"columns\": [],\n                        }\n\n                    # add column info\n                    column = mdj_json_model_lookup_table[table_name][\"column_lookup\"][\n                        column_name\n                    ]\n                    model_candidates[table_name][\"columns\"].append(column)\n\n            contexts_in_set = set(contexts)\n            for relationship in mdl_json[\"relationships\"]:\n                relationship_name = relationship[\"name\"]\n                condition_str = \"\".join(\n                    relationship[\"condition\"].split()\n                )  # remove all whitespaces\n                conditions = condition_str.split(\"=\")\n                if (\n                    conditions[0] in contexts_in_set\n                    and conditions[1] in contexts_in_set\n                ):\n                    table_name_first_condition = conditions[0].split(\".\")[0]\n                    table_name_second_condition = conditions[1].split(\".\")[0]\n                    # add relationship column info\n                    if (\n                        relationship_column := mdj_json_model_lookup_table.get(\n                            table_name_first_condition, {}\n                        )\n                        .get(\"relationship_lookup\", {})\n                        .get(relationship_name, {})\n                    ):\n                        model_candidates[table_name_first_condition][\"columns\"].append(\n                            relationship_column\n                        )\n                    elif (\n                        relationship_column := mdj_json_model_lookup_table.get(\n                            table_name_second_condition, {}\n                        )\n                        .get(\"relationship_lookup\", {})\n                        .get(relationship_name, {})\n                    ):\n                        model_candidates[table_name_second_condition][\"columns\"].append(\n                            relationship_column\n                        )\n\n                    # add relationship info\n                    relationship_candidates.append(relationship)\n\n            new_mdl_jsons.append(\n                {\n                    \"models\": list(model_candidates.values()),\n                    \"relationships\": relationship_candidates,\n                    \"views\": [],\n                    \"metrics\": [],\n                }\n            )\n\n        return new_mdl_jsons\n\n    new_mdl_jsons = _build_partial_mdl_json(contexts_list, mdl_json_cloned)\n\n    return [\n        {\n            \"id\": str(i),\n            \"meta\": {\"id\": str(i)},\n            \"content\": ddl_command,\n        }\n        for new_mdl_json in new_mdl_jsons\n        for i, ddl_command in enumerate(get_ddl_commands(new_mdl_json))\n    ]\n\n\ndef get_eval_dataset_in_toml_string(mdl: dict, dataset: list) -> str:\n    doc = tomlkit.document()\n\n    doc.add(\"dataset_id\", str(uuid.uuid4()))\n    doc.add(\"date\", datetime.today().strftime(\"%Y_%m_%d\"))\n    doc.add(\"mdl\", mdl)\n    doc.add(\"eval_dataset\", dataset)\n\n    return tomlkit.dumps(doc, sort_keys=True)\n\n\ndef prepare_duckdb_session_sql(api_endpoint: str):\n    session_sql = \"INSTALL sqlite;\"\n\n    response = requests.put(\n        f\"{api_endpoint}/v1/data-source/duckdb/settings/session-sql\",\n        data=session_sql,\n    )\n\n    assert response.status_code == 200, response.text\n\n\ndef prepare_duckdb_init_sql(api_endpoint: str, db: str, path: str):\n    init_sql = f\"ATTACH '{path}/{db}/{db}.sqlite' AS {db} (TYPE sqlite);\"\n\n    response = requests.put(\n        f\"{api_endpoint}/v1/data-source/duckdb/settings/init-sql\",\n        data=init_sql,\n    )\n\n    assert response.status_code == 200, response.text\n\n\ndef load_eval_data_db_to_postgres(db: str, path: str):\n    abs_path = os.path.abspath(f\"tools/dev/{path}\")\n    postgres_info = EvalSettings().postgres_info\n\n    conn = psycopg2.connect(\n        host=\"localhost\",\n        port=postgres_info[\"port\"],\n        database=postgres_info[\"database\"],\n        user=postgres_info[\"user\"],\n        password=postgres_info[\"password\"],\n    )\n\n    # delete all tables in the database\n    cursor = conn.cursor()\n    cursor.execute(\"DROP SCHEMA IF EXISTS public CASCADE; CREATE SCHEMA public;\")\n    conn.commit()\n    cursor.close()\n    conn.close()\n\n    # load the eval data db to the postgres\n    docker_client = docker.from_env()\n    docker_client.containers.run(\n        \"dimitri/pgloader:latest\",\n        name=\"pgloader\",\n        volumes={abs_path: {\"bind\": \"/data\", \"mode\": \"ro\"}},\n        command=f'pgloader --with \"quote identifiers\" sqlite:///data/{db}/{db}.sqlite pgsql://{postgres_info[\"user\"]}:{postgres_info[\"password\"]}@{postgres_info[\"host\"]}:{postgres_info[\"port\"]}/{postgres_info[\"database\"]}',\n        network=\"wren_wren\",\n        remove=True,\n    )\n\n\ndef get_next_few_items_circular(items: list, i: int, few: int = 5):\n    list_length = len(items)\n    if list_length < few + 1:\n        few = list_length - 1\n    return [items[(i + j) % list_length] for j in range(1, few + 1)]\n\n\ndef get_openai_client(\n    api_key: str = os.getenv(\"OPENAI_API_KEY\"), timeout: float = 60\n) -> AsyncClient:\n    return AsyncClient(\n        api_key=api_key,\n        timeout=timeout,\n    )\n\n\ndef replace_wren_engine_env_variables(engine_type: str, data: dict, config_path: str):\n    assert engine_type in (\"wren_engine\", \"wren_ibis\")\n\n    with open(config_path, \"r\") as f:\n        configs = list(yaml.safe_load_all(f))\n\n        for config in configs:\n            if config.get(\"type\") == \"engine\" and config.get(\"provider\") == engine_type:\n                for key, value in data.items():\n                    config[key] = value\n            if \"pipes\" in config:\n                for i, pipe in enumerate(config[\"pipes\"]):\n                    if \"engine\" in pipe and pipe[\"name\"] != \"sql_functions_retrieval\":\n                        config[\"pipes\"][i][\"engine\"] = engine_type\n\n    with open(config_path, \"w\") as f:\n        yaml.safe_dump_all(configs, f, default_flow_style=False)\n"
  },
  {
    "path": "wren-ai-service/pyproject.toml",
    "content": "[tool.poetry]\nname = \"wren-ai-service\"\nversion = \"0.29.3\"\ndescription = \"\"\nauthors = [\"dev@getwren.ai\"]\nlicense = \"AGPL-3.0\"\nreadme = \"README.md\"\npackage-mode = false\n\n[tool.poetry.dependencies]\npython = \">=3.12.*, <3.13\"\nfastapi = \"^0.121.1\"\nuvicorn = {extras = [\"standard\"], version = \"^0.29.0\"} # Litellm requires uvicorn < 0.30.0\npython-dotenv = \"^1.0.1\"\nhaystack-ai = \"==2.7.0\"\nopenai = \"^1.40.0\"\nqdrant-haystack = \"^7.0.0\"\nbackoff = \"^2.2.1\"\ntqdm = \"^4.66.4\"\nnumpy = \"^1.26.4\"\nsqlparse = \"^0.5.0\"\norjson = \"^3.11.5\"\nsf-hamilton = {version = \"^1.69.0\"}\naiohttp = {extras = [\"speedups\"], version = \"^3.13.3\"}\nollama-haystack = \"^0.0.6\"\nlangfuse = \"^2.43.3\"\nollama = \"^0.2.1\"\ntoml = \"^0.10.2\"\ncachetools = \"^5.5.0\"\npyyaml = \"^6.0.2\"\npydantic-settings = \"^2.5.2\"\ngoogle-auth = \"^2.35.0\"\ntiktoken = \"^0.8.0\"\njsonschema = \"^4.23.0\"\nlitellm = \"^1.75.2\"\nboto3 = \"^1.34.34\" # Litellm requires boto3 = 1.34.34\nqdrant-client = \">=1.12.0,<2.0.0\"\nfilelock = \"^3.20.1\"\nurllib3 = \">=2.6.3\"\nwerkzeug = \">=3.1.5\"  # CVE: safe_join Windows device name vulnerability\nmarshmallow = \">=3.26.2\"  # CVE: Schema.load(many=True) DoS\npillow = \">=12.1.1\"  # CVE: out-of-bounds write when loading PSD images\nprotobuf = \">=5.29.6\"\n\n[tool.poetry.group.dev.dependencies]\npre-commit = \"^3.7.1\"\nstreamlit = \"^1.37.0\"\nwatchdog = \"^4.0.0\"\npandas = \"^2.2.2\"\nmatplotlib = \"^3.9.2\"\nsseclient-py = \"^1.8.0\"\ndspy-ai = \"^2.5.26\"\nrequests = \"^2.32.4\"\nextra-streamlit-components = \"^0.1.71\"\ndeepeval = \"^3.0.0\"\ntomlkit = \"^0.13.0\"\nnltk = \"^3.9.3\"\npsycopg2 = \"^2.9.10\"\n\n[tool.poetry.group.eval.dependencies]\ngitpython = \"^3.1.43\"\nplotly = \"^5.24.1\"\nnbformat = \"^5.1.3\"\nipykernel = \"^6.29.5\"\nitables = \"^2.2.1\"\ngdown = \"^5.2.0\"\nstreamlit-tags = \"^1.2.8\"\ndocker = \"^7.1.0\"\n\n[tool.poetry.group.test.dependencies]\nlocust = \"^2.32.0\"\npytest = \"^8.3.0\"\npytest-cov = \"^6.0.0\"\npytest-asyncio = \"^0.24.0\"\naioresponses = \"^0.7.0\"\npytest-mock = \"^3.14.0\"\n\n[build-system]\nrequires = [\"poetry-core\"]\nbuild-backend = \"poetry.core.masonry.api\"\n"
  },
  {
    "path": "wren-ai-service/ruff.toml",
    "content": "# Exclude a variety of commonly ignored directories.\nexclude = [\n    \".bzr\",\n    \".direnv\",\n    \".eggs\",\n    \".git\",\n    \".git-rewrite\",\n    \".hg\",\n    \".ipynb_checkpoints\",\n    \".mypy_cache\",\n    \".nox\",\n    \".pants.d\",\n    \".pyenv\",\n    \".pytest_cache\",\n    \".pytype\",\n    \".ruff_cache\",\n    \".svn\",\n    \".tox\",\n    \".venv\",\n    \".vscode\",\n    \"__pypackages__\",\n    \"_build\",\n    \"buck-out\",\n    \"build\",\n    \"dist\",\n    \"node_modules\",\n    \"site-packages\",\n    \"venv\",\n]\n\n# Same as Black.\nline-length = 88\nindent-width = 4\n\n# Assume Python 3.8\ntarget-version = \"py38\"\n\n[lint]\n# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`)  codes by default.\n# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or\n# McCabe complexity (`C901`) by default.\nselect = [\"E4\", \"E7\", \"E9\", \"F\", \"I001\"]\nignore = []\n\n# Allow fix for all enabled rules (when `--fix`) is provided.\nfixable = [\"ALL\"]\nunfixable = []\n\n# Allow unused variables when underscore-prefixed.\ndummy-variable-rgx = \"^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$\"\n\n[format]\n# Like Black, use double quotes for strings.\nquote-style = \"double\"\n\n# Like Black, indent with spaces, rather than tabs.\nindent-style = \"space\"\n\n# Like Black, respect magic trailing commas.\nskip-magic-trailing-comma = false\n\n# Like Black, automatically detect the appropriate line ending.\nline-ending = \"auto\"\n\n# Enable auto-formatting of code examples in docstrings. Markdown,\n# reStructuredText code/literal blocks and doctests are all supported.\n#\n# This is currently disabled by default, but it is planned for this\n# to be opt-out in the future.\ndocstring-code-format = false\n\n# Set the line length limit used when formatting code snippets in\n# docstrings.\n#\n# This only has an effect when the `docstring-code-format` setting is\n# enabled.\ndocstring-code-line-length = \"dynamic\"\n"
  },
  {
    "path": "wren-ai-service/src/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/src/__main__.py",
    "content": "from contextlib import asynccontextmanager\n\nimport uvicorn\nfrom fastapi import FastAPI\nfrom fastapi.exceptions import RequestValidationError\nfrom fastapi.middleware.cors import CORSMiddleware\nfrom fastapi.responses import ORJSONResponse, RedirectResponse\nfrom langfuse.decorators import langfuse_context\n\nfrom src.config import settings\nfrom src.globals import (\n    create_service_container,\n    create_service_metadata,\n)\nfrom src.providers import generate_components\nfrom src.utils import (\n    init_langfuse,\n    setup_custom_logger,\n)\nfrom src.web.v1 import routers\n\nsetup_custom_logger(\n    \"wren-ai-service\", level_str=settings.logging_level, is_dev=settings.development\n)\n\n\n# https://fastapi.tiangolo.com/advanced/events/#lifespan\n@asynccontextmanager\nasync def lifespan(app: FastAPI):\n    # startup events\n    pipe_components = generate_components(settings.components)\n    app.state.service_container = create_service_container(pipe_components, settings)\n    app.state.service_metadata = create_service_metadata(pipe_components)\n    init_langfuse(settings)\n\n    yield\n\n    # shutdown events\n    langfuse_context.flush()\n\n\napp = FastAPI(\n    title=\"wren-ai-service API Docs\",\n    lifespan=lifespan,\n    redoc_url=None,\n    default_response_class=ORJSONResponse,\n)\n\napp.add_middleware(\n    CORSMiddleware,\n    allow_origins=[\"*\"],\n    allow_credentials=True,\n    allow_methods=[\"*\"],\n    allow_headers=[\"*\"],\n)\napp.include_router(routers.router, prefix=\"/v1\", tags=[\"v1\"])\nif settings.development:\n    from src.web import development\n\n    app.include_router(development.router, prefix=\"/dev\", tags=[\"dev\"])\n\n\n@app.exception_handler(Exception)\nasync def exception_handler(_, exc: Exception):\n    return ORJSONResponse(\n        status_code=500,\n        content={\"detail\": str(exc)},\n    )\n\n\n@app.exception_handler(RequestValidationError)\nasync def request_exception_handler(_, exc: Exception):\n    return ORJSONResponse(\n        status_code=400,\n        content={\"detail\": str(exc)},\n    )\n\n\n@app.get(\"/\")\ndef root():\n    return RedirectResponse(url=\"/docs\")\n\n\n@app.get(\"/health\")\ndef health():\n    return {\"status\": \"ok\"}\n\n\nif __name__ == \"__main__\":\n    uvicorn.run(\n        \"src.__main__:app\",\n        host=settings.host,\n        port=settings.port,\n        reload=settings.development,\n        reload_includes=[\"src/**/*.py\", \".env.dev\", \"config.yaml\"],\n        reload_excludes=[\"tests/**/*.py\", \"eval/**/*.py\"],\n        workers=1,\n        loop=\"uvloop\",\n        http=\"httptools\",\n    )\n"
  },
  {
    "path": "wren-ai-service/src/config.py",
    "content": "import logging\n\nimport yaml\nfrom dotenv import load_dotenv\nfrom pydantic import Field\nfrom pydantic_settings import BaseSettings\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nclass Settings(BaseSettings):\n    \"\"\"\n    Configuration settings for the Wren AI service.\n\n    The settings are loaded in the following order of precedence:\n    1. Default values: Defined in the class attributes.\n    2. Environment variables: Overrides default values if set.\n    3. .env.dev file: Loads additional settings or overrides previous ones.\n    4. config.yaml file: Provides the highest priority configuration.\n\n    This hierarchical loading allows for flexible configuration management\n    across different environments and deployment scenarios.\n    \"\"\"\n\n    host: str = Field(default=\"127.0.0.1\", alias=\"WREN_AI_SERVICE_HOST\")\n    port: int = Field(default=5555, alias=\"WREN_AI_SERVICE_PORT\")\n\n    # indexing and retrieval config\n    column_indexing_batch_size: int = Field(default=50)\n    table_retrieval_size: int = Field(default=10)\n    table_column_retrieval_size: int = Field(default=100)\n    enable_column_pruning: bool = Field(default=False)\n    historical_question_retrieval_similarity_threshold: float = Field(default=0.9)\n    sql_pairs_similarity_threshold: float = Field(default=0.7)\n    sql_pairs_retrieval_max_size: int = Field(default=10)\n    instructions_similarity_threshold: float = Field(default=0.7)\n    instructions_top_k: int = Field(default=10)\n\n    # generation config\n    allow_intent_classification: bool = Field(default=True)\n    allow_sql_generation_reasoning: bool = Field(default=True)\n    allow_sql_functions_retrieval: bool = Field(default=True)\n    allow_sql_diagnosis: bool = Field(default=True)\n    allow_sql_knowledge_retrieval: bool = Field(default=False)\n    max_histories: int = Field(default=5)\n    max_sql_correction_retries: int = Field(default=3)\n\n    # engine config\n    engine_timeout: float = Field(default=30.0)\n\n    # service config\n    query_cache_ttl: int = Field(default=3600)  # unit: seconds\n    query_cache_maxsize: int = Field(\n        default=1_000_000,\n        comment=\"\"\"\n        the maxsize is a necessary parameter to init cache, but we don't want to expose it to the user\n        so we set it to 1_000_000, which is a large number\n        \"\"\",\n    )\n\n    # user guide config\n    is_oss: bool = Field(default=True)\n    doc_endpoint: str = Field(default=\"https://docs.getwren.ai\")\n\n    # langfuse config\n    # in order to use langfuse, we also need to set the LANGFUSE_SECRET_KEY and LANGFUSE_PUBLIC_KEY in the .env or .env.dev file\n    langfuse_host: str = Field(default=\"https://cloud.langfuse.com\")\n    langfuse_enable: bool = Field(default=True)\n\n    # debug config\n    logging_level: str = Field(default=\"INFO\")\n    development: bool = Field(default=False)\n\n    # this is used to store the config like type: llm, embedder, etc. and we will process them later\n    config_path: str = Field(default=\"config.yaml\")\n    _components: list[dict]\n\n    sql_pairs_path: str = Field(default=\"sql_pairs.json\")\n\n    def __init__(self):\n        load_dotenv(\".env.dev\", override=True)\n        super().__init__()\n        raw = self.config_loader()\n        self.override(raw)\n        self._components = [\n            component for component in raw if \"settings\" not in component\n        ]\n\n    def config_loader(self):\n        try:\n            with open(self.config_path, \"r\") as file:\n                return list(yaml.load_all(file, Loader=yaml.SafeLoader))\n        except FileNotFoundError:\n            message = f\"Warning: Configuration file {self.config_path} not found. Using default settings.\"\n            logger.warning(message)\n            return []\n        except yaml.YAMLError as e:\n            logger.exception(f\"Error parsing YAML file: {e}\")\n            return []\n\n    def override(self, raw: list[dict]) -> None:\n        override_settings = {}\n\n        for doc in raw:\n            if \"settings\" in doc:\n                override_settings = doc[\"settings\"]\n                break\n\n        for key, value in override_settings.items():\n            if hasattr(self, key):\n                setattr(self, key, value)\n            else:\n                message = f\"Warning: Unknown configuration key '{key}' in YAML file.\"\n                logger.warning(message)\n\n    @property\n    def components(self) -> list[dict]:\n        return self._components\n\n\nsettings = Settings()\n"
  },
  {
    "path": "wren-ai-service/src/core/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/src/core/engine.py",
    "content": "import logging\nimport re\nfrom abc import ABCMeta, abstractmethod\nfrom typing import Any, Dict, Optional, Tuple\n\nimport aiohttp\nfrom pydantic import BaseModel\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nclass EngineConfig(BaseModel):\n    provider: str = \"wren_ui\"\n    config: dict = {}\n\n\nclass Engine(metaclass=ABCMeta):\n    @abstractmethod\n    async def execute_sql(\n        self,\n        sql: str,\n        session: aiohttp.ClientSession,\n        dry_run: bool = True,\n        **kwargs,\n    ) -> Tuple[bool, Optional[Dict[str, Any]]]:\n        ...\n\n\ndef clean_generation_result(result: str) -> str:\n    def _normalize_whitespace(s: str) -> str:\n        return re.sub(r\"\\s+\", \" \", s).strip()\n\n    return (\n        _normalize_whitespace(result)\n        .replace(\"```sql\", \"\")\n        .replace(\"```json\", \"\")\n        .replace('\"\"\"', \"\")\n        .replace(\"'''\", \"\")\n        .replace(\"```\", \"\")\n        .replace(\";\", \"\")\n    )\n\n\ndef remove_limit_statement(sql: str) -> str:\n    pattern = r\"\\s*LIMIT\\s+\\d+(\\s*;?\\s*--.*|\\s*;?\\s*)$\"\n    modified_sql = re.sub(pattern, \"\", sql, flags=re.IGNORECASE)\n\n    return modified_sql\n"
  },
  {
    "path": "wren-ai-service/src/core/pipeline.py",
    "content": "from abc import ABCMeta, abstractmethod\nfrom collections.abc import Mapping\nfrom dataclasses import dataclass\nfrom typing import Any, Dict\n\nfrom hamilton.async_driver import AsyncDriver\nfrom hamilton.driver import Driver\nfrom haystack import Pipeline\n\nfrom src.core.engine import Engine\nfrom src.core.provider import DocumentStoreProvider, EmbedderProvider, LLMProvider\n\n\nclass BasicPipeline(metaclass=ABCMeta):\n    def __init__(self, pipe: Pipeline | AsyncDriver | Driver):\n        self._pipe = pipe\n\n    @abstractmethod\n    def run(self, *args, **kwargs) -> Dict[str, Any]:\n        ...\n\n\n@dataclass\nclass PipelineComponent(Mapping):\n    llm_provider: LLMProvider = None\n    embedder_provider: EmbedderProvider = None\n    document_store_provider: DocumentStoreProvider = None\n    engine: Engine = None\n\n    def __getitem__(self, key):\n        return getattr(self, key)\n\n    def __iter__(self):\n        return iter(self.__dict__)\n\n    def __len__(self):\n        return len(self.__dict__)\n"
  },
  {
    "path": "wren-ai-service/src/core/provider.py",
    "content": "from abc import ABCMeta, abstractmethod\n\nfrom haystack.document_stores.types import DocumentStore\n\n\nclass LLMProvider(metaclass=ABCMeta):\n    @abstractmethod\n    def get_generator(self, *args, **kwargs):\n        ...\n\n    def get_model(self):\n        return self._model\n\n    def get_model_kwargs(self):\n        return self._model_kwargs\n\n    def get_context_window_size(self):\n        return self._context_window_size\n\n\nclass EmbedderProvider(metaclass=ABCMeta):\n    @abstractmethod\n    def get_text_embedder(self, *args, **kwargs):\n        ...\n\n    @abstractmethod\n    def get_document_embedder(self, *args, **kwargs):\n        ...\n\n    def get_model(self):\n        return self._embedding_model\n\n\nclass DocumentStoreProvider(metaclass=ABCMeta):\n    @abstractmethod\n    def get_store(self, *args, **kwargs) -> DocumentStore:\n        ...\n\n    @abstractmethod\n    def get_retriever(self, *args, **kwargs):\n        ...\n"
  },
  {
    "path": "wren-ai-service/src/force_deploy.py",
    "content": "# This file is only used for OSS, it will force deploy the mdl for the OSS users\n# Since we allow users to customize llm and embedding models, which means qdrant collections may need to be recreated\n# So, this file automates the process of force deploying the mdl\n\nimport asyncio\nimport os\nfrom pathlib import Path\n\nimport aiohttp\nimport backoff\nfrom dotenv import load_dotenv\n\nif Path(\".env.dev\").exists():\n    load_dotenv(\".env.dev\", override=True)\n\n\n@backoff.on_exception(backoff.expo, aiohttp.ClientError, max_time=60, max_tries=3)\nasync def force_deploy():\n    async with aiohttp.ClientSession() as session:\n        async with session.post(\n            f\"{os.getenv(\"WREN_UI_ENDPOINT\", \"http://wren-ui:3000\")}/api/graphql\",\n            json={\n                \"query\": \"mutation Deploy($force: Boolean) { deploy(force: $force) }\",\n                \"variables\": {\"force\": True},\n            },\n            timeout=aiohttp.ClientTimeout(total=60),  # 60 seconds\n        ) as response:\n            res = await response.json()\n            print(f\"Forcing deployment: {res}\")\n\n\nif os.getenv(\"ENGINE\", \"wren_ui\") == \"wren_ui\":\n    asyncio.run(force_deploy())\n"
  },
  {
    "path": "wren-ai-service/src/force_update_config.py",
    "content": "# This file is only used for local development\n# It will update the config.yaml file to use correct engine name for all pipelines\n# Since the demo app uses the same config.yaml and the app will update the engine names while deploying mdl,\n# so we need to force update the engine names to the correct ones when we would like to use Wren UI\n\nimport yaml\n\n\ndef update_config():\n    # Read the config file\n    with open(\"config.yaml\", \"r\") as file:\n        # Load all documents from YAML file (since it has multiple documents separated by ---)\n        documents = list(yaml.safe_load_all(file))\n\n    # Find the pipeline configuration document\n    for doc in documents:\n        if doc.get(\"type\") == \"pipeline\":\n            # Update engine name in all pipelines\n            for pipe in doc.get(\"pipes\", []):\n                if \"engine\" in pipe:\n                    if pipe[\"name\"] in [\n                        \"sql_functions_retrieval\",\n                        \"sql_knowledge_retrieval\",\n                    ]:\n                        pipe[\"engine\"] = \"wren_ibis\"\n                    else:\n                        pipe[\"engine\"] = \"wren_ui\"\n\n    # Write back to the file\n    with open(\"config.yaml\", \"w\") as file:\n        yaml.safe_dump_all(documents, file, default_flow_style=False)\n\n    print(\"Successfully updated engine names to 'wren_ui' in all pipelines\")\n\n\nif __name__ == \"__main__\":\n    update_config()\n"
  },
  {
    "path": "wren-ai-service/src/globals.py",
    "content": "import logging\nfrom dataclasses import asdict, dataclass\n\nimport toml\n\nfrom src.config import Settings\nfrom src.core.pipeline import PipelineComponent\nfrom src.core.provider import EmbedderProvider, LLMProvider\nfrom src.pipelines import generation, indexing, retrieval\nfrom src.utils import fetch_wren_ai_docs\nfrom src.web.v1 import services\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n@dataclass\nclass ServiceContainer:\n    ask_service: services.AskService\n    ask_feedback_service: services.AskFeedbackService\n    question_recommendation: services.QuestionRecommendation\n    relationship_recommendation: services.RelationshipRecommendation\n    semantics_description: services.SemanticsDescription\n    semantics_preparation_service: services.SemanticsPreparationService\n    chart_service: services.ChartService\n    chart_adjustment_service: services.ChartAdjustmentService\n    sql_answer_service: services.SqlAnswerService\n    sql_pairs_service: services.SqlPairsService\n    sql_question_service: services.SqlQuestionService\n    instructions_service: services.InstructionsService\n    sql_correction_service: services.SqlCorrectionService\n\n\n@dataclass\nclass ServiceMetadata:\n    pipes_metadata: dict\n    service_version: str\n\n\ndef create_service_container(\n    pipe_components: dict[str, PipelineComponent],\n    settings: Settings,\n) -> ServiceContainer:\n    query_cache = {\n        \"maxsize\": settings.query_cache_maxsize,\n        \"ttl\": settings.query_cache_ttl,\n    }\n    wren_ai_docs = fetch_wren_ai_docs(settings.doc_endpoint, settings.is_oss)\n    if not wren_ai_docs:\n        logger.warning(\"Failed to fetch Wren AI docs or response was empty.\")\n\n    _db_schema_retrieval_pipeline = retrieval.DbSchemaRetrieval(\n        **pipe_components[\"db_schema_retrieval\"],\n        table_retrieval_size=settings.table_retrieval_size,\n        table_column_retrieval_size=settings.table_column_retrieval_size,\n    )\n    _sql_pair_indexing_pipeline = indexing.SqlPairs(\n        **pipe_components[\"sql_pairs_indexing\"],\n        sql_pairs_path=settings.sql_pairs_path,\n    )\n    _instructions_indexing_pipeline = indexing.Instructions(\n        **pipe_components[\"instructions_indexing\"],\n    )\n    _sql_pair_retrieval_pipeline = retrieval.SqlPairsRetrieval(\n        **pipe_components[\"sql_pairs_retrieval\"],\n        sql_pairs_similarity_threshold=settings.sql_pairs_similarity_threshold,\n        sql_pairs_retrieval_max_size=settings.sql_pairs_retrieval_max_size,\n    )\n    _instructions_retrieval_pipeline = retrieval.Instructions(\n        **pipe_components[\"instructions_retrieval\"],\n        similarity_threshold=settings.instructions_similarity_threshold,\n        top_k=settings.instructions_top_k,\n    )\n    _sql_correction_pipeline = generation.SQLCorrection(\n        **pipe_components[\"sql_correction\"],\n    )\n    _sql_functions_retrieval_pipeline = retrieval.SqlFunctions(\n        **pipe_components[\"sql_functions_retrieval\"],\n    )\n    _sql_executor_pipeline = retrieval.SQLExecutor(\n        **pipe_components[\"sql_executor\"],\n    )\n    _sql_diagnosis_pipeline = generation.SQLDiagnosis(\n        **pipe_components[\"sql_diagnosis\"],\n    )\n\n    return ServiceContainer(\n        semantics_description=services.SemanticsDescription(\n            pipelines={\n                \"semantics_description\": generation.SemanticsDescription(\n                    **pipe_components[\"semantics_description\"],\n                )\n            },\n            **query_cache,\n        ),\n        semantics_preparation_service=services.SemanticsPreparationService(\n            pipelines={\n                \"db_schema\": indexing.DBSchema(\n                    **pipe_components[\"db_schema_indexing\"],\n                    column_batch_size=settings.column_indexing_batch_size,\n                ),\n                \"historical_question\": indexing.HistoricalQuestion(\n                    **pipe_components[\"historical_question_indexing\"],\n                ),\n                \"table_description\": indexing.TableDescription(\n                    **pipe_components[\"table_description_indexing\"],\n                ),\n                \"sql_pairs\": _sql_pair_indexing_pipeline,\n                \"instructions\": _instructions_indexing_pipeline,\n                \"project_meta\": indexing.ProjectMeta(\n                    **pipe_components[\"project_meta_indexing\"],\n                ),\n            },\n            **query_cache,\n        ),\n        ask_service=services.AskService(\n            pipelines={\n                \"intent_classification\": generation.IntentClassification(\n                    **pipe_components[\"intent_classification\"],\n                    wren_ai_docs=wren_ai_docs,\n                ),\n                \"misleading_assistance\": generation.MisleadingAssistance(\n                    **pipe_components[\"misleading_assistance\"],\n                ),\n                \"data_assistance\": generation.DataAssistance(\n                    **pipe_components[\"data_assistance\"]\n                ),\n                \"user_guide_assistance\": generation.UserGuideAssistance(\n                    **pipe_components[\"user_guide_assistance\"],\n                    wren_ai_docs=wren_ai_docs,\n                ),\n                \"db_schema_retrieval\": _db_schema_retrieval_pipeline,\n                \"historical_question\": retrieval.HistoricalQuestionRetrieval(\n                    **pipe_components[\"historical_question_retrieval\"],\n                    historical_question_retrieval_similarity_threshold=settings.historical_question_retrieval_similarity_threshold,\n                ),\n                \"sql_pairs_retrieval\": _sql_pair_retrieval_pipeline,\n                \"instructions_retrieval\": _instructions_retrieval_pipeline,\n                \"sql_generation\": generation.SQLGeneration(\n                    **pipe_components[\"sql_generation\"],\n                ),\n                \"sql_generation_reasoning\": generation.SQLGenerationReasoning(\n                    **pipe_components[\"sql_generation_reasoning\"],\n                ),\n                \"followup_sql_generation_reasoning\": generation.FollowUpSQLGenerationReasoning(\n                    **pipe_components[\"followup_sql_generation_reasoning\"],\n                ),\n                \"sql_correction\": _sql_correction_pipeline,\n                \"followup_sql_generation\": generation.FollowUpSQLGeneration(\n                    **pipe_components[\"followup_sql_generation\"],\n                ),\n                \"sql_functions_retrieval\": _sql_functions_retrieval_pipeline,\n                \"sql_diagnosis\": _sql_diagnosis_pipeline,\n                \"sql_knowledge_retrieval\": retrieval.SqlKnowledges(\n                    **pipe_components[\"sql_knowledge_retrieval\"],\n                ),\n            },\n            allow_intent_classification=settings.allow_intent_classification,\n            allow_sql_generation_reasoning=settings.allow_sql_generation_reasoning,\n            allow_sql_functions_retrieval=settings.allow_sql_functions_retrieval,\n            allow_sql_diagnosis=settings.allow_sql_diagnosis,\n            allow_sql_knowledge_retrieval=settings.allow_sql_knowledge_retrieval,\n            max_histories=settings.max_histories,\n            enable_column_pruning=settings.enable_column_pruning,\n            max_sql_correction_retries=settings.max_sql_correction_retries,\n            **query_cache,\n        ),\n        ask_feedback_service=services.AskFeedbackService(\n            pipelines={\n                \"db_schema_retrieval\": _db_schema_retrieval_pipeline,\n                \"sql_pairs_retrieval\": _sql_pair_retrieval_pipeline,\n                \"instructions_retrieval\": _instructions_retrieval_pipeline,\n                \"sql_functions_retrieval\": _sql_functions_retrieval_pipeline,\n                \"sql_regeneration\": generation.SQLRegeneration(\n                    **pipe_components[\"sql_regeneration\"],\n                ),\n                \"sql_correction\": _sql_correction_pipeline,\n                \"sql_diagnosis\": _sql_diagnosis_pipeline,\n                \"sql_knowledge_retrieval\": retrieval.SqlKnowledges(\n                    **pipe_components[\"sql_knowledge_retrieval\"],\n                ),\n            },\n            allow_sql_functions_retrieval=settings.allow_sql_functions_retrieval,\n            allow_sql_diagnosis=settings.allow_sql_diagnosis,\n            allow_sql_knowledge_retrieval=settings.allow_sql_knowledge_retrieval,\n            **query_cache,\n        ),\n        chart_service=services.ChartService(\n            pipelines={\n                \"sql_executor\": _sql_executor_pipeline,\n                \"chart_generation\": generation.ChartGeneration(\n                    **pipe_components[\"chart_generation\"],\n                ),\n            },\n            **query_cache,\n        ),\n        chart_adjustment_service=services.ChartAdjustmentService(\n            pipelines={\n                \"sql_executor\": _sql_executor_pipeline,\n                \"chart_adjustment\": generation.ChartAdjustment(\n                    **pipe_components[\"chart_adjustment\"],\n                ),\n            },\n            **query_cache,\n        ),\n        sql_answer_service=services.SqlAnswerService(\n            pipelines={\n                \"preprocess_sql_data\": retrieval.PreprocessSqlData(\n                    **pipe_components[\"preprocess_sql_data\"],\n                ),\n                \"sql_answer\": generation.SQLAnswer(\n                    **pipe_components[\"sql_answer\"],\n                ),\n            },\n            **query_cache,\n        ),\n        relationship_recommendation=services.RelationshipRecommendation(\n            pipelines={\n                \"relationship_recommendation\": generation.RelationshipRecommendation(\n                    **pipe_components[\"relationship_recommendation\"],\n                )\n            },\n            **query_cache,\n        ),\n        question_recommendation=services.QuestionRecommendation(\n            pipelines={\n                \"question_recommendation\": generation.QuestionRecommendation(\n                    **pipe_components[\"question_recommendation\"],\n                ),\n                \"db_schema_retrieval\": _db_schema_retrieval_pipeline,\n                \"sql_generation\": generation.SQLGeneration(\n                    **pipe_components[\"question_recommendation_sql_generation\"],\n                ),\n                \"sql_pairs_retrieval\": _sql_pair_retrieval_pipeline,\n                \"instructions_retrieval\": _instructions_retrieval_pipeline,\n                \"sql_functions_retrieval\": _sql_functions_retrieval_pipeline,\n                \"sql_knowledge_retrieval\": retrieval.SqlKnowledges(\n                    **pipe_components[\"sql_knowledge_retrieval\"],\n                ),\n            },\n            allow_sql_functions_retrieval=settings.allow_sql_functions_retrieval,\n            allow_sql_knowledge_retrieval=settings.allow_sql_knowledge_retrieval,\n            **query_cache,\n        ),\n        sql_pairs_service=services.SqlPairsService(\n            pipelines={\n                \"sql_pairs\": _sql_pair_indexing_pipeline,\n            },\n            **query_cache,\n        ),\n        sql_question_service=services.SqlQuestionService(\n            pipelines={\n                \"sql_question_generation\": generation.SQLQuestion(\n                    **pipe_components[\"sql_question_generation\"],\n                )\n            },\n            **query_cache,\n        ),\n        instructions_service=services.InstructionsService(\n            pipelines={\n                \"instructions_indexing\": _instructions_indexing_pipeline,\n            },\n            **query_cache,\n        ),\n        sql_correction_service=services.SqlCorrectionService(\n            pipelines={\n                \"sql_tables_extraction\": generation.SQLTablesExtraction(\n                    **pipe_components[\"sql_tables_extraction\"],\n                ),\n                \"db_schema_retrieval\": _db_schema_retrieval_pipeline,\n                \"sql_correction\": _sql_correction_pipeline,\n                \"sql_knowledge_retrieval\": retrieval.SqlKnowledges(\n                    **pipe_components[\"sql_knowledge_retrieval\"],\n                ),\n            },\n            allow_sql_knowledge_retrieval=settings.allow_sql_knowledge_retrieval,\n            **query_cache,\n        ),\n    )\n\n\n# Create a dependency that will be used to access the ServiceContainer\ndef get_service_container():\n    from src.__main__ import app\n\n    return app.state.service_container\n\n\ndef create_service_metadata(\n    pipe_components: dict[str, PipelineComponent],\n    pyproject_path: str = \"pyproject.toml\",\n) -> ServiceMetadata:\n    \"\"\"\n    This service metadata is used for logging purposes and will be sent to Langfuse.\n    \"\"\"\n\n    def _get_version_from_pyproject() -> str:\n        with open(pyproject_path, \"r\") as f:\n            pyproject = toml.load(f)\n            return pyproject[\"tool\"][\"poetry\"][\"version\"]\n\n    def _convert_pipe_metadata(\n        llm_provider: LLMProvider,\n        embedder_provider: EmbedderProvider,\n        **_,\n    ) -> dict:\n        llm_metadata = (\n            {\n                \"llm_model\": llm_provider.get_model(),\n                \"llm_model_kwargs\": llm_provider.get_model_kwargs(),\n            }\n            if llm_provider\n            else {}\n        )\n\n        embedding_metadata = (\n            {\n                \"embedding_model\": embedder_provider.get_model(),\n            }\n            if embedder_provider\n            else {}\n        )\n        return {**llm_metadata, **embedding_metadata}\n\n    pipes_metadata = {\n        pipe_name: _convert_pipe_metadata(**asdict(component))\n        for pipe_name, component in pipe_components.items()\n    }\n\n    service_version = _get_version_from_pyproject()\n\n    logger.info(f\"Service version: {service_version}\")\n\n    return ServiceMetadata(pipes_metadata, service_version)\n\n\n# Create a dependency that will be used to access the ServiceMetadata\ndef get_service_metadata():\n    from src.__main__ import app\n\n    return app.state.service_metadata\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/src/pipelines/common.py",
    "content": "import re\nfrom typing import Any, List, Optional, Tuple\n\nfrom haystack import Document, component\n\n\ndef get_engine_supported_data_type(data_type: str) -> str:\n    \"\"\"\n    This function makes sure downstream ai pipeline get column data types in a format that is supported by the data engine.\n    \"\"\"\n    match data_type.upper():\n        case \"BPCHAR\" | \"NAME\" | \"UUID\" | \"INET\":\n            return \"VARCHAR\"\n        case \"OID\":\n            return \"INT\"\n        case \"BIGNUMERIC\":\n            return \"NUMERIC\"\n        case \"BYTES\":\n            return \"BYTEA\"\n        case \"DATETIME\":\n            return \"TIMESTAMP\"\n        case \"FLOAT64\":\n            return \"DOUBLE\"\n        case \"INT64\":\n            return \"BIGINT\"\n        case _:\n            return data_type.upper()\n\n\ndef build_table_ddl(\n    content: dict, columns: Optional[set[str]] = None, tables: Optional[set[str]] = None\n) -> Tuple[str, bool, bool]:\n    columns_ddl = []\n    has_calculated_field = False\n    has_json_field = False\n\n    for column in content[\"columns\"]:\n        if column[\"type\"] == \"COLUMN\":\n            if (\n                (not columns or (columns and column[\"name\"] in columns))\n                and column[\"data_type\"].lower()\n                != \"unknown\"  # quick fix: filtering out UNKNOWN column type\n            ):\n                if \"This column is a Calculated Field\" in column[\"comment\"]:\n                    has_calculated_field = True\n                if column[\"data_type\"].lower() == \"json\":\n                    has_json_field = True\n                column_ddl = f\"{column['comment']}{column['name']} {get_engine_supported_data_type(column['data_type'])}\"\n                if column[\"is_primary_key\"]:\n                    column_ddl += \" PRIMARY KEY\"\n                columns_ddl.append(column_ddl)\n        elif column[\"type\"] == \"FOREIGN_KEY\":\n            if not tables or (tables and set(column[\"tables\"]).issubset(tables)):\n                columns_ddl.append(f\"{column['comment']}{column['constraint']}\")\n\n    return (\n        (\n            f\"{content['comment']}CREATE TABLE {content['name']} (\\n  \"\n            + \",\\n  \".join(columns_ddl)\n            + \"\\n);\"\n        ),\n        has_calculated_field,\n        has_json_field,\n    )\n\n\nasync def retrieve_metadata(project_id: str, retriever) -> dict[str, Any]:\n    filters = None\n    if project_id:\n        filters = {\n            \"operator\": \"AND\",\n            \"conditions\": [\n                {\"field\": \"project_id\", \"operator\": \"==\", \"value\": project_id},\n            ],\n        }\n\n    result = await retriever.run(query_embedding=[], filters=filters)\n    documents = result[\"documents\"]\n\n    # only one document for a project, thus we can return the first one\n    if documents:\n        doc = documents[0]\n        return doc.meta\n    else:\n        return {}\n\n\n@component\nclass ScoreFilter:\n    @component.output_types(\n        documents=List[Document],\n    )\n    def run(\n        self,\n        documents: List[Document],\n        score: float = 0.9,\n        max_size: int = 10,\n    ):\n        return {\n            \"documents\": sorted(\n                filter(lambda document: document.score >= score, documents),\n                key=lambda document: document.score,\n                reverse=True,\n            )[:max_size]\n        }\n\n\nMULTIPLE_NEW_LINE_REGEX = re.compile(r\"\\n{3,}\")\n\n\ndef clean_up_new_lines(text: str) -> str:\n    return MULTIPLE_NEW_LINE_REGEX.sub(\"\\n\\n\\n\", text)\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/__init__.py",
    "content": "from .chart_adjustment import ChartAdjustment\nfrom .chart_generation import ChartGeneration\nfrom .data_assistance import DataAssistance\nfrom .followup_sql_generation import FollowUpSQLGeneration\nfrom .followup_sql_generation_reasoning import FollowUpSQLGenerationReasoning\nfrom .intent_classification import IntentClassification\nfrom .misleading_assistance import MisleadingAssistance\nfrom .question_recommendation import QuestionRecommendation\nfrom .relationship_recommendation import RelationshipRecommendation\nfrom .semantics_description import SemanticsDescription\nfrom .sql_answer import SQLAnswer\nfrom .sql_correction import SQLCorrection\nfrom .sql_diagnosis import SQLDiagnosis\nfrom .sql_generation import SQLGeneration\nfrom .sql_generation_reasoning import SQLGenerationReasoning\nfrom .sql_question import SQLQuestion\nfrom .sql_regeneration import SQLRegeneration\nfrom .sql_tables_extraction import SQLTablesExtraction\nfrom .user_guide_assistance import UserGuideAssistance\n\n__all__ = [\n    \"ChartGeneration\",\n    \"ChartAdjustment\",\n    \"DataAssistance\",\n    \"FollowUpSQLGeneration\",\n    \"IntentClassification\",\n    \"QuestionRecommendation\",\n    \"RelationshipRecommendation\",\n    \"SemanticsDescription\",\n    \"SQLAnswer\",\n    \"SQLCorrection\",\n    \"SQLDiagnosis\",\n    \"SQLGeneration\",\n    \"SQLGenerationReasoning\",\n    \"UserGuideAssistance\",\n    \"SQLQuestion\",\n    \"SQLRegeneration\",\n    \"FollowUpSQLGenerationReasoning\",\n    \"MisleadingAssistance\",\n    \"SQLTablesExtraction\",\n]\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/chart_adjustment.py",
    "content": "import logging\nimport sys\nfrom typing import Any, Dict\n\nimport orjson\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import LLMProvider\nfrom src.pipelines.common import clean_up_new_lines\nfrom src.pipelines.generation.utils.chart import (\n    ChartDataPreprocessor,\n    ChartGenerationPostProcessor,\n    ChartGenerationResults,\n    chart_generation_instructions,\n)\nfrom src.utils import trace_cost\nfrom src.web.v1.services.chart_adjustment import ChartAdjustmentOption\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nchart_adjustment_system_prompt = f\"\"\"\n### TASK ###\n\nYou are a data analyst great at visualizing data using vega-lite! Given the user's question, SQL, sample data, sample column values, original vega-lite schema and adjustment options, \nyou need to re-generate vega-lite schema in JSON and provide suitable chart type.\nBesides, you need to give a concise and easy-to-understand reasoning to describe why you provide such vega-lite schema based on the question, SQL, sample data, sample column values, original vega-lite schema and adjustment options.\n\n{chart_generation_instructions}\n- If you think the adjustment options are not suitable for the data, you can return an empty string for the schema and chart type and give reasoning to explain why.\n\n### OUTPUT FORMAT ###\n\nPlease provide your chain of thought reasoning, chart type and the vega-lite schema in JSON format.\n\n{{\n    \"reasoning\": <REASON_TO_CHOOSE_THE_SCHEMA_IN_STRING_FORMATTED_IN_LANGUAGE_PROVIDED_BY_USER>,\n    \"chart_type\": \"line\" | \"multi_line\" | \"bar\" | \"pie\" | \"grouped_bar\" | \"stacked_bar\" | \"area\" | \"\",\n    \"chart_schema\": <VEGA_LITE_JSON_SCHEMA>\n}}\n\"\"\"\n\nchart_adjustment_user_prompt_template = \"\"\"\n### INPUT ###\nOriginal Question: {{ query }}\nOriginal SQL: {{ sql }}\nOriginal Vega-Lite Schema: {{ chart_schema }}\nSample Data: {{ sample_data }}\nSample Column Values: {{ sample_column_values }}\nLanguage: {{ language }}\n\nAdjustment Options:\n- Chart Type: {{ adjustment_option.chart_type }}\n{% if adjustment_option.chart_type != \"pie\" %}\n{% if adjustment_option.x_axis %}\n- X Axis: {{ adjustment_option.x_axis }}\n{% endif %}\n{% if adjustment_option.y_axis %}\n- Y Axis: {{ adjustment_option.y_axis }}\n{% endif %}\n{% endif %}\n{% if adjustment_option.x_offset and adjustment_option.chart_type == \"grouped_bar\" %}\n- X Offset: {{ adjustment_option.x_offset }}\n{% endif %}\n{% if adjustment_option.color and adjustment_option.chart_type != \"area\" %}\n- Color: {{ adjustment_option.color }}\n{% endif %}\n{% if adjustment_option.theta and adjustment_option.chart_type == \"pie\" %}\n- Theta: {{ adjustment_option.theta }}\n{% endif %}\n\nPlease think step by step\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef preprocess_data(\n    data: Dict[str, Any], chart_data_preprocessor: ChartDataPreprocessor\n) -> dict:\n    return chart_data_preprocessor.run(data)\n\n\n@observe(capture_input=False)\ndef prompt(\n    query: str,\n    sql: str,\n    adjustment_option: ChartAdjustmentOption,\n    chart_schema: dict,\n    preprocess_data: dict,\n    language: str,\n    prompt_builder: PromptBuilder,\n) -> dict:\n    sample_data = preprocess_data.get(\"sample_data\")\n    sample_column_values = preprocess_data.get(\"sample_column_values\")\n\n    _prompt = prompt_builder.run(\n        query=query,\n        sql=sql,\n        adjustment_option=adjustment_option,\n        chart_schema=chart_schema,\n        sample_data=sample_data,\n        sample_column_values=sample_column_values,\n        language=language,\n    )\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def generate_chart_adjustment(\n    prompt: dict,\n    generator: Any,\n    generator_name: str,\n) -> dict:\n    return await generator(prompt=prompt.get(\"prompt\")), generator_name\n\n\n@observe(capture_input=False)\ndef post_process(\n    generate_chart_adjustment: dict,\n    vega_schema: Dict[str, Any],\n    preprocess_data: dict,\n    post_processor: ChartGenerationPostProcessor,\n) -> dict:\n    return post_processor.run(\n        generate_chart_adjustment.get(\"replies\"),\n        vega_schema,\n        preprocess_data[\"sample_data\"],\n    )\n\n\n## End of Pipeline\nCHART_ADJUSTMENT_MODEL_KWARGS = {\n    \"response_format\": {\n        \"type\": \"json_schema\",\n        \"json_schema\": {\n            \"name\": \"chart_adjustment_results\",\n            \"schema\": ChartGenerationResults.model_json_schema(),\n        },\n    }\n}\n\n\nclass ChartAdjustment(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        **kwargs,\n    ):\n        self._components = {\n            \"prompt_builder\": PromptBuilder(\n                template=chart_adjustment_user_prompt_template\n            ),\n            \"generator\": llm_provider.get_generator(\n                system_prompt=chart_adjustment_system_prompt,\n                generation_kwargs=CHART_ADJUSTMENT_MODEL_KWARGS,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n            \"chart_data_preprocessor\": ChartDataPreprocessor(),\n            \"post_processor\": ChartGenerationPostProcessor(),\n        }\n\n        with open(\"src/pipelines/generation/utils/vega-lite-schema-v5.json\", \"r\") as f:\n            _vega_schema = orjson.loads(f.read())\n\n        self._configs = {\n            \"vega_schema\": _vega_schema,\n        }\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"Chart Adjustment\")\n    async def run(\n        self,\n        query: str,\n        sql: str,\n        adjustment_option: ChartAdjustmentOption,\n        chart_schema: dict,\n        data: dict,\n        language: str,\n    ) -> dict:\n        logger.info(\"Chart Adjustment pipeline is running...\")\n\n        return await self._pipe.execute(\n            [\"post_process\"],\n            inputs={\n                \"query\": query,\n                \"sql\": sql,\n                \"adjustment_option\": adjustment_option,\n                \"chart_schema\": chart_schema,\n                \"data\": data,\n                \"language\": language,\n                **self._components,\n                **self._configs,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/chart_generation.py",
    "content": "import logging\nimport sys\nfrom typing import Any, Dict, Optional\n\nimport orjson\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import LLMProvider\nfrom src.pipelines.common import clean_up_new_lines\nfrom src.pipelines.generation.utils.chart import (\n    ChartDataPreprocessor,\n    ChartGenerationPostProcessor,\n    ChartGenerationResults,\n    chart_generation_instructions,\n)\nfrom src.utils import trace_cost\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\nchart_generation_system_prompt = f\"\"\"\n### TASK ###\n\nYou are a data analyst great at visualizing data using vega-lite! Given the user's question, SQL, sample data and sample column values, you need to generate vega-lite schema in JSON and provide suitable chart type.\nBesides, you need to give a concise and easy-to-understand reasoning to describe why you provide such vega-lite schema based on the question, SQL, sample data and sample column values.\n\n{chart_generation_instructions}\n- If the user provides a custom instruction, it should be followed strictly and you should use it to change the style of response for reasoning.\n\n### OUTPUT FORMAT ###\n\nPlease provide your chain of thought reasoning, chart type and the vega-lite schema in JSON format.\n\n{{\n    \"reasoning\": <REASON_TO_CHOOSE_THE_SCHEMA_IN_STRING_FORMATTED_IN_LANGUAGE_PROVIDED_BY_USER>,\n    \"chart_type\": \"line\" | \"multi_line\" | \"bar\" | \"pie\" | \"grouped_bar\" | \"stacked_bar\" | \"area\" | \"\",\n    \"chart_schema\": <VEGA_LITE_JSON_SCHEMA>\n}}\n\"\"\"\n\nchart_generation_user_prompt_template = \"\"\"\n### INPUT ###\nQuestion: {{ query }}\nSQL: {{ sql }}\nSample Data: {{ sample_data }}\nSample Column Values: {{ sample_column_values }}\nLanguage: {{ language }}\nCustom Instruction: {{ custom_instruction }}\n\nPlease think step by step\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef preprocess_data(\n    data: Dict[str, Any], chart_data_preprocessor: ChartDataPreprocessor\n) -> dict:\n    return chart_data_preprocessor.run(data)\n\n\n@observe(capture_input=False)\ndef prompt(\n    query: str,\n    sql: str,\n    preprocess_data: dict,\n    language: str,\n    custom_instruction: str,\n    prompt_builder: PromptBuilder,\n) -> dict:\n    sample_data = preprocess_data.get(\"sample_data\")\n    sample_column_values = preprocess_data.get(\"sample_column_values\")\n\n    _prompt = prompt_builder.run(\n        query=query,\n        sql=sql,\n        sample_data=sample_data,\n        sample_column_values=sample_column_values,\n        language=language,\n        custom_instruction=custom_instruction,\n    )\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def generate_chart(prompt: dict, generator: Any, generator_name: str) -> dict:\n    return await generator(prompt=prompt.get(\"prompt\")), generator_name\n\n\n@observe(capture_input=False)\ndef post_process(\n    generate_chart: dict,\n    vega_schema: Dict[str, Any],\n    remove_data_from_chart_schema: bool,\n    preprocess_data: dict,\n    post_processor: ChartGenerationPostProcessor,\n) -> dict:\n    return post_processor.run(\n        generate_chart.get(\"replies\"),\n        vega_schema,\n        preprocess_data[\"sample_data\"],\n        remove_data_from_chart_schema,\n    )\n\n\n## End of Pipeline\nCHART_GENERATION_MODEL_KWARGS = {\n    \"response_format\": {\n        \"type\": \"json_schema\",\n        \"json_schema\": {\n            \"name\": \"chart_generation_schema\",\n            \"schema\": ChartGenerationResults.model_json_schema(),\n        },\n    }\n}\n\n\nclass ChartGeneration(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        **kwargs,\n    ):\n        self._components = {\n            \"prompt_builder\": PromptBuilder(\n                template=chart_generation_user_prompt_template\n            ),\n            \"generator\": llm_provider.get_generator(\n                system_prompt=chart_generation_system_prompt,\n                generation_kwargs=CHART_GENERATION_MODEL_KWARGS,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n            \"chart_data_preprocessor\": ChartDataPreprocessor(),\n            \"post_processor\": ChartGenerationPostProcessor(),\n        }\n\n        with open(\"src/pipelines/generation/utils/vega-lite-schema-v5.json\", \"r\") as f:\n            _vega_schema = orjson.loads(f.read())\n\n        self._configs = {\n            \"vega_schema\": _vega_schema,\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"Chart Generation\")\n    async def run(\n        self,\n        query: str,\n        sql: str,\n        data: dict,\n        language: str,\n        remove_data_from_chart_schema: bool = True,\n        custom_instruction: Optional[str] = None,\n    ) -> dict:\n        logger.info(\"Chart Generation pipeline is running...\")\n        return await self._pipe.execute(\n            [\"post_process\"],\n            inputs={\n                \"query\": query,\n                \"sql\": sql,\n                \"data\": data,\n                \"language\": language,\n                \"remove_data_from_chart_schema\": remove_data_from_chart_schema,\n                \"custom_instruction\": custom_instruction or \"\",\n                **self._components,\n                **self._configs,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/data_assistance.py",
    "content": "import asyncio\nimport logging\nimport sys\nfrom typing import Any, Optional\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import LLMProvider\nfrom src.pipelines.common import clean_up_new_lines\nfrom src.utils import trace_cost\nfrom src.web.v1.services.ask import AskHistory\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\ndata_assistance_system_prompt = \"\"\"\n### TASK ###\nYou are a data analyst great at answering user's questions about given database schema.\nPlease carefully read user's question and database schema to answer it in easy to understand manner\nusing the Markdown format. Your goal is to help guide user understand its database!\n\n### INSTRUCTIONS ###\n\n- Answer must be in the same language user specified.\n- There should be proper line breaks, whitespace, and Markdown formatting(headers, lists, tables, etc.) in your response.\n- If the language is Traditional/Simplified Chinese, Korean, or Japanese, the maximum response length is 150 words; otherwise, the maximum response length is 110 words.\n- MUST NOT add SQL code in your response.\n- If the user provides a custom instruction, it should be followed strictly and you should use it to change the style of response.\n\n### OUTPUT FORMAT ###\nPlease provide your response in proper Markdown format without ```markdown``` tags.\n\"\"\"\n\ndata_assistance_user_prompt_template = \"\"\"\n### DATABASE SCHEMA ###\n{% for db_schema in db_schemas %}\n    {{ db_schema }}\n{% endfor %}\n\n### INPUT ###\nUser's question: {{query}}\nLanguage: {{language}}\n\nCustom Instruction: {{ custom_instruction }}\n\nPlease think step by step\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef prompt(\n    query: str,\n    db_schemas: list[str],\n    language: str,\n    histories: list[AskHistory],\n    prompt_builder: PromptBuilder,\n    custom_instruction: str,\n) -> dict:\n    previous_query_summaries = (\n        [history.question for history in histories] if histories else []\n    )\n    query = \"\\n\".join(previous_query_summaries) + \"\\n\" + query\n\n    _prompt = prompt_builder.run(\n        query=query,\n        db_schemas=db_schemas,\n        language=language,\n        custom_instruction=custom_instruction,\n    )\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def data_assistance(\n    prompt: dict, generator: Any, query_id: str, generator_name: str\n) -> dict:\n    return await generator(\n        prompt=prompt.get(\"prompt\"),\n        query_id=query_id,\n    ), generator_name\n\n\n## End of Pipeline\n\n\nclass DataAssistance(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        **kwargs,\n    ):\n        self._user_queues = {}\n        self._components = {\n            \"generator\": llm_provider.get_generator(\n                system_prompt=data_assistance_system_prompt,\n                streaming_callback=self._streaming_callback,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n            \"prompt_builder\": PromptBuilder(\n                template=data_assistance_user_prompt_template\n            ),\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    def _streaming_callback(self, chunk, query_id):\n        if query_id not in self._user_queues:\n            self._user_queues[\n                query_id\n            ] = asyncio.Queue()  # Create a new queue for the user if it doesn't exist\n        # Put the chunk content into the user's queue\n        asyncio.create_task(self._user_queues[query_id].put(chunk.content))\n        if chunk.meta.get(\"finish_reason\"):\n            asyncio.create_task(self._user_queues[query_id].put(\"<DONE>\"))\n\n    async def get_streaming_results(self, query_id):\n        async def _get_streaming_results(query_id):\n            return await self._user_queues[query_id].get()\n\n        if query_id not in self._user_queues:\n            self._user_queues[\n                query_id\n            ] = asyncio.Queue()  # Ensure the user's queue exists\n        while True:\n            try:\n                # Wait for an item from the user's queue\n                self._streaming_results = await asyncio.wait_for(\n                    _get_streaming_results(query_id), timeout=120\n                )\n                if (\n                    self._streaming_results == \"<DONE>\"\n                ):  # Check for end-of-stream signal\n                    del self._user_queues[query_id]\n                    break\n                if self._streaming_results:  # Check if there are results to yield\n                    yield self._streaming_results\n                    self._streaming_results = \"\"  # Clear after yielding\n            except TimeoutError:\n                break\n\n    @observe(name=\"Data Assistance\")\n    async def run(\n        self,\n        query: str,\n        db_schemas: list[str],\n        language: str,\n        query_id: Optional[str] = None,\n        histories: Optional[list[AskHistory]] = None,\n        custom_instruction: Optional[str] = None,\n    ):\n        logger.info(\"Data Assistance pipeline is running...\")\n        return await self._pipe.execute(\n            [\"data_assistance\"],\n            inputs={\n                \"query\": query,\n                \"db_schemas\": db_schemas,\n                \"language\": language,\n                \"query_id\": query_id or \"\",\n                \"histories\": histories or [],\n                \"custom_instruction\": custom_instruction or \"\",\n                **self._components,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/followup_sql_generation.py",
    "content": "import logging\nimport sys\nfrom typing import Any\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\n\nfrom src.core.engine import Engine\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import DocumentStoreProvider, LLMProvider\nfrom src.pipelines.common import clean_up_new_lines, retrieve_metadata\nfrom src.pipelines.generation.utils.sql import (\n    SQL_GENERATION_MODEL_KWARGS,\n    SQLGenPostProcessor,\n    construct_ask_history_messages,\n    construct_instructions,\n    get_calculated_field_instructions,\n    get_json_field_instructions,\n    get_metric_instructions,\n    get_sql_generation_system_prompt,\n)\nfrom src.pipelines.retrieval.sql_functions import SqlFunction\nfrom src.pipelines.retrieval.sql_knowledge import SqlKnowledge\nfrom src.utils import trace_cost\nfrom src.web.v1.services.ask import AskHistory\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\ntext_to_sql_with_followup_user_prompt_template = \"\"\"\n### TASK ###\nGiven the following user's follow-up question and previous SQL query and summary,\ngenerate one SQL query to best answer user's question.\n\n### DATABASE SCHEMA ###\n{% for document in documents %}\n    {{ document }}\n{% endfor %}\n\n{% if calculated_field_instructions %}\n{{ calculated_field_instructions }}\n{% endif %}\n\n{% if metric_instructions %}\n{{ metric_instructions }}\n{% endif %}\n\n{% if json_field_instructions %}\n{{ json_field_instructions }}\n{% endif %}\n\n{% if sql_functions %}\n### SQL FUNCTIONS ###\n{% for function in sql_functions %}\n{{ function }}\n{% endfor %}\n{% endif %}\n\n{% if sql_samples %}\n### SQL SAMPLES ###\n{% for sample in sql_samples %}\nSummary:\n{{sample.summary}}\nSQL:\n{{sample.sql}}\n{% endfor %}\n{% endif %}\n\n{% if instructions %}\n### USER INSTRUCTIONS ###\n{% for instruction in instructions %}\n{{ loop.index }}. {{ instruction }}\n{% endfor %}\n{% endif %}\n\n### QUESTION ###\nUser's Follow-up Question: {{ query }}\n\n### REASONING PLAN ###\n{{ sql_generation_reasoning }}\n\nLet's think step by step.\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef prompt(\n    query: str,\n    documents: list[str],\n    sql_generation_reasoning: str,\n    prompt_builder: PromptBuilder,\n    sql_samples: list[dict] | None = None,\n    instructions: list[dict] | None = None,\n    has_calculated_field: bool = False,\n    has_metric: bool = False,\n    has_json_field: bool = False,\n    sql_functions: list[SqlFunction] | None = None,\n    sql_knowledge: SqlKnowledge | None = None,\n) -> dict:\n    _prompt = prompt_builder.run(\n        query=query,\n        documents=documents,\n        sql_generation_reasoning=sql_generation_reasoning,\n        instructions=construct_instructions(\n            instructions=instructions,\n        ),\n        calculated_field_instructions=(\n            get_calculated_field_instructions(sql_knowledge)\n            if has_calculated_field\n            else \"\"\n        ),\n        metric_instructions=(\n            get_metric_instructions(sql_knowledge) if has_metric else \"\"\n        ),\n        json_field_instructions=(\n            get_json_field_instructions(sql_knowledge) if has_json_field else \"\"\n        ),\n        sql_samples=sql_samples,\n        sql_functions=sql_functions,\n    )\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def generate_sql_in_followup(\n    prompt: dict,\n    generator: Any,\n    histories: list[AskHistory],\n    generator_name: str,\n    sql_knowledge: SqlKnowledge | None = None,\n) -> dict:\n    history_messages = construct_ask_history_messages(histories)\n    current_system_prompt = get_sql_generation_system_prompt(sql_knowledge)\n    return await generator(\n        prompt=prompt.get(\"prompt\"),\n        history_messages=history_messages,\n        current_system_prompt=current_system_prompt,\n    ), generator_name\n\n\n@observe(capture_input=False)\nasync def post_process(\n    generate_sql_in_followup: dict,\n    post_processor: SQLGenPostProcessor,\n    data_source: str,\n    project_id: str | None = None,\n    use_dry_plan: bool = False,\n    allow_dry_plan_fallback: bool = True,\n) -> dict:\n    return await post_processor.run(\n        generate_sql_in_followup.get(\"replies\"),\n        project_id=project_id,\n        use_dry_plan=use_dry_plan,\n        data_source=data_source,\n        allow_dry_plan_fallback=allow_dry_plan_fallback,\n    )\n\n\n## End of Pipeline\n\n\nclass FollowUpSQLGeneration(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        document_store_provider: DocumentStoreProvider,\n        engine: Engine,\n        **kwargs,\n    ):\n        self._retriever = document_store_provider.get_retriever(\n            document_store_provider.get_store(\"project_meta\")\n        )\n\n        self._components = {\n            \"generator\": llm_provider.get_generator(\n                system_prompt=get_sql_generation_system_prompt(None),\n                generation_kwargs=SQL_GENERATION_MODEL_KWARGS,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n            \"prompt_builder\": PromptBuilder(\n                template=text_to_sql_with_followup_user_prompt_template\n            ),\n            \"post_processor\": SQLGenPostProcessor(engine=engine),\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"Follow-Up SQL Generation\")\n    async def run(\n        self,\n        query: str,\n        contexts: list[str],\n        sql_generation_reasoning: str,\n        histories: list[AskHistory],\n        sql_samples: list[dict] | None = None,\n        instructions: list[dict] | None = None,\n        project_id: str | None = None,\n        has_calculated_field: bool = False,\n        has_metric: bool = False,\n        has_json_field: bool = False,\n        sql_functions: list[SqlFunction] | None = None,\n        use_dry_plan: bool = False,\n        allow_dry_plan_fallback: bool = True,\n        sql_knowledge: SqlKnowledge | None = None,\n    ):\n        logger.info(\"Follow-Up SQL Generation pipeline is running...\")\n\n        if use_dry_plan:\n            metadata = await retrieve_metadata(project_id or \"\", self._retriever)\n        else:\n            metadata = {}\n\n        return await self._pipe.execute(\n            [\"post_process\"],\n            inputs={\n                \"query\": query,\n                \"documents\": contexts,\n                \"sql_generation_reasoning\": sql_generation_reasoning,\n                \"histories\": histories,\n                \"project_id\": project_id,\n                \"sql_samples\": sql_samples,\n                \"instructions\": instructions,\n                \"has_calculated_field\": has_calculated_field,\n                \"has_metric\": has_metric,\n                \"has_json_field\": has_json_field,\n                \"sql_functions\": sql_functions,\n                \"use_dry_plan\": use_dry_plan,\n                \"allow_dry_plan_fallback\": allow_dry_plan_fallback,\n                \"data_source\": metadata.get(\"data_source\", \"local_file\"),\n                \"sql_knowledge\": sql_knowledge,\n                **self._components,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/followup_sql_generation_reasoning.py",
    "content": "import asyncio\nimport logging\nimport sys\nfrom typing import Any, Optional\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import LLMProvider\nfrom src.pipelines.common import clean_up_new_lines\nfrom src.pipelines.generation.utils.sql import (\n    construct_instructions,\n    sql_generation_reasoning_system_prompt,\n)\nfrom src.utils import trace_cost\nfrom src.web.v1.services import Configuration\nfrom src.web.v1.services.ask import AskHistory\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nsql_generation_reasoning_user_prompt_template = \"\"\"\n### DATABASE SCHEMA ###\n{% for document in documents %}\n    {{ document }}\n{% endfor %}\n\n{% if sql_samples %}\n### SQL SAMPLES ###\n{% for sql_sample in sql_samples %}\nQuestion:\n{{sql_sample.question}}\nSQL:\n{{sql_sample.sql}}\n{% endfor %}\n{% endif %}\n\n{% if instructions %}\n### USER INSTRUCTIONS ###\n{% for instruction in instructions %}\n{{ loop.index }}. {{ instruction }}\n{% endfor %}\n{% endif %}\n\n### User's QUERY HISTORY ###\n{% for history in histories %}\nQuestion:\n{{ history.question }}\nSQL:\n{{ history.sql }}\n{% endfor %}\n\n### QUESTION ###\nUser's Question: {{ query }}\nLanguage: {{ language }}\nCurrent Time: {{ current_time }}\n\nLet's think step by step.\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef prompt(\n    query: str,\n    documents: list[str],\n    histories: list[AskHistory],\n    sql_samples: list[dict],\n    instructions: list[dict],\n    prompt_builder: PromptBuilder,\n    configuration: Configuration | None = Configuration(),\n) -> dict:\n    _prompt = prompt_builder.run(\n        query=query,\n        documents=documents,\n        histories=histories,\n        sql_samples=sql_samples,\n        instructions=construct_instructions(\n            instructions=instructions,\n        ),\n        language=configuration.language,\n        current_time=configuration.show_current_time(),\n    )\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def generate_sql_reasoning(\n    prompt: dict,\n    generator: Any,\n    query_id: str,\n    generator_name: str,\n) -> dict:\n    return await generator(\n        prompt=prompt.get(\"prompt\"),\n        query_id=query_id,\n    ), generator_name\n\n\n@observe()\ndef post_process(\n    generate_sql_reasoning: dict,\n) -> dict:\n    return generate_sql_reasoning.get(\"replies\")[0]\n\n\n## End of Pipeline\n\n\nclass FollowUpSQLGenerationReasoning(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        **kwargs,\n    ):\n        self._user_queues = {}\n        self._components = {\n            \"generator\": llm_provider.get_generator(\n                system_prompt=sql_generation_reasoning_system_prompt,\n                streaming_callback=self._streaming_callback,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n            \"prompt_builder\": PromptBuilder(\n                template=sql_generation_reasoning_user_prompt_template\n            ),\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    def _streaming_callback(self, chunk, query_id):\n        if query_id not in self._user_queues:\n            self._user_queues[query_id] = asyncio.Queue()\n\n        # Put the chunk content into the user's queue\n        asyncio.create_task(self._user_queues[query_id].put(chunk.content))\n        if chunk.meta.get(\"finish_reason\"):\n            asyncio.create_task(self._user_queues[query_id].put(\"<DONE>\"))\n\n    async def get_streaming_results(self, query_id):\n        async def _get_streaming_results(query_id):\n            return await self._user_queues[query_id].get()\n\n        if query_id not in self._user_queues:\n            self._user_queues[query_id] = asyncio.Queue()\n\n        while True:\n            try:\n                # Wait for an item from the user's queue\n                self._streaming_results = await asyncio.wait_for(\n                    _get_streaming_results(query_id), timeout=120\n                )\n                if (\n                    self._streaming_results == \"<DONE>\"\n                ):  # Check for end-of-stream signal\n                    del self._user_queues[query_id]\n                    break\n                if self._streaming_results:  # Check if there are results to yield\n                    yield self._streaming_results\n                    self._streaming_results = \"\"  # Clear after yielding\n            except TimeoutError:\n                break\n\n    @observe(name=\"FollowupSQL Generation Reasoning\")\n    async def run(\n        self,\n        query: str,\n        contexts: list[str],\n        histories: list[AskHistory],\n        sql_samples: Optional[list[dict]] = None,\n        instructions: Optional[list[dict]] = None,\n        configuration: Configuration = Configuration(),\n        query_id: Optional[str] = None,\n    ):\n        logger.info(\"Followup SQL Generation Reasoning pipeline is running...\")\n        return await self._pipe.execute(\n            [\"post_process\"],\n            inputs={\n                \"query\": query,\n                \"documents\": contexts,\n                \"histories\": histories,\n                \"sql_samples\": sql_samples or [],\n                \"instructions\": instructions or [],\n                \"configuration\": configuration,\n                \"query_id\": query_id,\n                **self._components,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/intent_classification.py",
    "content": "import ast\nimport logging\nimport sys\nfrom typing import Any, Literal, Optional\n\nimport orjson\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack import Document\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import DocumentStoreProvider, EmbedderProvider, LLMProvider\nfrom src.pipelines.common import build_table_ddl, clean_up_new_lines\nfrom src.pipelines.generation.utils.sql import construct_instructions\nfrom src.utils import trace_cost\nfrom src.web.v1.services import Configuration\nfrom src.web.v1.services.ask import AskHistory\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nintent_classification_system_prompt = \"\"\"\n### Task ###\nYou are an expert detective specializing in intent classification. Combine the user's current question and previous questions to determine their true intent based on the provided database schema. Classify the intent into one of these categories: `MISLEADING_QUERY`, `TEXT_TO_SQL`, `GENERAL`, or `USER_GUIDE`. Additionally, provide a concise reasoning (maximum 20 words) for your classification.\n\n### Instructions ###\n- **Follow the user's previous questions:** If there are previous questions, try to understand the user's current question as following the previous questions.\n- **Follow the user's instructions:** If there are instructions, strictly follow the instructions.\n- **Consider Context of Inputs:** Combine the user's current question, their previous questions, and the user's instructions together to identify the user's true intent.\n- **Rephrase Question:** Rewrite follow-up questions into full standalone questions using prior conversation context.\n- **Concise Reasoning:** The reasoning must be clear, concise, and limited to 20 words.\n- **Language Consistency:** Use the same language as specified in the user's output language for the rephrased question and reasoning.\n- **Vague Queries:** If the question is vague or does not related to a table or property from the schema, classify it as `MISLEADING_QUERY`.\n- **Incomplete Queries:** If the question is related to the database schema but references unspecified values (e.g., \"the following\", \"these\", \"those\") without providing them, classify as `GENERAL`.\n- **Time-related Queries:** Don't rephrase time-related information in the user's question.\n\n### Intent Definitions ###\n\n<TEXT_TO_SQL>\n**When to Use:**  \n- The user's inputs are about modifying SQL from previous questions.\n- The user's inputs are related to the database schema and requires an SQL query.\n- The question (or related previous query) includes references to specific tables, columns, or data details.\n- The question includes **complete information** with specific tables, columns, or data values needed for execution.\n- The question provides **all necessary parameters** to generate executable SQL.\n\n**Requirements:**\n- Must have complete filter criteria, specific values, or clear references to previous context.\n- Include specific table and column names from the schema in your reasoning or modifying SQL from previous questions.\n- Reference phrases from the user's inputs that clearly relate to the schema.\n\n**Examples:**  \n- \"What is the total sales for last quarter?\"\n- \"Show me all customers who purchased product X.\"\n- \"List the top 10 products by revenue.\"\n</TEXT_TO_SQL>\n\n<GENERAL>\n**When to Use:**  \n- The user seeks general information about the database schema or its overall capabilities.\n- The query references **missing information** (e.g., \"the following items\" without listing them).\n- The query contains **placeholder references** that cannot be resolved from context.\n- The query is **incomplete for SQL generation** despite mentioning database concepts.\n\n**Requirements:**  \n- Incorporate phrases from the user's inputs that indicate incompleteness or lack of relevance to the database schema.\n- Identify missing parameters, unspecified references, or incomplete filter criteria.\n\n**Examples:**\n- \"What is the dataset about?\"\n- \"Tell me more about the database.\"\n- \"How can I analyze customer behavior with this data?\"\n- \"Show me orders for these products\" (without specifying which products)\n- \"Filter by the criteria I mentioned\" (without previous context defining criteria)\n</GENERAL>\n\n<USER_GUIDE>\n**When to Use:**  \n- The user's inputs pertains to Wren AI's features, usage, or capabilities.\n- The query relates directly to content in the user guide.\n\n**Examples:**  \n- \"What can Wren AI do?\"\n- \"How can I reset a project?\"\n- \"How can I delete a project?\"\n- \"How can I connect to other databases?\"\n- \"How do I draw a chart?\"\n</USER_GUIDE>\n\n<MISLEADING_QUERY>\n**When to Use:**  \n- The user's inputs is irrelevant to the database schema or includes SQL code.\n- The user's inputs lacks specific details (like table names or columns) needed to generate an SQL query.\n- It appears off-topic or is simply a casual conversation starter.\n\n**Requirements:**  \n- Incorporate phrases from the user's inputs that indicate lack of relevance to the database schema.\n\n**Examples:**  \n- \"How are you?\"\n- \"What's the weather like today?\"\n- \"Tell me a joke.\"\n</MISLEADING_QUERY>\n\n### Output Format ###\nReturn your response as a JSON object with the following structure:\n\n{\n    \"rephrased_question\": \"<rephrased question in full standalone question if there are previous questions, otherwise the original question>\",\n    \"reasoning\": \"<brief chain-of-thought reasoning (max 20 words)>\",\n    \"results\": \"MISLEADING_QUERY\" | \"TEXT_TO_SQL\" | \"GENERAL\" | \"USER_GUIDE\"\n}\n\"\"\"\n\nintent_classification_user_prompt_template = \"\"\"\n### DATABASE SCHEMA ###\n{% for db_schema in db_schemas %}\n    {{ db_schema }}\n{% endfor %}\n\n{% if sql_samples %}\n### SQL SAMPLES ###\n{% for sql_sample in sql_samples %}\nQuestion:\n{{sql_sample.question}}\nSQL:\n{{sql_sample.sql}}\n{% endfor %}\n{% endif %}\n\n{% if instructions %}\n### USER INSTRUCTIONS ###\n{% for instruction in instructions %}\n{{ loop.index }}. {{ instruction }}\n{% endfor %}\n{% endif %}\n\n### USER GUIDE ###\n{% for doc in docs %}\n- {{doc.path}}: {{doc.content}}\n{% endfor %}\n\n### INPUT ###\n{% if histories %}\nUser's previous questions:\n{% for history in histories %}\nQuestion:\n{{ history.question }}\nSQL:\n{{ history.sql }}\n{% endfor %}\n{% endif %}\n\nUser's current question: {{query}}\nOutput Language: {{ language }}\n\nLet's think step by step\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False, capture_output=False)\nasync def embedding(query: str, embedder: Any, histories: list[AskHistory]) -> dict:\n    previous_query_summaries = (\n        [history.question for history in histories] if histories else []\n    )\n\n    query = \"\\n\".join(previous_query_summaries) + \"\\n\" + query\n\n    return await embedder.run(query)\n\n\n@observe(capture_input=False)\nasync def table_retrieval(\n    embedding: dict, project_id: str, table_retriever: Any\n) -> dict:\n    filters = {\n        \"operator\": \"AND\",\n        \"conditions\": [\n            {\"field\": \"type\", \"operator\": \"==\", \"value\": \"TABLE_DESCRIPTION\"},\n        ],\n    }\n\n    if project_id:\n        filters[\"conditions\"].append(\n            {\"field\": \"project_id\", \"operator\": \"==\", \"value\": project_id}\n        )\n\n    return await table_retriever.run(\n        query_embedding=embedding.get(\"embedding\"),\n        filters=filters,\n    )\n\n\n@observe(capture_input=False)\nasync def dbschema_retrieval(\n    table_retrieval: dict, embedding: dict, project_id: str, dbschema_retriever: Any\n) -> list[Document]:\n    tables = table_retrieval.get(\"documents\", [])\n    table_names = []\n    for table in tables:\n        content = ast.literal_eval(table.content)\n        table_names.append(content[\"name\"])\n\n    logger.info(f\"dbschema_retrieval with table_names: {table_names}\")\n\n    table_name_conditions = [\n        {\"field\": \"name\", \"operator\": \"==\", \"value\": table_name}\n        for table_name in table_names\n    ]\n\n    filters = {\n        \"operator\": \"AND\",\n        \"conditions\": [\n            {\"field\": \"type\", \"operator\": \"==\", \"value\": \"TABLE_SCHEMA\"},\n            {\"operator\": \"OR\", \"conditions\": table_name_conditions},\n        ],\n    }\n\n    if project_id:\n        filters[\"conditions\"].append(\n            {\"field\": \"project_id\", \"operator\": \"==\", \"value\": project_id}\n        )\n\n    results = await dbschema_retriever.run(\n        query_embedding=embedding.get(\"embedding\"), filters=filters\n    )\n    return results[\"documents\"]\n\n\n@observe()\ndef construct_db_schemas(dbschema_retrieval: list[Document]) -> list[str]:\n    db_schemas = {}\n    for document in dbschema_retrieval:\n        content = ast.literal_eval(document.content)\n        if content[\"type\"] == \"TABLE\":\n            if document.meta[\"name\"] not in db_schemas:\n                db_schemas[document.meta[\"name\"]] = content\n            else:\n                db_schemas[document.meta[\"name\"]] = {\n                    **content,\n                    \"columns\": db_schemas[document.meta[\"name\"]].get(\"columns\", []),\n                }\n        elif content[\"type\"] == \"TABLE_COLUMNS\":\n            if document.meta[\"name\"] not in db_schemas:\n                db_schemas[document.meta[\"name\"]] = {\"columns\": content[\"columns\"]}\n            else:\n                if \"columns\" not in db_schemas[document.meta[\"name\"]]:\n                    db_schemas[document.meta[\"name\"]][\"columns\"] = content[\"columns\"]\n                else:\n                    db_schemas[document.meta[\"name\"]][\"columns\"] += content[\"columns\"]\n\n    # remove incomplete schemas\n    db_schemas = {k: v for k, v in db_schemas.items() if \"type\" in v and \"columns\" in v}\n\n    db_schemas_in_ddl = []\n    for table_schema in list(db_schemas.values()):\n        if table_schema[\"type\"] == \"TABLE\":\n            ddl, _, _ = build_table_ddl(table_schema)\n            db_schemas_in_ddl.append(ddl)\n\n    return db_schemas_in_ddl\n\n\n@observe(capture_input=False)\ndef prompt(\n    query: str,\n    wren_ai_docs: list[dict],\n    construct_db_schemas: list[str],\n    histories: list[AskHistory],\n    prompt_builder: PromptBuilder,\n    sql_samples: Optional[list[dict]] = None,\n    instructions: Optional[list[dict]] = None,\n    configuration: Configuration | None = None,\n) -> dict:\n    _prompt = prompt_builder.run(\n        query=query,\n        language=configuration.language,\n        db_schemas=construct_db_schemas,\n        histories=histories,\n        sql_samples=sql_samples,\n        instructions=construct_instructions(\n            instructions=instructions,\n        ),\n        docs=wren_ai_docs,\n    )\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def classify_intent(prompt: dict, generator: Any, generator_name: str) -> dict:\n    return await generator(prompt=prompt.get(\"prompt\")), generator_name\n\n\n@observe(capture_input=False)\ndef post_process(classify_intent: dict, construct_db_schemas: list[str]) -> dict:\n    try:\n        results = orjson.loads(classify_intent.get(\"replies\")[0])\n        return {\n            \"rephrased_question\": results[\"rephrased_question\"],\n            \"intent\": results[\"results\"],\n            \"reasoning\": results[\"reasoning\"],\n            \"db_schemas\": construct_db_schemas,\n        }\n    except Exception:\n        return {\n            \"rephrased_question\": \"\",\n            \"intent\": \"TEXT_TO_SQL\",\n            \"reasoning\": \"\",\n            \"db_schemas\": construct_db_schemas,\n        }\n\n\n## End of Pipeline\n\n\nclass IntentClassificationResult(BaseModel):\n    rephrased_question: str\n    results: Literal[\"MISLEADING_QUERY\", \"TEXT_TO_SQL\", \"GENERAL\", \"USER_GUIDE\"]\n    reasoning: str\n\n\nINTENT_CLASSIFICAION_MODEL_KWARGS = {\n    \"response_format\": {\n        \"type\": \"json_schema\",\n        \"json_schema\": {\n            \"name\": \"intent_classification\",\n            \"schema\": IntentClassificationResult.model_json_schema(),\n        },\n    }\n}\n\n\nclass IntentClassification(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        embedder_provider: EmbedderProvider,\n        document_store_provider: DocumentStoreProvider,\n        wren_ai_docs: list[dict],\n        table_retrieval_size: Optional[int] = 50,\n        table_column_retrieval_size: Optional[int] = 100,\n        **kwargs,\n    ):\n        self._components = {\n            \"embedder\": embedder_provider.get_text_embedder(),\n            \"table_retriever\": document_store_provider.get_retriever(\n                document_store_provider.get_store(dataset_name=\"table_descriptions\"),\n                top_k=table_retrieval_size,\n            ),\n            \"dbschema_retriever\": document_store_provider.get_retriever(\n                document_store_provider.get_store(),\n                top_k=table_column_retrieval_size,\n            ),\n            \"generator\": llm_provider.get_generator(\n                system_prompt=intent_classification_system_prompt,\n                generation_kwargs=INTENT_CLASSIFICAION_MODEL_KWARGS,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n            \"prompt_builder\": PromptBuilder(\n                template=intent_classification_user_prompt_template\n            ),\n        }\n\n        self._configs = {\n            \"wren_ai_docs\": wren_ai_docs,\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"Intent Classification\")\n    async def run(\n        self,\n        query: str,\n        project_id: Optional[str] = None,\n        histories: Optional[list[AskHistory]] = None,\n        sql_samples: Optional[list[dict]] = None,\n        instructions: Optional[list[dict]] = None,\n        configuration: Configuration = Configuration(),\n    ):\n        logger.info(\"Intent Classification pipeline is running...\")\n        return await self._pipe.execute(\n            [\"post_process\"],\n            inputs={\n                \"query\": query,\n                \"project_id\": project_id or \"\",\n                \"histories\": histories or [],\n                \"sql_samples\": sql_samples or [],\n                \"instructions\": instructions or [],\n                \"configuration\": configuration,\n                **self._components,\n                **self._configs,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/misleading_assistance.py",
    "content": "import asyncio\nimport logging\nimport sys\nfrom typing import Any, Optional\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import LLMProvider\nfrom src.pipelines.common import clean_up_new_lines\nfrom src.utils import trace_cost\nfrom src.web.v1.services.ask import AskHistory\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nmisleading_assistance_system_prompt = \"\"\"\n### TASK ###\nYou are a helpful assistant that can help users understand their data better. Currently, you are given a user's question that is potentially misleading.\nYour goal is to help guide user understand its data better and suggest few better questions to ask.\n\n### INSTRUCTIONS ###\n\n- Answer must be in the same language user specified in the Language section of the `### INPUT ###` section.\n- There should be proper line breaks, whitespace, and Markdown formatting(headers, lists, tables, etc.) in your response.\n- MUST NOT add SQL code in your response.\n- MUST consider database schema when suggesting better questions.\n- The maximum response length is 100 words.\n- If the user provides a custom instruction, it should be followed strictly and you should use it to change the style of response.\n\n### OUTPUT FORMAT ###\nPlease provide your response in proper Markdown format without ```markdown``` tags.\n\"\"\"\n\nmisleading_assistance_user_prompt_template = \"\"\"\n### DATABASE SCHEMA ###\n{% for db_schema in db_schemas %}\n    {{ db_schema }}\n{% endfor %}\n\n### INPUT ###\nUser's question: {{query}}\nLanguage: {{language}}\n\nCustom Instruction: {{ custom_instruction }}\n\nPlease think step by step\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef prompt(\n    query: str,\n    db_schemas: list[str],\n    language: str,\n    histories: list[AskHistory],\n    prompt_builder: PromptBuilder,\n    custom_instruction: str,\n) -> dict:\n    previous_query_summaries = (\n        [history.question for history in histories] if histories else []\n    )\n    query = \"\\n\".join(previous_query_summaries) + \"\\n\" + query\n\n    _prompt = prompt_builder.run(\n        query=query,\n        db_schemas=db_schemas,\n        language=language,\n        custom_instruction=custom_instruction,\n    )\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def misleading_assistance(\n    prompt: dict, generator: Any, query_id: str, generator_name: str\n) -> dict:\n    return await generator(\n        prompt=prompt.get(\"prompt\"),\n        query_id=query_id,\n    ), generator_name\n\n\n## End of Pipeline\n\n\nclass MisleadingAssistance(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        **kwargs,\n    ):\n        self._user_queues = {}\n        self._components = {\n            \"generator\": llm_provider.get_generator(\n                system_prompt=misleading_assistance_system_prompt,\n                streaming_callback=self._streaming_callback,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n            \"prompt_builder\": PromptBuilder(\n                template=misleading_assistance_user_prompt_template\n            ),\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    def _streaming_callback(self, chunk, query_id):\n        if query_id not in self._user_queues:\n            self._user_queues[\n                query_id\n            ] = asyncio.Queue()  # Create a new queue for the user if it doesn't exist\n        # Put the chunk content into the user's queue\n        asyncio.create_task(self._user_queues[query_id].put(chunk.content))\n        if chunk.meta.get(\"finish_reason\"):\n            asyncio.create_task(self._user_queues[query_id].put(\"<DONE>\"))\n\n    async def get_streaming_results(self, query_id):\n        async def _get_streaming_results(query_id):\n            return await self._user_queues[query_id].get()\n\n        if query_id not in self._user_queues:\n            self._user_queues[\n                query_id\n            ] = asyncio.Queue()  # Ensure the user's queue exists\n        while True:\n            try:\n                # Wait for an item from the user's queue\n                self._streaming_results = await asyncio.wait_for(\n                    _get_streaming_results(query_id), timeout=120\n                )\n                if (\n                    self._streaming_results == \"<DONE>\"\n                ):  # Check for end-of-stream signal\n                    del self._user_queues[query_id]\n                    break\n                if self._streaming_results:  # Check if there are results to yield\n                    yield self._streaming_results\n                    self._streaming_results = \"\"  # Clear after yielding\n            except TimeoutError:\n                break\n\n    @observe(name=\"Misleading Assistance\")\n    async def run(\n        self,\n        query: str,\n        db_schemas: list[str],\n        language: str,\n        query_id: Optional[str] = None,\n        histories: Optional[list[AskHistory]] = None,\n        custom_instruction: Optional[str] = None,\n    ):\n        logger.info(\"Misleading Assistance pipeline is running...\")\n        return await self._pipe.execute(\n            [\"misleading_assistance\"],\n            inputs={\n                \"query\": query,\n                \"db_schemas\": db_schemas,\n                \"language\": language,\n                \"query_id\": query_id or \"\",\n                \"histories\": histories or [],\n                \"custom_instruction\": custom_instruction or \"\",\n                **self._components,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/question_recommendation.py",
    "content": "import logging\nimport sys\nfrom typing import Any\n\nimport orjson\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import LLMProvider\nfrom src.pipelines.common import clean_up_new_lines\nfrom src.utils import trace_cost\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nsystem_prompt = \"\"\"\nYou are an expert in data analysis and SQL query generation. Given a data model specification, optionally a user's question, and a list of categories, your task is to generate insightful, specific questions that can be answered using the provided data model. Each question should be accompanied by a brief explanation of its relevance or importance.\n\n### JSON Output Structure\n\nOutput all questions in the following JSON format:\n\n```json\n{\n    \"questions\": [\n        {\n            \"question\": \"<generated question>\",\n            \"category\": \"<category of the question>\"\n        },\n        ...\n    ]\n}\n```\n\n### Guidelines for Generating Questions\n\n1. **If Categories Are Provided:**\n\n   - **Randomly select categories** from the list and ensure no single category dominates the output.\n   - Ensure a balanced distribution of questions across all provided categories.\n   - For each generated question, **randomize the category selection** to avoid a fixed order.\n\n2. **Incorporate Diverse Analysis Techniques:**\n\n   - Use a mix of the following analysis techniques for each category:\n     - **Drill-down:** Delve into detailed levels of data.\n     - **Roll-up:** Aggregate data to higher levels.\n     - **Slice and Dice:** Analyze data from different perspectives.\n     - **Trend Analysis:** Identify patterns or changes over time.\n     - **Comparative Analysis:** Compare segments, groups, or time periods.\n\n3. **If a User Question is Provided:**\n\n   - Generate questions that are closely related to the user's previous question, ensuring that the new questions build upon or provide deeper insights into the original query.\n   - Use **random category selection** to introduce diverse perspectives while maintaining a focus on the context of the previous question.\n   - Apply the analysis techniques above to enhance the relevance and depth of the generated questions.\n\n4. **If No User Question is Provided:**\n\n   - Ensure questions cover different aspects of the data model.\n   - Randomly distribute questions across all categories to ensure variety.\n\n5. **General Guidelines for All Questions:**\n   - Ensure questions can be answered using the data model.\n   - Mix simple and complex questions.\n   - Avoid open-ended questions - each should have a definite answer.\n   - Incorporate time-based analysis where relevant.\n   - Combine multiple analysis techniques when appropriate for deeper insights.\n\n### Categories of Questions\n\n1. **Descriptive Questions**  \n   Summarize historical data.\n\n   - Example: _\"What was the total sales volume for each product last quarter?\"_\n\n2. **Segmentation Questions**  \n   Identify meaningful data segments.\n\n   - Example: _\"Which customer segments contributed most to revenue growth?\"_\n\n3. **Comparative Questions**  \n   Compare data across segments or periods.\n\n   - Example: _\"How did Product A perform compared to Product B last year?\"_\n\n4. **Data Quality/Accuracy Questions**  \n   Assess data reliability and completeness.\n\n   - Example: _\"Are there inconsistencies in the sales records for Q1?\"_\n\n---\n\n### Example JSON Output\n\n```json\n{\n  \"questions\": [\n    {\n      \"question\": \"What was the total revenue generated by each region in the last year?\",\n      \"category\": \"Descriptive Questions\"\n    },\n    {\n      \"question\": \"How do customer preferences differ between age groups?\",\n      \"category\": \"Segmentation Questions\"\n    },\n    {\n      \"question\": \"How does the conversion rate vary across different lead sources?\",\n      \"category\": \"Comparative Questions\"\n    },\n    {\n      \"question\": \"What percentage of contacts have incomplete or missing key properties (e.g., email, lifecycle stage, or deal association)\",\n      \"category\": \"Data Quality/Accuracy Questions\"\n    }\n  ]\n}\n```\n\n---\n\n### Additional Instructions for Randomization\n\n- **Randomize Category Order:**  \n  Ensure that categories are selected in a random order for each question generation session.\n\n- **Avoid Repetition:**  \n  Ensure the same category doesn't dominate the list by limiting the number of questions from any single category unless specified otherwise.\n\n- **Diversity of Analysis:**  \n  Combine different analysis techniques (drill-down, roll-up, etc.) within the selected categories for richer insights.\n\n- **Shuffle Categories:**  \n  If possible, shuffle the list of categories internally before generating questions to ensure varied selection.\n\n\n\"\"\"\n\nuser_prompt_template = \"\"\"\n\n{% if previous_questions %}\nPrevious Questions: {{previous_questions}}\n{% endif %}\n\n{% if categories %}\nCategories: {{categories}}\n{% endif %}\n\n{% if documents %}\n### DATABASE SCHEMA ###\n{% for document in documents %}\n    {{ document }}\n{% endfor %}\n{% endif %}\n\nPlease generate {{max_questions}} insightful questions for each of the {{max_categories}} categories based on the provided data model. Both the questions and category names should be translated into {{language}}{% if user_question %} and be related to the user's question{% endif %}. The output format should maintain the structure but with localized text.\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef prompt(\n    previous_questions: list[str],\n    documents: list,\n    language: str,\n    max_questions: int,\n    max_categories: int,\n    prompt_builder: PromptBuilder,\n) -> dict:\n    \"\"\"\n    If previous_questions is provided, the MDL is omitted to allow the LLM to focus on\n    generating recommendations based on the question history. This helps provide more\n    contextually relevant questions that build on previous questions.\n    \"\"\"\n\n    _prompt = prompt_builder.run(\n        documents=documents,\n        previous_questions=previous_questions,\n        language=language,\n        max_questions=max_questions,\n        max_categories=max_categories,\n    )\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def generate(prompt: dict, generator: Any, generator_name: str) -> dict:\n    return await generator(prompt=prompt.get(\"prompt\")), generator_name\n\n\n@observe(capture_input=False)\ndef normalized(generate: dict) -> dict:\n    def wrapper(text: str) -> list:\n        text = text.replace(\"\\n\", \" \")\n        text = \" \".join(text.split())\n        try:\n            text_list = orjson.loads(text.strip())\n            return text_list\n        except orjson.JSONDecodeError as e:\n            logger.error(f\"Error decoding JSON: {e}\")\n            return []  # Return an empty list if JSON decoding fails\n\n    reply = generate.get(\"replies\")[0]  # Expecting only one reply\n    normalized = wrapper(reply)\n\n    return normalized\n\n\n## End of Pipeline\nclass Question(BaseModel):\n    question: str\n    category: str\n\n\nclass QuestionResult(BaseModel):\n    questions: list[Question]\n\n\nQUESTION_RECOMMENDATION_MODEL_KWARGS = {\n    \"response_format\": {\n        \"type\": \"json_schema\",\n        \"json_schema\": {\n            \"name\": \"question_recommendation\",\n            \"schema\": QuestionResult.model_json_schema(),\n        },\n    }\n}\n\n\nclass QuestionRecommendation(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        **_,\n    ):\n        self._components = {\n            \"prompt_builder\": PromptBuilder(template=user_prompt_template),\n            \"generator\": llm_provider.get_generator(\n                system_prompt=system_prompt,\n                generation_kwargs=QUESTION_RECOMMENDATION_MODEL_KWARGS,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n        }\n\n        self._final = \"normalized\"\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"Question Recommendation\")\n    async def run(\n        self,\n        contexts: list[str],\n        previous_questions: list[str] = [],\n        categories: list[str] = [],\n        language: str = \"en\",\n        max_questions: int = 5,\n        max_categories: int = 3,\n        **_,\n    ) -> dict:\n        logger.info(\"Question Recommendation pipeline is running...\")\n        return await self._pipe.execute(\n            [self._final],\n            inputs={\n                \"documents\": contexts,\n                \"previous_questions\": previous_questions,\n                \"categories\": categories,\n                \"language\": language,\n                \"max_questions\": max_questions,\n                \"max_categories\": max_categories,\n                **self._components,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/relationship_recommendation.py",
    "content": "import logging\nimport sys\nfrom enum import Enum\nfrom typing import Any\n\nimport orjson\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import LLMProvider\nfrom src.pipelines.common import clean_up_new_lines\nfrom src.utils import trace_cost\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nsystem_prompt = \"\"\"\nYou are an expert in database schema design and relationship recommendation. Given a data model specification that includes various models and their attributes, your task is to analyze the models and suggest appropriate relationships between them, but only if there are clear and beneficial relationships to recommend. For each valid relationship, provide the following details:\n\n- **name**: A descriptive name for the relationship.\n- **fromModel**: The name of the source model.\n- **fromColumn**: The column in the source model that forms the relationship.\n- **type**: The type of relationship, which can be \"MANY_TO_ONE\", \"ONE_TO_MANY\" or \"ONE_TO_ONE\" only.\n- **toModel**: The name of the target model.\n- **toColumn**: The column in the target model that forms the relationship.\n- **reason**: The reason for recommending this relationship.\n\nImportant guidelines:\n1. Do not recommend relationships within the same model (fromModel and toModel must be different).\n2. Only suggest relationships if there is a clear and beneficial reason to do so.\n3. If there are no good relationships to recommend or if there are fewer than two models, return an empty list of relationships.\n4. Use \"MANY_TO_ONE\" and \"ONE_TO_MANY\" instead of \"MANY_TO_MANY\" relationships.\n\nOutput all relationships in the following JSON structure:\n\n{\n    \"relationships\": [\n        {\n            \"name\": \"<name_for_the_relationship>\",\n            \"fromModel\": \"<model_name>\",\n            \"fromColumn\": \"<column_name>\",\n            \"type\": \"<relationship_type>\",\n            \"toModel\": \"<model_name>\",\n            \"toColumn\": \"<column_name>\",\n            \"reason\": \"<reason_for_this_relationship>\"\n        }\n        ...\n    ]\n}\n\nIf no relationships are recommended, return:\n\n{\n    \"relationships\": []\n}\n\"\"\"\n\nuser_prompt_template = \"\"\"\nHere is the relationship specification for my data model:\n\n{{models}}\n\n**Please analyze these models and suggest optimizations for their relationships.**\nTake into account best practices in database design, opportunities for normalization, indexing strategies, and any additional relationships that could improve data integrity and enhance query performance.\n\nUse this for the relationship name and reason based on the localization language: {{language}}\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef cleaned_models(mdl: dict) -> dict:\n    def remove_display_name(d: dict) -> dict:\n        if \"properties\" in d and isinstance(d[\"properties\"], dict):\n            d[\"properties\"] = d[\"properties\"].copy()\n            d[\"properties\"].pop(\"displayName\", None)\n        return d\n\n    def column_filter(columns: list[dict]) -> list[dict]:\n        filtered_columns = []\n        for column in columns:\n            if \"relationship\" not in column:\n                # Create a copy of the column to avoid modifying the original\n                filtered_column = column.copy()\n                filtered_column = remove_display_name(filtered_column)\n                filtered_columns.append(filtered_column)\n        return filtered_columns\n\n    return [\n        remove_display_name(\n            {**model, \"columns\": column_filter(model.get(\"columns\", []))}\n        )\n        for model in mdl.get(\"models\", [])\n    ]\n\n\n@observe(capture_input=False)\ndef prompt(\n    cleaned_models: dict,\n    prompt_builder: PromptBuilder,\n    language: str,\n) -> dict:\n    _prompt = prompt_builder.run(models=cleaned_models, language=language)\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def generate(prompt: dict, generator: Any, generator_name: str) -> dict:\n    return await generator(prompt=prompt.get(\"prompt\")), generator_name\n\n\n@observe(capture_input=False)\ndef normalized(generate: dict) -> dict:\n    def wrapper(text: str) -> str:\n        text = text.replace(\"\\n\", \" \")\n        text = \" \".join(text.split())\n        # Convert the normalized text to a dictionary\n        try:\n            text_dict = orjson.loads(text.strip())\n            return text_dict\n        except orjson.JSONDecodeError as e:\n            logger.error(f\"Error decoding JSON: {e}\")\n            return {}  # Return an empty dictionary if JSON decoding fails\n\n    reply = generate.get(\"replies\")[0]  # Expecting only one reply\n    normalized = wrapper(reply)\n\n    return normalized\n\n\n@observe(capture_input=False)\ndef validated(normalized: dict, mdl: dict) -> dict:\n    model_columns = {\n        model[\"name\"]: set(\n            [\n                column[\"name\"]\n                for column in model.get(\"columns\", [])\n                if not column.get(\"relationship\")\n            ]\n        )\n        for model in mdl.get(\"models\", [])\n    }\n\n    relationships = normalized.get(\"relationships\", [])\n    validated_relationships = [\n        relationship\n        for relationship in relationships\n        if RelationType.is_include(relationship.get(\"type\"))\n        and relationship.get(\"fromModel\") in model_columns\n        and relationship.get(\"toModel\") in model_columns\n        and relationship.get(\"fromColumn\")\n        in model_columns.get(relationship.get(\"fromModel\"))\n        and relationship.get(\"toColumn\")\n        in model_columns.get(relationship.get(\"toModel\"))\n    ]\n\n    return {\"relationships\": validated_relationships}\n\n\n## End of Pipeline\nclass RelationType(Enum):\n    MANY_TO_ONE = \"MANY_TO_ONE\"\n    ONE_TO_MANY = \"ONE_TO_MANY\"\n    ONE_TO_ONE = \"ONE_TO_ONE\"\n\n    @classmethod\n    def is_include(cls, value: str) -> bool:\n        return value in cls._value2member_map_\n\n\nclass ModelRelationship(BaseModel):\n    name: str\n    fromModel: str\n    fromColumn: str\n    type: RelationType\n    toModel: str\n    toColumn: str\n    reason: str\n\n\nclass RelationshipResult(BaseModel):\n    relationships: list[ModelRelationship]\n\n\nRELATIONSHIP_RECOMMENDATION_MODEL_KWARGS = {\n    \"response_format\": {\n        \"type\": \"json_schema\",\n        \"json_schema\": {\n            \"name\": \"semantic_description\",\n            \"schema\": RelationshipResult.model_json_schema(),\n        },\n    }\n}\n\n\nclass RelationshipRecommendation(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        **_,\n    ):\n        self._components = {\n            \"prompt_builder\": PromptBuilder(template=user_prompt_template),\n            \"generator\": llm_provider.get_generator(\n                system_prompt=system_prompt,\n                generation_kwargs=RELATIONSHIP_RECOMMENDATION_MODEL_KWARGS,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n        }\n\n        self._final = \"validated\"\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"Relationship Recommendation\")\n    async def run(\n        self,\n        mdl: dict,\n        language: str = \"English\",\n    ) -> dict:\n        logger.info(\"Relationship Recommendation pipeline is running...\")\n        return await self._pipe.execute(\n            [self._final],\n            inputs={\n                \"mdl\": mdl,\n                \"language\": language,\n                **self._components,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/semantics_description.py",
    "content": "import logging\nimport sys\nfrom typing import Any\n\nimport orjson\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import LLMProvider\nfrom src.pipelines.common import clean_up_new_lines\nfrom src.pipelines.indexing import clean_display_name\nfrom src.utils import trace_cost\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nsystem_prompt = \"\"\"\nI have a data model represented in JSON format, with the following structure:\n\n```\n[\n    {'name': 'model', 'columns': [\n            {'name': 'column_1', 'type': 'type', 'properties': {}\n            },\n            {'name': 'column_2', 'type': 'type', 'properties': {}\n            },\n            {'name': 'column_3', 'type': 'type', 'properties': {}\n            }\n        ], 'properties': {}\n    }\n]\n```\n\nYour task is to update this JSON structure by adding a `description` field inside both the `properties` attribute of each `column` and the `model` itself.\nEach `description` should be derived from a user-provided input that explains the purpose or context of the `model` and its respective columns.\nFollow these steps:\n1. **For the `model`**: Prompt the user to provide a brief description of the model's overall purpose or its context. Insert this description in the `properties` field of the `model`.\n2. **For each `column`**: Ask the user to describe each column's role or significance. Each column's description should be added under its respective `properties` field in the format: `'description': 'user-provided text'`.\n3. Ensure that the output is a well-formatted JSON structure, preserving the input's original format and adding the appropriate `description` fields.\n\n### Output Format:\n\n```\n{\n    \"models\": [\n        {\n        \"name\": \"model\",\n        \"columns\": [\n            {\n                \"name\": \"column_1\",\n                \"properties\": {\n                    \"description\": \"<description for column_1>\"\n                }\n            },\n            {\n                \"name\": \"column_2\",\n                \"properties\": {\n                    \"description\": \"<description for column_1>\"\n                }\n            },\n            {\n                \"name\": \"column_3\",\n                \"properties\": {\n                    \"description\": \"<description for column_1>\"\n                }\n            }\n        ],\n        \"properties\": {\n                \"description\": \"<description for model>\"\n            }\n        }\n    ]\n}\n```\n\nMake sure that the descriptions are concise, informative, and contextually appropriate based on the input provided by the user.\n\"\"\"\n\nuser_prompt_template = \"\"\"\n### Input:\nUser's prompt: {{ user_prompt }}\nPicked models: {{ picked_models }}\nLocalization Language: {{ language }}\n\nPlease provide a brief description for the model and each column based on the user's prompt.\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef picked_models(mdl: dict, selected_models: list[str]) -> list[dict]:\n    def relation_filter(column: dict) -> bool:\n        return \"relationship\" not in column\n\n    def column_formatter(columns: list[dict]) -> list[dict]:\n        return [\n            {\n                \"name\": column[\"name\"],\n                \"type\": column[\"type\"],\n                \"properties\": {\n                    \"description\": column[\"properties\"].get(\"description\", \"\"),\n                    \"alias\": clean_display_name(\n                        column[\"properties\"].get(\"displayName\", \"\")\n                    ),\n                },\n            }\n            for column in columns\n            if relation_filter(column)\n        ]\n\n    def extract(model: dict) -> dict:\n        return {\n            \"name\": model[\"name\"],\n            \"columns\": column_formatter(model[\"columns\"]),\n            \"properties\": {\n                \"description\": model[\"properties\"].get(\"description\", \"\"),\n                \"alias\": clean_display_name(model[\"properties\"].get(\"displayName\", \"\")),\n            },\n        }\n\n    return [\n        extract(model)\n        for model in mdl.get(\"models\", [])\n        if model.get(\"name\", \"\") in selected_models\n    ]\n\n\n@observe(capture_input=False)\ndef prompt(\n    picked_models: list[dict],\n    user_prompt: str,\n    prompt_builder: PromptBuilder,\n    language: str,\n) -> dict:\n    _prompt = prompt_builder.run(\n        picked_models=picked_models,\n        user_prompt=user_prompt,\n        language=language,\n    )\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def generate(prompt: dict, generator: Any, generator_name: str) -> dict:\n    return await generator(prompt=prompt.get(\"prompt\")), generator_name\n\n\n@observe(capture_input=False)\ndef normalize(generate: dict) -> dict:\n    def wrapper(text: str) -> str:\n        text = text.replace(\"\\n\", \" \")\n        text = \" \".join(text.split())\n        # Convert the normalized text to a dictionary\n        try:\n            text_dict = orjson.loads(text.strip())\n            return text_dict\n        except orjson.JSONDecodeError as e:\n            logger.error(f\"Error decoding JSON: {e}\")\n            return {\"models\": []}  # Return an empty list if JSON decoding fails\n\n    reply = generate.get(\"replies\")[0]  # Expecting only one reply\n    normalized = wrapper(reply)\n\n    return {model[\"name\"]: model for model in normalized[\"models\"]}\n\n\n@observe(capture_input=False)\ndef output(normalize: dict, picked_models: list[dict]) -> dict:\n    def _filter(enriched: list[dict], columns: list[dict]) -> list[dict]:\n        valid_columns = [col[\"name\"] for col in columns]\n\n        return [col for col in enriched if col[\"name\"] in valid_columns]\n\n    models = {model[\"name\"]: model for model in picked_models}\n\n    return {\n        name: {**data, \"columns\": _filter(data[\"columns\"], models[name][\"columns\"])}\n        for name, data in normalize.items()\n        if name in models\n    }\n\n\n## End of Pipeline\nclass ModelProperties(BaseModel):\n    description: str\n\n\nclass ModelColumns(BaseModel):\n    name: str\n    properties: ModelProperties\n\n\nclass SemanticModel(BaseModel):\n    name: str\n    columns: list[ModelColumns]\n    properties: ModelProperties\n\n\nclass SemanticResult(BaseModel):\n    models: list[SemanticModel]\n\n\nSEMANTICS_DESCRIPTION_MODEL_KWARGS = {\n    \"response_format\": {\n        \"type\": \"json_schema\",\n        \"json_schema\": {\n            \"name\": \"semantic_description\",\n            \"schema\": SemanticResult.model_json_schema(),\n        },\n    }\n}\n\n\nclass SemanticsDescription(BasicPipeline):\n    def __init__(self, llm_provider: LLMProvider, **_):\n        self._components = {\n            \"prompt_builder\": PromptBuilder(template=user_prompt_template),\n            \"generator\": llm_provider.get_generator(\n                system_prompt=system_prompt,\n                generation_kwargs=SEMANTICS_DESCRIPTION_MODEL_KWARGS,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n        }\n        self._final = \"output\"\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"Semantics Description Generation\")\n    async def run(\n        self,\n        user_prompt: str,\n        selected_models: list[str],\n        mdl: dict,\n        language: str = \"en\",\n    ) -> dict:\n        logger.info(\"Semantics Description Generation pipeline is running...\")\n        return await self._pipe.execute(\n            [self._final],\n            inputs={\n                \"user_prompt\": user_prompt,\n                \"selected_models\": selected_models,\n                \"mdl\": mdl,\n                \"language\": language,\n                **self._components,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/sql_answer.py",
    "content": "import asyncio\nimport logging\nimport sys\nfrom typing import Any, Optional\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import LLMProvider\nfrom src.pipelines.common import clean_up_new_lines\nfrom src.utils import trace_cost\nfrom src.web.v1.services import Configuration\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\nsql_to_answer_system_prompt = \"\"\"\n### TASK\n\nYou are a data analyst that great at answering non-technical user's questions based on the data, sql so that even non technical users can easily understand.\nPlease answer the user's question in concise and clear manner in Markdown format.\n\n### INSTRUCTIONS\n\n1. Read the user's question and understand the user's intention.\n2. Read the sql and understand the data.\n3. Make sure the answer is aimed for non-technical users, so don't mention any technical terms such as SQL syntax.\n4. Generate a concise and clear answer in string format to answerthe user's question based on the data and sql.\n5. If answer is in list format, only list top few examples, and tell users there are more results omitted.\n6. Answer must be in the same language user specified.\n7. Do not include ```markdown or ``` in the answer.\n8. If the user provides a custom instruction, it should be followed strictly and you should use it to change the style of response.\n\n### OUTPUT FORMAT\n\nPlease provide your response in proper Markdown stringformat.\n\"\"\"\n\nsql_to_answer_user_prompt_template = \"\"\"\n### Inputs ###\nUser's question: {{ query }}\nSQL: {{ sql }}\nData: \ncolumns: {{ sql_data.columns }}\nrows: {{ sql_data.data }}\nLanguage: {{ language }}\nCurrent Time: {{ current_time }}\n\nCustom Instruction: {{ custom_instruction }}\n\nPlease think step by step and answer the user's question.\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef prompt(\n    query: str,\n    sql: str,\n    sql_data: dict,\n    language: str,\n    current_time: str,\n    custom_instruction: str,\n    prompt_builder: PromptBuilder,\n) -> dict:\n    _prompt = prompt_builder.run(\n        query=query,\n        sql=sql,\n        sql_data=sql_data,\n        language=language,\n        current_time=current_time,\n        custom_instruction=custom_instruction,\n    )\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def generate_answer(\n    prompt: dict, generator: Any, query_id: str, generator_name: str\n) -> dict:\n    return await generator(\n        prompt=prompt.get(\"prompt\"), query_id=query_id\n    ), generator_name\n\n\n## End of Pipeline\n\n\nclass SQLAnswer(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        **kwargs,\n    ):\n        self._user_queues = {}\n        self._components = {\n            \"prompt_builder\": PromptBuilder(\n                template=sql_to_answer_user_prompt_template\n            ),\n            \"generator\": llm_provider.get_generator(\n                system_prompt=sql_to_answer_system_prompt,\n                streaming_callback=self._streaming_callback,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    def _streaming_callback(self, chunk, query_id):\n        if query_id not in self._user_queues:\n            self._user_queues[\n                query_id\n            ] = asyncio.Queue()  # Create a new queue for the user if it doesn't exist\n        # Put the chunk content into the user's queue\n        asyncio.create_task(self._user_queues[query_id].put(chunk.content))\n        if chunk.meta.get(\"finish_reason\"):\n            asyncio.create_task(self._user_queues[query_id].put(\"<DONE>\"))\n\n    async def get_streaming_results(self, query_id):\n        async def _get_streaming_results(query_id):\n            return await self._user_queues[query_id].get()\n\n        if query_id not in self._user_queues:\n            self._user_queues[\n                query_id\n            ] = asyncio.Queue()  # Ensure the user's queue exists\n        while True:\n            try:\n                # Wait for an item from the user's queue\n                self._streaming_results = await asyncio.wait_for(\n                    _get_streaming_results(query_id), timeout=120\n                )\n                if (\n                    self._streaming_results == \"<DONE>\"\n                ):  # Check for end-of-stream signal\n                    del self._user_queues[query_id]\n                    break\n                if self._streaming_results:  # Check if there are results to yield\n                    yield self._streaming_results\n                    self._streaming_results = \"\"  # Clear after yielding\n            except TimeoutError:\n                break\n\n    @observe(name=\"SQL Answer Generation\")\n    async def run(\n        self,\n        query: str,\n        sql: str,\n        sql_data: dict,\n        language: str,\n        current_time: str = Configuration().show_current_time(),\n        query_id: Optional[str] = None,\n        custom_instruction: Optional[str] = None,\n    ) -> dict:\n        logger.info(\"Sql_Answer Generation pipeline is running...\")\n        return await self._pipe.execute(\n            [\"generate_answer\"],\n            inputs={\n                \"query\": query,\n                \"sql\": sql,\n                \"sql_data\": sql_data,\n                \"language\": language,\n                \"current_time\": current_time,\n                \"query_id\": query_id,\n                \"custom_instruction\": custom_instruction or \"\",\n                **self._components,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/sql_correction.py",
    "content": "import logging\nimport sys\nfrom typing import Any, Dict, List\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack import Document\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\n\nfrom src.core.engine import Engine\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import DocumentStoreProvider, LLMProvider\nfrom src.pipelines.common import clean_up_new_lines, retrieve_metadata\nfrom src.pipelines.generation.utils.sql import (\n    SQL_GENERATION_MODEL_KWARGS,\n    SQLGenPostProcessor,\n    construct_instructions,\n    get_text_to_sql_rules,\n)\nfrom src.pipelines.retrieval.sql_functions import SqlFunction\nfrom src.pipelines.retrieval.sql_knowledge import SqlKnowledge\nfrom src.utils import trace_cost\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\ndef get_sql_correction_system_prompt(sql_knowledge: SqlKnowledge | None = None) -> str:\n    text_to_sql_rules = get_text_to_sql_rules(sql_knowledge)\n\n    return f\"\"\"\n### TASK ###\nYou are an ANSI SQL expert with exceptional logical thinking skills and debugging skills, you need to fix the syntactically incorrect ANSI SQL query.\n\n### SQL CORRECTION INSTRUCTIONS ###\n\n1. First, think hard about the error message, and figure out the root cause first(please use the DATABASE SCHEMA, SQL FUNCTIONS and USER INSTRUCTIONS to help you figure out the root cause).\n2. Then, generate the syntactically correct ANSI SQL query to correct the error.\n\n### SQL RULES ###\nMake sure you follow the SQL Rules strictly.\n\n{text_to_sql_rules}\n\n### FINAL ANSWER FORMAT ###\nThe final answer must be in JSON format:\n\n{{\n    \"sql\": <CORRECTED_SQL_QUERY_STRING>\n}}\n\"\"\"\n\n\nsql_correction_user_prompt_template = \"\"\"\n{% if documents %}\n### DATABASE SCHEMA ###\n{% for document in documents %}\n    {{ document }}\n{% endfor %}\n{% endif %}\n\n{% if sql_functions %}\n### SQL FUNCTIONS ###\n{% for function in sql_functions %}\n{{ function }}\n{% endfor %}\n{% endif %}\n\n{% if instructions %}\n### USER INSTRUCTIONS ###\n{% for instruction in instructions %}\n{{ loop.index }}. {{ instruction }}\n{% endfor %}\n{% endif %}\n\n### QUESTION ###\nSQL: {{ invalid_generation_result.sql }}\nError Message: {{ invalid_generation_result.error }}\n\nLet's think step by step.\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef prompt(\n    documents: List[Document],\n    invalid_generation_result: Dict,\n    prompt_builder: PromptBuilder,\n    instructions: list[dict] | None = None,\n    sql_functions: list[SqlFunction] | None = None,\n) -> dict:\n    _prompt = prompt_builder.run(\n        documents=documents,\n        invalid_generation_result=invalid_generation_result,\n        instructions=construct_instructions(\n            instructions=instructions,\n        ),\n        sql_functions=sql_functions,\n    )\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def generate_sql_correction(\n    prompt: dict,\n    generator: Any,\n    generator_name: str,\n    sql_knowledge: SqlKnowledge | None = None,\n) -> dict:\n    current_system_prompt = get_sql_correction_system_prompt(sql_knowledge)\n    return await generator(\n        prompt=prompt.get(\"prompt\"), current_system_prompt=current_system_prompt\n    ), generator_name\n\n\n@observe(capture_input=False)\nasync def post_process(\n    generate_sql_correction: dict,\n    post_processor: SQLGenPostProcessor,\n    data_source: str,\n    project_id: str | None = None,\n    use_dry_plan: bool = False,\n    allow_dry_plan_fallback: bool = True,\n) -> dict:\n    return await post_processor.run(\n        generate_sql_correction.get(\"replies\"),\n        project_id=project_id,\n        use_dry_plan=use_dry_plan,\n        data_source=data_source,\n        allow_dry_plan_fallback=allow_dry_plan_fallback,\n    )\n\n\n## End of Pipeline\n\n\nclass SQLCorrection(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        document_store_provider: DocumentStoreProvider,\n        engine: Engine,\n        **kwargs,\n    ):\n        self._retriever = document_store_provider.get_retriever(\n            document_store_provider.get_store(\"project_meta\")\n        )\n\n        self._components = {\n            \"generator\": llm_provider.get_generator(\n                system_prompt=get_sql_correction_system_prompt(None),\n                generation_kwargs=SQL_GENERATION_MODEL_KWARGS,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n            \"prompt_builder\": PromptBuilder(\n                template=sql_correction_user_prompt_template\n            ),\n            \"post_processor\": SQLGenPostProcessor(engine=engine),\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"SQL Correction\")\n    async def run(\n        self,\n        contexts: List[Document],\n        invalid_generation_result: Dict[str, str],\n        instructions: list[dict] | None = None,\n        sql_functions: list[SqlFunction] | None = None,\n        project_id: str | None = None,\n        use_dry_plan: bool = False,\n        allow_dry_plan_fallback: bool = True,\n        sql_knowledge: SqlKnowledge | None = None,\n    ):\n        logger.info(\"SQLCorrection pipeline is running...\")\n\n        if use_dry_plan:\n            metadata = await retrieve_metadata(project_id or \"\", self._retriever)\n        else:\n            metadata = {}\n\n        return await self._pipe.execute(\n            [\"post_process\"],\n            inputs={\n                \"invalid_generation_result\": invalid_generation_result,\n                \"documents\": contexts,\n                \"instructions\": instructions,\n                \"sql_functions\": sql_functions,\n                \"project_id\": project_id,\n                \"use_dry_plan\": use_dry_plan,\n                \"allow_dry_plan_fallback\": allow_dry_plan_fallback,\n                \"data_source\": metadata.get(\"data_source\", \"local_file\"),\n                \"sql_knowledge\": sql_knowledge,\n                **self._components,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/sql_diagnosis.py",
    "content": "import logging\nimport sys\nfrom typing import Any, List\n\nimport orjson\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack import Document\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import LLMProvider\nfrom src.pipelines.common import clean_up_new_lines\nfrom src.utils import trace_cost\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nsql_diagnosis_system_prompt = \"\"\"\n### TASK ###\nYou are an ANSI SQL expert with exceptional logical thinking skills and debugging skills, you need to diagnose the issue with the given SQL query, error message and database schema.\n\n### SQL DIAGNOSIS INSTRUCTIONS ###\n\n1. First, think hard about the error message, and analyze the invalid SQL query to figure out the root cause and which part is incorrect.\n2. Then, map the incorrect part of the invalid SQL query to the corresponding part of the original SQL query.\n3. Then, return the reasoning behind the diagnosis.(You should give me the part of the original SQL query that is incorrect and the reason why it is incorrect)\n4. Reasoning should be in the language same as the language user provided in the INPUTS section.\n5. Reasoning should be concise and to the point and within 50 words.\n\n### FINAL ANSWER FORMAT ###\nThe final answer must be in JSON format:\n\n{\n    \"reasoning\": <REASONING_STRING>\n}\n\"\"\"\n\nsql_diagnosis_user_prompt_template = \"\"\"\n### DATABASE SCHEMA ###\n{% for document in documents %}\n    {{ document }}\n{% endfor %}\n\n### INPUTS ###\nOriginal SQL:\n{{ original_sql }}\n\nInvalid SQL:\n{{ invalid_sql }}\n\nError Message:\n{{ error_message }}\n\nLanguage: {{ language }}\n\nPlease think step by step.\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef prompt(\n    documents: List[Document],\n    original_sql: str,\n    invalid_sql: str,\n    error_message: str,\n    language: str,\n    prompt_builder: PromptBuilder,\n) -> dict:\n    _prompt = prompt_builder.run(\n        documents=documents,\n        original_sql=original_sql,\n        invalid_sql=invalid_sql,\n        error_message=error_message,\n        language=language,\n    )\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def generate_sql_diagnosis(\n    prompt: dict, generator: Any, generator_name: str\n) -> dict:\n    return await generator(prompt=prompt.get(\"prompt\")), generator_name\n\n\n@observe(capture_input=False)\nasync def post_process(\n    generate_sql_diagnosis: dict,\n) -> str:\n    return orjson.loads(generate_sql_diagnosis.get(\"replies\")[0])\n\n\n## End of Pipeline\n\n\nclass SqlDiagnosisResult(BaseModel):\n    reasoning: str\n\n\nSQL_DIAGNOSIS_MODEL_KWARGS = {\n    \"response_format\": {\n        \"type\": \"json_schema\",\n        \"json_schema\": {\n            \"name\": \"sql_diagnosis_result\",\n            \"schema\": SqlDiagnosisResult.model_json_schema(),\n        },\n    }\n}\n\n\nclass SQLDiagnosis(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        **kwargs,\n    ):\n        self._components = {\n            \"generator\": llm_provider.get_generator(\n                system_prompt=sql_diagnosis_system_prompt,\n                generation_kwargs=SQL_DIAGNOSIS_MODEL_KWARGS,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n            \"prompt_builder\": PromptBuilder(\n                template=sql_diagnosis_user_prompt_template\n            ),\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"SQL Diagnosis\")\n    async def run(\n        self,\n        contexts: List[Document],\n        original_sql: str,\n        invalid_sql: str,\n        error_message: str,\n        language: str,\n    ):\n        logger.info(\"SQLDiagnosis pipeline is running...\")\n\n        return await self._pipe.execute(\n            [\"post_process\"],\n            inputs={\n                \"documents\": contexts,\n                \"original_sql\": original_sql,\n                \"invalid_sql\": invalid_sql,\n                \"error_message\": error_message,\n                \"language\": language,\n                **self._components,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/sql_generation.py",
    "content": "import logging\nimport sys\nfrom typing import Any\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\n\nfrom src.core.engine import Engine\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import DocumentStoreProvider, LLMProvider\nfrom src.pipelines.common import clean_up_new_lines, retrieve_metadata\nfrom src.pipelines.generation.utils.sql import (\n    SQL_GENERATION_MODEL_KWARGS,\n    SQLGenPostProcessor,\n    construct_instructions,\n    get_calculated_field_instructions,\n    get_json_field_instructions,\n    get_metric_instructions,\n    get_sql_generation_system_prompt,\n)\nfrom src.pipelines.retrieval.sql_functions import SqlFunction\nfrom src.pipelines.retrieval.sql_knowledge import SqlKnowledge\nfrom src.utils import trace_cost\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nsql_generation_user_prompt_template = \"\"\"\n### DATABASE SCHEMA ###\n{% for document in documents %}\n    {{ document }}\n{% endfor %}\n\n{% if calculated_field_instructions %}\n{{ calculated_field_instructions }}\n{% endif %}\n\n{% if metric_instructions %}\n{{ metric_instructions }}\n{% endif %}\n\n{% if json_field_instructions %}\n{{ json_field_instructions }}\n{% endif %}\n\n{% if sql_functions %}\n### SQL FUNCTIONS ###\n{% for function in sql_functions %}\n{{ function }}\n{% endfor %}\n{% endif %}\n\n{% if sql_samples %}\n### SQL SAMPLES ###\n{% for sample in sql_samples %}\nQuestion:\n{{sample.question}}\nSQL:\n{{sample.sql}}\n{% endfor %}\n{% endif %}\n\n{% if instructions %}\n### USER INSTRUCTIONS ###\n{% for instruction in instructions %}\n{{ loop.index }}. {{ instruction }}\n{% endfor %}\n{% endif %}\n\n### QUESTION ###\nUser's Question: {{ query }}\n\n{% if sql_generation_reasoning %}\n### REASONING PLAN ###\n{{ sql_generation_reasoning }}\n{% endif %}\n\nLet's think step by step.\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef prompt(\n    query: str,\n    documents: list[str],\n    prompt_builder: PromptBuilder,\n    sql_generation_reasoning: str | None = None,\n    sql_samples: list[dict] | None = None,\n    instructions: list[dict] | None = None,\n    has_calculated_field: bool = False,\n    has_metric: bool = False,\n    has_json_field: bool = False,\n    sql_functions: list[SqlFunction] | None = None,\n    sql_knowledge: SqlKnowledge | None = None,\n) -> dict:\n    _prompt = prompt_builder.run(\n        query=query,\n        documents=documents,\n        sql_generation_reasoning=sql_generation_reasoning,\n        instructions=construct_instructions(\n            instructions=instructions,\n        ),\n        calculated_field_instructions=(\n            get_calculated_field_instructions(sql_knowledge)\n            if has_calculated_field\n            else \"\"\n        ),\n        metric_instructions=(\n            get_metric_instructions(sql_knowledge) if has_metric else \"\"\n        ),\n        json_field_instructions=(\n            get_json_field_instructions(sql_knowledge) if has_json_field else \"\"\n        ),\n        sql_samples=sql_samples,\n        sql_functions=sql_functions,\n    )\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def generate_sql(\n    prompt: dict,\n    generator: Any,\n    generator_name: str,\n    sql_knowledge: SqlKnowledge | None = None,\n) -> dict:\n    current_system_prompt = get_sql_generation_system_prompt(sql_knowledge)\n    return await generator(\n        prompt=prompt.get(\"prompt\"), current_system_prompt=current_system_prompt\n    ), generator_name\n\n\n@observe(capture_input=False)\nasync def post_process(\n    generate_sql: dict,\n    post_processor: SQLGenPostProcessor,\n    data_source: str,\n    project_id: str | None = None,\n    use_dry_plan: bool = False,\n    allow_dry_plan_fallback: bool = True,\n    allow_data_preview: bool = False,\n) -> dict:\n    return await post_processor.run(\n        generate_sql.get(\"replies\"),\n        project_id=project_id,\n        use_dry_plan=use_dry_plan,\n        data_source=data_source,\n        allow_dry_plan_fallback=allow_dry_plan_fallback,\n        allow_data_preview=allow_data_preview,\n    )\n\n\n## End of Pipeline\n\n\nclass SQLGeneration(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        document_store_provider: DocumentStoreProvider,\n        engine: Engine,\n        **kwargs,\n    ):\n        self._retriever = document_store_provider.get_retriever(\n            document_store_provider.get_store(\"project_meta\")\n        )\n\n        self._components = {\n            \"generator\": llm_provider.get_generator(\n                system_prompt=get_sql_generation_system_prompt(None),\n                generation_kwargs=SQL_GENERATION_MODEL_KWARGS,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n            \"prompt_builder\": PromptBuilder(\n                template=sql_generation_user_prompt_template\n            ),\n            \"post_processor\": SQLGenPostProcessor(engine=engine),\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"SQL Generation\")\n    async def run(\n        self,\n        query: str,\n        contexts: list[str],\n        sql_generation_reasoning: str | None = None,\n        sql_samples: list[dict] | None = None,\n        instructions: list[dict] | None = None,\n        project_id: str | None = None,\n        has_calculated_field: bool = False,\n        has_metric: bool = False,\n        has_json_field: bool = False,\n        sql_functions: list[SqlFunction] | None = None,\n        use_dry_plan: bool = False,\n        allow_dry_plan_fallback: bool = True,\n        allow_data_preview: bool = False,\n        sql_knowledge: SqlKnowledge | None = None,\n    ):\n        logger.info(\"SQL Generation pipeline is running...\")\n\n        if use_dry_plan:\n            metadata = await retrieve_metadata(project_id or \"\", self._retriever)\n        else:\n            metadata = {}\n\n        return await self._pipe.execute(\n            [\"post_process\"],\n            inputs={\n                \"query\": query,\n                \"documents\": contexts,\n                \"sql_generation_reasoning\": sql_generation_reasoning,\n                \"sql_samples\": sql_samples,\n                \"instructions\": instructions,\n                \"project_id\": project_id,\n                \"has_calculated_field\": has_calculated_field,\n                \"has_metric\": has_metric,\n                \"has_json_field\": has_json_field,\n                \"sql_functions\": sql_functions,\n                \"use_dry_plan\": use_dry_plan,\n                \"allow_dry_plan_fallback\": allow_dry_plan_fallback,\n                \"data_source\": metadata.get(\"data_source\", \"local_file\"),\n                \"allow_data_preview\": allow_data_preview,\n                \"sql_knowledge\": sql_knowledge,\n                **self._components,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/sql_generation_reasoning.py",
    "content": "import asyncio\nimport logging\nimport sys\nfrom typing import Any, Optional\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import LLMProvider\nfrom src.pipelines.common import clean_up_new_lines\nfrom src.pipelines.generation.utils.sql import (\n    construct_instructions,\n    sql_generation_reasoning_system_prompt,\n)\nfrom src.utils import trace_cost\nfrom src.web.v1.services import Configuration\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nsql_generation_reasoning_user_prompt_template = \"\"\"\n### DATABASE SCHEMA ###\n{% for document in documents %}\n    {{ document }}\n{% endfor %}\n\n{% if sql_samples %}\n### SQL SAMPLES ###\n{% for sql_sample in sql_samples %}\nQuestion:\n{{sql_sample.question}}\nSQL:\n{{sql_sample.sql}}\n{% endfor %}\n{% endif %}\n\n{% if instructions %}\n### USER INSTRUCTIONS ###\n{% for instruction in instructions %}\n{{ loop.index }}. {{ instruction }}\n{% endfor %}\n{% endif %}\n\n### INPUTS ###\nUser's Question: {{ query }}\nLanguage: {{ language }}\nCurrent Time: {{ current_time }}\n\nLet's think step by step.\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef prompt(\n    query: str,\n    documents: list[str],\n    sql_samples: list[dict],\n    instructions: list[dict],\n    prompt_builder: PromptBuilder,\n    configuration: Configuration | None = Configuration(),\n) -> dict:\n    _prompt = prompt_builder.run(\n        query=query,\n        documents=documents,\n        sql_samples=sql_samples,\n        instructions=construct_instructions(\n            instructions=instructions,\n        ),\n        language=configuration.language,\n        current_time=configuration.show_current_time(),\n    )\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def generate_sql_reasoning(\n    prompt: dict, generator: Any, query_id: str, generator_name: str\n) -> dict:\n    return await generator(\n        prompt=prompt.get(\"prompt\"), query_id=query_id\n    ), generator_name\n\n\n@observe()\ndef post_process(\n    generate_sql_reasoning: dict,\n) -> dict:\n    return generate_sql_reasoning.get(\"replies\")[0]\n\n\n## End of Pipeline\n\n\nclass SQLGenerationReasoning(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        **kwargs,\n    ):\n        self._user_queues = {}\n        self._components = {\n            \"generator\": llm_provider.get_generator(\n                system_prompt=sql_generation_reasoning_system_prompt,\n                streaming_callback=self._streaming_callback,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n            \"prompt_builder\": PromptBuilder(\n                template=sql_generation_reasoning_user_prompt_template\n            ),\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    def _streaming_callback(self, chunk, query_id):\n        if query_id not in self._user_queues:\n            self._user_queues[query_id] = asyncio.Queue()\n\n        # Put the chunk content into the user's queue\n        asyncio.create_task(self._user_queues[query_id].put(chunk.content))\n        if chunk.meta.get(\"finish_reason\"):\n            asyncio.create_task(self._user_queues[query_id].put(\"<DONE>\"))\n\n    async def get_streaming_results(self, query_id):\n        async def _get_streaming_results(query_id):\n            return await self._user_queues[query_id].get()\n\n        if query_id not in self._user_queues:\n            self._user_queues[query_id] = asyncio.Queue()\n\n        while True:\n            try:\n                # Wait for an item from the user's queue\n                self._streaming_results = await asyncio.wait_for(\n                    _get_streaming_results(query_id), timeout=120\n                )\n                if (\n                    self._streaming_results == \"<DONE>\"\n                ):  # Check for end-of-stream signal\n                    del self._user_queues[query_id]\n                    break\n                if self._streaming_results:  # Check if there are results to yield\n                    yield self._streaming_results\n                    self._streaming_results = \"\"  # Clear after yielding\n            except TimeoutError:\n                break\n\n    @observe(name=\"SQL Generation Reasoning\")\n    async def run(\n        self,\n        query: str,\n        contexts: list[str],\n        sql_samples: Optional[list[dict]] = None,\n        instructions: Optional[list[str]] = None,\n        configuration: Configuration = Configuration(),\n        query_id: Optional[str] = None,\n    ):\n        logger.info(\"SQL Generation Reasoning pipeline is running...\")\n        return await self._pipe.execute(\n            [\"post_process\"],\n            inputs={\n                \"query\": query,\n                \"documents\": contexts,\n                \"sql_samples\": sql_samples or [],\n                \"instructions\": instructions or [],\n                \"configuration\": configuration,\n                \"query_id\": query_id,\n                **self._components,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/sql_question.py",
    "content": "import logging\nimport sys\nfrom typing import Any\n\nimport orjson\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import LLMProvider\nfrom src.pipelines.common import clean_up_new_lines\nfrom src.utils import trace_cost\nfrom src.web.v1.services import Configuration\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nsql_question_system_prompt = \"\"\"\n### TASK ###\n\nYou are a data analyst great at translating any SQL query into a question that can be answered by the given SQL query.\n\n### INSTRUCTIONS ###\n\n- The question should be in the language of the user provided\n- The question should be a single sentence, concise, and easy to understand\n\n### OUTPUT FORMAT ###\n\nPlease return the result in the following JSON format:\n\n{\n    \"question\": <QUESTION_STRING_IN_USER_LANGUAGE>\n}\n\"\"\"\n\nsql_question_user_prompt_template = \"\"\"\nSQL: {{sql}}\nLanguage: {{language}}\n\nLet's think step by step.\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef prompt(\n    sql: str,\n    language: str,\n    prompt_builder: PromptBuilder,\n) -> dict:\n    _prompt = prompt_builder.run(\n        sql=sql,\n        language=language,\n    )\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def generate_sql_question(\n    prompt: dict, generator: Any, generator_name: str\n) -> dict:\n    return await generator(prompt=prompt.get(\"prompt\")), generator_name\n\n\n@observe(capture_input=False)\ndef post_process(\n    generate_sql_question: dict,\n) -> str:\n    return orjson.loads(generate_sql_question.get(\"replies\")[0])[\"question\"]\n\n\n## End of Pipeline\n\n\nclass SQLQuestionResult(BaseModel):\n    question: str\n\n\nSQL_QUESTION_MODEL_KWARGS = {\n    \"response_format\": {\n        \"type\": \"json_schema\",\n        \"json_schema\": {\n            \"name\": \"sql_question_result\",\n            \"schema\": SQLQuestionResult.model_json_schema(),\n        },\n    }\n}\n\n\nclass SQLQuestion(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        **kwargs,\n    ):\n        self._components = {\n            \"generator\": llm_provider.get_generator(\n                system_prompt=sql_question_system_prompt,\n                generation_kwargs=SQL_QUESTION_MODEL_KWARGS,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n            \"prompt_builder\": PromptBuilder(template=sql_question_user_prompt_template),\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"Sql Question Generation\")\n    async def run(\n        self,\n        sql: str,\n        configuration: Configuration = Configuration(),\n    ):\n        logger.info(\"Sql Question Generation pipeline is running...\")\n        return await self._pipe.execute(\n            [\"post_process\"],\n            inputs={\n                \"sql\": sql,\n                \"language\": configuration.language or \"English\",\n                **self._components,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/sql_regeneration.py",
    "content": "import logging\nimport sys\nfrom typing import Any\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\n\nfrom src.core.engine import Engine\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import LLMProvider\nfrom src.pipelines.common import clean_up_new_lines\nfrom src.pipelines.generation.utils.sql import (\n    SQL_GENERATION_MODEL_KWARGS,\n    SQLGenPostProcessor,\n    construct_instructions,\n    get_calculated_field_instructions,\n    get_json_field_instructions,\n    get_metric_instructions,\n    get_text_to_sql_rules,\n)\nfrom src.pipelines.retrieval.sql_functions import SqlFunction\nfrom src.pipelines.retrieval.sql_knowledge import SqlKnowledge\nfrom src.utils import trace_cost\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\ndef get_sql_regeneration_system_prompt(\n    sql_knowledge: SqlKnowledge | None = None,\n) -> str:\n    text_to_sql_rules = get_text_to_sql_rules(sql_knowledge)\n\n    return f\"\"\"\n### TASK ###\nYou are a great ANSI SQL expert. Now you are given database schema, SQL generation reasoning and an original SQL query, \nplease carefully review the reasoning, and then generate a new SQL query that matches the reasoning.\nWhile generating the new SQL query, you should use the original SQL query as a reference.\nWhile generating the new SQL query, make sure to use the database schema to generate the SQL query.\n\n{text_to_sql_rules}\n\n### FINAL ANSWER FORMAT ###\nThe final answer must be a ANSI SQL query in JSON format:\n\n{{\n    \"sql\": <SQL_QUERY_STRING>\n}}\n\"\"\"\n\n\nsql_regeneration_user_prompt_template = \"\"\"\n### DATABASE SCHEMA ###\n{% for document in documents %}\n    {{ document }}\n{% endfor %}\n\n{% if calculated_field_instructions %}\n{{ calculated_field_instructions }}\n{% endif %}\n\n{% if metric_instructions %}\n{{ metric_instructions }}\n{% endif %}\n\n{% if json_field_instructions %}\n{{ json_field_instructions }}\n{% endif %}\n\n{% if sql_functions %}\n### SQL FUNCTIONS ###\n{% for function in sql_functions %}\n{{ function }}\n{% endfor %}\n{% endif %}\n\n{% if sql_samples %}\n### SQL SAMPLES ###\n{% for sample in sql_samples %}\nQuestion:\n{{sample.question}}\nSQL:\n{{sample.sql}}\n{% endfor %}\n{% endif %}\n\n{% if instructions %}\n### USER INSTRUCTIONS ###\n{% for instruction in instructions %}\n{{ loop.index }}. {{ instruction }}\n{% endfor %}\n{% endif %}\n\n### QUESTION ###\nSQL generation reasoning: {{ sql_generation_reasoning }}\nOriginal SQL query: {{ sql }}\n\nLet's think step by step.\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef prompt(\n    documents: list[str],\n    sql_generation_reasoning: str,\n    sql: str,\n    prompt_builder: PromptBuilder,\n    sql_samples: list[dict] | None = None,\n    instructions: list[dict] | None = None,\n    has_calculated_field: bool = False,\n    has_metric: bool = False,\n    has_json_field: bool = False,\n    sql_functions: list[SqlFunction] | None = None,\n    sql_knowledge: SqlKnowledge | None = None,\n) -> dict:\n    _prompt = prompt_builder.run(\n        sql=sql,\n        documents=documents,\n        sql_generation_reasoning=sql_generation_reasoning,\n        instructions=construct_instructions(\n            instructions=instructions,\n        ),\n        calculated_field_instructions=(\n            get_calculated_field_instructions(sql_knowledge)\n            if has_calculated_field\n            else \"\"\n        ),\n        metric_instructions=(\n            get_metric_instructions(sql_knowledge) if has_metric else \"\"\n        ),\n        json_field_instructions=(\n            get_json_field_instructions(sql_knowledge) if has_json_field else \"\"\n        ),\n        sql_samples=sql_samples,\n        sql_functions=sql_functions,\n    )\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def regenerate_sql(\n    prompt: dict,\n    generator: Any,\n    generator_name: str,\n    sql_knowledge: SqlKnowledge | None = None,\n) -> dict:\n    current_system_prompt = get_sql_regeneration_system_prompt(sql_knowledge)\n    return await generator(\n        prompt=prompt.get(\"prompt\"), current_system_prompt=current_system_prompt\n    ), generator_name\n\n\n@observe(capture_input=False)\nasync def post_process(\n    regenerate_sql: dict,\n    post_processor: SQLGenPostProcessor,\n    project_id: str | None = None,\n) -> dict:\n    return await post_processor.run(\n        regenerate_sql.get(\"replies\"),\n        project_id=project_id,\n    )\n\n\n## End of Pipeline\n\n\nclass SQLRegeneration(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        engine: Engine,\n        **kwargs,\n    ):\n        self._components = {\n            \"generator\": llm_provider.get_generator(\n                system_prompt=get_sql_regeneration_system_prompt(None),\n                generation_kwargs=SQL_GENERATION_MODEL_KWARGS,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n            \"prompt_builder\": PromptBuilder(\n                template=sql_regeneration_user_prompt_template\n            ),\n            \"post_processor\": SQLGenPostProcessor(engine=engine),\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"SQL Regeneration\")\n    async def run(\n        self,\n        contexts: list[str],\n        sql_generation_reasoning: str,\n        sql: str,\n        sql_samples: list[dict] | None = None,\n        instructions: list[dict] | None = None,\n        project_id: str | None = None,\n        has_calculated_field: bool = False,\n        has_metric: bool = False,\n        has_json_field: bool = False,\n        sql_functions: list[SqlFunction] | None = None,\n        sql_knowledge: SqlKnowledge | None = None,\n    ):\n        logger.info(\"SQL Regeneration pipeline is running...\")\n\n        return await self._pipe.execute(\n            [\"post_process\"],\n            inputs={\n                \"documents\": contexts,\n                \"sql_generation_reasoning\": sql_generation_reasoning,\n                \"sql\": sql,\n                \"sql_samples\": sql_samples,\n                \"instructions\": instructions,\n                \"project_id\": project_id,\n                \"has_calculated_field\": has_calculated_field,\n                \"has_metric\": has_metric,\n                \"has_json_field\": has_json_field,\n                \"sql_functions\": sql_functions,\n                \"sql_knowledge\": sql_knowledge,\n                **self._components,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/sql_tables_extraction.py",
    "content": "import logging\nimport sys\nfrom typing import Any\n\nimport orjson\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import LLMProvider\nfrom src.pipelines.common import clean_up_new_lines\nfrom src.utils import trace_cost\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nsql_tables_extraction_system_prompt = \"\"\"\n### TASK ###\n\nYou are a data analyst great at extracting a list of tables from any SQL query.\n\n### EXAMPLES ###\n\nSQL: SELECT * FROM table1\nOutput: {\n    \"tables\": [\"table1\"]\n}\n\nSQL: SELECT * FROM table1, table2\nOutput: {\n    \"tables\": [\"table1\", \"table2\"]\n}\n\nSQL: SELECT * FROM table1 JOIN table2 ON table1.id = table2.id\nOutput: {\n    \"tables\": [\"table1\", \"table2\"]\n}\n\n### OUTPUT FORMAT ###\n\nPlease return the result in the following JSON format:\n\n{\n    \"tables\": <LIST_OF_TABLES_IN_STRING_FORMAT>\n}\n\"\"\"\n\nsql_tables_extraction_user_prompt_template = \"\"\"\nSQL: {{sql}}\n\nLet's think step by step.\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef prompt(\n    sql: str,\n    prompt_builder: PromptBuilder,\n) -> dict:\n    _prompt = prompt_builder.run(sql=sql)\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def extract_sql_tables(prompt: dict, generator: Any, generator_name: str) -> dict:\n    return await generator(prompt=prompt.get(\"prompt\")), generator_name\n\n\n@observe(capture_input=False)\nasync def post_process(\n    extract_sql_tables: dict,\n) -> list[str]:\n    return orjson.loads(extract_sql_tables.get(\"replies\")[0])[\"tables\"]\n\n\n## End of Pipeline\n\n\nclass SQLTablesExtractionResult(BaseModel):\n    tables: list[str]\n\n\nSQL_TABLES_EXTRACTION_MODEL_KWARGS = {\n    \"response_format\": {\n        \"type\": \"json_schema\",\n        \"json_schema\": {\n            \"name\": \"sql_tables_extraction_result\",\n            \"schema\": SQLTablesExtractionResult.model_json_schema(),\n        },\n    }\n}\n\n\nclass SQLTablesExtraction(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        **kwargs,\n    ):\n        self._components = {\n            \"generator\": llm_provider.get_generator(\n                system_prompt=sql_tables_extraction_system_prompt,\n                generation_kwargs=SQL_TABLES_EXTRACTION_MODEL_KWARGS,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n            \"prompt_builder\": PromptBuilder(\n                template=sql_tables_extraction_user_prompt_template\n            ),\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"Sql Tables Extraction\")\n    async def run(\n        self,\n        sql: str,\n    ):\n        logger.info(\"Sql Tables Extraction pipeline is running...\")\n        return await self._pipe.execute(\n            [\"post_process\"],\n            inputs={\n                \"sql\": sql,\n                **self._components,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/user_guide_assistance.py",
    "content": "import asyncio\nimport logging\nimport sys\nfrom typing import Any, Optional\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import LLMProvider\nfrom src.pipelines.common import clean_up_new_lines\nfrom src.utils import trace_cost\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nuser_guide_assistance_system_prompt = \"\"\"\nYou are a helpful assistant that can help users understand Wren AI. \nYou are given a user question and a user guide.\nYou need to understand the user question and the user guide, and then answer the user question.\n\n### INSTRUCTIONS ###\n1. Your answer should be in the same language as the language user provided.\n2. You must follow the user guide to answer the user question.\n3. If you think you cannot answer the user question given the user guide, please kindly respond user that you don't find relevant answer in the user guide.\n4. You should add citations to the user guide(document url) in your answer.\n5. You should provide your answer in Markdown format.\n6. If the user provides a custom instruction, it should be followed strictly and you should use it to change the style of response.\n\n### OUTPUT FORMAT ###\nPlease provide your response in proper Markdown format without ```markdown``` tags.\n\"\"\"\n\nuser_guide_assistance_user_prompt_template = \"\"\"\nUser Question: {{query}}\nLanguage: {{language}}\nUser Guide:\n{% for doc in docs %}\n- {{doc.path}}: {{doc.content}}\n{% endfor %}\n\nCustom Instruction: {{ custom_instruction }}\n\nPlease think step by step.\n\"\"\"\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef prompt(\n    query: str,\n    language: str,\n    wren_ai_docs: list[dict],\n    prompt_builder: PromptBuilder,\n    custom_instruction: str,\n) -> dict:\n    _prompt = prompt_builder.run(\n        query=query,\n        language=language,\n        docs=wren_ai_docs,\n        custom_instruction=custom_instruction,\n    )\n    return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def user_guide_assistance(\n    prompt: dict, generator: Any, query_id: str, generator_name: str\n) -> dict:\n    return await generator(\n        prompt=prompt.get(\"prompt\"), query_id=query_id\n    ), generator_name\n\n\n## End of Pipeline\n\n\nclass UserGuideAssistance(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        wren_ai_docs: list[dict],\n        **kwargs,\n    ):\n        self._user_queues = {}\n        self._components = {\n            \"generator\": llm_provider.get_generator(\n                system_prompt=user_guide_assistance_system_prompt,\n                streaming_callback=self._streaming_callback,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n            \"prompt_builder\": PromptBuilder(\n                template=user_guide_assistance_user_prompt_template\n            ),\n        }\n        self._configs = {\n            \"wren_ai_docs\": wren_ai_docs,\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    def _streaming_callback(self, chunk, query_id):\n        if query_id not in self._user_queues:\n            self._user_queues[\n                query_id\n            ] = asyncio.Queue()  # Create a new queue for the user if it doesn't exist\n        # Put the chunk content into the user's queue\n        asyncio.create_task(self._user_queues[query_id].put(chunk.content))\n        if chunk.meta.get(\"finish_reason\"):\n            asyncio.create_task(self._user_queues[query_id].put(\"<DONE>\"))\n\n    async def get_streaming_results(self, query_id):\n        async def _get_streaming_results(query_id):\n            return await self._user_queues[query_id].get()\n\n        if query_id not in self._user_queues:\n            self._user_queues[query_id] = asyncio.Queue()\n\n        while True:\n            try:\n                # Wait for an item from the user's queue\n                self._streaming_results = await asyncio.wait_for(\n                    _get_streaming_results(query_id), timeout=120\n                )\n                if (\n                    self._streaming_results == \"<DONE>\"\n                ):  # Check for end-of-stream signal\n                    del self._user_queues[query_id]\n                    break\n                if self._streaming_results:  # Check if there are results to yield\n                    yield self._streaming_results\n                    self._streaming_results = \"\"  # Clear after yielding\n            except TimeoutError:\n                break\n\n    @observe(name=\"User Guide Assistance\")\n    async def run(\n        self,\n        query: str,\n        language: str,\n        query_id: Optional[str] = None,\n        custom_instruction: Optional[str] = None,\n    ):\n        logger.info(\"User Guide Assistance pipeline is running...\")\n        return await self._pipe.execute(\n            [\"user_guide_assistance\"],\n            inputs={\n                \"query\": query,\n                \"language\": language,\n                \"query_id\": query_id or \"\",\n                \"custom_instruction\": custom_instruction or \"\",\n                **self._components,\n                **self._configs,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/utils/chart.py",
    "content": "import logging\nfrom typing import Any, Dict, Literal, Optional\n\nimport orjson\nimport pandas as pd\nfrom haystack import component\nfrom jsonschema import validate\nfrom jsonschema.exceptions import ValidationError\nfrom pydantic import BaseModel, Field\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nchart_generation_instructions = \"\"\"\n### INSTRUCTIONS ###\n\n- Chart types: Bar chart, Line chart, Multi line chart, Area chart, Pie chart, Stacked bar chart, Grouped bar chart\n- You can only use the chart types provided in the instructions\n- Generated chart should answer the user's question and based on the semantics of the SQL query, and the sample data, sample column values are used to help you generate the suitable chart type\n- If the sample data is not suitable for visualization, you must return an empty string for the schema and chart type\n- If the sample data is empty, you must return an empty string for the schema and chart type\n- The language for the chart and reasoning must be the same language provided by the user\n- Please use the current time provided by the user to generate the chart\n- In order to generate the grouped bar chart, you need to follow the given instructions:\n    - Disable Stacking: Add \"stack\": null to the y-encoding.\n    - Use xOffset for subcategories to group bars.\n    - Don't use \"transform\" section.\n- In order to generate the pie chart, you need to follow the given instructions:\n    - Add {\"type\": \"arc\"} to the mark section.\n    - Add \"theta\" encoding to the encoding section.\n    - Add \"color\" encoding to the encoding section.\n    - Don't add \"innerRadius\" to the mark section.\n- If the x-axis of the chart is a temporal field, the time unit should be the same as the question user asked.\n    - For yearly question, the time unit should be \"year\".\n    - For monthly question, the time unit should be \"yearmonth\".\n    - For weekly question, the time unit should be \"yearmonthdate\".\n    - For daily question, the time unit should be \"yearmonthdate\".\n    - Default time unit is \"yearmonth\".\n- For each axis, generate the corresponding human-readable title based on the language provided by the user.\n- Make sure all of the fields(x, y, xOffset, color, etc.) in the encoding section of the chart schema are present in the column names of the data.\n\n### GUIDELINES TO PLOT CHART ###\n\n1. Understanding Your Data Types\n- Nominal (Categorical): Names or labels without a specific order (e.g., types of fruits, countries).\n- Ordinal: Categorical data with a meaningful order but no fixed intervals (e.g., rankings, satisfaction levels).\n- Quantitative: Numerical values representing counts or measurements (e.g., sales figures, temperatures).\n- Temporal: Date or time data (e.g., timestamps, dates).\n2. Chart Types and When to Use Them\n- Bar Chart\n    - Use When: Comparing quantities across different categories.\n    - Data Requirements:\n        - One categorical variable (x-axis).\n        - One quantitative variable (y-axis).\n    - Example: Comparing sales numbers for different product categories.\n- Grouped Bar Chart\n    - Use When: Comparing sub-categories within main categories.\n    - Data Requirements:\n        - Two categorical variables (x-axis grouped by one, color-coded by another).\n        - One quantitative variable (y-axis).\n        - Example: Sales numbers for different products across various regions.\n- Line Chart\n    - Use When: Displaying trends over continuous data, especially time.\n    - Data Requirements:\n        - One temporal or ordinal variable (x-axis).\n        - One quantitative variable (y-axis).\n    - Example: Tracking monthly revenue over a year.\n- Multi Line Chart\n    - Use When: Displaying trends over continuous data, especially time.\n    - Data Requirements:\n        - One temporal or ordinal variable (x-axis).\n        - Two or more quantitative variables (y-axis and color).\n    - Implementation Notes:\n        - Uses `transform` with `fold` to combine multiple metrics into a single series\n        - The folded metrics are distinguished using the color encoding\n    - Example: Tracking monthly click rate and read rate over a year.\n- Area Chart\n    - Use When: Similar to line charts but emphasizing the volume of change over time.\n    - Data Requirements:\n        - Same as Line Chart.\n    - Example: Visualizing cumulative rainfall over months.\n- Pie Chart\n    - Use When: Showing parts of a whole as percentages.\n    - Data Requirements:\n        - One categorical variable.\n        - One quantitative variable representing proportions.\n    - Example: Market share distribution among companies.\n- Stacked Bar Chart\n    - Use When: Showing composition and comparison across categories.\n    - Data Requirements: Same as grouped bar chart.\n    - Example: Sales by region and product type.\n- Guidelines for Selecting Chart Types\n    - Comparing Categories:\n        - Bar Chart: Best for simple comparisons across categories.\n        - Grouped Bar Chart: Use when you have sub-categories.\n        - Stacked Bar Chart: Use to show composition within categories.\n    - Showing Trends Over Time:\n        - Line Chart: Ideal for continuous data over time.\n        - Area Chart: Use when you want to emphasize volume or total value over time.\n    - Displaying Proportions:\n        - Pie Chart: Use for simple compositions at a single point in time.\n        - Stacked Bar Chart (100%): Use for comparing compositions across multiple categories.\n    \n### EXAMPLES ###\n\n1. Bar Chart\n- Sample Data:\n [\n    {\"Region\": \"North\", \"Sales\": 100},\n    {\"Region\": \"South\", \"Sales\": 200},\n    {\"Region\": \"East\", \"Sales\": 300},\n    {\"Region\": \"West\", \"Sales\": 400}\n]\n- Chart Schema:\n{\n    \"title\": <TITLE_IN_LANGUAGE_PROVIDED_BY_USER>,\n    \"mark\": {\"type\": \"bar\"},\n    \"encoding\": {\n        \"x\": {\"field\": \"Region\", \"type\": \"nominal\", \"title\": <TITLE_IN_LANGUAGE_PROVIDED_BY_USER>},\n        \"y\": {\"field\": \"Sales\", \"type\": \"quantitative\", \"title\": <TITLE_IN_LANGUAGE_PROVIDED_BY_USER>},\n        \"color\": {\"field\": \"Region\", \"type\": \"nominal\", \"title\": \"<TITLE_IN_LANGUAGE_PROVIDED_BY_USER>\"}\n    }\n}\n2. Line Chart\n- Sample Data:\n[\n    {\"Date\": \"2022-01-01\", \"Sales\": 100},\n    {\"Date\": \"2022-01-02\", \"Sales\": 200},\n    {\"Date\": \"2022-01-03\", \"Sales\": 300},\n    {\"Date\": \"2022-01-04\", \"Sales\": 400}\n]\n- Chart Schema:\n{\n    \"title\": <TITLE_IN_LANGUAGE_PROVIDED_BY_USER>,\n    \"mark\": {\"type\": \"line\"},\n    \"encoding\": {\n        \"x\": {\"field\": \"Date\", \"type\": \"temporal\", \"title\": <TITLE_IN_LANGUAGE_PROVIDED_BY_USER>},\n        \"y\": {\"field\": \"Sales\", \"type\": \"quantitative\", \"title\": <TITLE_IN_LANGUAGE_PROVIDED_BY_USER>}\n    }\n}\n3. Pie Chart\n- Sample Data:\n[\n    {\"Company\": \"Company A\", \"Market Share\": 0.4},\n    {\"Company\": \"Company B\", \"Market Share\": 0.3},\n    {\"Company\": \"Company C\", \"Market Share\": 0.2},\n    {\"Company\": \"Company D\", \"Market Share\": 0.1}\n]\n- Chart Schema:\n{\n    \"title\": <TITLE_IN_LANGUAGE_PROVIDED_BY_USER>,\n    \"mark\": {\"type\": \"arc\"},\n    \"encoding\": {\n        \"theta\": {\"field\": \"Market Share\", \"type\": \"quantitative\"},\n        \"color\": {\"field\": \"Company\", \"type\": \"nominal\", \"title\": <TITLE_IN_LANGUAGE_PROVIDED_BY_USER>}\n    }\n}\n4. Area Chart\n- Sample Data:\n[\n    {\"Date\": \"2022-01-01\", \"Sales\": 100},\n    {\"Date\": \"2022-01-02\", \"Sales\": 200},\n    {\"Date\": \"2022-01-03\", \"Sales\": 300},\n    {\"Date\": \"2022-01-04\", \"Sales\": 400}\n]\n- Chart Schema:\n{\n    \"title\": \"<TITLE_IN_LANGUAGE_PROVIDED_BY_USER>\",\n    \"mark\": {\"type\": \"area\"},\n    \"encoding\": {\n        \"x\": {\"field\": \"Date\", \"type\": \"temporal\", \"title\": \"<TITLE_IN_LANGUAGE_PROVIDED_BY_USER>\"},\n        \"y\": {\"field\": \"Sales\", \"type\": \"quantitative\", \"title\": \"<TITLE_IN_LANGUAGE_PROVIDED_BY_USER>\"}\n    }\n}\n5. Stacked Bar Chart\n- Sample Data:\n[\n    {\"Region\": \"North\", \"Product\": \"A\", \"Sales\": 100},\n    {\"Region\": \"North\", \"Product\": \"B\", \"Sales\": 150},\n    {\"Region\": \"South\", \"Product\": \"A\", \"Sales\": 200},\n    {\"Region\": \"South\", \"Product\": \"B\", \"Sales\": 250},\n    {\"Region\": \"East\", \"Product\": \"A\", \"Sales\": 300},\n    {\"Region\": \"East\", \"Product\": \"B\", \"Sales\": 350},\n    {\"Region\": \"West\", \"Product\": \"A\", \"Sales\": 400},\n    {\"Region\": \"West\", \"Product\": \"B\", \"Sales\": 450}\n]\n- Chart Schema:\n{\n    \"title\": \"<TITLE_IN_LANGUAGE_PROVIDED_BY_USER>\",\n    \"mark\": {\"type\": \"bar\"},\n    \"encoding\": {\n        \"x\": {\"field\": \"Region\", \"type\": \"nominal\", \"title\": \"<TITLE_IN_LANGUAGE_PROVIDED_BY_USER>\"},\n        \"y\": {\"field\": \"Sales\", \"type\": \"quantitative\", \"title\": \"<TITLE_IN_LANGUAGE_PROVIDED_BY_USER>\", \"stack\": \"zero\"},\n        \"color\": {\"field\": \"Product\", \"type\": \"nominal\", \"title\": \"<TITLE_IN_LANGUAGE_PROVIDED_BY_USER>\"}\n    }\n}\n6. Grouped Bar Chart\n- Sample Data:\n[\n    {\"Region\": \"North\", \"Product\": \"A\", \"Sales\": 100},\n    {\"Region\": \"North\", \"Product\": \"B\", \"Sales\": 150},\n    {\"Region\": \"South\", \"Product\": \"A\", \"Sales\": 200},\n    {\"Region\": \"South\", \"Product\": \"B\", \"Sales\": 250},\n    {\"Region\": \"East\", \"Product\": \"A\", \"Sales\": 300},\n    {\"Region\": \"East\", \"Product\": \"B\", \"Sales\": 350},\n    {\"Region\": \"West\", \"Product\": \"A\", \"Sales\": 400},\n    {\"Region\": \"West\", \"Product\": \"B\", \"Sales\": 450}\n]\n- Chart Schema:\n{\n    \"title\": \"<TITLE_IN_LANGUAGE_PROVIDED_BY_USER>\",\n    \"mark\": {\"type\": \"bar\"},\n    \"encoding\": {\n        \"x\": {\"field\": \"Region\", \"type\": \"nominal\", \"title\": \"<TITLE_IN_LANGUAGE_PROVIDED_BY_USER>\"},\n        \"y\": {\"field\": \"Sales\", \"type\": \"quantitative\", \"title\": \"<TITLE_IN_LANGUAGE_PROVIDED_BY_USER>\"},\n        \"xOffset\": {\"field\": \"Product\", \"type\": \"nominal\", \"title\": \"<TITLE_IN_LANGUAGE_PROVIDED_BY_USER>\"},\n        \"color\": {\"field\": \"Product\", \"type\": \"nominal\", \"title\": \"<TITLE_IN_LANGUAGE_PROVIDED_BY_USER>\"}\n    }\n}\n7. Multi Line Chart\n- Sample Data:\n[\n    {\"Date\": \"2022-01-01\", \"readCount\": 100, \"clickCount\": 10},\n    {\"Date\": \"2022-01-02\", \"readCount\": 200, \"clickCount\": 30},\n    {\"Date\": \"2022-01-03\", \"readCount\": 300, \"clickCount\": 20},\n    {\"Date\": \"2022-01-04\", \"readCount\": 400, \"clickCount\": 40}\n]\n- Chart Schema:\n{\n    \"title\": <TITLE_IN_LANGUAGE_PROVIDED_BY_USER>,\n    \"mark\": {\"type\": \"line\"},\n    \"transform\": [\n        {\n        \"fold\": [\"readCount\", \"clickCount\"],\n        \"as\": [\"Metric\", \"Value\"]\n        }\n    ],\n    \"encoding\": {\n        \"x\": {\"field\": \"Date\", \"type\": \"temporal\", \"title\": <TITLE_IN_LANGUAGE_PROVIDED_BY_USER>},\n        \"y\": {\"field\": \"Value\", \"type\": \"quantitative\", \"title\": <TITLE_IN_LANGUAGE_PROVIDED_BY_USER>},\n        \"color\": {\"field\": \"Metric\", \"type\": \"nominal\", \"title\": <TITLE_IN_LANGUAGE_PROVIDED_BY_USER>}\n    }\n}\n\"\"\"\n\n\n@component\nclass ChartDataPreprocessor:\n    @component.output_types(\n        sample_data=list[dict],\n        sample_column_values=dict[str, Any],\n    )\n    def run(\n        self,\n        data: Dict[str, Any],\n        sample_data_count: int = 15,\n        sample_column_size: int = 5,\n    ):\n        columns = [\n            column.get(\"name\", \"\") if isinstance(column, dict) else column\n            for column in data.get(\"columns\", [])\n        ]\n        data = data.get(\"data\", [])\n\n        df = pd.DataFrame(data, columns=columns)\n        sample_column_values = {\n            col: list(df[col].unique())[:sample_column_size] for col in df.columns\n        }\n\n        if len(df) > sample_data_count:\n            sample_data = df.sample(n=sample_data_count).to_dict(orient=\"records\")\n        else:\n            sample_data = df.to_dict(orient=\"records\")\n\n        return {\n            \"sample_data\": sample_data,\n            \"sample_column_values\": sample_column_values,\n        }\n\n\n@component\nclass ChartGenerationPostProcessor:\n    @component.output_types(\n        results=Dict[str, Any],\n    )\n    def run(\n        self,\n        replies: str,\n        vega_schema: Dict[str, Any],\n        sample_data: list[dict],\n        remove_data_from_chart_schema: Optional[bool] = True,\n    ):\n        try:\n            generation_result = orjson.loads(replies[0])\n            reasoning = generation_result.get(\"reasoning\", \"\")\n            chart_type = generation_result.get(\"chart_type\", \"\")\n            if chart_schema := generation_result.get(\"chart_schema\", {}):\n                # sometimes the chart_schema is still in string format\n                if isinstance(chart_schema, str):\n                    chart_schema = orjson.loads(chart_schema)\n\n                chart_schema[\n                    \"$schema\"\n                ] = \"https://vega.github.io/schema/vega-lite/v5.json\"\n                chart_schema[\"data\"] = {\"values\": sample_data}\n\n                validate(chart_schema, schema=vega_schema)\n\n                if remove_data_from_chart_schema:\n                    chart_schema[\"data\"][\"values\"] = []\n\n                return {\n                    \"results\": {\n                        \"chart_schema\": chart_schema,\n                        \"reasoning\": reasoning,\n                        \"chart_type\": chart_type,\n                    }\n                }\n\n            return {\n                \"results\": {\n                    \"chart_schema\": {},\n                    \"reasoning\": reasoning,\n                    \"chart_type\": chart_type,\n                }\n            }\n        except ValidationError as e:\n            logger.exception(f\"Vega-lite schema is not valid: {e}\")\n\n            return {\n                \"results\": {\n                    \"chart_schema\": {},\n                    \"reasoning\": \"\",\n                    \"chart_type\": \"\",\n                }\n            }\n        except Exception as e:\n            logger.exception(f\"JSON deserialization failed: {e}\")\n\n            return {\n                \"results\": {\n                    \"chart_schema\": {},\n                    \"reasoning\": \"\",\n                    \"chart_type\": \"\",\n                }\n            }\n\n\nclass ChartSchema(BaseModel):\n    class ChartType(BaseModel):\n        type: Literal[\"bar\", \"line\", \"area\", \"arc\"]\n\n    class ChartEncoding(BaseModel):\n        field: str\n        type: Literal[\"ordinal\", \"quantitative\", \"nominal\"]\n        title: str\n\n    title: str\n    mark: ChartType\n    encoding: ChartEncoding\n\n\nclass TemporalChartEncoding(ChartSchema.ChartEncoding):\n    type: Literal[\"temporal\"] = Field(default=\"temporal\")\n    timeUnit: str = Field(default=\"yearmonth\")\n\n\nclass LineChartSchema(ChartSchema):\n    class LineChartMark(BaseModel):\n        type: Literal[\"line\"] = Field(default=\"line\")\n\n    class LineChartEncoding(BaseModel):\n        x: TemporalChartEncoding | ChartSchema.ChartEncoding\n        y: ChartSchema.ChartEncoding\n        color: ChartSchema.ChartEncoding\n\n    mark: LineChartMark\n    encoding: LineChartEncoding\n\n\nclass MultiLineChartSchema(ChartSchema):\n    class MultiLineChartMark(BaseModel):\n        type: Literal[\"line\"] = Field(default=\"line\")\n\n    class MultiLineChartTransform(BaseModel):\n        fold: list[str]\n        as_: list[str] = Field(alias=\"as\")\n\n    class MultiLineChartEncoding(BaseModel):\n        x: TemporalChartEncoding | ChartSchema.ChartEncoding\n        y: ChartSchema.ChartEncoding\n        color: ChartSchema.ChartEncoding\n\n    mark: MultiLineChartMark\n    transform: list[MultiLineChartTransform]\n    encoding: MultiLineChartEncoding\n\n\nclass BarChartSchema(ChartSchema):\n    class BarChartMark(BaseModel):\n        type: Literal[\"bar\"] = Field(default=\"bar\")\n\n    class BarChartEncoding(BaseModel):\n        x: TemporalChartEncoding | ChartSchema.ChartEncoding\n        y: ChartSchema.ChartEncoding\n        color: ChartSchema.ChartEncoding\n\n    mark: BarChartMark\n    encoding: BarChartEncoding\n\n\nclass GroupedBarChartSchema(ChartSchema):\n    class GroupedBarChartMark(BaseModel):\n        type: Literal[\"bar\"] = Field(default=\"bar\")\n\n    class GroupedBarChartEncoding(BaseModel):\n        x: TemporalChartEncoding | ChartSchema.ChartEncoding\n        y: ChartSchema.ChartEncoding\n        xOffset: ChartSchema.ChartEncoding\n        color: ChartSchema.ChartEncoding\n\n    mark: GroupedBarChartMark\n    encoding: GroupedBarChartEncoding\n\n\nclass StackedBarChartYEncoding(ChartSchema.ChartEncoding):\n    stack: Literal[\"zero\"] = Field(default=\"zero\")\n\n\nclass StackedBarChartSchema(ChartSchema):\n    class StackedBarChartMark(BaseModel):\n        type: Literal[\"bar\"] = Field(default=\"bar\")\n\n    class StackedBarChartEncoding(BaseModel):\n        x: TemporalChartEncoding | ChartSchema.ChartEncoding\n        y: StackedBarChartYEncoding\n        color: ChartSchema.ChartEncoding\n\n    mark: StackedBarChartMark\n    encoding: StackedBarChartEncoding\n\n\nclass PieChartSchema(ChartSchema):\n    class PieChartMark(BaseModel):\n        type: Literal[\"arc\"] = Field(default=\"arc\")\n\n    class PieChartEncoding(BaseModel):\n        theta: ChartSchema.ChartEncoding\n        color: ChartSchema.ChartEncoding\n\n    mark: PieChartMark\n    encoding: PieChartEncoding\n\n\nclass AreaChartSchema(ChartSchema):\n    class AreaChartMark(BaseModel):\n        type: Literal[\"area\"] = Field(default=\"area\")\n\n    class AreaChartEncoding(BaseModel):\n        x: TemporalChartEncoding | ChartSchema.ChartEncoding\n        y: ChartSchema.ChartEncoding\n\n    mark: AreaChartMark\n    encoding: AreaChartEncoding\n\n\nclass ChartGenerationResults(BaseModel):\n    reasoning: str\n    chart_type: Literal[\n        \"line\", \"multi_line\", \"bar\", \"pie\", \"grouped_bar\", \"stacked_bar\", \"area\", \"\"\n    ]  # empty string for no chart\n    chart_schema: (\n        LineChartSchema\n        | MultiLineChartSchema\n        | BarChartSchema\n        | PieChartSchema\n        | GroupedBarChartSchema\n        | StackedBarChartSchema\n        | AreaChartSchema\n    )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/utils/sql.py",
    "content": "import logging\nfrom typing import Any, Dict, List\n\nimport aiohttp\nimport orjson\nfrom haystack import component\nfrom haystack.dataclasses import ChatMessage\nfrom pydantic import BaseModel\n\nfrom src.core.engine import (\n    Engine,\n    clean_generation_result,\n)\nfrom src.pipelines.retrieval.sql_knowledge import SqlKnowledge\nfrom src.web.v1.services.ask import AskHistory\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n@component\nclass SQLGenPostProcessor:\n    def __init__(self, engine: Engine):\n        self._engine = engine\n\n    @component.output_types(\n        valid_generation_result=Dict[str, Any],\n        invalid_generation_result=Dict[str, Any],\n    )\n    async def run(\n        self,\n        replies: List[str] | List[List[str]],\n        project_id: str | None = None,\n        use_dry_plan: bool = False,\n        allow_dry_plan_fallback: bool = True,\n        data_source: str = \"\",\n        allow_data_preview: bool = False,\n    ) -> dict:\n        try:\n            cleaned_generation_result = clean_generation_result(replies[0])\n\n            # test if cleaned_generation_result in string format is actually a dictionary with key 'sql'\n            if cleaned_generation_result.startswith(\"{\"):\n                cleaned_generation_result = orjson.loads(cleaned_generation_result)[\n                    \"sql\"\n                ]\n\n            (\n                valid_generation_result,\n                invalid_generation_result,\n            ) = await self._classify_generation_result(\n                cleaned_generation_result,\n                project_id=project_id,\n                use_dry_plan=use_dry_plan,\n                allow_dry_plan_fallback=allow_dry_plan_fallback,\n                data_source=data_source,\n                allow_data_preview=allow_data_preview,\n            )\n\n            return {\n                \"valid_generation_result\": valid_generation_result,\n                \"invalid_generation_result\": invalid_generation_result,\n            }\n        except Exception as e:\n            logger.exception(f\"Error in SQLGenPostProcessor: {e}\")\n\n            return {\n                \"valid_generation_result\": {},\n                \"invalid_generation_result\": {},\n            }\n\n    async def _classify_generation_result(\n        self,\n        generation_result: str,\n        project_id: str | None = None,\n        use_dry_plan: bool = False,\n        allow_dry_plan_fallback: bool = True,\n        data_source: str = \"\",\n        allow_data_preview: bool = False,\n    ) -> Dict[str, str]:\n        valid_generation_result = {}\n        invalid_generation_result = {}\n        use_dry_run = not allow_data_preview\n\n        async with aiohttp.ClientSession() as session:\n            if use_dry_plan:\n                dry_plan_result, error_message = await self._engine.dry_plan(\n                    session,\n                    generation_result,\n                    data_source,\n                    allow_fallback=allow_dry_plan_fallback,\n                )\n\n                if dry_plan_result:\n                    valid_generation_result = {\n                        \"sql\": generation_result,\n                        \"correlation_id\": \"\",\n                    }\n                else:\n                    invalid_generation_result = {\n                        \"sql\": generation_result,\n                        \"type\": \"TIME_OUT\"\n                        if error_message.startswith(\"Request timed out\")\n                        else \"DRY_PLAN\",\n                        \"error\": error_message,\n                        \"correlation_id\": \"\",\n                    }\n            elif use_dry_run:\n                success, _, addition = await self._engine.execute_sql(\n                    generation_result,\n                    session,\n                    project_id=project_id,\n                    limit=1,\n                    dry_run=True,\n                )\n\n                if success:\n                    valid_generation_result = {\n                        \"sql\": generation_result,\n                        \"correlation_id\": addition.get(\"correlation_id\", \"\"),\n                    }\n                else:\n                    error_message = addition.get(\"error_message\", \"\")\n                    invalid_generation_result = {\n                        \"sql\": addition.get(\"error_sql\", generation_result),\n                        \"original_sql\": generation_result,\n                        \"type\": \"TIME_OUT\"\n                        if error_message.startswith(\"Request timed out\")\n                        else \"DRY_RUN\",\n                        \"error\": error_message,\n                        \"correlation_id\": addition.get(\"correlation_id\", \"\"),\n                    }\n            else:\n                has_data, _, addition = await self._engine.execute_sql(\n                    generation_result,\n                    session,\n                    project_id=project_id,\n                    limit=1,\n                    dry_run=False,\n                )\n\n                if has_data:\n                    valid_generation_result = {\n                        \"sql\": generation_result,\n                        \"correlation_id\": addition.get(\"correlation_id\", \"\"),\n                    }\n                else:\n                    error_message = addition.get(\"error_message\", \"\")\n                    preview_data_status = (\n                        \"PREVIEW_EMPTY_DATA\"\n                        if error_message == \"\"\n                        else \"PREVIEW_FAILED\"\n                    )\n                    invalid_generation_result = {\n                        \"sql\": addition.get(\"error_sql\", generation_result),\n                        \"original_sql\": generation_result,\n                        \"type\": \"TIME_OUT\"\n                        if error_message.startswith(\"Request timed out\")\n                        else preview_data_status,\n                        \"error\": error_message,\n                        \"correlation_id\": addition.get(\"correlation_id\", \"\"),\n                    }\n\n        return valid_generation_result, invalid_generation_result\n\n\n_DEFAULT_TEXT_TO_SQL_RULES = \"\"\"\n### SQL RULES ###\n- ONLY USE SELECT statements, NO DELETE, UPDATE OR INSERT etc. statements that might change the data in the database.\n- ONLY USE the tables and columns mentioned in the database schema.\n- ONLY USE \"*\" if the user query asks for all the columns of a table.\n- ONLY CHOOSE columns belong to the tables mentioned in the database schema.\n- DON'T INCLUDE comments in the generated SQL query.\n- YOU MUST USE \"JOIN\" if you choose columns from multiple tables!\n- PREFER USING CTEs over subqueries.\n- When generating SQL query, always:\n    - Put double quotes around column and table names.\n    - Put single quotes around string literals.\n    - Never quote numeric literals.\n    For example: SELECT \"customers\".\"customer_name\" FROM \"customers\" WHERE \"customers\".\"city\" = 'Taipei' and \"customers\".\"year\" = 1992;\n- YOU MUST USE \"lower(<table_name>.<column_name>) like lower(<value>)\" function or \"lower(<table_name>.<column_name>) = lower(<value>)\" function for case-insensitive comparison!\n    - Use \"lower(<table_name>.<column_name>) LIKE lower(<value>)\" when:\n        - The user requests a pattern or partial match.\n        - The value is not specific enough to be a single, exact value.\n        - Wildcards (%) are needed to capture the pattern.\n    - Use \"lower(<table_name>.<column_name>) = lower(<value>)\" when:\n        - The user requests an exact, specific value.\n        - There is no ambiguity or pattern in the value.\n- If the column is date/time related field, and it is a INT/BIGINT/DOUBLE/FLOAT type, please use the appropriate function mentioned in the SQL FUNCTIONS section to cast the column to \"TIMESTAMP\" type first before using it in the query\n    - example: TO_TIMESTAMP_MILLIS(\"<timestamp_column>\")  # if the timestamp_column is in milliseconds\n    - example: TO_TIMESTAMP_SECONDS(\"<timestamp_column>\")  # if the timestamp_column is in seconds\n    - example: TO_TIMESTAMP_MICROS(\"<timestamp_column>\")  # if the timestamp_column is in microseconds\n- ALWAYS CAST the date/time related field to \"TIMESTAMP WITH TIME ZONE\" type when using them in the query\n    - example 1: CAST(properties_closedate AS TIMESTAMP WITH TIME ZONE)\n    - example 2: CAST('2024-11-09 00:00:00' AS TIMESTAMP WITH TIME ZONE)\n    - example 3: CAST(DATE_TRUNC('month', CURRENT_DATE - INTERVAL '1 month') AS TIMESTAMP WITH TIME ZONE)\n- If the user asks for a specific date, please give the date range in SQL query\n    - example: \"What is the total revenue for the month of 2024-11-01?\"\n    - answer: \"SELECT SUM(r.PriceSum) FROM Revenue r WHERE CAST(r.PurchaseTimestamp AS TIMESTAMP WITH TIME ZONE) >= CAST('2024-11-01 00:00:00' AS TIMESTAMP WITH TIME ZONE) AND CAST(r.PurchaseTimestamp AS TIMESTAMP WITH TIME ZONE) < CAST('2024-11-02 00:00:00' AS TIMESTAMP WITH TIME ZONE)\"\n- USE THE VIEW TO SIMPLIFY THE QUERY.\n- DON'T MISUSE THE VIEW NAME. THE ACTUAL NAME IS FOLLOWING THE CREATE VIEW STATEMENT.\n- ONLY USE table/column alias in the final SELECT clause; don't use table/columnalias in the other clauses.\n- Refer to the value of alias from the comment section of the corresponding table or column in the DATABASE SCHEMA section for reference when using alias in the final SELECT clause.\n  - EXAMPLE\n    DATABASE SCHEMA\n    /* {\"alias\":\"_orders\",\"description\":\"A model representing the orders data.\"} */\n    CREATE TABLE orders (\n      -- {\"description\":\"A column that represents the timestamp when the order was approved.\",\"alias\":\"_timestamp\"}\n      ApprovedTimestamp TIMESTAMP\n    }\n\n    SQL\n    SELECT \"_orders\".\"ApprovedTimestamp\" AS \"_timestamp\" FROM \"orders\" AS \"_orders\";\n- DON'T USE '.' in column/table alias, replace '.' with '_' in column/table alias.\n- DON'T USE \"FILTER(WHERE <expression>)\" clause in the generated SQL query.\n- DON'T USE \"EXTRACT(EPOCH FROM <expression>)\" clause in the generated SQL query.\n- DON'T USE \"EXTRACT()\" function with INTERVAL data types as arguments\n- DON'T USE INTERVAL or generate INTERVAL-like expression in the generated SQL query.\n- DON'T USE \"TO_CHAR\" function in the generated SQL query.\n- Aggregate functions are not allowed in the WHERE clause. Instead, they belong in the HAVING clause, which is used to filter after aggregation.\n- You can only add \"ORDER BY\" and \"LIMIT\" to the final \"UNION\" result.\n- For the ranking problem, you must use the ranking function, `DENSE_RANK()` to rank the results and then use `WHERE` clause to filter the results.\n- For the ranking problem, you must add the ranking column to the final SELECT clause.\n\"\"\"\n\n\n_DEFAULT_CALCULATED_FIELD_INSTRUCTIONS = \"\"\"\n#### Instructions for Calculated Field ####\n\nThe first structure is the special column marked as \"Calculated Field\". You need to interpret the purpose and calculation basis for these columns, then utilize them in the following text-to-sql generation tasks.\nFirst, provide a brief explanation of what each field represents in the context of the schema, including how each field is computed using the relationships between models.\nThen, during the following tasks, if the user queries pertain to any calculated fields defined in the database schema, ensure to utilize those calculated fields appropriately in the output SQL queries.\nThe goal is to accurately reflect the intent of the question in the SQL syntax, leveraging the pre-computed logic embedded within the calculated fields.\n\nEXAMPLES:\nThe given schema is created by the SQL command:\n\nCREATE TABLE orders (\n  OrderId VARCHAR PRIMARY KEY,\n  CustomerId VARCHAR,\n  -- This column is a Calculated Field\n  -- column expression: avg(reviews.Score)\n  Rating DOUBLE,\n  -- This column is a Calculated Field\n  -- column expression: count(reviews.Id)\n  ReviewCount BIGINT,\n  -- This column is a Calculated Field\n  -- column expression: count(order_items.ItemNumber)\n  Size BIGINT,\n  -- This column is a Calculated Field\n  -- column expression: count(order_items.ItemNumber) > 1\n  Large BOOLEAN,\n  FOREIGN KEY (CustomerId) REFERENCES customers(Id)\n);\n\nInterpret the columns that are marked as Calculated Fields in the schema:\nRating (DOUBLE) - Calculated as the average score (avg) of the Score field from the reviews table where the reviews are associated with the order. This field represents the overall customer satisfaction rating for the order based on review scores.\nReviewCount (BIGINT) - Calculated by counting (count) the number of entries in the reviews table associated with this order. It measures the volume of customer feedback received for the order.\nSize (BIGINT) - Represents the total number of items in the order, calculated by counting the number of item entries (ItemNumber) in the order_items table linked to this order. This field is useful for understanding the scale or size of an order.\nLarge (BOOLEAN) - A boolean value calculated to check if the number of items in the order exceeds one (count(order_items.ItemNumber) > 1). It indicates whether the order is considered large in terms of item quantity.\n\nAnd if the user input queries like these:\n1. \"How many large orders have been placed by customer with ID 'C1234'?\"\n2. \"What is the average customer rating for orders that were rated by more than 10 reviewers?\"\n\nFor the first query:\nFirst try to intepret the user query, the user wants to know the average rating for orders which have attracted significant review activity, specifically those with more than 10 reviews.\nThen, according to the above intepretation about the given schema, the term 'Rating' is predefined in the Calculated Field of the 'orders' model. And, the number of reviews is also predefined in the 'ReviewCount' Calculated Field.\nSo utilize those Calculated Fields in the SQL generation process to give an answer like this:\n\nSQL Query: SELECT AVG(Rating) FROM orders WHERE ReviewCount > 10\n\"\"\"\n\n_DEFAULT_METRIC_INSTRUCTIONS = \"\"\"\n#### Instructions for Metric ####\n\nSecond, you will learn how to effectively utilize the special \"metric\" structure in text-to-SQL generation tasks.\nMetrics in a data model simplify complex data analysis by structuring data through predefined dimensions and measures.\nThis structuring closely mirrors the concept of OLAP (Online Analytical Processing) cubes but is implemented in a more flexible and SQL-friendly manner.\n\nThe metric typically constructed of the following components:\n1. Base Object\nThe \"base object\" of a metric indicates the primary data source or table that provides the raw data.\nMetrics are constructed by selecting specific data points (dimensions and measures) from this base object, effectively creating a summarized or aggregated view of the data that can be queried like a normal table.\nBase object is the attribute of the metric, showing the origin of this metric and is typically not used in the query.\n2. Dimensions\nDimensions in a metric represent the various axes along which data can be segmented for analysis.\nThese are fields that provide a categorical breakdown of data.\nEach dimension provides a unique perspective on the data, allowing users to \"slice and dice\" the data cube to view different facets of the information contained within the base dataset.\nDimensions are used as table columns in the querying process. Querying a dimension means to get the statistic from the certain perspective.\n3. Measures\nMeasures are numerical or quantitative statistics calculated from the data. Measures are key results or outputs derived from data aggregation functions like SUM, COUNT, or AVG.\nMeasures are used as table columns in the querying process, and are the main querying items in the metric structure.\nThe expression of a measure represents the definition of the  that users are intrested in. Make sure to understand the meaning of measures from their expressions.\n4. Time Grain\nTime Grain specifies the granularity of time-based data aggregation, such as daily, monthly, or yearly, facilitating trend analysis over specified periods.\n\nIf the given schema contains the structures marked as 'metric', you should first interpret the metric schema based on the above definition.\nThen, during the following tasks, if the user queries pertain to any metrics defined in the database schema, ensure to utilize those metrics appropriately in the output SQL queries.\nThe target is making complex data analysis more accessible and manageable by pre-aggregating data and structuring it using the metric structure, and supporting direct querying for business insights.\n\nEXAMPLES:\nThe given schema is created by the SQL command:\n\n/* This table is a metric */\n/* Metric Base Object: orders */\nCREATE TABLE Revenue (\n  -- This column is a dimension\n  PurchaseTimestamp TIMESTAMP,\n  -- This column is a dimension\n  CustomerId VARCHAR,\n  -- This column is a dimension\n  Status VARCHAR,\n  -- This column is a measure\n  -- expression: sum(order_items.Price)\n  PriceSum DOUBLE,\n  -- This column is a measure\n  -- expression: count(OrderId)\n  NumberOfOrders BIGINT\n);\n\nInterpret the metric with the understanding of the metric structure:\n1. Base Object: orders\nThis is the primary data source for the metric.\nThe orders table provides the underlying data from which dimensions and measures are derived.\nIt is the foundation upon which the metric is built, though it itself is not directly used in queries against the Revenue table.\nIt shows the reference between the 'Revenue' metric and the 'orders' model. For the user queries pretain to the 'Revenue' of 'orders', the metric should be utilize in the sql generation process.\n2. Dimensions\nThe metric contains the columns marked as 'dimension'. They can be interpreted as below:\n- PurchaseTimestamp (TIMESTAMP)\n  Acts as a temporal dimension, allowing analysis of revenue over time. This can be used to observe trends, seasonal variations, or performance over specific periods.\n- CustomerId (VARCHAR)\n  A key dimension for customer segmentation, it enables the analysis of revenue generated from individual customers or customer groups.\n- Status (VARCHAR)\n  Reflects the current state of an order (e.g., pending, completed, cancelled). This dimension is crucial for analyses that differentiate performance based on order status.\n3. Measures\nThe metric contains the columns marked as 'measure'. They can be interpreted as below:\n- PriceSum (DOUBLE)\n  A financial measure calculated as sum(order_items.Price), representing the total revenue generated from orders. This measure is vital for tracking overall sales performance and is the primary output of interest in many financial and business analyses.\n- NumberOfOrders (BIGINT)\n  A count measure that provides the total number of orders. This is essential for operational metrics, such as assessing the volume of business activity and evaluating the efficiency of sales processes.\n\nNow, if the user input queries like this:\nQuestion: \"What was the total revenue from each customer last month?\"\n\nFirst try to intepret the user query, the user asks for a breakdown of the total revenue generated by each customer in the previous calendar month.\nThe user is specifically interested in understanding how much each customer contributed to the total sales during this period.\nTo answer this question, it is suitable to use the following components from the metric:\n1. CustomerId (Dimension): This will be used to group the revenue data by each unique customer, allowing us to segment the total revenue by customer.\n2. PurchaseTimestamp (Dimension): This timestamp field will be used to filter the data to only include orders from the last month.\n3. PriceSum (Measure): Since PriceSum is a pre-aggregated measure of total revenue (sum of order_items.Price), it can be directly used to sum up the revenue without needing further aggregation in the SQL query.\nSo utilize those metric components in the SQL generation process to give an answer like this:\n\nSQL Query:\nSELECT\n  CustomerId,\n  PriceSum AS TotalRevenue\nFROM\n  Revenue\nWHERE\n  PurchaseTimestamp >= DATE_TRUNC('month', CURRENT_DATE - INTERVAL '1 month') AND\n  PurchaseTimestamp < DATE_TRUNC('month', CURRENT_DATE)\n\"\"\"\n\n_DEFAULT_JSON_FIELD_INSTRUCTIONS = \"\"\"\n#### Instructions for JSON related functions ####\n- ONLY USE JSON_QUERY for querying fields if \"json_type\":\"JSON\" is identified in the columns comment, NOT the deprecated JSON_EXTRACT_SCALAR function.\n    - DON'T USE CAST for JSON fields, ONLY USE the following funtions:\n      - LAX_BOOL for boolean fields\n      - LAX_FLOAT64 for double and float fields\n      - LAX_INT64 for bigint fields\n      - LAX_STRING for varchar fields\n    - For Example:\n      DATA SCHEMA:\n        `/* {\"alias\":\"users\",\"description\":\"A model representing the users data.\"} */\n        CREATE TABLE users (\n            -- {\"alias\":\"address\",\"description\":\"A JSON object that represents address information of this user.\",\"json_type\":\"JSON\",\"json_fields\":{\"json_type\":\"JSON\",\"address.json.city\":{\"name\":\"city\",\"type\":\"varchar\",\"path\":\"$.city\",\"properties\":{\"alias\":\"city\",\"description\":\"City Name.\"}},\"address.json.state\":{\"name\":\"state\",\"type\":\"varchar\",\"path\":\"$.state\",\"properties\":{\"alias\":\"state\",\"description\":\"ISO code or name of the state, province or district.\"}},\"address.json.postcode\":{\"name\":\"postcode\",\"type\":\"varchar\",\"path\":\"$.postcode\",\"properties\":{\"alias\":\"postcode\",\"description\":\"Postal code.\"}},\"address.json.country\":{\"name\":\"country\",\"type\":\"varchar\",\"path\":\"$.country\",\"properties\":{\"alias\":\"country\",\"description\":\"ISO code of the country.\"}}}}\n            address JSON\n        )`\n      To get the city of address in user table use SQL:\n      `SELECT LAX_STRING(JSON_QUERY(u.address, '$.city')) FROM user as u`\n- ONLY USE JSON_QUERY_ARRAY for querying \"json_type\":\"JSON_ARRAY\" is identified in the comment of the column, NOT the deprecated JSON_EXTRACT_ARRAY.\n    - USE UNNEST to analysis each item individually in the ARRAY. YOU MUST SELECT FROM the parent table ahead of the UNNEST ARRAY.\n    - The alias of the UNNEST(ARRAY) should be in the format `unnest_table_alias(individual_item_alias)`\n      - For Example: `SELECT item FROM UNNEST(ARRAY[1,2,3]) as my_unnested_table(item)`\n    - If the items in the ARRAY are JSON objects, use JSON_QUERY to query the fields inside each JSON item.\n      - For Example:\n      DATA SCHEMA\n        `/* {\"alias\":\"my_table\",\"description\":\"A test my_table\"} */\n        CREATE TABLE my_table (\n            -- {\"alias\":\"elements\",\"description\":\"elements column\",\"json_type\":\"JSON_ARRAY\",\"json_fields\":{\"json_type\":\"JSON_ARRAY\",\"elements.json_array.id\":{\"name\":\"id\",\"type\":\"bigint\",\"path\":\"$.id\",\"properties\":{\"alias\":\"id\",\"description\":\"data ID.\"}},\"elements.json_array.key\":{\"name\":\"key\",\"type\":\"varchar\",\"path\":\"$.key\",\"properties\":{\"alias\":\"key\",\"description\":\"data Key.\"}},\"elements.json_array.value\":{\"name\":\"value\",\"type\":\"varchar\",\"path\":\"$.value\",\"properties\":{\"alias\":\"value\",\"description\":\"data Value.\"}}}}\n            elements JSON\n        )`\n        To get the number of elements in my_table table use SQL:\n        `SELECT LAX_INT64(JSON_QUERY(element, '$.number')) FROM my_table as t, UNNEST(JSON_QUERY_ARRAY(elements)) AS my_unnested_table(element) WHERE LAX_FLOAT64(JSON_QUERY(element, '$.value')) > 3.5`\n    - To JOIN ON the fields inside UNNEST(ARRAY), YOU MUST SELECT FROM the parent table ahead of the UNNEST syntax, and the alias of the UNNEST(ARRAY) SHOULD BE IN THE FORMAT unnest_table_alias(individual_item_alias)\n      - For Example: `SELECT p.column_1, j.column_2 FROM parent_table AS p, join_table AS j JOIN UNNEST(p.array_column) AS unnested(array_item) ON j.id = array_item.id`\n- DON'T USE JSON_QUERY and JSON_QUERY_ARRAY when \"json_type\":\"\".\n- DON'T USE LAX_BOOL, LAX_FLOAT64, LAX_INT64, LAX_STRING when \"json_type\":\"\".\n\"\"\"\n\nsql_samples_instructions = \"\"\"\n#### Instructions for SQL Samples ####\n\nFinally, you will learn from the sample SQL queries provided in the input. These samples demonstrate best practices and common patterns for querying this specific database.\n\nFor each sample, you should:\n1. Study the question that explains what the query aims to accomplish\n2. Analyze the SQL implementation to understand:\n   - Table structures and relationships used\n   - Specific functions and operators employed\n   - Query patterns and techniques demonstrated\n3. Use these samples as reference patterns when generating similar queries\n4. Adapt the techniques shown in the samples to match new query requirements while maintaining consistent style and approach\n\nThe samples will help you understand:\n- Preferred table join patterns\n- Common aggregation methods\n- Specific function usage\n- Query structure and formatting conventions\n\nWhen generating new queries, try to follow similar patterns when applicable, while adapting them to the specific requirements of each new query.\n\nLearn about the usage of the schema structures and generate SQL based on them.\n\"\"\"\n\n\nsql_generation_reasoning_system_prompt = \"\"\"\n### TASK ###\nYou are a helpful data analyst who is great at thinking deeply and reasoning about the user's question and the database schema, and you provide a step-by-step reasoning plan in order to answer the user's question.\n\n### INSTRUCTIONS ###\n1. Think deeply and reason about the user's question, the database schema, and the user's query history if provided.\n2. Explicitly state the following information in the reasoning plan: \nif the user puts any specific timeframe(e.g. YYYY-MM-DD) in the user's question(excluding the value of the current time), you will put the absolute time frame in the SQL query; \notherwise, you will put the relative timeframe in the SQL query.\n3. For the ranking problem(e.g. \"top x\", \"bottom x\", \"first x\", \"last x\"), you must use the ranking function, `DENSE_RANK()` to rank the results and then use `WHERE` clause to filter the results.\n4. For the ranking problem(e.g. \"top x\", \"bottom x\", \"first x\", \"last x\"), you must add the ranking column to the final SELECT clause.\n5. If USER INSTRUCTIONS section is provided, make sure to consider them in the reasoning plan.\n6. If SQL SAMPLES section is provided, make sure to consider them in the reasoning plan.\n7. Give a step by step reasoning plan in order to answer user's question.\n8. The reasoning plan should be in the language same as the language user provided in the input.\n9. Don't include SQL in the reasoning plan.\n10. Each step in the reasoning plan must start with a number, a title(in bold format in markdown), and a reasoning for the step.\n11. Do not include ```markdown or ``` in the answer.\n12. A table name in the reasoning plan must be in this format: `table: <table_name>`.\n13. A column name in the reasoning plan must be in this format: `column: <table_name>.<column_name>`.\n14. ONLY SHOWING the reasoning plan in bullet points.\n\n### FINAL ANSWER FORMAT ###\nThe final answer must be a reasoning plan in plain Markdown string format\n\"\"\"\n\n\ndef _extract_from_sql_knowledge(\n    sql_knowledge: SqlKnowledge | None, attribute_name: str, default_value: str\n) -> str:\n    if sql_knowledge is None:\n        return default_value\n\n    value = getattr(sql_knowledge, attribute_name, \"\")\n    return value if value and value.strip() else default_value\n\n\ndef get_text_to_sql_rules(sql_knowledge: SqlKnowledge | None = None) -> str:\n    if sql_knowledge is not None:\n        return _extract_from_sql_knowledge(\n            sql_knowledge, \"text_to_sql_rule\", _DEFAULT_TEXT_TO_SQL_RULES\n        )\n\n    return _DEFAULT_TEXT_TO_SQL_RULES\n\n\ndef get_calculated_field_instructions(sql_knowledge: SqlKnowledge | None = None) -> str:\n    if sql_knowledge is not None:\n        return _extract_from_sql_knowledge(\n            sql_knowledge,\n            \"calculated_field_instructions\",\n            _DEFAULT_CALCULATED_FIELD_INSTRUCTIONS,\n        )\n\n    return _DEFAULT_CALCULATED_FIELD_INSTRUCTIONS\n\n\ndef get_metric_instructions(sql_knowledge: SqlKnowledge | None = None) -> str:\n    if sql_knowledge is not None:\n        return _extract_from_sql_knowledge(\n            sql_knowledge, \"metric_instructions\", _DEFAULT_METRIC_INSTRUCTIONS\n        )\n\n    return _DEFAULT_METRIC_INSTRUCTIONS\n\n\ndef get_json_field_instructions(sql_knowledge: SqlKnowledge | None = None) -> str:\n    if sql_knowledge is not None:\n        return _extract_from_sql_knowledge(\n            sql_knowledge, \"json_field_instructions\", _DEFAULT_JSON_FIELD_INSTRUCTIONS\n        )\n\n    return _DEFAULT_JSON_FIELD_INSTRUCTIONS\n\n\ndef get_sql_generation_system_prompt(sql_knowledge: SqlKnowledge | None = None) -> str:\n    text_to_sql_rules = get_text_to_sql_rules(sql_knowledge)\n\n    return f\"\"\"\nYou are a helpful assistant that converts natural language queries into ANSI SQL queries.\n\nGiven user's question, database schema, etc., you should think deeply and carefully and generate the SQL query based on the given reasoning plan step by step.\n\n### GENERAL RULES ###\n\n1. YOU MUST FOLLOW the instructions strictly to generate the SQL query if the section of USER INSTRUCTIONS is available in user's input.\n2. YOU MUST ONLY CHOOSE the appropriate functions from the sql functions list and use them in the SQL query if the section of SQL FUNCTIONS is available in user's input.\n3. YOU MUST REFER to the sql samples and learn the usage of the schema structures and how SQL is written based on them if the section of SQL SAMPLES is available in user's input.\n4. YOU MUST FOLLOW the reasoning plan step by step strictly to generate the SQL query if the section of REASONING PLAN is available in user's input.\n5. YOU MUST FOLLOW SQL Rules if they are not contradicted with instructions.\n\n{text_to_sql_rules}\n\n### FINAL ANSWER FORMAT ###\nThe final answer must be a ANSI SQL query in JSON format:\n\n{{\n    \"sql\": <SQL_QUERY_STRING>\n}}\n\"\"\"\n\n\nclass SqlGenerationResult(BaseModel):\n    sql: str\n\n\nSQL_GENERATION_MODEL_KWARGS = {\n    \"response_format\": {\n        \"type\": \"json_schema\",\n        \"json_schema\": {\n            \"name\": \"sql_generation_result\",\n            \"schema\": SqlGenerationResult.model_json_schema(),\n        },\n    }\n}\n\n\ndef construct_instructions(\n    instructions: list[dict] | None = None,\n):\n    _instructions = []\n    if instructions:\n        _instructions += [\n            instruction.get(\"instruction\") for instruction in instructions\n        ]\n\n    return _instructions\n\n\ndef construct_ask_history_messages(\n    histories: list[AskHistory] | list[dict],\n) -> list[ChatMessage]:\n    messages = []\n    for history in histories:\n        messages.append(\n            ChatMessage.from_user(\n                history.question\n                if hasattr(history, \"question\")\n                else history[\"question\"]\n            )\n        )\n        messages.append(\n            ChatMessage.from_assistant(\n                history.sql if hasattr(history, \"sql\") else history[\"sql\"]\n            )\n        )\n    return messages\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/generation/utils/vega-lite-schema-v5.json",
    "content": "{\n    \"$ref\": \"#/definitions/TopLevelSpec\",\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"definitions\": {\n        \"Aggregate\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/NonArgAggregateOp\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ArgmaxDef\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ArgminDef\"\n                }\n            ]\n        },\n        \"AggregateOp\": {\n            \"enum\": [\n                \"argmax\",\n                \"argmin\",\n                \"average\",\n                \"count\",\n                \"distinct\",\n                \"max\",\n                \"mean\",\n                \"median\",\n                \"min\",\n                \"missing\",\n                \"product\",\n                \"q1\",\n                \"q3\",\n                \"ci0\",\n                \"ci1\",\n                \"stderr\",\n                \"stdev\",\n                \"stdevp\",\n                \"sum\",\n                \"valid\",\n                \"values\",\n                \"variance\",\n                \"variancep\",\n                \"exponential\",\n                \"exponentialb\"\n            ],\n            \"type\": \"string\"\n        },\n        \"AggregateTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"aggregate\": {\n                    \"description\": \"Array of objects that define fields to aggregate.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/AggregatedFieldDef\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"groupby\": {\n                    \"description\": \"The data fields to group by. If not specified, a single group containing all data objects will be used.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"aggregate\"\n            ],\n            \"type\": \"object\"\n        },\n        \"AggregatedFieldDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"as\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The output field names to use for each aggregated field.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The data field for which to compute aggregate function. This is required for all aggregation operations except `\\\"count\\\"`.\"\n                },\n                \"op\": {\n                    \"$ref\": \"#/definitions/AggregateOp\",\n                    \"description\": \"The aggregation operation to apply to the fields (e.g., `\\\"sum\\\"`, `\\\"average\\\"`, or `\\\"count\\\"`). See the [full list of supported aggregation operations](https://vega.github.io/vega-lite/docs/aggregate.html#ops) for more information.\"\n                }\n            },\n            \"required\": [\n                \"op\",\n                \"as\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Align\": {\n            \"enum\": [\n                \"left\",\n                \"center\",\n                \"right\"\n            ],\n            \"type\": \"string\"\n        },\n        \"AllSortString\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/SortOrder\"\n                },\n                {\n                    \"$ref\": \"#/definitions/SortByChannel\"\n                },\n                {\n                    \"$ref\": \"#/definitions/SortByChannelDesc\"\n                }\n            ]\n        },\n        \"AnyMark\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/CompositeMark\"\n                },\n                {\n                    \"$ref\": \"#/definitions/CompositeMarkDef\"\n                },\n                {\n                    \"$ref\": \"#/definitions/Mark\"\n                },\n                {\n                    \"$ref\": \"#/definitions/MarkDef\"\n                }\n            ]\n        },\n        \"AnyMarkConfig\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/MarkConfig\"\n                },\n                {\n                    \"$ref\": \"#/definitions/AreaConfig\"\n                },\n                {\n                    \"$ref\": \"#/definitions/BarConfig\"\n                },\n                {\n                    \"$ref\": \"#/definitions/RectConfig\"\n                },\n                {\n                    \"$ref\": \"#/definitions/LineConfig\"\n                },\n                {\n                    \"$ref\": \"#/definitions/TickConfig\"\n                }\n            ]\n        },\n        \"AreaConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The horizontal alignment of the text or ranged marks (area, bar, image, rect, rule). One of `\\\"left\\\"`, `\\\"right\\\"`, `\\\"center\\\"`.\\n\\n__Note:__ Expression reference is *not* supported for range marks.\"\n                },\n                \"angle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The rotation angle of the text, in degrees.\",\n                            \"maximum\": 360,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aria\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag indicating if [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) should be included (SVG output only). If `false`, the \\\"aria-hidden\\\" attribute will be set on the output SVG element, removing the mark item from the ARIA accessibility tree.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ariaRole\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Sets the type of user interface element of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the \\\"role\\\" attribute. Warning: this property is experimental and may be changed in the future.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ariaRoleDescription\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A human-readable, author-localized description for the role of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the \\\"aria-roledescription\\\" attribute. Warning: this property is experimental and may be changed in the future.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aspect\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Whether to keep aspect ratio of image marks.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"baseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"For text marks, the vertical text baseline. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, `\\\"line-bottom\\\"`, or an expression reference that provides one of the valid values. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the `lineHeight` rather than `fontSize` alone.\\n\\nFor range marks, the vertical alignment of the marks. One of `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`.\\n\\n__Note:__ Expression reference is *not* supported for range marks.\"\n                },\n                \"blend\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Blend\",\n                            \"description\": \"The color blend mode for drawing an item on its current background. Any valid [CSS mix-blend-mode](https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode) value can be used.\\n\\n__Default value: `\\\"source-over\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"color\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default color.\\n\\n__Default value:__ <span style=\\\"color: #4682b4;\\\">&#9632;</span> `\\\"#4682b4\\\"`\\n\\n__Note:__\\n- This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\\n- The `fill` and `stroke` properties have higher precedence than `color` and will override `color`.\"\n                },\n                \"cornerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles or arcs' corners.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusBottomLeft\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' bottom left corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusBottomRight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' bottom right corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusTopLeft\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' top right corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusTopRight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' top left corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cursor\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Cursor\",\n                            \"description\": \"The mouse cursor used over the mark. Any valid [CSS cursor type](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"description\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A text description of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the [\\\"aria-label\\\" attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dir\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextDirection\",\n                            \"description\": \"The direction of the text. One of `\\\"ltr\\\"` (left-to-right) or `\\\"rtl\\\"` (right-to-left). This property determines on which side is truncated in response to the limit parameter.\\n\\n__Default value:__ `\\\"ltr\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dx\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The horizontal offset, in pixels, between the text label and its anchor point. The offset is applied after rotation by the _angle_ property.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dy\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The vertical offset, in pixels, between the text label and its anchor point. The offset is applied after rotation by the _angle_ property.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ellipsis\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The ellipsis string for text truncated in response to the limit parameter.\\n\\n__Default value:__ `\\\"…\\\"`\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"endAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The end angle in radians for arc marks. A value of `0` indicates up (north), increasing values proceed clockwise.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fill\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default fill color. This property has higher precedence than `config.color`. Set to `null` to remove fill.\\n\\n__Default value:__ (None)\"\n                },\n                \"fillOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The fill opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"filled\": {\n                    \"description\": \"Whether the mark's color should be used as fill color instead of stroke color.\\n\\n__Default value:__ `false` for all `point`, `line`, and `rule` marks as well as `geoshape` marks for [`graticule`](https://vega.github.io/vega-lite/docs/data.html#graticule) data sources; otherwise, `true`.\\n\\n__Note:__ This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\",\n                    \"type\": \"boolean\"\n                },\n                \"font\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The typeface to set the text in (e.g., `\\\"Helvetica Neue\\\"`).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font size, in pixels.\\n\\n__Default value:__ `11`\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"The font style (e.g., `\\\"italic\\\"`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"The font weight. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"height\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Height of the marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"href\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/URI\",\n                            \"description\": \"A URL to load upon mouse click. If defined, the mark acts as a hyperlink.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"innerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The inner radius in pixels of arc marks. `innerRadius` is an alias for `radius2`.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"interpolate\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Interpolate\",\n                            \"description\": \"The line interpolation method to use for line and area marks. One of the following:\\n- `\\\"linear\\\"`: piecewise linear segments, as in a polyline.\\n- `\\\"linear-closed\\\"`: close the linear segments to form a polygon.\\n- `\\\"step\\\"`: alternate between horizontal and vertical segments, as in a step function.\\n- `\\\"step-before\\\"`: alternate between vertical and horizontal segments, as in a step function.\\n- `\\\"step-after\\\"`: alternate between horizontal and vertical segments, as in a step function.\\n- `\\\"basis\\\"`: a B-spline, with control point duplication on the ends.\\n- `\\\"basis-open\\\"`: an open B-spline; may not intersect the start or end.\\n- `\\\"basis-closed\\\"`: a closed B-spline, as in a loop.\\n- `\\\"cardinal\\\"`: a Cardinal spline, with control point duplication on the ends.\\n- `\\\"cardinal-open\\\"`: an open Cardinal spline; may not intersect the start or end, but will intersect other control points.\\n- `\\\"cardinal-closed\\\"`: a closed Cardinal spline, as in a loop.\\n- `\\\"bundle\\\"`: equivalent to basis, except the tension parameter is used to straighten the spline.\\n- `\\\"monotone\\\"`: cubic interpolation that preserves monotonicity in y.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"invalid\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/MarkInvalidDataMode\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"Invalid data mode, which defines how the marks and corresponding scales should represent invalid values (`null` and `NaN` in continuous scales *without* defined output for invalid values).\\n\\n- `\\\"filter\\\"` — *Exclude* all invalid values from the visualization's *marks* and *scales*. For path marks (for line, area, trail), this option will create paths that connect valid points, as if the data rows with invalid values do not exist.\\n\\n- `\\\"break-paths-filter-domains\\\"` — Break path marks (for line, area, trail) at invalid values.  For non-path marks, this is equivalent to `\\\"filter\\\"`. All *scale* domains will *exclude* these filtered data points.\\n\\n- `\\\"break-paths-show-domains\\\"` — Break paths (for line, area, trail) at invalid values.  Hide invalid values for non-path marks. All *scale* domains will *include* these filtered data points (for both path and non-path marks).\\n\\n- `\\\"show\\\"` or `null` — Show all data points in the marks and scale domains. Each scale will use the output for invalid values defined in `config.scale.invalid` or, if unspecified, by default invalid values will produce the same visual values as zero (if the scale includes zero) or the minimum value (if the scale does not include zero).\\n\\n- `\\\"break-paths-show-path-domains\\\"` (default) — This is equivalent to `\\\"break-paths-show-domains\\\"` for path-based marks (line/area/trail) and `\\\"filter\\\"` for non-path marks.\\n\\n__Note__: If any channel's scale has an output for invalid values defined in `config.scale.invalid`, all values for the scales will be considered \\\"valid\\\" since they can produce a reasonable output for the scales. Thus, fields for such channels will not be filtered and will not cause path breaks.\"\n                },\n                \"limit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The maximum length of the text mark in pixels. The text value will be automatically truncated if the rendered size exceeds the limit.\\n\\n__Default value:__ `0` -- indicating no limit\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"line\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/OverlayMarkDef\"\n                        }\n                    ],\n                    \"description\": \"A flag for overlaying line on top of area marks, or an object defining the properties of the overlayed lines.\\n\\n- If this value is an empty object (`{}`) or `true`, lines with default properties will be used.\\n\\n- If this value is `false`, no lines would be automatically added to area marks.\\n\\n__Default value:__ `false`.\"\n                },\n                \"lineBreak\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A delimiter, such as a newline character, upon which to break text strings into multiple lines. This property is ignored if the text is array-valued.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"lineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The line height in pixels (the spacing between subsequent lines of text) for multi-line text marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"opacity\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The overall opacity (value between [0,1]).\\n\\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or `square` marks or layered `bar` charts and `1` otherwise.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"order\": {\n                    \"description\": \"For line and trail marks, this `order` property can be set to `null` or `false` to make the lines use the original order in the data sources.\",\n                    \"type\": [\n                        \"null\",\n                        \"boolean\"\n                    ]\n                },\n                \"orient\": {\n                    \"$ref\": \"#/definitions/Orientation\",\n                    \"description\": \"The orientation of a non-stacked bar, tick, area, and line charts. The value is either horizontal (default) or vertical.\\n- For bar, rule and tick, this determines whether the size of the bar and tick should be applied to x or y dimension.\\n- For area, this property determines the orient property of the Vega output.\\n- For line and trail marks, this property determines the sort order of the points in the line if `config.sortLineBy` is not specified. For stacked charts, this is always determined by the orientation of the stack; therefore explicitly specified value will be ignored.\"\n                },\n                \"outerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The outer radius in pixels of arc marks. `outerRadius` is an alias for `radius`.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"padAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The angular padding applied to sides of the arc, in radians.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"point\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/OverlayMarkDef\"\n                        },\n                        {\n                            \"const\": \"transparent\",\n                            \"type\": \"string\"\n                        }\n                    ],\n                    \"description\": \"A flag for overlaying points on top of line or area marks, or an object defining the properties of the overlayed points.\\n\\n- If this property is `\\\"transparent\\\"`, transparent points will be used (for enhancing tooltips and selections).\\n\\n- If this property is an empty object (`{}`) or `true`, filled points with default properties will be used.\\n\\n- If this property is `false`, no points would be automatically added to line or area marks.\\n\\n__Default value:__ `false`.\"\n                },\n                \"radius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"For arc mark, the primary (outer) radius in pixels.\\n\\nFor text marks, polar coordinate radial offset, in pixels, of the text from the origin determined by the `x` and `y` properties.\\n\\n__Default value:__ `min(plot_width, plot_height)/2`\",\n                    \"minimum\": 0\n                },\n                \"radius2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The secondary (inner) radius in pixels of arc marks.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"shape\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/SymbolShape\"\n                                },\n                                {\n                                    \"type\": \"string\"\n                                }\n                            ],\n                            \"description\": \"Shape of the point marks. Supported values include:\\n- plotting shapes: `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"cross\\\"`, `\\\"diamond\\\"`, `\\\"triangle-up\\\"`, `\\\"triangle-down\\\"`, `\\\"triangle-right\\\"`, or `\\\"triangle-left\\\"`.\\n- the line symbol `\\\"stroke\\\"`\\n- centered directional shapes `\\\"arrow\\\"`, `\\\"wedge\\\"`, or `\\\"triangle\\\"`\\n- a custom [SVG path string](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths) (For correct sizing, custom shape paths should be defined within a square bounding box with coordinates ranging from -1 to 1 along both the x and y dimensions.)\\n\\n__Default value:__ `\\\"circle\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"size\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default size for marks.\\n- For `point`/`circle`/`square`, this represents the pixel area of the marks. Note that this value sets the area of the symbol; the side lengths will increase with the square root of this value.\\n- For `bar`, this represents the band size of the bar, in pixels.\\n- For `text`, this represents the font size, in pixels.\\n\\n__Default value:__\\n- `30` for point, circle, square marks; width/height's `step`\\n- `2` for bar marks with discrete dimensions;\\n- `5` for bar marks with continuous dimensions;\\n- `11` for text marks.\",\n                    \"minimum\": 0\n                },\n                \"smooth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag (default true) indicating if the image should be smoothed when resized. If false, individual pixels should be scaled directly rather than interpolated with smoothing. For SVG rendering, this option may not work in some browsers due to lack of standardization.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"startAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The start angle in radians for arc marks. A value of `0` indicates up (north), increasing values proceed clockwise.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"stroke\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default stroke color. This property has higher precedence than `config.color`. Set to `null` to remove stroke.\\n\\n__Default value:__ (None)\"\n                },\n                \"strokeCap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeCap\",\n                            \"description\": \"The stroke cap for line ending style. One of `\\\"butt\\\"`, `\\\"round\\\"`, or `\\\"square\\\"`.\\n\\n__Default value:__ `\\\"butt\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating stroke, space lengths for creating dashed or dotted lines.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset (in pixels) into which to begin drawing with the stroke dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeJoin\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeJoin\",\n                            \"description\": \"The stroke line join method. One of `\\\"miter\\\"`, `\\\"round\\\"` or `\\\"bevel\\\"`.\\n\\n__Default value:__ `\\\"miter\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeMiterLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The miter limit at which to bevel a line join.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset in pixels at which to draw the group stroke and fill. If unspecified, the default behavior is to dynamically offset stroked groups such that 1 pixel stroke widths align with the pixel grid.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke width, in pixels.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"tension\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Depending on the interpolation type, sets the tension parameter (for line and area marks).\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"text\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\",\n                            \"description\": \"Placeholder text if the `text` channel is not specified\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"theta\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"- For arc marks, the arc length in radians if theta2 is not specified, otherwise the start arc angle. (A value of 0 indicates up or “north”, increasing values proceed clockwise.)\\n\\n- For text marks, polar coordinate angle in radians.\",\n                    \"maximum\": 360,\n                    \"minimum\": 0\n                },\n                \"theta2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The end angle of arc marks in radians. A value of 0 indicates up or “north”, increasing values proceed clockwise.\"\n                },\n                \"time\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"timeUnitBandPosition\": {\n                    \"description\": \"Default relative band position for a time unit. If set to `0`, the marks will be positioned at the beginning of the time unit band step. If set to `0.5`, the marks will be positioned in the middle of the time unit band step.\",\n                    \"type\": \"number\"\n                },\n                \"timeUnitBandSize\": {\n                    \"description\": \"Default relative band size for a time unit. If set to `1`, the bandwidth of the marks will be equal to the time unit band step. If set to `0.5`, bandwidth of the marks will be half of the time unit band step.\",\n                    \"type\": \"number\"\n                },\n                \"tooltip\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TooltipContent\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"The tooltip text string to show upon mouse hover or an object defining which fields should the tooltip be derived from.\\n\\n- If `tooltip` is `true` or `{\\\"content\\\": \\\"encoding\\\"}`, then all fields from `encoding` will be used.\\n- If `tooltip` is `{\\\"content\\\": \\\"data\\\"}`, then all fields that appear in the highlighted data point will be used.\\n- If set to `null` or `false`, then no tooltip will be used.\\n\\nSee the [`tooltip`](https://vega.github.io/vega-lite/docs/tooltip.html) documentation for a detailed discussion about tooltip  in Vega-Lite.\\n\\n__Default value:__ `null`\"\n                },\n                \"url\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/URI\",\n                            \"description\": \"The URL of the image file for image marks.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"width\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Width of the marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"x\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"X coordinates of the marks, or width of horizontal `\\\"bar\\\"` and `\\\"area\\\"` without specified `x2` or `width`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"x2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"X2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"y\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Y coordinates of the marks, or height of vertical `\\\"bar\\\"` and `\\\"area\\\"` without specified `y2` or `height`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                },\n                \"y2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Y2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ArgmaxDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"argmax\": {\n                    \"$ref\": \"#/definitions/FieldName\"\n                }\n            },\n            \"required\": [\n                \"argmax\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ArgminDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"argmin\": {\n                    \"$ref\": \"#/definitions/FieldName\"\n                }\n            },\n            \"required\": [\n                \"argmin\"\n            ],\n            \"type\": \"object\"\n        },\n        \"AutoSizeParams\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"contains\": {\n                    \"description\": \"Determines how size calculation should be performed, one of `\\\"content\\\"` or `\\\"padding\\\"`. The default setting (`\\\"content\\\"`) interprets the width and height settings as the data rectangle (plotting) dimensions, to which padding is then added. In contrast, the `\\\"padding\\\"` setting includes the padding within the view size calculations, such that the width and height settings indicate the **total** intended size of the view.\\n\\n__Default value__: `\\\"content\\\"`\",\n                    \"enum\": [\n                        \"content\",\n                        \"padding\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"resize\": {\n                    \"description\": \"A boolean flag indicating if autosize layout should be re-calculated on every view update.\\n\\n__Default value__: `false`\",\n                    \"type\": \"boolean\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/AutosizeType\",\n                    \"description\": \"The sizing format type. One of `\\\"pad\\\"`, `\\\"fit\\\"`, `\\\"fit-x\\\"`, `\\\"fit-y\\\"`,  or `\\\"none\\\"`. See the [autosize type](https://vega.github.io/vega-lite/docs/size.html#autosize) documentation for descriptions of each.\\n\\n__Default value__: `\\\"pad\\\"`\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"AutosizeType\": {\n            \"enum\": [\n                \"pad\",\n                \"none\",\n                \"fit\",\n                \"fit-x\",\n                \"fit-y\"\n            ],\n            \"type\": \"string\"\n        },\n        \"Axis\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"aria\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag indicating if [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) should be included (SVG output only). If `false`, the \\\"aria-hidden\\\" attribute will be set on the output SVG group, removing the axis from the ARIA accessibility tree.\\n\\n__Default value:__ `true`\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"bandPosition\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An interpolation fraction indicating where, for `band` scales, axis ticks should be positioned. A value of `0` places ticks at the left edge of their bands. A value of `0.5` places ticks in the middle of their bands.\\n\\n __Default value:__ `0.5`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"description\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A text description of this axis for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If the `aria` property is true, for SVG output the [\\\"aria-label\\\" attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute) will be set to this description. If the description is unspecified it will be automatically generated.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"domain\": {\n                    \"description\": \"A boolean flag indicating if the domain (the axis baseline) should be included as part of the axis.\\n\\n__Default value:__ `true`\",\n                    \"type\": \"boolean\"\n                },\n                \"domainCap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeCap\",\n                            \"description\": \"The stroke cap for the domain line's ending style. One of `\\\"butt\\\"`, `\\\"round\\\"` or `\\\"square\\\"`.\\n\\n__Default value:__ `\\\"butt\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"domainColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Color of axis domain line.\\n\\n__Default value:__ `\\\"gray\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"domainDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating [stroke, space] lengths for dashed domain lines.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"domainDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The pixel offset at which to start drawing with the domain dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"domainOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Opacity of the axis domain line.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"domainWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Stroke width of axis domain line\\n\\n__Default value:__ `1`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"format\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Dict\"\n                        }\n                    ],\n                    \"description\": \"When used with the default `\\\"number\\\"` and `\\\"time\\\"` format type, the text formatting pattern for labels of guides (axes, legends, headers) and text marks.\\n\\n- If the format type is `\\\"number\\\"` (e.g., for quantitative fields), this is D3's [number format pattern](https://github.com/d3/d3-format#locale_format).\\n- If the format type is `\\\"time\\\"` (e.g., for temporal fields), this is D3's [time format pattern](https://github.com/d3/d3-time-format#locale_format).\\n\\nSee the [format documentation](https://vega.github.io/vega-lite/docs/format.html) for more examples.\\n\\nWhen used with a [custom `formatType`](https://vega.github.io/vega-lite/docs/config.html#custom-format-type), this value will be passed as `format` alongside `datum.value` to the registered function.\\n\\n__Default value:__  Derived from [numberFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for number format and from [timeFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for time format.\"\n                },\n                \"formatType\": {\n                    \"description\": \"The format type for labels. One of `\\\"number\\\"`, `\\\"time\\\"`, or a [registered custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type).\\n\\n__Default value:__\\n- `\\\"time\\\"` for temporal fields and ordinal and nominal fields with `timeUnit`.\\n- `\\\"number\\\"` for quantitative fields as well as ordinal and nominal fields without `timeUnit`.\",\n                    \"type\": \"string\"\n                },\n                \"grid\": {\n                    \"description\": \"A boolean flag indicating if grid lines should be included as part of the axis\\n\\n__Default value:__ `true` for [continuous scales](https://vega.github.io/vega-lite/docs/scale.html#continuous) that are not binned; otherwise, `false`.\",\n                    \"type\": \"boolean\"\n                },\n                \"gridCap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeCap\",\n                            \"description\": \"The stroke cap for grid lines' ending style. One of `\\\"butt\\\"`, `\\\"round\\\"` or `\\\"square\\\"`.\\n\\n__Default value:__ `\\\"butt\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"gridColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Color of gridlines.\\n\\n__Default value:__ `\\\"lightGray\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisColor\"\n                        }\n                    ]\n                },\n                \"gridDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating [stroke, space] lengths for dashed grid lines.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumberArray\"\n                        }\n                    ]\n                },\n                \"gridDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The pixel offset at which to start drawing with the grid dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"gridOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke opacity of grid (value between [0,1])\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"gridWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The grid width, in pixels.\\n\\n__Default value:__ `1`\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"labelAlign\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\",\n                            \"description\": \"Horizontal text alignment of axis tick labels, overriding the default setting for the current axis orientation.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisLabelAlign\"\n                        }\n                    ]\n                },\n                \"labelAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The rotation angle of the axis labels.\\n\\n__Default value:__ `-90` for nominal and ordinal fields; `0` otherwise.\",\n                            \"maximum\": 360,\n                            \"minimum\": -360,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelBaseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\",\n                            \"description\": \"Vertical text baseline of axis tick labels, overriding the default setting for the current axis orientation. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, or `\\\"line-bottom\\\"`. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the *lineHeight* rather than *fontSize* alone.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisLabelBaseline\"\n                        }\n                    ]\n                },\n                \"labelBound\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Indicates if labels should be hidden if they exceed the axis range. If `false` (the default) no bounds overlap analysis is performed. If `true`, labels will be hidden if they exceed the axis range by more than 1 pixel. If this property is a number, it specifies the pixel tolerance: the maximum amount by which a label bounding box may exceed the axis range.\\n\\n__Default value:__ `false`.\",\n                            \"type\": [\n                                \"number\",\n                                \"boolean\"\n                            ]\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"The color of the tick label, can be in hex color code or regular color name.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisColor\"\n                        }\n                    ]\n                },\n                \"labelExpr\": {\n                    \"description\": \"[Vega expression](https://vega.github.io/vega/docs/expressions/) for customizing labels.\\n\\n__Note:__ The label text and value can be assessed via the `label` and `value` properties of the axis's backing `datum` object.\",\n                    \"type\": \"string\"\n                },\n                \"labelFlush\": {\n                    \"description\": \"Indicates if the first and last axis labels should be aligned flush with the scale range. Flush alignment for a horizontal axis will left-align the first label and right-align the last label. For vertical axes, bottom and top text baselines are applied instead. If this property is a number, it also indicates the number of pixels by which to offset the first and last labels; for example, a value of 2 will flush-align the first and last labels and also push them 2 pixels outward from the center of the axis. The additional adjustment can sometimes help the labels better visually group with corresponding axis ticks.\\n\\n__Default value:__ `true` for axis of a continuous x-scale. Otherwise, `false`.\",\n                    \"type\": [\n                        \"boolean\",\n                        \"number\"\n                    ]\n                },\n                \"labelFlushOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Indicates the number of pixels by which to offset flush-adjusted labels. For example, a value of `2` will push flush-adjusted labels 2 pixels outward from the center of the axis. Offsets can help the labels better visually group with corresponding axis ticks.\\n\\n__Default value:__ `0`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelFont\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font of the tick label.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisString\"\n                        }\n                    ]\n                },\n                \"labelFontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font size of the label, in pixels.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"labelFontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"Font style of the title.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisLabelFontStyle\"\n                        }\n                    ]\n                },\n                \"labelFontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"Font weight of axis tick labels.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisLabelFontWeight\"\n                        }\n                    ]\n                },\n                \"labelLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Maximum allowed pixel width of axis tick labels.\\n\\n__Default value:__ `180`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelLineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Line height in pixels for multi-line label text or label text with `\\\"line-top\\\"` or `\\\"line-bottom\\\"` baseline.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Position offset in pixels to apply to labels, in addition to tickOffset.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"labelOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The opacity of the labels.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"labelOverlap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LabelOverlap\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The strategy to use for resolving overlap of axis labels. If `false` (the default), no overlap reduction is attempted. If set to `true` or `\\\"parity\\\"`, a strategy of removing every other label is used (this works well for standard linear axes). If set to `\\\"greedy\\\"`, a linear scan of the labels is performed, removing any labels that overlaps with the last visible label (this often works better for log-scaled axes).\\n\\n__Default value:__ `true` for non-nominal fields with non-log scales; `\\\"greedy\\\"` for log scales; otherwise `false`.\"\n                },\n                \"labelPadding\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The padding in pixels between labels and ticks.\\n\\n__Default value:__ `2`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"labelSeparation\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The minimum separation that must be between label bounding boxes for them to be considered non-overlapping (default `0`). This property is ignored if *labelOverlap* resolution is not enabled.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labels\": {\n                    \"description\": \"A boolean flag indicating if labels should be included as part of the axis.\\n\\n__Default value:__ `true`.\",\n                    \"type\": \"boolean\"\n                },\n                \"maxExtent\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The maximum extent in pixels that axis ticks and labels should use. This determines a maximum offset value for axis titles.\\n\\n__Default value:__ `undefined`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"minExtent\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The minimum extent in pixels that axis ticks and labels should use. This determines a minimum offset value for axis titles.\\n\\n__Default value:__ `30` for y-axis; `undefined` for x-axis.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"offset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The offset, in pixels, by which to displace the axis from the edge of the enclosing group or data rectangle.\\n\\n__Default value:__ derived from the [axis config](https://vega.github.io/vega-lite/docs/config.html#facet-scale-config)'s `offset` (`0` by default)\"\n                },\n                \"orient\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/AxisOrient\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The orientation of the axis. One of `\\\"top\\\"`, `\\\"bottom\\\"`, `\\\"left\\\"` or `\\\"right\\\"`. The orientation can be used to further specialize the axis type (e.g., a y-axis oriented towards the right edge of the chart).\\n\\n__Default value:__ `\\\"bottom\\\"` for x-axes and `\\\"left\\\"` for y-axes.\"\n                },\n                \"position\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The anchor position of the axis in pixels. For x-axes with top or bottom orientation, this sets the axis group x coordinate. For y-axes with left or right orientation, this sets the axis group y coordinate.\\n\\n__Default value__: `0`\"\n                },\n                \"style\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"items\": {\n                                \"type\": \"string\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"A string or array of strings indicating the name of custom styles to apply to the axis. A style is a named collection of axis property defined within the [style configuration](https://vega.github.io/vega-lite/docs/mark.html#style-config). If style is an array, later styles will override earlier styles.\\n\\n__Default value:__ (none) __Note:__ Any specified style will augment the default style. For example, an x-axis mark with `\\\"style\\\": \\\"foo\\\"` will use `config.axisX` and `config.style.foo` (the specified style `\\\"foo\\\"` has higher precedence).\"\n                },\n                \"tickBand\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"For band scales, indicates if ticks and grid lines should be placed at the `\\\"center\\\"` of a band (default) or at the band `\\\"extent\\\"`s to indicate intervals\",\n                            \"enum\": [\n                                \"center\",\n                                \"extent\"\n                            ],\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"tickCap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeCap\",\n                            \"description\": \"The stroke cap for the tick lines' ending style. One of `\\\"butt\\\"`, `\\\"round\\\"` or `\\\"square\\\"`.\\n\\n__Default value:__ `\\\"butt\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"tickColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"The color of the axis's tick.\\n\\n__Default value:__ `\\\"gray\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisColor\"\n                        }\n                    ]\n                },\n                \"tickCount\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeInterval\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeIntervalStep\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A desired number of ticks, for axes visualizing quantitative scales. The resulting number may be different so that values are \\\"nice\\\" (multiples of 2, 5, 10) and lie within the underlying scale's range.\\n\\nFor scales of type `\\\"time\\\"` or `\\\"utc\\\"`, the tick count can instead be a time interval specifier. Legal string values are `\\\"millisecond\\\"`, `\\\"second\\\"`, `\\\"minute\\\"`, `\\\"hour\\\"`, `\\\"day\\\"`, `\\\"week\\\"`, `\\\"month\\\"`, and `\\\"year\\\"`. Alternatively, an object-valued interval specifier of the form `{\\\"interval\\\": \\\"month\\\", \\\"step\\\": 3}` includes a desired number of interval steps. Here, ticks are generated for each quarter (Jan, Apr, Jul, Oct) boundary.\\n\\n__Default value__: Determine using a formula `ceil(width/40)` for x and `ceil(height/40)` for y.\",\n                    \"minimum\": 0\n                },\n                \"tickDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating [stroke, space] lengths for dashed tick mark lines.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumberArray\"\n                        }\n                    ]\n                },\n                \"tickDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The pixel offset at which to start drawing with the tick mark dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"tickExtra\": {\n                    \"description\": \"Boolean flag indicating if an extra axis tick should be added for the initial position of the axis. This flag is useful for styling axes for `band` scales such that ticks are placed on band boundaries rather in the middle of a band. Use in conjunction with `\\\"bandPosition\\\": 1` and an axis `\\\"padding\\\"` value of `0`.\",\n                    \"type\": \"boolean\"\n                },\n                \"tickMinStep\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The minimum desired step between axis ticks, in terms of scale domain values. For example, a value of `1` indicates that ticks should not be less than 1 unit apart. If `tickMinStep` is specified, the `tickCount` value will be adjusted, if necessary, to enforce the minimum step value.\"\n                },\n                \"tickOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Position offset in pixels to apply to ticks, labels, and gridlines.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"tickOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Opacity of the ticks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"tickRound\": {\n                    \"description\": \"Boolean flag indicating if pixel position values should be rounded to the nearest integer.\\n\\n__Default value:__ `true`\",\n                    \"type\": \"boolean\"\n                },\n                \"tickSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The size in pixels of axis ticks.\\n\\n__Default value:__ `5`\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"tickWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The width, in pixels, of ticks.\\n\\n__Default value:__ `1`\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"ticks\": {\n                    \"description\": \"Boolean value that determines whether the axis should include ticks.\\n\\n__Default value:__ `true`\",\n                    \"type\": \"boolean\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"titleAlign\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\",\n                            \"description\": \"Horizontal text alignment of axis titles.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleAnchor\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TitleAnchor\",\n                            \"description\": \"Text anchor position for placing axis titles.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Angle in degrees of axis titles.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleBaseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\",\n                            \"description\": \"Vertical text baseline for axis titles. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, or `\\\"line-bottom\\\"`. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the *lineHeight* rather than *fontSize* alone.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Color of the title, can be in hex color code or regular color name.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleFont\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Font of the title. (e.g., `\\\"Helvetica Neue\\\"`).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleFontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Font size of the title.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleFontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"Font style of the title.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleFontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"Font weight of the title. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Maximum allowed pixel width of axis titles.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleLineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Line height in pixels for multi-line title text or title text with `\\\"line-top\\\"` or `\\\"line-bottom\\\"` baseline.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Opacity of the axis title.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titlePadding\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The padding, in pixels, between title and axis.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleX\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"X-coordinate of the axis title relative to the axis group.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleY\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Y-coordinate of the axis title relative to the axis group.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"translate\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Coordinate space translation offset for axis layout. By default, axes are translated by a 0.5 pixel offset for both the x and y coordinates in order to align stroked lines with the pixel grid. However, for vector graphics output these pixel-specific adjustments may be undesirable, in which case translate can be changed (for example, to zero).\\n\\n__Default value:__ `0.5`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"values\": {\n                    \"anyOf\": [\n                        {\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"items\": {\n                                \"type\": \"string\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"items\": {\n                                \"type\": \"boolean\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/DateTime\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Explicitly set the visible axis tick values.\"\n                },\n                \"zindex\": {\n                    \"description\": \"A non-negative integer indicating the z-index of the axis. If zindex is 0, axes should be drawn behind all chart elements. To put them in front, set `zindex` to `1` or more.\\n\\n__Default value:__ `0` (behind the marks).\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"AxisConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"aria\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag indicating if [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) should be included (SVG output only). If `false`, the \\\"aria-hidden\\\" attribute will be set on the output SVG group, removing the axis from the ARIA accessibility tree.\\n\\n__Default value:__ `true`\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"bandPosition\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An interpolation fraction indicating where, for `band` scales, axis ticks should be positioned. A value of `0` places ticks at the left edge of their bands. A value of `0.5` places ticks in the middle of their bands.\\n\\n __Default value:__ `0.5`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"description\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A text description of this axis for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If the `aria` property is true, for SVG output the [\\\"aria-label\\\" attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute) will be set to this description. If the description is unspecified it will be automatically generated.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"disable\": {\n                    \"description\": \"Disable axis by default.\",\n                    \"type\": \"boolean\"\n                },\n                \"domain\": {\n                    \"description\": \"A boolean flag indicating if the domain (the axis baseline) should be included as part of the axis.\\n\\n__Default value:__ `true`\",\n                    \"type\": \"boolean\"\n                },\n                \"domainCap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeCap\",\n                            \"description\": \"The stroke cap for the domain line's ending style. One of `\\\"butt\\\"`, `\\\"round\\\"` or `\\\"square\\\"`.\\n\\n__Default value:__ `\\\"butt\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"domainColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Color of axis domain line.\\n\\n__Default value:__ `\\\"gray\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"domainDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating [stroke, space] lengths for dashed domain lines.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"domainDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The pixel offset at which to start drawing with the domain dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"domainOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Opacity of the axis domain line.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"domainWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Stroke width of axis domain line\\n\\n__Default value:__ `1`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"format\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Dict\"\n                        }\n                    ],\n                    \"description\": \"When used with the default `\\\"number\\\"` and `\\\"time\\\"` format type, the text formatting pattern for labels of guides (axes, legends, headers) and text marks.\\n\\n- If the format type is `\\\"number\\\"` (e.g., for quantitative fields), this is D3's [number format pattern](https://github.com/d3/d3-format#locale_format).\\n- If the format type is `\\\"time\\\"` (e.g., for temporal fields), this is D3's [time format pattern](https://github.com/d3/d3-time-format#locale_format).\\n\\nSee the [format documentation](https://vega.github.io/vega-lite/docs/format.html) for more examples.\\n\\nWhen used with a [custom `formatType`](https://vega.github.io/vega-lite/docs/config.html#custom-format-type), this value will be passed as `format` alongside `datum.value` to the registered function.\\n\\n__Default value:__  Derived from [numberFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for number format and from [timeFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for time format.\"\n                },\n                \"formatType\": {\n                    \"description\": \"The format type for labels. One of `\\\"number\\\"`, `\\\"time\\\"`, or a [registered custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type).\\n\\n__Default value:__\\n- `\\\"time\\\"` for temporal fields and ordinal and nominal fields with `timeUnit`.\\n- `\\\"number\\\"` for quantitative fields as well as ordinal and nominal fields without `timeUnit`.\",\n                    \"type\": \"string\"\n                },\n                \"grid\": {\n                    \"description\": \"A boolean flag indicating if grid lines should be included as part of the axis\\n\\n__Default value:__ `true` for [continuous scales](https://vega.github.io/vega-lite/docs/scale.html#continuous) that are not binned; otherwise, `false`.\",\n                    \"type\": \"boolean\"\n                },\n                \"gridCap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeCap\",\n                            \"description\": \"The stroke cap for grid lines' ending style. One of `\\\"butt\\\"`, `\\\"round\\\"` or `\\\"square\\\"`.\\n\\n__Default value:__ `\\\"butt\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"gridColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Color of gridlines.\\n\\n__Default value:__ `\\\"lightGray\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisColor\"\n                        }\n                    ]\n                },\n                \"gridDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating [stroke, space] lengths for dashed grid lines.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumberArray\"\n                        }\n                    ]\n                },\n                \"gridDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The pixel offset at which to start drawing with the grid dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"gridOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke opacity of grid (value between [0,1])\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"gridWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The grid width, in pixels.\\n\\n__Default value:__ `1`\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"labelAlign\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\",\n                            \"description\": \"Horizontal text alignment of axis tick labels, overriding the default setting for the current axis orientation.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisLabelAlign\"\n                        }\n                    ]\n                },\n                \"labelAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The rotation angle of the axis labels.\\n\\n__Default value:__ `-90` for nominal and ordinal fields; `0` otherwise.\",\n                            \"maximum\": 360,\n                            \"minimum\": -360,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelBaseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\",\n                            \"description\": \"Vertical text baseline of axis tick labels, overriding the default setting for the current axis orientation. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, or `\\\"line-bottom\\\"`. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the *lineHeight* rather than *fontSize* alone.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisLabelBaseline\"\n                        }\n                    ]\n                },\n                \"labelBound\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Indicates if labels should be hidden if they exceed the axis range. If `false` (the default) no bounds overlap analysis is performed. If `true`, labels will be hidden if they exceed the axis range by more than 1 pixel. If this property is a number, it specifies the pixel tolerance: the maximum amount by which a label bounding box may exceed the axis range.\\n\\n__Default value:__ `false`.\",\n                            \"type\": [\n                                \"number\",\n                                \"boolean\"\n                            ]\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"The color of the tick label, can be in hex color code or regular color name.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisColor\"\n                        }\n                    ]\n                },\n                \"labelExpr\": {\n                    \"description\": \"[Vega expression](https://vega.github.io/vega/docs/expressions/) for customizing labels.\\n\\n__Note:__ The label text and value can be assessed via the `label` and `value` properties of the axis's backing `datum` object.\",\n                    \"type\": \"string\"\n                },\n                \"labelFlush\": {\n                    \"description\": \"Indicates if the first and last axis labels should be aligned flush with the scale range. Flush alignment for a horizontal axis will left-align the first label and right-align the last label. For vertical axes, bottom and top text baselines are applied instead. If this property is a number, it also indicates the number of pixels by which to offset the first and last labels; for example, a value of 2 will flush-align the first and last labels and also push them 2 pixels outward from the center of the axis. The additional adjustment can sometimes help the labels better visually group with corresponding axis ticks.\\n\\n__Default value:__ `true` for axis of a continuous x-scale. Otherwise, `false`.\",\n                    \"type\": [\n                        \"boolean\",\n                        \"number\"\n                    ]\n                },\n                \"labelFlushOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Indicates the number of pixels by which to offset flush-adjusted labels. For example, a value of `2` will push flush-adjusted labels 2 pixels outward from the center of the axis. Offsets can help the labels better visually group with corresponding axis ticks.\\n\\n__Default value:__ `0`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelFont\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font of the tick label.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisString\"\n                        }\n                    ]\n                },\n                \"labelFontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font size of the label, in pixels.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"labelFontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"Font style of the title.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisLabelFontStyle\"\n                        }\n                    ]\n                },\n                \"labelFontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"Font weight of axis tick labels.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisLabelFontWeight\"\n                        }\n                    ]\n                },\n                \"labelLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Maximum allowed pixel width of axis tick labels.\\n\\n__Default value:__ `180`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelLineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Line height in pixels for multi-line label text or label text with `\\\"line-top\\\"` or `\\\"line-bottom\\\"` baseline.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Position offset in pixels to apply to labels, in addition to tickOffset.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"labelOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The opacity of the labels.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"labelOverlap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LabelOverlap\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The strategy to use for resolving overlap of axis labels. If `false` (the default), no overlap reduction is attempted. If set to `true` or `\\\"parity\\\"`, a strategy of removing every other label is used (this works well for standard linear axes). If set to `\\\"greedy\\\"`, a linear scan of the labels is performed, removing any labels that overlaps with the last visible label (this often works better for log-scaled axes).\\n\\n__Default value:__ `true` for non-nominal fields with non-log scales; `\\\"greedy\\\"` for log scales; otherwise `false`.\"\n                },\n                \"labelPadding\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The padding in pixels between labels and ticks.\\n\\n__Default value:__ `2`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"labelSeparation\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The minimum separation that must be between label bounding boxes for them to be considered non-overlapping (default `0`). This property is ignored if *labelOverlap* resolution is not enabled.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labels\": {\n                    \"description\": \"A boolean flag indicating if labels should be included as part of the axis.\\n\\n__Default value:__ `true`.\",\n                    \"type\": \"boolean\"\n                },\n                \"maxExtent\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The maximum extent in pixels that axis ticks and labels should use. This determines a maximum offset value for axis titles.\\n\\n__Default value:__ `undefined`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"minExtent\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The minimum extent in pixels that axis ticks and labels should use. This determines a minimum offset value for axis titles.\\n\\n__Default value:__ `30` for y-axis; `undefined` for x-axis.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"offset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The offset, in pixels, by which to displace the axis from the edge of the enclosing group or data rectangle.\\n\\n__Default value:__ derived from the [axis config](https://vega.github.io/vega-lite/docs/config.html#facet-scale-config)'s `offset` (`0` by default)\"\n                },\n                \"orient\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/AxisOrient\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The orientation of the axis. One of `\\\"top\\\"`, `\\\"bottom\\\"`, `\\\"left\\\"` or `\\\"right\\\"`. The orientation can be used to further specialize the axis type (e.g., a y-axis oriented towards the right edge of the chart).\\n\\n__Default value:__ `\\\"bottom\\\"` for x-axes and `\\\"left\\\"` for y-axes.\"\n                },\n                \"position\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The anchor position of the axis in pixels. For x-axes with top or bottom orientation, this sets the axis group x coordinate. For y-axes with left or right orientation, this sets the axis group y coordinate.\\n\\n__Default value__: `0`\"\n                },\n                \"style\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"items\": {\n                                \"type\": \"string\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"A string or array of strings indicating the name of custom styles to apply to the axis. A style is a named collection of axis property defined within the [style configuration](https://vega.github.io/vega-lite/docs/mark.html#style-config). If style is an array, later styles will override earlier styles.\\n\\n__Default value:__ (none) __Note:__ Any specified style will augment the default style. For example, an x-axis mark with `\\\"style\\\": \\\"foo\\\"` will use `config.axisX` and `config.style.foo` (the specified style `\\\"foo\\\"` has higher precedence).\"\n                },\n                \"tickBand\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"For band scales, indicates if ticks and grid lines should be placed at the `\\\"center\\\"` of a band (default) or at the band `\\\"extent\\\"`s to indicate intervals\",\n                            \"enum\": [\n                                \"center\",\n                                \"extent\"\n                            ],\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"tickCap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeCap\",\n                            \"description\": \"The stroke cap for the tick lines' ending style. One of `\\\"butt\\\"`, `\\\"round\\\"` or `\\\"square\\\"`.\\n\\n__Default value:__ `\\\"butt\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"tickColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"The color of the axis's tick.\\n\\n__Default value:__ `\\\"gray\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisColor\"\n                        }\n                    ]\n                },\n                \"tickCount\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeInterval\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeIntervalStep\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A desired number of ticks, for axes visualizing quantitative scales. The resulting number may be different so that values are \\\"nice\\\" (multiples of 2, 5, 10) and lie within the underlying scale's range.\\n\\nFor scales of type `\\\"time\\\"` or `\\\"utc\\\"`, the tick count can instead be a time interval specifier. Legal string values are `\\\"millisecond\\\"`, `\\\"second\\\"`, `\\\"minute\\\"`, `\\\"hour\\\"`, `\\\"day\\\"`, `\\\"week\\\"`, `\\\"month\\\"`, and `\\\"year\\\"`. Alternatively, an object-valued interval specifier of the form `{\\\"interval\\\": \\\"month\\\", \\\"step\\\": 3}` includes a desired number of interval steps. Here, ticks are generated for each quarter (Jan, Apr, Jul, Oct) boundary.\\n\\n__Default value__: Determine using a formula `ceil(width/40)` for x and `ceil(height/40)` for y.\",\n                    \"minimum\": 0\n                },\n                \"tickDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating [stroke, space] lengths for dashed tick mark lines.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumberArray\"\n                        }\n                    ]\n                },\n                \"tickDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The pixel offset at which to start drawing with the tick mark dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"tickExtra\": {\n                    \"description\": \"Boolean flag indicating if an extra axis tick should be added for the initial position of the axis. This flag is useful for styling axes for `band` scales such that ticks are placed on band boundaries rather in the middle of a band. Use in conjunction with `\\\"bandPosition\\\": 1` and an axis `\\\"padding\\\"` value of `0`.\",\n                    \"type\": \"boolean\"\n                },\n                \"tickMinStep\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The minimum desired step between axis ticks, in terms of scale domain values. For example, a value of `1` indicates that ticks should not be less than 1 unit apart. If `tickMinStep` is specified, the `tickCount` value will be adjusted, if necessary, to enforce the minimum step value.\"\n                },\n                \"tickOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Position offset in pixels to apply to ticks, labels, and gridlines.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"tickOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Opacity of the ticks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"tickRound\": {\n                    \"description\": \"Boolean flag indicating if pixel position values should be rounded to the nearest integer.\\n\\n__Default value:__ `true`\",\n                    \"type\": \"boolean\"\n                },\n                \"tickSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The size in pixels of axis ticks.\\n\\n__Default value:__ `5`\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"tickWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The width, in pixels, of ticks.\\n\\n__Default value:__ `1`\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalAxisNumber\"\n                        }\n                    ]\n                },\n                \"ticks\": {\n                    \"description\": \"Boolean value that determines whether the axis should include ticks.\\n\\n__Default value:__ `true`\",\n                    \"type\": \"boolean\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"titleAlign\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\",\n                            \"description\": \"Horizontal text alignment of axis titles.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleAnchor\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TitleAnchor\",\n                            \"description\": \"Text anchor position for placing axis titles.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Angle in degrees of axis titles.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleBaseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\",\n                            \"description\": \"Vertical text baseline for axis titles. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, or `\\\"line-bottom\\\"`. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the *lineHeight* rather than *fontSize* alone.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Color of the title, can be in hex color code or regular color name.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleFont\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Font of the title. (e.g., `\\\"Helvetica Neue\\\"`).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleFontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Font size of the title.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleFontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"Font style of the title.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleFontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"Font weight of the title. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Maximum allowed pixel width of axis titles.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleLineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Line height in pixels for multi-line title text or title text with `\\\"line-top\\\"` or `\\\"line-bottom\\\"` baseline.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Opacity of the axis title.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titlePadding\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The padding, in pixels, between title and axis.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleX\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"X-coordinate of the axis title relative to the axis group.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleY\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Y-coordinate of the axis title relative to the axis group.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"translate\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Coordinate space translation offset for axis layout. By default, axes are translated by a 0.5 pixel offset for both the x and y coordinates in order to align stroked lines with the pixel grid. However, for vector graphics output these pixel-specific adjustments may be undesirable, in which case translate can be changed (for example, to zero).\\n\\n__Default value:__ `0.5`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"values\": {\n                    \"anyOf\": [\n                        {\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"items\": {\n                                \"type\": \"string\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"items\": {\n                                \"type\": \"boolean\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/DateTime\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Explicitly set the visible axis tick values.\"\n                },\n                \"zindex\": {\n                    \"description\": \"A non-negative integer indicating the z-index of the axis. If zindex is 0, axes should be drawn behind all chart elements. To put them in front, set `zindex` to `1` or more.\\n\\n__Default value:__ `0` (behind the marks).\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"AxisOrient\": {\n            \"enum\": [\n                \"top\",\n                \"bottom\",\n                \"left\",\n                \"right\"\n            ],\n            \"type\": \"string\"\n        },\n        \"AxisResolveMap\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"x\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"y\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"BBox\": {\n            \"anyOf\": [\n                {\n                    \"items\": {\n                        \"type\": \"number\"\n                    },\n                    \"maxItems\": 4,\n                    \"minItems\": 4,\n                    \"type\": \"array\"\n                },\n                {\n                    \"items\": {\n                        \"type\": \"number\"\n                    },\n                    \"maxItems\": 6,\n                    \"minItems\": 6,\n                    \"type\": \"array\"\n                }\n            ],\n            \"description\": \"Bounding box https://tools.ietf.org/html/rfc7946#section-5\"\n        },\n        \"BarConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The horizontal alignment of the text or ranged marks (area, bar, image, rect, rule). One of `\\\"left\\\"`, `\\\"right\\\"`, `\\\"center\\\"`.\\n\\n__Note:__ Expression reference is *not* supported for range marks.\"\n                },\n                \"angle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The rotation angle of the text, in degrees.\",\n                            \"maximum\": 360,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aria\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag indicating if [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) should be included (SVG output only). If `false`, the \\\"aria-hidden\\\" attribute will be set on the output SVG element, removing the mark item from the ARIA accessibility tree.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ariaRole\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Sets the type of user interface element of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the \\\"role\\\" attribute. Warning: this property is experimental and may be changed in the future.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ariaRoleDescription\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A human-readable, author-localized description for the role of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the \\\"aria-roledescription\\\" attribute. Warning: this property is experimental and may be changed in the future.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aspect\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Whether to keep aspect ratio of image marks.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"baseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"For text marks, the vertical text baseline. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, `\\\"line-bottom\\\"`, or an expression reference that provides one of the valid values. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the `lineHeight` rather than `fontSize` alone.\\n\\nFor range marks, the vertical alignment of the marks. One of `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`.\\n\\n__Note:__ Expression reference is *not* supported for range marks.\"\n                },\n                \"binSpacing\": {\n                    \"description\": \"Offset between bars for binned field. The ideal value for this is either 0 (preferred by statisticians) or 1 (Vega-Lite default, D3 example style).\\n\\n__Default value:__ `1`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"blend\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Blend\",\n                            \"description\": \"The color blend mode for drawing an item on its current background. Any valid [CSS mix-blend-mode](https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode) value can be used.\\n\\n__Default value: `\\\"source-over\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"color\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default color.\\n\\n__Default value:__ <span style=\\\"color: #4682b4;\\\">&#9632;</span> `\\\"#4682b4\\\"`\\n\\n__Note:__\\n- This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\\n- The `fill` and `stroke` properties have higher precedence than `color` and will override `color`.\"\n                },\n                \"continuousBandSize\": {\n                    \"description\": \"The default size of the bars on continuous scales.\\n\\n__Default value:__ `5`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"cornerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles or arcs' corners.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusBottomLeft\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' bottom left corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusBottomRight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' bottom right corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusEnd\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"- For vertical bars, top-left and top-right corner radius.\\n\\n- For horizontal bars, top-right and bottom-right corner radius.\"\n                },\n                \"cornerRadiusTopLeft\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' top right corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusTopRight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' top left corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cursor\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Cursor\",\n                            \"description\": \"The mouse cursor used over the mark. Any valid [CSS cursor type](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"description\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A text description of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the [\\\"aria-label\\\" attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dir\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextDirection\",\n                            \"description\": \"The direction of the text. One of `\\\"ltr\\\"` (left-to-right) or `\\\"rtl\\\"` (right-to-left). This property determines on which side is truncated in response to the limit parameter.\\n\\n__Default value:__ `\\\"ltr\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"discreteBandSize\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RelativeBandSize\"\n                        }\n                    ],\n                    \"description\": \"The default size of the bars with discrete dimensions. If unspecified, the default size is  `step-2`, which provides 2 pixel offset between bars.\",\n                    \"minimum\": 0\n                },\n                \"dx\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The horizontal offset, in pixels, between the text label and its anchor point. The offset is applied after rotation by the _angle_ property.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dy\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The vertical offset, in pixels, between the text label and its anchor point. The offset is applied after rotation by the _angle_ property.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ellipsis\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The ellipsis string for text truncated in response to the limit parameter.\\n\\n__Default value:__ `\\\"…\\\"`\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"endAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The end angle in radians for arc marks. A value of `0` indicates up (north), increasing values proceed clockwise.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fill\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default fill color. This property has higher precedence than `config.color`. Set to `null` to remove fill.\\n\\n__Default value:__ (None)\"\n                },\n                \"fillOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The fill opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"filled\": {\n                    \"description\": \"Whether the mark's color should be used as fill color instead of stroke color.\\n\\n__Default value:__ `false` for all `point`, `line`, and `rule` marks as well as `geoshape` marks for [`graticule`](https://vega.github.io/vega-lite/docs/data.html#graticule) data sources; otherwise, `true`.\\n\\n__Note:__ This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\",\n                    \"type\": \"boolean\"\n                },\n                \"font\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The typeface to set the text in (e.g., `\\\"Helvetica Neue\\\"`).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font size, in pixels.\\n\\n__Default value:__ `11`\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"The font style (e.g., `\\\"italic\\\"`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"The font weight. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"height\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Height of the marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"href\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/URI\",\n                            \"description\": \"A URL to load upon mouse click. If defined, the mark acts as a hyperlink.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"innerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The inner radius in pixels of arc marks. `innerRadius` is an alias for `radius2`.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"interpolate\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Interpolate\",\n                            \"description\": \"The line interpolation method to use for line and area marks. One of the following:\\n- `\\\"linear\\\"`: piecewise linear segments, as in a polyline.\\n- `\\\"linear-closed\\\"`: close the linear segments to form a polygon.\\n- `\\\"step\\\"`: alternate between horizontal and vertical segments, as in a step function.\\n- `\\\"step-before\\\"`: alternate between vertical and horizontal segments, as in a step function.\\n- `\\\"step-after\\\"`: alternate between horizontal and vertical segments, as in a step function.\\n- `\\\"basis\\\"`: a B-spline, with control point duplication on the ends.\\n- `\\\"basis-open\\\"`: an open B-spline; may not intersect the start or end.\\n- `\\\"basis-closed\\\"`: a closed B-spline, as in a loop.\\n- `\\\"cardinal\\\"`: a Cardinal spline, with control point duplication on the ends.\\n- `\\\"cardinal-open\\\"`: an open Cardinal spline; may not intersect the start or end, but will intersect other control points.\\n- `\\\"cardinal-closed\\\"`: a closed Cardinal spline, as in a loop.\\n- `\\\"bundle\\\"`: equivalent to basis, except the tension parameter is used to straighten the spline.\\n- `\\\"monotone\\\"`: cubic interpolation that preserves monotonicity in y.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"invalid\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/MarkInvalidDataMode\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"Invalid data mode, which defines how the marks and corresponding scales should represent invalid values (`null` and `NaN` in continuous scales *without* defined output for invalid values).\\n\\n- `\\\"filter\\\"` — *Exclude* all invalid values from the visualization's *marks* and *scales*. For path marks (for line, area, trail), this option will create paths that connect valid points, as if the data rows with invalid values do not exist.\\n\\n- `\\\"break-paths-filter-domains\\\"` — Break path marks (for line, area, trail) at invalid values.  For non-path marks, this is equivalent to `\\\"filter\\\"`. All *scale* domains will *exclude* these filtered data points.\\n\\n- `\\\"break-paths-show-domains\\\"` — Break paths (for line, area, trail) at invalid values.  Hide invalid values for non-path marks. All *scale* domains will *include* these filtered data points (for both path and non-path marks).\\n\\n- `\\\"show\\\"` or `null` — Show all data points in the marks and scale domains. Each scale will use the output for invalid values defined in `config.scale.invalid` or, if unspecified, by default invalid values will produce the same visual values as zero (if the scale includes zero) or the minimum value (if the scale does not include zero).\\n\\n- `\\\"break-paths-show-path-domains\\\"` (default) — This is equivalent to `\\\"break-paths-show-domains\\\"` for path-based marks (line/area/trail) and `\\\"filter\\\"` for non-path marks.\\n\\n__Note__: If any channel's scale has an output for invalid values defined in `config.scale.invalid`, all values for the scales will be considered \\\"valid\\\" since they can produce a reasonable output for the scales. Thus, fields for such channels will not be filtered and will not cause path breaks.\"\n                },\n                \"limit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The maximum length of the text mark in pixels. The text value will be automatically truncated if the rendered size exceeds the limit.\\n\\n__Default value:__ `0` -- indicating no limit\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"lineBreak\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A delimiter, such as a newline character, upon which to break text strings into multiple lines. This property is ignored if the text is array-valued.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"lineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The line height in pixels (the spacing between subsequent lines of text) for multi-line text marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"minBandSize\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The minimum band size for bar and rectangle marks. __Default value:__ `0.25`\"\n                },\n                \"opacity\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The overall opacity (value between [0,1]).\\n\\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or `square` marks or layered `bar` charts and `1` otherwise.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"order\": {\n                    \"description\": \"For line and trail marks, this `order` property can be set to `null` or `false` to make the lines use the original order in the data sources.\",\n                    \"type\": [\n                        \"null\",\n                        \"boolean\"\n                    ]\n                },\n                \"orient\": {\n                    \"$ref\": \"#/definitions/Orientation\",\n                    \"description\": \"The orientation of a non-stacked bar, tick, area, and line charts. The value is either horizontal (default) or vertical.\\n- For bar, rule and tick, this determines whether the size of the bar and tick should be applied to x or y dimension.\\n- For area, this property determines the orient property of the Vega output.\\n- For line and trail marks, this property determines the sort order of the points in the line if `config.sortLineBy` is not specified. For stacked charts, this is always determined by the orientation of the stack; therefore explicitly specified value will be ignored.\"\n                },\n                \"outerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The outer radius in pixels of arc marks. `outerRadius` is an alias for `radius`.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"padAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The angular padding applied to sides of the arc, in radians.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"radius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"For arc mark, the primary (outer) radius in pixels.\\n\\nFor text marks, polar coordinate radial offset, in pixels, of the text from the origin determined by the `x` and `y` properties.\\n\\n__Default value:__ `min(plot_width, plot_height)/2`\",\n                    \"minimum\": 0\n                },\n                \"radius2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The secondary (inner) radius in pixels of arc marks.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"shape\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/SymbolShape\"\n                                },\n                                {\n                                    \"type\": \"string\"\n                                }\n                            ],\n                            \"description\": \"Shape of the point marks. Supported values include:\\n- plotting shapes: `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"cross\\\"`, `\\\"diamond\\\"`, `\\\"triangle-up\\\"`, `\\\"triangle-down\\\"`, `\\\"triangle-right\\\"`, or `\\\"triangle-left\\\"`.\\n- the line symbol `\\\"stroke\\\"`\\n- centered directional shapes `\\\"arrow\\\"`, `\\\"wedge\\\"`, or `\\\"triangle\\\"`\\n- a custom [SVG path string](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths) (For correct sizing, custom shape paths should be defined within a square bounding box with coordinates ranging from -1 to 1 along both the x and y dimensions.)\\n\\n__Default value:__ `\\\"circle\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"size\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default size for marks.\\n- For `point`/`circle`/`square`, this represents the pixel area of the marks. Note that this value sets the area of the symbol; the side lengths will increase with the square root of this value.\\n- For `bar`, this represents the band size of the bar, in pixels.\\n- For `text`, this represents the font size, in pixels.\\n\\n__Default value:__\\n- `30` for point, circle, square marks; width/height's `step`\\n- `2` for bar marks with discrete dimensions;\\n- `5` for bar marks with continuous dimensions;\\n- `11` for text marks.\",\n                    \"minimum\": 0\n                },\n                \"smooth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag (default true) indicating if the image should be smoothed when resized. If false, individual pixels should be scaled directly rather than interpolated with smoothing. For SVG rendering, this option may not work in some browsers due to lack of standardization.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"startAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The start angle in radians for arc marks. A value of `0` indicates up (north), increasing values proceed clockwise.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"stroke\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default stroke color. This property has higher precedence than `config.color`. Set to `null` to remove stroke.\\n\\n__Default value:__ (None)\"\n                },\n                \"strokeCap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeCap\",\n                            \"description\": \"The stroke cap for line ending style. One of `\\\"butt\\\"`, `\\\"round\\\"`, or `\\\"square\\\"`.\\n\\n__Default value:__ `\\\"butt\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating stroke, space lengths for creating dashed or dotted lines.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset (in pixels) into which to begin drawing with the stroke dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeJoin\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeJoin\",\n                            \"description\": \"The stroke line join method. One of `\\\"miter\\\"`, `\\\"round\\\"` or `\\\"bevel\\\"`.\\n\\n__Default value:__ `\\\"miter\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeMiterLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The miter limit at which to bevel a line join.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset in pixels at which to draw the group stroke and fill. If unspecified, the default behavior is to dynamically offset stroked groups such that 1 pixel stroke widths align with the pixel grid.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke width, in pixels.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"tension\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Depending on the interpolation type, sets the tension parameter (for line and area marks).\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"text\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\",\n                            \"description\": \"Placeholder text if the `text` channel is not specified\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"theta\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"- For arc marks, the arc length in radians if theta2 is not specified, otherwise the start arc angle. (A value of 0 indicates up or “north”, increasing values proceed clockwise.)\\n\\n- For text marks, polar coordinate angle in radians.\",\n                    \"maximum\": 360,\n                    \"minimum\": 0\n                },\n                \"theta2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The end angle of arc marks in radians. A value of 0 indicates up or “north”, increasing values proceed clockwise.\"\n                },\n                \"time\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"timeUnitBandPosition\": {\n                    \"description\": \"Default relative band position for a time unit. If set to `0`, the marks will be positioned at the beginning of the time unit band step. If set to `0.5`, the marks will be positioned in the middle of the time unit band step.\",\n                    \"type\": \"number\"\n                },\n                \"timeUnitBandSize\": {\n                    \"description\": \"Default relative band size for a time unit. If set to `1`, the bandwidth of the marks will be equal to the time unit band step. If set to `0.5`, bandwidth of the marks will be half of the time unit band step.\",\n                    \"type\": \"number\"\n                },\n                \"tooltip\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TooltipContent\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"The tooltip text string to show upon mouse hover or an object defining which fields should the tooltip be derived from.\\n\\n- If `tooltip` is `true` or `{\\\"content\\\": \\\"encoding\\\"}`, then all fields from `encoding` will be used.\\n- If `tooltip` is `{\\\"content\\\": \\\"data\\\"}`, then all fields that appear in the highlighted data point will be used.\\n- If set to `null` or `false`, then no tooltip will be used.\\n\\nSee the [`tooltip`](https://vega.github.io/vega-lite/docs/tooltip.html) documentation for a detailed discussion about tooltip  in Vega-Lite.\\n\\n__Default value:__ `null`\"\n                },\n                \"url\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/URI\",\n                            \"description\": \"The URL of the image file for image marks.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"width\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Width of the marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"x\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"X coordinates of the marks, or width of horizontal `\\\"bar\\\"` and `\\\"area\\\"` without specified `x2` or `width`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"x2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"X2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"y\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Y coordinates of the marks, or height of vertical `\\\"bar\\\"` and `\\\"area\\\"` without specified `y2` or `height`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                },\n                \"y2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Y2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"BaseTitleNoValueRefs\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"align\": {\n                    \"$ref\": \"#/definitions/Align\",\n                    \"description\": \"Horizontal text alignment for title text. One of `\\\"left\\\"`, `\\\"center\\\"`, or `\\\"right\\\"`.\"\n                },\n                \"anchor\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TitleAnchor\",\n                            \"description\": \"The anchor position for placing the title and subtitle text. One of `\\\"start\\\"`, `\\\"middle\\\"`, or `\\\"end\\\"`. For example, with an orientation of top these anchor positions map to a left-, center-, or right-aligned title.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"angle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Angle in degrees of title and subtitle text.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aria\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag indicating if [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) should be included (SVG output only). If `false`, the \\\"aria-hidden\\\" attribute will be set on the output SVG group, removing the title from the ARIA accessibility tree.\\n\\n__Default value:__ `true`\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"baseline\": {\n                    \"$ref\": \"#/definitions/TextBaseline\",\n                    \"description\": \"Vertical text baseline for title and subtitle text. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, or `\\\"line-bottom\\\"`. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the *lineHeight* rather than *fontSize* alone.\"\n                },\n                \"color\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Text color for title text.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dx\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Delta offset for title and subtitle text x-coordinate.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dy\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Delta offset for title and subtitle text y-coordinate.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"font\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Font name for title text.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Font size in pixels for title text.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"Font style for title text.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"Font weight for title text. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"frame\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TitleFrame\"\n                                },\n                                {\n                                    \"type\": \"string\"\n                                }\n                            ],\n                            \"description\": \"The reference frame for the anchor position, one of `\\\"bounds\\\"` (to anchor relative to the full bounding box) or `\\\"group\\\"` (to anchor relative to the group width or height).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"limit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The maximum allowed length in pixels of title and subtitle text.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"lineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Line height in pixels for multi-line title text or title text with `\\\"line-top\\\"` or `\\\"line-bottom\\\"` baseline.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"offset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The orthogonal offset in pixels by which to displace the title group from its position along the edge of the chart.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"orient\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TitleOrient\",\n                            \"description\": \"Default title orientation (`\\\"top\\\"`, `\\\"bottom\\\"`, `\\\"left\\\"`, or `\\\"right\\\"`)\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"subtitleColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Text color for subtitle text.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"subtitleFont\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Font name for subtitle text.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"subtitleFontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Font size in pixels for subtitle text.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"subtitleFontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"Font style for subtitle text.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"subtitleFontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"Font weight for subtitle text. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"subtitleLineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Line height in pixels for multi-line subtitle text.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"subtitlePadding\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The padding in pixels between title and subtitle text.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"zindex\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The integer z-index indicating the layering of the title group relative to other axis, mark, and legend groups.\\n\\n__Default value:__ `0`.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"Baseline\": {\n            \"enum\": [\n                \"top\",\n                \"middle\",\n                \"bottom\"\n            ],\n            \"type\": \"string\"\n        },\n        \"BinExtent\": {\n            \"anyOf\": [\n                {\n                    \"items\": {\n                        \"type\": \"number\"\n                    },\n                    \"maxItems\": 2,\n                    \"minItems\": 2,\n                    \"type\": \"array\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ParameterExtent\"\n                }\n            ]\n        },\n        \"BinParams\": {\n            \"additionalProperties\": false,\n            \"description\": \"Binning properties or boolean flag for determining whether to bin data or not.\",\n            \"properties\": {\n                \"anchor\": {\n                    \"description\": \"A value in the binned domain at which to anchor the bins, shifting the bin boundaries if necessary to ensure that a boundary aligns with the anchor value.\\n\\n__Default value:__ the minimum bin extent value\",\n                    \"type\": \"number\"\n                },\n                \"base\": {\n                    \"description\": \"The number base to use for automatic bin determination (default is base 10).\\n\\n__Default value:__ `10`\",\n                    \"type\": \"number\"\n                },\n                \"binned\": {\n                    \"description\": \"When set to `true`, Vega-Lite treats the input data as already binned.\",\n                    \"type\": \"boolean\"\n                },\n                \"divide\": {\n                    \"description\": \"Scale factors indicating allowable subdivisions. The default value is [5, 2], which indicates that for base 10 numbers (the default base), the method may consider dividing bin sizes by 5 and/or 2. For example, for an initial step size of 10, the method can check if bin sizes of 2 (= 10/5), 5 (= 10/2), or 1 (= 10/(5*2)) might also satisfy the given constraints.\\n\\n__Default value:__ `[5, 2]`\",\n                    \"items\": {\n                        \"type\": \"number\"\n                    },\n                    \"maxItems\": 2,\n                    \"minItems\": 1,\n                    \"type\": \"array\"\n                },\n                \"extent\": {\n                    \"$ref\": \"#/definitions/BinExtent\",\n                    \"description\": \"A two-element (`[min, max]`) array indicating the range of desired bin values.\"\n                },\n                \"maxbins\": {\n                    \"description\": \"Maximum number of bins.\\n\\n__Default value:__ `6` for `row`, `column` and `shape` channels; `10` for other channels\",\n                    \"minimum\": 2,\n                    \"type\": \"number\"\n                },\n                \"minstep\": {\n                    \"description\": \"A minimum allowable step size (particularly useful for integer values).\",\n                    \"type\": \"number\"\n                },\n                \"nice\": {\n                    \"description\": \"If true, attempts to make the bin boundaries use human-friendly boundaries, such as multiples of ten.\\n\\n__Default value:__ `true`\",\n                    \"type\": \"boolean\"\n                },\n                \"step\": {\n                    \"description\": \"An exact step size to use between bins.\\n\\n__Note:__ If provided, options such as maxbins will be ignored.\",\n                    \"type\": \"number\"\n                },\n                \"steps\": {\n                    \"description\": \"An array of allowable step sizes to choose from.\",\n                    \"items\": {\n                        \"type\": \"number\"\n                    },\n                    \"minItems\": 1,\n                    \"type\": \"array\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"BinTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"as\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FieldName\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/FieldName\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"The output fields at which to write the start and end bin values. This can be either a string or an array of strings with two elements denoting the name for the fields for bin start and bin end respectively. If a single string (e.g., `\\\"val\\\"`) is provided, the end field will be `\\\"val_end\\\"`.\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"const\": true,\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        }\n                    ],\n                    \"description\": \"An object indicating bin properties, or simply `true` for using default bin parameters.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The data field to bin.\"\n                }\n            },\n            \"required\": [\n                \"bin\",\n                \"field\",\n                \"as\"\n            ],\n            \"type\": \"object\"\n        },\n        \"BindCheckbox\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"debounce\": {\n                    \"description\": \"If defined, delays event handling until the specified milliseconds have elapsed since the last event was fired.\",\n                    \"type\": \"number\"\n                },\n                \"element\": {\n                    \"$ref\": \"#/definitions/Element\",\n                    \"description\": \"An optional CSS selector string indicating the parent element to which the input element should be added. By default, all input elements are added within the parent container of the Vega view.\"\n                },\n                \"input\": {\n                    \"const\": \"checkbox\",\n                    \"type\": \"string\"\n                },\n                \"name\": {\n                    \"description\": \"By default, the signal name is used to label input elements. This `name` property can be used instead to specify a custom label for the bound signal.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"input\"\n            ],\n            \"type\": \"object\"\n        },\n        \"BindDirect\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"debounce\": {\n                    \"description\": \"If defined, delays event handling until the specified milliseconds have elapsed since the last event was fired.\",\n                    \"type\": \"number\"\n                },\n                \"element\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Element\"\n                        },\n                        {\n                            \"additionalProperties\": false,\n                            \"type\": \"object\"\n                        }\n                    ],\n                    \"description\": \"An input element that exposes a _value_ property and supports the [EventTarget](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget) interface, or a CSS selector string to such an element. When the element updates and dispatches an event, the _value_ property will be used as the new, bound signal value. When the signal updates independent of the element, the _value_ property will be set to the signal value and a new event will be dispatched on the element.\"\n                },\n                \"event\": {\n                    \"description\": \"The event (default `\\\"input\\\"`) to listen for to track changes on the external element.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"element\"\n            ],\n            \"type\": \"object\"\n        },\n        \"BindInput\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"autocomplete\": {\n                    \"description\": \"A hint for form autofill. See the [HTML autocomplete attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) for additional information.\",\n                    \"type\": \"string\"\n                },\n                \"debounce\": {\n                    \"description\": \"If defined, delays event handling until the specified milliseconds have elapsed since the last event was fired.\",\n                    \"type\": \"number\"\n                },\n                \"element\": {\n                    \"$ref\": \"#/definitions/Element\",\n                    \"description\": \"An optional CSS selector string indicating the parent element to which the input element should be added. By default, all input elements are added within the parent container of the Vega view.\"\n                },\n                \"input\": {\n                    \"description\": \"The type of input element to use. The valid values are `\\\"checkbox\\\"`, `\\\"radio\\\"`, `\\\"range\\\"`, `\\\"select\\\"`, and any other legal [HTML form input type](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input).\",\n                    \"type\": \"string\"\n                },\n                \"name\": {\n                    \"description\": \"By default, the signal name is used to label input elements. This `name` property can be used instead to specify a custom label for the bound signal.\",\n                    \"type\": \"string\"\n                },\n                \"placeholder\": {\n                    \"description\": \"Text that appears in the form control when it has no value set.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"BindRadioSelect\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"debounce\": {\n                    \"description\": \"If defined, delays event handling until the specified milliseconds have elapsed since the last event was fired.\",\n                    \"type\": \"number\"\n                },\n                \"element\": {\n                    \"$ref\": \"#/definitions/Element\",\n                    \"description\": \"An optional CSS selector string indicating the parent element to which the input element should be added. By default, all input elements are added within the parent container of the Vega view.\"\n                },\n                \"input\": {\n                    \"enum\": [\n                        \"radio\",\n                        \"select\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"labels\": {\n                    \"description\": \"An array of label strings to represent the `options` values. If unspecified, the `options` value will be coerced to a string and used as the label.\",\n                    \"items\": {\n                        \"type\": \"string\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"name\": {\n                    \"description\": \"By default, the signal name is used to label input elements. This `name` property can be used instead to specify a custom label for the bound signal.\",\n                    \"type\": \"string\"\n                },\n                \"options\": {\n                    \"description\": \"An array of options to select from.\",\n                    \"items\": {},\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"input\",\n                \"options\"\n            ],\n            \"type\": \"object\"\n        },\n        \"BindRange\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"debounce\": {\n                    \"description\": \"If defined, delays event handling until the specified milliseconds have elapsed since the last event was fired.\",\n                    \"type\": \"number\"\n                },\n                \"element\": {\n                    \"$ref\": \"#/definitions/Element\",\n                    \"description\": \"An optional CSS selector string indicating the parent element to which the input element should be added. By default, all input elements are added within the parent container of the Vega view.\"\n                },\n                \"input\": {\n                    \"const\": \"range\",\n                    \"type\": \"string\"\n                },\n                \"max\": {\n                    \"description\": \"Sets the maximum slider value. Defaults to the larger of the signal value and `100`.\",\n                    \"type\": \"number\"\n                },\n                \"min\": {\n                    \"description\": \"Sets the minimum slider value. Defaults to the smaller of the signal value and `0`.\",\n                    \"type\": \"number\"\n                },\n                \"name\": {\n                    \"description\": \"By default, the signal name is used to label input elements. This `name` property can be used instead to specify a custom label for the bound signal.\",\n                    \"type\": \"string\"\n                },\n                \"step\": {\n                    \"description\": \"Sets the minimum slider increment. If undefined, the step size will be automatically determined based on the `min` and `max` values.\",\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"input\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Binding\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/BindCheckbox\"\n                },\n                {\n                    \"$ref\": \"#/definitions/BindRadioSelect\"\n                },\n                {\n                    \"$ref\": \"#/definitions/BindRange\"\n                },\n                {\n                    \"$ref\": \"#/definitions/BindInput\"\n                },\n                {\n                    \"$ref\": \"#/definitions/BindDirect\"\n                }\n            ]\n        },\n        \"BinnedTimeUnit\": {\n            \"enum\": [\n                \"binnedyear\",\n                \"binnedyearquarter\",\n                \"binnedyearquartermonth\",\n                \"binnedyearmonth\",\n                \"binnedyearmonthdate\",\n                \"binnedyearmonthdatehours\",\n                \"binnedyearmonthdatehoursminutes\",\n                \"binnedyearmonthdatehoursminutesseconds\",\n                \"binnedyearweek\",\n                \"binnedyearweekday\",\n                \"binnedyearweekdayhours\",\n                \"binnedyearweekdayhoursminutes\",\n                \"binnedyearweekdayhoursminutesseconds\",\n                \"binnedyeardayofyear\",\n                \"binnedutcyear\",\n                \"binnedutcyearquarter\",\n                \"binnedutcyearquartermonth\",\n                \"binnedutcyearmonth\",\n                \"binnedutcyearmonthdate\",\n                \"binnedutcyearmonthdatehours\",\n                \"binnedutcyearmonthdatehoursminutes\",\n                \"binnedutcyearmonthdatehoursminutesseconds\",\n                \"binnedutcyearweek\",\n                \"binnedutcyearweekday\",\n                \"binnedutcyearweekdayhours\",\n                \"binnedutcyearweekdayhoursminutes\",\n                \"binnedutcyearweekdayhoursminutesseconds\",\n                \"binnedutcyeardayofyear\"\n            ],\n            \"type\": \"string\"\n        },\n        \"Blend\": {\n            \"enum\": [\n                null,\n                \"multiply\",\n                \"screen\",\n                \"overlay\",\n                \"darken\",\n                \"lighten\",\n                \"color-dodge\",\n                \"color-burn\",\n                \"hard-light\",\n                \"soft-light\",\n                \"difference\",\n                \"exclusion\",\n                \"hue\",\n                \"saturation\",\n                \"color\",\n                \"luminosity\"\n            ],\n            \"type\": [\n                \"null\",\n                \"string\"\n            ]\n        },\n        \"BoxPlot\": {\n            \"const\": \"boxplot\",\n            \"type\": \"string\"\n        },\n        \"BoxPlotConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"box\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                },\n                \"extent\": {\n                    \"anyOf\": [\n                        {\n                            \"const\": \"min-max\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"number\"\n                        }\n                    ],\n                    \"description\": \"The extent of the whiskers. Available options include:\\n- `\\\"min-max\\\"`: min and max are the lower and upper whiskers respectively.\\n- A number representing multiple of the interquartile range. This number will be multiplied by the IQR to determine whisker boundary, which spans from the smallest data to the largest data within the range _[Q1 - k * IQR, Q3 + k * IQR]_ where _Q1_ and _Q3_ are the first and third quartiles while _IQR_ is the interquartile range (_Q3-Q1_).\\n\\n__Default value:__ `1.5`.\"\n                },\n                \"median\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                },\n                \"outliers\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                },\n                \"rule\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                },\n                \"size\": {\n                    \"description\": \"Size of the box and median tick of a box plot\",\n                    \"type\": \"number\"\n                },\n                \"ticks\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"BoxPlotDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"box\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                },\n                \"clip\": {\n                    \"description\": \"Whether a composite mark be clipped to the enclosing group’s width and height.\",\n                    \"type\": \"boolean\"\n                },\n                \"color\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default color.\\n\\n__Default value:__ <span style=\\\"color: #4682b4;\\\">&#9632;</span> `\\\"#4682b4\\\"`\\n\\n__Note:__\\n- This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\\n- The `fill` and `stroke` properties have higher precedence than `color` and will override `color`.\"\n                },\n                \"extent\": {\n                    \"anyOf\": [\n                        {\n                            \"const\": \"min-max\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"number\"\n                        }\n                    ],\n                    \"description\": \"The extent of the whiskers. Available options include:\\n- `\\\"min-max\\\"`: min and max are the lower and upper whiskers respectively.\\n- A number representing multiple of the interquartile range. This number will be multiplied by the IQR to determine whisker boundary, which spans from the smallest data to the largest data within the range _[Q1 - k * IQR, Q3 + k * IQR]_ where _Q1_ and _Q3_ are the first and third quartiles while _IQR_ is the interquartile range (_Q3-Q1_).\\n\\n__Default value:__ `1.5`.\"\n                },\n                \"invalid\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/MarkInvalidDataMode\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"Invalid data mode, which defines how the marks and corresponding scales should represent invalid values (`null` and `NaN` in continuous scales *without* defined output for invalid values).\\n\\n- `\\\"filter\\\"` — *Exclude* all invalid values from the visualization's *marks* and *scales*. For path marks (for line, area, trail), this option will create paths that connect valid points, as if the data rows with invalid values do not exist.\\n\\n- `\\\"break-paths-filter-domains\\\"` — Break path marks (for line, area, trail) at invalid values.  For non-path marks, this is equivalent to `\\\"filter\\\"`. All *scale* domains will *exclude* these filtered data points.\\n\\n- `\\\"break-paths-show-domains\\\"` — Break paths (for line, area, trail) at invalid values.  Hide invalid values for non-path marks. All *scale* domains will *include* these filtered data points (for both path and non-path marks).\\n\\n- `\\\"show\\\"` or `null` — Show all data points in the marks and scale domains. Each scale will use the output for invalid values defined in `config.scale.invalid` or, if unspecified, by default invalid values will produce the same visual values as zero (if the scale includes zero) or the minimum value (if the scale does not include zero).\\n\\n- `\\\"break-paths-show-path-domains\\\"` (default) — This is equivalent to `\\\"break-paths-show-domains\\\"` for path-based marks (line/area/trail) and `\\\"filter\\\"` for non-path marks.\\n\\n__Note__: If any channel's scale has an output for invalid values defined in `config.scale.invalid`, all values for the scales will be considered \\\"valid\\\" since they can produce a reasonable output for the scales. Thus, fields for such channels will not be filtered and will not cause path breaks.\"\n                },\n                \"median\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                },\n                \"opacity\": {\n                    \"description\": \"The opacity (value between [0,1]) of the mark.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"orient\": {\n                    \"$ref\": \"#/definitions/Orientation\",\n                    \"description\": \"Orientation of the box plot. This is normally automatically determined based on types of fields on x and y channels. However, an explicit `orient` be specified when the orientation is ambiguous.\\n\\n__Default value:__ `\\\"vertical\\\"`.\"\n                },\n                \"outliers\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                },\n                \"rule\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                },\n                \"size\": {\n                    \"description\": \"Size of the box and median tick of a box plot\",\n                    \"type\": \"number\"\n                },\n                \"ticks\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/BoxPlot\",\n                    \"description\": \"The mark type. This could a primitive mark type (one of `\\\"bar\\\"`, `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"tick\\\"`, `\\\"line\\\"`, `\\\"area\\\"`, `\\\"point\\\"`, `\\\"geoshape\\\"`, `\\\"rule\\\"`, and `\\\"text\\\"`) or a composite mark type (`\\\"boxplot\\\"`, `\\\"errorband\\\"`, `\\\"errorbar\\\"`).\"\n                }\n            },\n            \"required\": [\n                \"type\"\n            ],\n            \"type\": \"object\"\n        },\n        \"BrushConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"cursor\": {\n                    \"$ref\": \"#/definitions/Cursor\",\n                    \"description\": \"The mouse cursor used over the interval mark. Any valid [CSS cursor type](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used.\"\n                },\n                \"fill\": {\n                    \"$ref\": \"#/definitions/Color\",\n                    \"description\": \"The fill color of the interval mark.\\n\\n__Default value:__ `\\\"#333333\\\"`\"\n                },\n                \"fillOpacity\": {\n                    \"description\": \"The fill opacity of the interval mark (a value between `0` and `1`).\\n\\n__Default value:__ `0.125`\",\n                    \"type\": \"number\"\n                },\n                \"stroke\": {\n                    \"$ref\": \"#/definitions/Color\",\n                    \"description\": \"The stroke color of the interval mark.\\n\\n__Default value:__ `\\\"#ffffff\\\"`\"\n                },\n                \"strokeDash\": {\n                    \"description\": \"An array of alternating stroke and space lengths, for creating dashed or dotted lines.\",\n                    \"items\": {\n                        \"type\": \"number\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"strokeDashOffset\": {\n                    \"description\": \"The offset (in pixels) with which to begin drawing the stroke dash array.\",\n                    \"type\": \"number\"\n                },\n                \"strokeOpacity\": {\n                    \"description\": \"The stroke opacity of the interval mark (a value between `0` and `1`).\",\n                    \"type\": \"number\"\n                },\n                \"strokeWidth\": {\n                    \"description\": \"The stroke width of the interval mark.\",\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"CalculateTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"as\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The field for storing the computed formula value.\"\n                },\n                \"calculate\": {\n                    \"description\": \"A [expression](https://vega.github.io/vega-lite/docs/types.html#expression) string. Use the variable `datum` to refer to the current data object.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"calculate\",\n                \"as\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Categorical\": {\n            \"enum\": [\n                \"accent\",\n                \"category10\",\n                \"category20\",\n                \"category20b\",\n                \"category20c\",\n                \"dark2\",\n                \"paired\",\n                \"pastel1\",\n                \"pastel2\",\n                \"set1\",\n                \"set2\",\n                \"set3\",\n                \"tableau10\",\n                \"tableau20\",\n                \"observable10\"\n            ],\n            \"type\": \"string\"\n        },\n        \"Color\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ColorName\"\n                },\n                {\n                    \"$ref\": \"#/definitions/HexColor\"\n                },\n                {\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ColorDef\": {\n            \"$ref\": \"#/definitions/MarkPropDef<(Gradient|string|null)>\"\n        },\n        \"ColorName\": {\n            \"enum\": [\n                \"black\",\n                \"silver\",\n                \"gray\",\n                \"white\",\n                \"maroon\",\n                \"red\",\n                \"purple\",\n                \"fuchsia\",\n                \"green\",\n                \"lime\",\n                \"olive\",\n                \"yellow\",\n                \"navy\",\n                \"blue\",\n                \"teal\",\n                \"aqua\",\n                \"orange\",\n                \"aliceblue\",\n                \"antiquewhite\",\n                \"aquamarine\",\n                \"azure\",\n                \"beige\",\n                \"bisque\",\n                \"blanchedalmond\",\n                \"blueviolet\",\n                \"brown\",\n                \"burlywood\",\n                \"cadetblue\",\n                \"chartreuse\",\n                \"chocolate\",\n                \"coral\",\n                \"cornflowerblue\",\n                \"cornsilk\",\n                \"crimson\",\n                \"cyan\",\n                \"darkblue\",\n                \"darkcyan\",\n                \"darkgoldenrod\",\n                \"darkgray\",\n                \"darkgreen\",\n                \"darkgrey\",\n                \"darkkhaki\",\n                \"darkmagenta\",\n                \"darkolivegreen\",\n                \"darkorange\",\n                \"darkorchid\",\n                \"darkred\",\n                \"darksalmon\",\n                \"darkseagreen\",\n                \"darkslateblue\",\n                \"darkslategray\",\n                \"darkslategrey\",\n                \"darkturquoise\",\n                \"darkviolet\",\n                \"deeppink\",\n                \"deepskyblue\",\n                \"dimgray\",\n                \"dimgrey\",\n                \"dodgerblue\",\n                \"firebrick\",\n                \"floralwhite\",\n                \"forestgreen\",\n                \"gainsboro\",\n                \"ghostwhite\",\n                \"gold\",\n                \"goldenrod\",\n                \"greenyellow\",\n                \"grey\",\n                \"honeydew\",\n                \"hotpink\",\n                \"indianred\",\n                \"indigo\",\n                \"ivory\",\n                \"khaki\",\n                \"lavender\",\n                \"lavenderblush\",\n                \"lawngreen\",\n                \"lemonchiffon\",\n                \"lightblue\",\n                \"lightcoral\",\n                \"lightcyan\",\n                \"lightgoldenrodyellow\",\n                \"lightgray\",\n                \"lightgreen\",\n                \"lightgrey\",\n                \"lightpink\",\n                \"lightsalmon\",\n                \"lightseagreen\",\n                \"lightskyblue\",\n                \"lightslategray\",\n                \"lightslategrey\",\n                \"lightsteelblue\",\n                \"lightyellow\",\n                \"limegreen\",\n                \"linen\",\n                \"magenta\",\n                \"mediumaquamarine\",\n                \"mediumblue\",\n                \"mediumorchid\",\n                \"mediumpurple\",\n                \"mediumseagreen\",\n                \"mediumslateblue\",\n                \"mediumspringgreen\",\n                \"mediumturquoise\",\n                \"mediumvioletred\",\n                \"midnightblue\",\n                \"mintcream\",\n                \"mistyrose\",\n                \"moccasin\",\n                \"navajowhite\",\n                \"oldlace\",\n                \"olivedrab\",\n                \"orangered\",\n                \"orchid\",\n                \"palegoldenrod\",\n                \"palegreen\",\n                \"paleturquoise\",\n                \"palevioletred\",\n                \"papayawhip\",\n                \"peachpuff\",\n                \"peru\",\n                \"pink\",\n                \"plum\",\n                \"powderblue\",\n                \"rosybrown\",\n                \"royalblue\",\n                \"saddlebrown\",\n                \"salmon\",\n                \"sandybrown\",\n                \"seagreen\",\n                \"seashell\",\n                \"sienna\",\n                \"skyblue\",\n                \"slateblue\",\n                \"slategray\",\n                \"slategrey\",\n                \"snow\",\n                \"springgreen\",\n                \"steelblue\",\n                \"tan\",\n                \"thistle\",\n                \"tomato\",\n                \"turquoise\",\n                \"violet\",\n                \"wheat\",\n                \"whitesmoke\",\n                \"yellowgreen\",\n                \"rebeccapurple\"\n            ],\n            \"type\": \"string\"\n        },\n        \"ColorScheme\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/Categorical\"\n                },\n                {\n                    \"$ref\": \"#/definitions/SequentialSingleHue\"\n                },\n                {\n                    \"$ref\": \"#/definitions/SequentialMultiHue\"\n                },\n                {\n                    \"$ref\": \"#/definitions/Diverging\"\n                },\n                {\n                    \"$ref\": \"#/definitions/Cyclical\"\n                }\n            ]\n        },\n        \"Encoding\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"angle\": {\n                    \"$ref\": \"#/definitions/NumericMarkPropDef\",\n                    \"description\": \"Rotation angle of point and text marks.\"\n                },\n                \"color\": {\n                    \"$ref\": \"#/definitions/ColorDef\",\n                    \"description\": \"Color of the marks – either fill or stroke color based on  the `filled` property of mark definition. By default, `color` represents fill color for `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"tick\\\"`, `\\\"text\\\"`, `\\\"trail\\\"`, `\\\"circle\\\"`, and `\\\"square\\\"` / stroke color for `\\\"line\\\"` and `\\\"point\\\"`.\\n\\n__Default value:__ If undefined, the default color depends on [mark config](https://vega.github.io/vega-lite/docs/config.html#mark-config)'s `color` property.\\n\\n_Note:_ 1) For fine-grained control over both fill and stroke colors of the marks, please use the `fill` and `stroke` channels. The `fill` or `stroke` encodings have higher precedence than `color`, thus may override the `color` encoding if conflicting encodings are specified. 2) See the scale documentation for more information about customizing [color scheme](https://vega.github.io/vega-lite/docs/scale.html#scheme).\"\n                },\n                \"description\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StringFieldDefWithCondition\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/StringValueDefWithCondition\"\n                        }\n                    ],\n                    \"description\": \"A text description of this mark for ARIA accessibility (SVG output only). For SVG output the `\\\"aria-label\\\"` attribute will be set to this description.\"\n                },\n                \"detail\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FieldDefWithoutScale\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/FieldDefWithoutScale\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"Additional levels of detail for grouping data in aggregate views and in line, trail, and area marks without mapping data to a specific visual channel.\"\n                },\n                \"fill\": {\n                    \"$ref\": \"#/definitions/ColorDef\",\n                    \"description\": \"Fill color of the marks. __Default value:__ If undefined, the default color depends on [mark config](https://vega.github.io/vega-lite/docs/config.html#mark-config)'s `color` property.\\n\\n_Note:_ The `fill` encoding has higher precedence than `color`, thus may override the `color` encoding if conflicting encodings are specified.\"\n                },\n                \"fillOpacity\": {\n                    \"$ref\": \"#/definitions/NumericMarkPropDef\",\n                    \"description\": \"Fill opacity of the marks.\\n\\n__Default value:__ If undefined, the default opacity depends on [mark config](https://vega.github.io/vega-lite/docs/config.html#mark-config)'s `fillOpacity` property.\"\n                },\n                \"href\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StringFieldDefWithCondition\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/StringValueDefWithCondition\"\n                        }\n                    ],\n                    \"description\": \"A URL to load upon mouse click.\"\n                },\n                \"key\": {\n                    \"$ref\": \"#/definitions/FieldDefWithoutScale\",\n                    \"description\": \"A data field to use as a unique key for data binding. When a visualization’s data is updated, the key value will be used to match data elements to existing mark instances. Use a key channel to enable object constancy for transitions over dynamic data.\"\n                },\n                \"latitude\": {\n                    \"$ref\": \"#/definitions/LatLongDef\",\n                    \"description\": \"Latitude position of geographically projected marks.\"\n                },\n                \"latitude2\": {\n                    \"$ref\": \"#/definitions/Position2Def\",\n                    \"description\": \"Latitude-2 position for geographically projected ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\"\n                },\n                \"longitude\": {\n                    \"$ref\": \"#/definitions/LatLongDef\",\n                    \"description\": \"Longitude position of geographically projected marks.\"\n                },\n                \"longitude2\": {\n                    \"$ref\": \"#/definitions/Position2Def\",\n                    \"description\": \"Longitude-2 position for geographically projected ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\"\n                },\n                \"opacity\": {\n                    \"$ref\": \"#/definitions/NumericMarkPropDef\",\n                    \"description\": \"Opacity of the marks.\\n\\n__Default value:__ If undefined, the default opacity depends on [mark config](https://vega.github.io/vega-lite/docs/config.html#mark-config)'s `opacity` property.\"\n                },\n                \"order\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/OrderFieldDef\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/OrderFieldDef\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/OrderValueDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/OrderOnlyDef\"\n                        }\n                    ],\n                    \"description\": \"Order of the marks.\\n- For stacked marks, this `order` channel encodes [stack order](https://vega.github.io/vega-lite/docs/stack.html#order).\\n- For line and trail marks, this `order` channel encodes order of data points in the lines. This can be useful for creating [a connected scatterplot](https://vega.github.io/vega-lite/examples/connected_scatterplot.html). Setting `order` to `{\\\"value\\\": null}` makes the line marks use the original order in the data sources.\\n- Otherwise, this `order` channel encodes layer order of the marks.\\n\\n__Note__: In aggregate plots, `order` field should be `aggregate`d to avoid creating additional aggregation grouping.\"\n                },\n                \"radius\": {\n                    \"$ref\": \"#/definitions/PolarDef\",\n                    \"description\": \"The outer radius in pixels of arc marks.\"\n                },\n                \"radius2\": {\n                    \"$ref\": \"#/definitions/Position2Def\",\n                    \"description\": \"The inner radius in pixels of arc marks.\"\n                },\n                \"shape\": {\n                    \"$ref\": \"#/definitions/ShapeDef\",\n                    \"description\": \"Shape of the mark.\\n\\n1. For `point` marks the supported values include:   - plotting shapes: `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"cross\\\"`, `\\\"diamond\\\"`, `\\\"triangle-up\\\"`, `\\\"triangle-down\\\"`, `\\\"triangle-right\\\"`, or `\\\"triangle-left\\\"`.   - the line symbol `\\\"stroke\\\"`   - centered directional shapes `\\\"arrow\\\"`, `\\\"wedge\\\"`, or `\\\"triangle\\\"`   - a custom [SVG path string](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths) (For correct sizing, custom shape paths should be defined within a square bounding box with coordinates ranging from -1 to 1 along both the x and y dimensions.)\\n\\n2. For `geoshape` marks it should be a field definition of the geojson data\\n\\n__Default value:__ If undefined, the default shape depends on [mark config](https://vega.github.io/vega-lite/docs/config.html#point-config)'s `shape` property. (`\\\"circle\\\"` if unset.)\"\n                },\n                \"size\": {\n                    \"$ref\": \"#/definitions/NumericMarkPropDef\",\n                    \"description\": \"Size of the mark.\\n- For `\\\"point\\\"`, `\\\"square\\\"` and `\\\"circle\\\"`, – the symbol size, or pixel area of the mark.\\n- For `\\\"bar\\\"` and `\\\"tick\\\"` – the bar and tick's size.\\n- For `\\\"text\\\"` – the text's font size.\\n- Size is unsupported for `\\\"line\\\"`, `\\\"area\\\"`, and `\\\"rect\\\"`. (Use `\\\"trail\\\"` instead of line with varying size)\"\n                },\n                \"stroke\": {\n                    \"$ref\": \"#/definitions/ColorDef\",\n                    \"description\": \"Stroke color of the marks. __Default value:__ If undefined, the default color depends on [mark config](https://vega.github.io/vega-lite/docs/config.html#mark-config)'s `color` property.\\n\\n_Note:_ The `stroke` encoding has higher precedence than `color`, thus may override the `color` encoding if conflicting encodings are specified.\"\n                },\n                \"strokeDash\": {\n                    \"$ref\": \"#/definitions/NumericArrayMarkPropDef\",\n                    \"description\": \"Stroke dash of the marks.\\n\\n__Default value:__ `[1,0]` (No dash).\"\n                },\n                \"strokeOpacity\": {\n                    \"$ref\": \"#/definitions/NumericMarkPropDef\",\n                    \"description\": \"Stroke opacity of the marks.\\n\\n__Default value:__ If undefined, the default opacity depends on [mark config](https://vega.github.io/vega-lite/docs/config.html#mark-config)'s `strokeOpacity` property.\"\n                },\n                \"strokeWidth\": {\n                    \"$ref\": \"#/definitions/NumericMarkPropDef\",\n                    \"description\": \"Stroke width of the marks.\\n\\n__Default value:__ If undefined, the default stroke width depends on [mark config](https://vega.github.io/vega-lite/docs/config.html#mark-config)'s `strokeWidth` property.\"\n                },\n                \"text\": {\n                    \"$ref\": \"#/definitions/TextDef\",\n                    \"description\": \"Text of the `text` mark.\"\n                },\n                \"theta\": {\n                    \"$ref\": \"#/definitions/PolarDef\",\n                    \"description\": \"- For arc marks, the arc length in radians if theta2 is not specified, otherwise the start arc angle. (A value of 0 indicates up or “north”, increasing values proceed clockwise.)\\n\\n- For text marks, polar coordinate angle in radians.\"\n                },\n                \"theta2\": {\n                    \"$ref\": \"#/definitions/Position2Def\",\n                    \"description\": \"The end angle of arc marks in radians. A value of 0 indicates up or “north”, increasing values proceed clockwise.\"\n                },\n                \"time\": {\n                    \"$ref\": \"#/definitions/TimeDef\"\n                },\n                \"tooltip\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StringFieldDefWithCondition\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/StringValueDefWithCondition\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/StringFieldDef\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"The tooltip text to show upon mouse hover. Specifying `tooltip` encoding overrides [the `tooltip` property in the mark definition](https://vega.github.io/vega-lite/docs/mark.html#mark-def).\\n\\nSee the [`tooltip`](https://vega.github.io/vega-lite/docs/tooltip.html) documentation for a detailed discussion about tooltip in Vega-Lite.\"\n                },\n                \"url\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StringFieldDefWithCondition\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/StringValueDefWithCondition\"\n                        }\n                    ],\n                    \"description\": \"The URL of an image mark.\"\n                },\n                \"x\": {\n                    \"$ref\": \"#/definitions/PositionDef\",\n                    \"description\": \"X coordinates of the marks, or width of horizontal `\\\"bar\\\"` and `\\\"area\\\"` without specified `x2` or `width`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"x2\": {\n                    \"$ref\": \"#/definitions/Position2Def\",\n                    \"description\": \"X2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"xError\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SecondaryFieldDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ValueDef<number>\"\n                        }\n                    ],\n                    \"description\": \"Error value of x coordinates for error specified `\\\"errorbar\\\"` and `\\\"errorband\\\"`.\"\n                },\n                \"xError2\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SecondaryFieldDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ValueDef<number>\"\n                        }\n                    ],\n                    \"description\": \"Secondary error value of x coordinates for error specified `\\\"errorbar\\\"` and `\\\"errorband\\\"`.\"\n                },\n                \"xOffset\": {\n                    \"$ref\": \"#/definitions/OffsetDef\",\n                    \"description\": \"Offset of x-position of the marks\"\n                },\n                \"y\": {\n                    \"$ref\": \"#/definitions/PositionDef\",\n                    \"description\": \"Y coordinates of the marks, or height of vertical `\\\"bar\\\"` and `\\\"area\\\"` without specified `y2` or `height`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                },\n                \"y2\": {\n                    \"$ref\": \"#/definitions/Position2Def\",\n                    \"description\": \"Y2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                },\n                \"yError\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SecondaryFieldDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ValueDef<number>\"\n                        }\n                    ],\n                    \"description\": \"Error value of y coordinates for error specified `\\\"errorbar\\\"` and `\\\"errorband\\\"`.\"\n                },\n                \"yError2\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SecondaryFieldDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ValueDef<number>\"\n                        }\n                    ],\n                    \"description\": \"Secondary error value of y coordinates for error specified `\\\"errorbar\\\"` and `\\\"errorband\\\"`.\"\n                },\n                \"yOffset\": {\n                    \"$ref\": \"#/definitions/OffsetDef\",\n                    \"description\": \"Offset of y-position of the marks\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"CompositeMark\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/BoxPlot\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ErrorBar\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ErrorBand\"\n                }\n            ]\n        },\n        \"CompositeMarkDef\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/BoxPlotDef\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ErrorBarDef\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ErrorBandDef\"\n                }\n            ]\n        },\n        \"CompositionConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"columns\": {\n                    \"description\": \"The number of columns to include in the view composition layout.\\n\\n__Default value__: `undefined` -- An infinite number of columns (a single row) will be assumed. This is equivalent to `hconcat` (for `concat`) and to using the `column` channel (for `facet` and `repeat`).\\n\\n__Note__:\\n\\n1) This property is only for:\\n- the general (wrappable) `concat` operator (not `hconcat`/`vconcat`)\\n- the `facet` and `repeat` operator with one field/repetition definition (without row/column nesting)\\n\\n2) Setting the `columns` to `1` is equivalent to `vconcat` (for `concat`) and to using the `row` channel (for `facet` and `repeat`).\",\n                    \"type\": \"number\"\n                },\n                \"spacing\": {\n                    \"description\": \"The default spacing in pixels between composed sub-views.\\n\\n__Default value__: `20`\",\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ConditionalMarkPropFieldOrDatumDef\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ConditionalPredicate<MarkPropFieldOrDatumDef>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ConditionalParameter<MarkPropFieldOrDatumDef>\"\n                }\n            ]\n        },\n        \"ConditionalMarkPropFieldOrDatumDef<TypeForShape>\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ConditionalPredicate<MarkPropFieldOrDatumDef<TypeForShape>>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ConditionalParameter<MarkPropFieldOrDatumDef<TypeForShape>>\"\n                }\n            ]\n        },\n        \"ConditionalStringFieldDef\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ConditionalPredicate<StringFieldDef>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ConditionalParameter<StringFieldDef>\"\n                }\n            ]\n        },\n        \"ConditionalValueDef<(Gradient|string|null|ExprRef)>\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ConditionalPredicate<ValueDef<(Gradient|string|null|ExprRef)>>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ConditionalParameter<ValueDef<(Gradient|string|null|ExprRef)>>\"\n                }\n            ]\n        },\n        \"ConditionalValueDef<(Text|ExprRef)>\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ConditionalPredicate<ValueDef<(Text|ExprRef)>>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ConditionalParameter<ValueDef<(Text|ExprRef)>>\"\n                }\n            ]\n        },\n        \"ConditionalValueDef<(number[]|ExprRef)>\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ConditionalPredicate<ValueDef<(number[]|ExprRef)>>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ConditionalParameter<ValueDef<(number[]|ExprRef)>>\"\n                }\n            ]\n        },\n        \"ConditionalValueDef<(number|ExprRef)>\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ConditionalPredicate<ValueDef<(number|ExprRef)>>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ConditionalParameter<ValueDef<(number|ExprRef)>>\"\n                }\n            ]\n        },\n        \"ConditionalValueDef<(string|ExprRef)>\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ConditionalPredicate<ValueDef<(string|ExprRef)>>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ConditionalParameter<ValueDef<(string|ExprRef)>>\"\n                }\n            ]\n        },\n        \"ConditionalValueDef<(string|null|ExprRef)>\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ConditionalPredicate<ValueDef<(string|null|ExprRef)>>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ConditionalParameter<ValueDef<(string|null|ExprRef)>>\"\n                }\n            ]\n        },\n        \"ConditionalValueDef<number>\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ConditionalPredicate<ValueDef<number>>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ConditionalParameter<ValueDef<number>>\"\n                }\n            ]\n        },\n        \"ConditionalAxisColor\": {\n            \"$ref\": \"#/definitions/ConditionalAxisProperty<(Color|null)>\"\n        },\n        \"ConditionalAxisLabelAlign\": {\n            \"$ref\": \"#/definitions/ConditionalAxisProperty<(Align|null)>\"\n        },\n        \"ConditionalAxisLabelBaseline\": {\n            \"$ref\": \"#/definitions/ConditionalAxisProperty<(TextBaseline|null)>\"\n        },\n        \"ConditionalAxisLabelFontStyle\": {\n            \"$ref\": \"#/definitions/ConditionalAxisProperty<(FontStyle|null)>\"\n        },\n        \"ConditionalAxisLabelFontWeight\": {\n            \"$ref\": \"#/definitions/ConditionalAxisProperty<(FontWeight|null)>\"\n        },\n        \"ConditionalAxisNumber\": {\n            \"$ref\": \"#/definitions/ConditionalAxisProperty<(number|null)>\"\n        },\n        \"ConditionalAxisNumberArray\": {\n            \"$ref\": \"#/definitions/ConditionalAxisProperty<(number[]|null)>\"\n        },\n        \"ConditionalAxisProperty<(Align|null)>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(Align|null)>|ExprRef)>\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(Align|null)>|ExprRef)>\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Align\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"required\": [\n                        \"condition\",\n                        \"value\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(Align|null)>|ExprRef)>\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(Align|null)>|ExprRef)>\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"expr\": {\n                            \"description\": \"Vega expression (which can refer to Vega-Lite parameters).\",\n                            \"type\": \"string\"\n                        }\n                    },\n                    \"required\": [\n                        \"condition\",\n                        \"expr\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalAxisProperty<(Color|null)>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(Color|null)>|ExprRef)>\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(Color|null)>|ExprRef)>\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"required\": [\n                        \"condition\",\n                        \"value\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(Color|null)>|ExprRef)>\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(Color|null)>|ExprRef)>\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"expr\": {\n                            \"description\": \"Vega expression (which can refer to Vega-Lite parameters).\",\n                            \"type\": \"string\"\n                        }\n                    },\n                    \"required\": [\n                        \"condition\",\n                        \"expr\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalAxisProperty<(FontStyle|null)>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(FontStyle|null)>|ExprRef)>\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(FontStyle|null)>|ExprRef)>\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/FontStyle\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"required\": [\n                        \"condition\",\n                        \"value\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(FontStyle|null)>|ExprRef)>\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(FontStyle|null)>|ExprRef)>\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"expr\": {\n                            \"description\": \"Vega expression (which can refer to Vega-Lite parameters).\",\n                            \"type\": \"string\"\n                        }\n                    },\n                    \"required\": [\n                        \"condition\",\n                        \"expr\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalAxisProperty<(FontWeight|null)>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(FontWeight|null)>|ExprRef)>\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(FontWeight|null)>|ExprRef)>\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/FontWeight\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"required\": [\n                        \"condition\",\n                        \"value\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(FontWeight|null)>|ExprRef)>\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(FontWeight|null)>|ExprRef)>\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"expr\": {\n                            \"description\": \"Vega expression (which can refer to Vega-Lite parameters).\",\n                            \"type\": \"string\"\n                        }\n                    },\n                    \"required\": [\n                        \"condition\",\n                        \"expr\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalAxisProperty<(TextBaseline|null)>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(TextBaseline|null)>|ExprRef)>\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(TextBaseline|null)>|ExprRef)>\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TextBaseline\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"required\": [\n                        \"condition\",\n                        \"value\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(TextBaseline|null)>|ExprRef)>\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(TextBaseline|null)>|ExprRef)>\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"expr\": {\n                            \"description\": \"Vega expression (which can refer to Vega-Lite parameters).\",\n                            \"type\": \"string\"\n                        }\n                    },\n                    \"required\": [\n                        \"condition\",\n                        \"expr\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalAxisProperty<(number[]|null)>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(number[]|null)>|ExprRef)>\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(number[]|null)>|ExprRef)>\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"items\": {\n                                        \"type\": \"number\"\n                                    },\n                                    \"type\": \"array\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"required\": [\n                        \"condition\",\n                        \"value\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(number[]|null)>|ExprRef)>\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(number[]|null)>|ExprRef)>\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"expr\": {\n                            \"description\": \"Vega expression (which can refer to Vega-Lite parameters).\",\n                            \"type\": \"string\"\n                        }\n                    },\n                    \"required\": [\n                        \"condition\",\n                        \"expr\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalAxisProperty<(number|null)>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(number|null)>|ExprRef)>\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(number|null)>|ExprRef)>\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"value\": {\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\",\n                            \"type\": [\n                                \"number\",\n                                \"null\"\n                            ]\n                        }\n                    },\n                    \"required\": [\n                        \"condition\",\n                        \"value\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(number|null)>|ExprRef)>\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(number|null)>|ExprRef)>\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"expr\": {\n                            \"description\": \"Vega expression (which can refer to Vega-Lite parameters).\",\n                            \"type\": \"string\"\n                        }\n                    },\n                    \"required\": [\n                        \"condition\",\n                        \"expr\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalAxisProperty<(string|null)>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(string|null)>|ExprRef)>\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(string|null)>|ExprRef)>\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"value\": {\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\",\n                            \"type\": [\n                                \"string\",\n                                \"null\"\n                            ]\n                        }\n                    },\n                    \"required\": [\n                        \"condition\",\n                        \"value\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(string|null)>|ExprRef)>\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/ConditionalPredicate<(ValueDef<(string|null)>|ExprRef)>\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"expr\": {\n                            \"description\": \"Vega expression (which can refer to Vega-Lite parameters).\",\n                            \"type\": \"string\"\n                        }\n                    },\n                    \"required\": [\n                        \"condition\",\n                        \"expr\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalAxisString\": {\n            \"$ref\": \"#/definitions/ConditionalAxisProperty<(string|null)>\"\n        },\n        \"ConditionalParameter<MarkPropFieldOrDatumDef>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"empty\": {\n                            \"description\": \"For selection parameters, the predicate of empty selections returns true by default. Override this behavior, by setting this property `empty: false`.\",\n                            \"type\": \"boolean\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"param\": {\n                            \"$ref\": \"#/definitions/ParameterName\",\n                            \"description\": \"Filter using a parameter name.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/StandardType\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        }\n                    },\n                    \"required\": [\n                        \"param\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"empty\": {\n                            \"description\": \"For selection parameters, the predicate of empty selections returns true by default. Override this behavior, by setting this property `empty: false`.\",\n                            \"type\": \"boolean\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"param\": {\n                            \"$ref\": \"#/definitions/ParameterName\",\n                            \"description\": \"Filter using a parameter name.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/Type\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        }\n                    },\n                    \"required\": [\n                        \"param\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalParameter<MarkPropFieldOrDatumDef<TypeForShape>>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"empty\": {\n                            \"description\": \"For selection parameters, the predicate of empty selections returns true by default. Override this behavior, by setting this property `empty: false`.\",\n                            \"type\": \"boolean\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"param\": {\n                            \"$ref\": \"#/definitions/ParameterName\",\n                            \"description\": \"Filter using a parameter name.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/TypeForShape\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        }\n                    },\n                    \"required\": [\n                        \"param\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"empty\": {\n                            \"description\": \"For selection parameters, the predicate of empty selections returns true by default. Override this behavior, by setting this property `empty: false`.\",\n                            \"type\": \"boolean\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"param\": {\n                            \"$ref\": \"#/definitions/ParameterName\",\n                            \"description\": \"Filter using a parameter name.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/Type\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        }\n                    },\n                    \"required\": [\n                        \"param\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalParameter<StringFieldDef>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"const\": \"binned\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"empty\": {\n                    \"description\": \"For selection parameters, the predicate of empty selections returns true by default. Override this behavior, by setting this property `empty: false`.\",\n                    \"type\": \"boolean\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"format\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Dict\"\n                        }\n                    ],\n                    \"description\": \"When used with the default `\\\"number\\\"` and `\\\"time\\\"` format type, the text formatting pattern for labels of guides (axes, legends, headers) and text marks.\\n\\n- If the format type is `\\\"number\\\"` (e.g., for quantitative fields), this is D3's [number format pattern](https://github.com/d3/d3-format#locale_format).\\n- If the format type is `\\\"time\\\"` (e.g., for temporal fields), this is D3's [time format pattern](https://github.com/d3/d3-time-format#locale_format).\\n\\nSee the [format documentation](https://vega.github.io/vega-lite/docs/format.html) for more examples.\\n\\nWhen used with a [custom `formatType`](https://vega.github.io/vega-lite/docs/config.html#custom-format-type), this value will be passed as `format` alongside `datum.value` to the registered function.\\n\\n__Default value:__  Derived from [numberFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for number format and from [timeFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for time format.\"\n                },\n                \"formatType\": {\n                    \"description\": \"The format type for labels. One of `\\\"number\\\"`, `\\\"time\\\"`, or a [registered custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type).\\n\\n__Default value:__\\n- `\\\"time\\\"` for temporal fields and ordinal and nominal fields with `timeUnit`.\\n- `\\\"number\\\"` for quantitative fields as well as ordinal and nominal fields without `timeUnit`.\",\n                    \"type\": \"string\"\n                },\n                \"param\": {\n                    \"$ref\": \"#/definitions/ParameterName\",\n                    \"description\": \"Filter using a parameter name.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/StandardType\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"required\": [\n                \"param\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ConditionalParameter<ValueDef<(Gradient|string|null|ExprRef)>>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"empty\": {\n                    \"description\": \"For selection parameters, the predicate of empty selections returns true by default. Override this behavior, by setting this property `empty: false`.\",\n                    \"type\": \"boolean\"\n                },\n                \"param\": {\n                    \"$ref\": \"#/definitions/ParameterName\",\n                    \"description\": \"Filter using a parameter name.\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"required\": [\n                \"param\",\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ConditionalParameter<ValueDef<(Text|ExprRef)>>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"empty\": {\n                    \"description\": \"For selection parameters, the predicate of empty selections returns true by default. Override this behavior, by setting this property `empty: false`.\",\n                    \"type\": \"boolean\"\n                },\n                \"param\": {\n                    \"$ref\": \"#/definitions/ParameterName\",\n                    \"description\": \"Filter using a parameter name.\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"required\": [\n                \"param\",\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ConditionalParameter<ValueDef<(number[]|ExprRef)>>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"empty\": {\n                    \"description\": \"For selection parameters, the predicate of empty selections returns true by default. Override this behavior, by setting this property `empty: false`.\",\n                    \"type\": \"boolean\"\n                },\n                \"param\": {\n                    \"$ref\": \"#/definitions/ParameterName\",\n                    \"description\": \"Filter using a parameter name.\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"required\": [\n                \"param\",\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ConditionalParameter<ValueDef<(number|ExprRef)>>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"empty\": {\n                    \"description\": \"For selection parameters, the predicate of empty selections returns true by default. Override this behavior, by setting this property `empty: false`.\",\n                    \"type\": \"boolean\"\n                },\n                \"param\": {\n                    \"$ref\": \"#/definitions/ParameterName\",\n                    \"description\": \"Filter using a parameter name.\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"required\": [\n                \"param\",\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ConditionalParameter<ValueDef<(string|ExprRef)>>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"empty\": {\n                    \"description\": \"For selection parameters, the predicate of empty selections returns true by default. Override this behavior, by setting this property `empty: false`.\",\n                    \"type\": \"boolean\"\n                },\n                \"param\": {\n                    \"$ref\": \"#/definitions/ParameterName\",\n                    \"description\": \"Filter using a parameter name.\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"required\": [\n                \"param\",\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ConditionalParameter<ValueDef<(string|null|ExprRef)>>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"empty\": {\n                    \"description\": \"For selection parameters, the predicate of empty selections returns true by default. Override this behavior, by setting this property `empty: false`.\",\n                    \"type\": \"boolean\"\n                },\n                \"param\": {\n                    \"$ref\": \"#/definitions/ParameterName\",\n                    \"description\": \"Filter using a parameter name.\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"required\": [\n                \"param\",\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ConditionalParameter<ValueDef<number>>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"empty\": {\n                    \"description\": \"For selection parameters, the predicate of empty selections returns true by default. Override this behavior, by setting this property `empty: false`.\",\n                    \"type\": \"boolean\"\n                },\n                \"param\": {\n                    \"$ref\": \"#/definitions/ParameterName\",\n                    \"description\": \"Filter using a parameter name.\"\n                },\n                \"value\": {\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\",\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"param\",\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ConditionalPredicate<(ValueDef<(Align|null)>|ExprRef)>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Align\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"required\": [\n                        \"test\",\n                        \"value\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"expr\": {\n                            \"description\": \"Vega expression (which can refer to Vega-Lite parameters).\",\n                            \"type\": \"string\"\n                        },\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        }\n                    },\n                    \"required\": [\n                        \"expr\",\n                        \"test\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalPredicate<(ValueDef<(Color|null)>|ExprRef)>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"required\": [\n                        \"test\",\n                        \"value\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"expr\": {\n                            \"description\": \"Vega expression (which can refer to Vega-Lite parameters).\",\n                            \"type\": \"string\"\n                        },\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        }\n                    },\n                    \"required\": [\n                        \"expr\",\n                        \"test\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalPredicate<(ValueDef<(FontStyle|null)>|ExprRef)>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/FontStyle\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"required\": [\n                        \"test\",\n                        \"value\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"expr\": {\n                            \"description\": \"Vega expression (which can refer to Vega-Lite parameters).\",\n                            \"type\": \"string\"\n                        },\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        }\n                    },\n                    \"required\": [\n                        \"expr\",\n                        \"test\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalPredicate<(ValueDef<(FontWeight|null)>|ExprRef)>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/FontWeight\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"required\": [\n                        \"test\",\n                        \"value\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"expr\": {\n                            \"description\": \"Vega expression (which can refer to Vega-Lite parameters).\",\n                            \"type\": \"string\"\n                        },\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        }\n                    },\n                    \"required\": [\n                        \"expr\",\n                        \"test\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalPredicate<(ValueDef<(TextBaseline|null)>|ExprRef)>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TextBaseline\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"required\": [\n                        \"test\",\n                        \"value\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"expr\": {\n                            \"description\": \"Vega expression (which can refer to Vega-Lite parameters).\",\n                            \"type\": \"string\"\n                        },\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        }\n                    },\n                    \"required\": [\n                        \"expr\",\n                        \"test\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalPredicate<(ValueDef<(number[]|null)>|ExprRef)>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"items\": {\n                                        \"type\": \"number\"\n                                    },\n                                    \"type\": \"array\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"required\": [\n                        \"test\",\n                        \"value\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"expr\": {\n                            \"description\": \"Vega expression (which can refer to Vega-Lite parameters).\",\n                            \"type\": \"string\"\n                        },\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        }\n                    },\n                    \"required\": [\n                        \"expr\",\n                        \"test\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalPredicate<(ValueDef<(number|null)>|ExprRef)>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        },\n                        \"value\": {\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\",\n                            \"type\": [\n                                \"number\",\n                                \"null\"\n                            ]\n                        }\n                    },\n                    \"required\": [\n                        \"test\",\n                        \"value\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"expr\": {\n                            \"description\": \"Vega expression (which can refer to Vega-Lite parameters).\",\n                            \"type\": \"string\"\n                        },\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        }\n                    },\n                    \"required\": [\n                        \"expr\",\n                        \"test\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalPredicate<(ValueDef<(string|null)>|ExprRef)>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        },\n                        \"value\": {\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\",\n                            \"type\": [\n                                \"string\",\n                                \"null\"\n                            ]\n                        }\n                    },\n                    \"required\": [\n                        \"test\",\n                        \"value\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"expr\": {\n                            \"description\": \"Vega expression (which can refer to Vega-Lite parameters).\",\n                            \"type\": \"string\"\n                        },\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        }\n                    },\n                    \"required\": [\n                        \"expr\",\n                        \"test\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalPredicate<MarkPropFieldOrDatumDef>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/StandardType\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        }\n                    },\n                    \"required\": [\n                        \"test\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/Type\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        }\n                    },\n                    \"required\": [\n                        \"test\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalPredicate<MarkPropFieldOrDatumDef<TypeForShape>>\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/TypeForShape\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        }\n                    },\n                    \"required\": [\n                        \"test\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"test\": {\n                            \"$ref\": \"#/definitions/PredicateComposition\",\n                            \"description\": \"Predicate for triggering the condition\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/Type\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        }\n                    },\n                    \"required\": [\n                        \"test\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ConditionalPredicate<StringFieldDef>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"const\": \"binned\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"format\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Dict\"\n                        }\n                    ],\n                    \"description\": \"When used with the default `\\\"number\\\"` and `\\\"time\\\"` format type, the text formatting pattern for labels of guides (axes, legends, headers) and text marks.\\n\\n- If the format type is `\\\"number\\\"` (e.g., for quantitative fields), this is D3's [number format pattern](https://github.com/d3/d3-format#locale_format).\\n- If the format type is `\\\"time\\\"` (e.g., for temporal fields), this is D3's [time format pattern](https://github.com/d3/d3-time-format#locale_format).\\n\\nSee the [format documentation](https://vega.github.io/vega-lite/docs/format.html) for more examples.\\n\\nWhen used with a [custom `formatType`](https://vega.github.io/vega-lite/docs/config.html#custom-format-type), this value will be passed as `format` alongside `datum.value` to the registered function.\\n\\n__Default value:__  Derived from [numberFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for number format and from [timeFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for time format.\"\n                },\n                \"formatType\": {\n                    \"description\": \"The format type for labels. One of `\\\"number\\\"`, `\\\"time\\\"`, or a [registered custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type).\\n\\n__Default value:__\\n- `\\\"time\\\"` for temporal fields and ordinal and nominal fields with `timeUnit`.\\n- `\\\"number\\\"` for quantitative fields as well as ordinal and nominal fields without `timeUnit`.\",\n                    \"type\": \"string\"\n                },\n                \"test\": {\n                    \"$ref\": \"#/definitions/PredicateComposition\",\n                    \"description\": \"Predicate for triggering the condition\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/StandardType\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"required\": [\n                \"test\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ConditionalPredicate<ValueDef<(Gradient|string|null|ExprRef)>>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"test\": {\n                    \"$ref\": \"#/definitions/PredicateComposition\",\n                    \"description\": \"Predicate for triggering the condition\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"required\": [\n                \"test\",\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ConditionalPredicate<ValueDef<(Text|ExprRef)>>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"test\": {\n                    \"$ref\": \"#/definitions/PredicateComposition\",\n                    \"description\": \"Predicate for triggering the condition\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"required\": [\n                \"test\",\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ConditionalPredicate<ValueDef<(number[]|ExprRef)>>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"test\": {\n                    \"$ref\": \"#/definitions/PredicateComposition\",\n                    \"description\": \"Predicate for triggering the condition\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"required\": [\n                \"test\",\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ConditionalPredicate<ValueDef<(number|ExprRef)>>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"test\": {\n                    \"$ref\": \"#/definitions/PredicateComposition\",\n                    \"description\": \"Predicate for triggering the condition\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"required\": [\n                \"test\",\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ConditionalPredicate<ValueDef<(string|ExprRef)>>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"test\": {\n                    \"$ref\": \"#/definitions/PredicateComposition\",\n                    \"description\": \"Predicate for triggering the condition\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"required\": [\n                \"test\",\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ConditionalPredicate<ValueDef<(string|null|ExprRef)>>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"test\": {\n                    \"$ref\": \"#/definitions/PredicateComposition\",\n                    \"description\": \"Predicate for triggering the condition\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"required\": [\n                \"test\",\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ConditionalPredicate<ValueDef<number>>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"test\": {\n                    \"$ref\": \"#/definitions/PredicateComposition\",\n                    \"description\": \"Predicate for triggering the condition\"\n                },\n                \"value\": {\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\",\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"test\",\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Config\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"arc\": {\n                    \"$ref\": \"#/definitions/RectConfig\",\n                    \"description\": \"Arc-specific Config\"\n                },\n                \"area\": {\n                    \"$ref\": \"#/definitions/AreaConfig\",\n                    \"description\": \"Area-Specific Config\"\n                },\n                \"aria\": {\n                    \"description\": \"A boolean flag indicating if ARIA default attributes should be included for marks and guides (SVG output only). If false, the `\\\"aria-hidden\\\"` attribute will be set for all guides, removing them from the ARIA accessibility tree and Vega-Lite will not generate default descriptions for marks.\\n\\n__Default value:__ `true`.\",\n                    \"type\": \"boolean\"\n                },\n                \"autosize\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/AutosizeType\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AutoSizeParams\"\n                        }\n                    ],\n                    \"description\": \"How the visualization size should be determined. If a string, should be one of `\\\"pad\\\"`, `\\\"fit\\\"` or `\\\"none\\\"`. Object values can additionally specify parameters for content sizing and automatic resizing.\\n\\n__Default value__: `pad`\"\n                },\n                \"axis\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Axis configuration, which determines default properties for all `x` and `y` [axes](https://vega.github.io/vega-lite/docs/axis.html). For a full list of axis configuration options, please see the [corresponding section of the axis documentation](https://vega.github.io/vega-lite/docs/axis.html#config).\"\n                },\n                \"axisBand\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for axes with \\\"band\\\" scales.\"\n                },\n                \"axisBottom\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for x-axis along the bottom edge of the chart.\"\n                },\n                \"axisDiscrete\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for axes with \\\"point\\\" or \\\"band\\\" scales.\"\n                },\n                \"axisLeft\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for y-axis along the left edge of the chart.\"\n                },\n                \"axisPoint\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for axes with \\\"point\\\" scales.\"\n                },\n                \"axisQuantitative\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for quantitative axes.\"\n                },\n                \"axisRight\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for y-axis along the right edge of the chart.\"\n                },\n                \"axisTemporal\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for temporal axes.\"\n                },\n                \"axisTop\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for x-axis along the top edge of the chart.\"\n                },\n                \"axisX\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"X-axis specific config.\"\n                },\n                \"axisXBand\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for x-axes with \\\"band\\\" scales.\"\n                },\n                \"axisXDiscrete\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for x-axes with \\\"point\\\" or \\\"band\\\" scales.\"\n                },\n                \"axisXPoint\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for x-axes with \\\"point\\\" scales.\"\n                },\n                \"axisXQuantitative\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for x-quantitative axes.\"\n                },\n                \"axisXTemporal\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for x-temporal axes.\"\n                },\n                \"axisY\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Y-axis specific config.\"\n                },\n                \"axisYBand\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for y-axes with \\\"band\\\" scales.\"\n                },\n                \"axisYDiscrete\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for y-axes with \\\"point\\\" or \\\"band\\\" scales.\"\n                },\n                \"axisYPoint\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for y-axes with \\\"point\\\" scales.\"\n                },\n                \"axisYQuantitative\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for y-quantitative axes.\"\n                },\n                \"axisYTemporal\": {\n                    \"$ref\": \"#/definitions/AxisConfig\",\n                    \"description\": \"Config for y-temporal axes.\"\n                },\n                \"background\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"CSS color property to use as the background of the entire view.\\n\\n__Default value:__ `\\\"white\\\"`\"\n                },\n                \"bar\": {\n                    \"$ref\": \"#/definitions/BarConfig\",\n                    \"description\": \"Bar-Specific Config\"\n                },\n                \"boxplot\": {\n                    \"$ref\": \"#/definitions/BoxPlotConfig\",\n                    \"description\": \"Box Config\"\n                },\n                \"circle\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Circle-Specific Config\"\n                },\n                \"concat\": {\n                    \"$ref\": \"#/definitions/CompositionConfig\",\n                    \"description\": \"Default configuration for all concatenation and repeat view composition operators (`concat`, `hconcat`, `vconcat`, and `repeat`)\"\n                },\n                \"countTitle\": {\n                    \"description\": \"Default axis and legend title for count fields.\\n\\n__Default value:__ `'Count of Records`.\",\n                    \"type\": \"string\"\n                },\n                \"customFormatTypes\": {\n                    \"description\": \"Allow the `formatType` property for text marks and guides to accept a custom formatter function [registered as a Vega expression](https://vega.github.io/vega-lite/usage/compile.html#format-type).\",\n                    \"type\": \"boolean\"\n                },\n                \"errorband\": {\n                    \"$ref\": \"#/definitions/ErrorBandConfig\",\n                    \"description\": \"ErrorBand Config\"\n                },\n                \"errorbar\": {\n                    \"$ref\": \"#/definitions/ErrorBarConfig\",\n                    \"description\": \"ErrorBar Config\"\n                },\n                \"facet\": {\n                    \"$ref\": \"#/definitions/CompositionConfig\",\n                    \"description\": \"Default configuration for the `facet` view composition operator\"\n                },\n                \"fieldTitle\": {\n                    \"description\": \"Defines how Vega-Lite generates title for fields. There are three possible styles:\\n- `\\\"verbal\\\"` (Default) - displays function in a verbal style (e.g., \\\"Sum of field\\\", \\\"Year-month of date\\\", \\\"field (binned)\\\").\\n- `\\\"function\\\"` - displays function using parentheses and capitalized texts (e.g., \\\"SUM(field)\\\", \\\"YEARMONTH(date)\\\", \\\"BIN(field)\\\").\\n- `\\\"plain\\\"` - displays only the field name without functions (e.g., \\\"field\\\", \\\"date\\\", \\\"field\\\").\",\n                    \"enum\": [\n                        \"verbal\",\n                        \"functional\",\n                        \"plain\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"font\": {\n                    \"description\": \"Default font for all text marks, titles, and labels.\",\n                    \"type\": \"string\"\n                },\n                \"geoshape\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Geoshape-Specific Config\"\n                },\n                \"header\": {\n                    \"$ref\": \"#/definitions/HeaderConfig\",\n                    \"description\": \"Header configuration, which determines default properties for all [headers](https://vega.github.io/vega-lite/docs/header.html).\\n\\nFor a full list of header configuration options, please see the [corresponding section of in the header documentation](https://vega.github.io/vega-lite/docs/header.html#config).\"\n                },\n                \"headerColumn\": {\n                    \"$ref\": \"#/definitions/HeaderConfig\",\n                    \"description\": \"Header configuration, which determines default properties for column [headers](https://vega.github.io/vega-lite/docs/header.html).\\n\\nFor a full list of header configuration options, please see the [corresponding section of in the header documentation](https://vega.github.io/vega-lite/docs/header.html#config).\"\n                },\n                \"headerFacet\": {\n                    \"$ref\": \"#/definitions/HeaderConfig\",\n                    \"description\": \"Header configuration, which determines default properties for non-row/column facet [headers](https://vega.github.io/vega-lite/docs/header.html).\\n\\nFor a full list of header configuration options, please see the [corresponding section of in the header documentation](https://vega.github.io/vega-lite/docs/header.html#config).\"\n                },\n                \"headerRow\": {\n                    \"$ref\": \"#/definitions/HeaderConfig\",\n                    \"description\": \"Header configuration, which determines default properties for row [headers](https://vega.github.io/vega-lite/docs/header.html).\\n\\nFor a full list of header configuration options, please see the [corresponding section of in the header documentation](https://vega.github.io/vega-lite/docs/header.html#config).\"\n                },\n                \"image\": {\n                    \"$ref\": \"#/definitions/RectConfig\",\n                    \"description\": \"Image-specific Config\"\n                },\n                \"legend\": {\n                    \"$ref\": \"#/definitions/LegendConfig\",\n                    \"description\": \"Legend configuration, which determines default properties for all [legends](https://vega.github.io/vega-lite/docs/legend.html). For a full list of legend configuration options, please see the [corresponding section of in the legend documentation](https://vega.github.io/vega-lite/docs/legend.html#config).\"\n                },\n                \"line\": {\n                    \"$ref\": \"#/definitions/LineConfig\",\n                    \"description\": \"Line-Specific Config\"\n                },\n                \"lineBreak\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A delimiter, such as a newline character, upon which to break text strings into multiple lines. This property provides a global default for text marks, which is overridden by mark or style config settings, and by the lineBreak mark encoding channel. If signal-valued, either string or regular expression (regexp) values are valid.\"\n                },\n                \"locale\": {\n                    \"$ref\": \"#/definitions/Locale\",\n                    \"description\": \"Locale definitions for string parsing and formatting of number and date values. The locale object should contain `number` and/or `time` properties with [locale definitions](https://vega.github.io/vega/docs/api/locale/). Locale definitions provided in the config block may be overridden by the View constructor locale option.\"\n                },\n                \"mark\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Mark Config\"\n                },\n                \"normalizedNumberFormat\": {\n                    \"description\": \"If normalizedNumberFormatType is not specified, D3 number format for axis labels, text marks, and tooltips of normalized stacked fields (fields with `stack: \\\"normalize\\\"`). For example `\\\"s\\\"` for SI units. Use [D3's number format pattern](https://github.com/d3/d3-format#locale_format).\\n\\nIf `config.normalizedNumberFormatType` is specified and `config.customFormatTypes` is `true`, this value will be passed as `format` alongside `datum.value` to the `config.numberFormatType` function. __Default value:__ `%`\",\n                    \"type\": \"string\"\n                },\n                \"normalizedNumberFormatType\": {\n                    \"description\": \"[Custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type) for `config.normalizedNumberFormat`.\\n\\n__Default value:__ `undefined` -- This is equilvalent to call D3-format, which is exposed as [`format` in Vega-Expression](https://vega.github.io/vega/docs/expressions/#format). __Note:__ You must also set `customFormatTypes` to `true` to use this feature.\",\n                    \"type\": \"string\"\n                },\n                \"numberFormat\": {\n                    \"description\": \"If numberFormatType is not specified, D3 number format for guide labels, text marks, and tooltips of non-normalized fields (fields *without* `stack: \\\"normalize\\\"`). For example `\\\"s\\\"` for SI units. Use [D3's number format pattern](https://github.com/d3/d3-format#locale_format).\\n\\nIf `config.numberFormatType` is specified and `config.customFormatTypes` is `true`, this value will be passed as `format` alongside `datum.value` to the `config.numberFormatType` function.\",\n                    \"type\": \"string\"\n                },\n                \"numberFormatType\": {\n                    \"description\": \"[Custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type) for `config.numberFormat`.\\n\\n__Default value:__ `undefined` -- This is equilvalent to call D3-format, which is exposed as [`format` in Vega-Expression](https://vega.github.io/vega/docs/expressions/#format). __Note:__ You must also set `customFormatTypes` to `true` to use this feature.\",\n                    \"type\": \"string\"\n                },\n                \"padding\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Padding\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The default visualization padding, in pixels, from the edge of the visualization canvas to the data rectangle. If a number, specifies padding for all sides. If an object, the value should have the format `{\\\"left\\\": 5, \\\"top\\\": 5, \\\"right\\\": 5, \\\"bottom\\\": 5}` to specify padding for each side of the visualization.\\n\\n__Default value__: `5`\"\n                },\n                \"params\": {\n                    \"description\": \"Dynamic variables or selections that parameterize a visualization.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/TopLevelParameter\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"point\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Point-Specific Config\"\n                },\n                \"projection\": {\n                    \"$ref\": \"#/definitions/ProjectionConfig\",\n                    \"description\": \"Projection configuration, which determines default properties for all [projections](https://vega.github.io/vega-lite/docs/projection.html). For a full list of projection configuration options, please see the [corresponding section of the projection documentation](https://vega.github.io/vega-lite/docs/projection.html#config).\"\n                },\n                \"range\": {\n                    \"$ref\": \"#/definitions/RangeConfig\",\n                    \"description\": \"An object hash that defines default range arrays or schemes for using with scales. For a full list of scale range configuration options, please see the [corresponding section of the scale documentation](https://vega.github.io/vega-lite/docs/scale.html#config).\"\n                },\n                \"rect\": {\n                    \"$ref\": \"#/definitions/RectConfig\",\n                    \"description\": \"Rect-Specific Config\"\n                },\n                \"rule\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Rule-Specific Config\"\n                },\n                \"scale\": {\n                    \"$ref\": \"#/definitions/ScaleConfig\",\n                    \"description\": \"Scale configuration determines default properties for all [scales](https://vega.github.io/vega-lite/docs/scale.html). For a full list of scale configuration options, please see the [corresponding section of the scale documentation](https://vega.github.io/vega-lite/docs/scale.html#config).\"\n                },\n                \"selection\": {\n                    \"$ref\": \"#/definitions/SelectionConfig\",\n                    \"description\": \"An object hash for defining default properties for each type of selections.\"\n                },\n                \"square\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Square-Specific Config\"\n                },\n                \"style\": {\n                    \"$ref\": \"#/definitions/StyleConfigIndex\",\n                    \"description\": \"An object hash that defines key-value mappings to determine default properties for marks with a given [style](https://vega.github.io/vega-lite/docs/mark.html#mark-def). The keys represent styles names; the values have to be valid [mark configuration objects](https://vega.github.io/vega-lite/docs/mark.html#config).\"\n                },\n                \"text\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Text-Specific Config\"\n                },\n                \"tick\": {\n                    \"$ref\": \"#/definitions/TickConfig\",\n                    \"description\": \"Tick-Specific Config\"\n                },\n                \"timeFormat\": {\n                    \"description\": \"Default time format for raw time values (without time units) in text marks, legend labels and header labels.\\n\\n__Default value:__ `\\\"%b %d, %Y\\\"` __Note:__ Axes automatically determine the format for each label automatically so this config does not affect axes.\",\n                    \"type\": \"string\"\n                },\n                \"timeFormatType\": {\n                    \"description\": \"[Custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type) for `config.timeFormat`.\\n\\n__Default value:__ `undefined` -- This is equilvalent to call D3-time-format, which is exposed as [`timeFormat` in Vega-Expression](https://vega.github.io/vega/docs/expressions/#timeFormat). __Note:__ You must also set `customFormatTypes` to `true` and there must *not* be a `timeUnit` defined to use this feature.\",\n                    \"type\": \"string\"\n                },\n                \"title\": {\n                    \"$ref\": \"#/definitions/TitleConfig\",\n                    \"description\": \"Title configuration, which determines default properties for all [titles](https://vega.github.io/vega-lite/docs/title.html). For a full list of title configuration options, please see the [corresponding section of the title documentation](https://vega.github.io/vega-lite/docs/title.html#config).\"\n                },\n                \"tooltipFormat\": {\n                    \"$ref\": \"#/definitions/FormatConfig\",\n                    \"description\": \"Define [custom format configuration](https://vega.github.io/vega-lite/docs/config.html#format) for tooltips. If unspecified, default format config will be applied.\"\n                },\n                \"trail\": {\n                    \"$ref\": \"#/definitions/LineConfig\",\n                    \"description\": \"Trail-Specific Config\"\n                },\n                \"view\": {\n                    \"$ref\": \"#/definitions/ViewConfig\",\n                    \"description\": \"Default properties for [single view plots](https://vega.github.io/vega-lite/docs/spec.html#single).\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"CsvDataFormat\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"parse\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Parse\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"If set to `null`, disable type inference based on the spec and only use type inference based on the data. Alternatively, a parsing directive object can be provided for explicit data types. Each property of the object corresponds to a field name, and the value to the desired data type (one of `\\\"number\\\"`, `\\\"boolean\\\"`, `\\\"date\\\"`, or null (do not parse the field)). For example, `\\\"parse\\\": {\\\"modified_on\\\": \\\"date\\\"}` parses the `modified_on` field in each input record a Date value.\\n\\nFor `\\\"date\\\"`, we parse data based using JavaScript's [`Date.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse). For Specific date formats can be provided (e.g., `{foo: \\\"date:'%m%d%Y'\\\"}`), using the [d3-time-format syntax](https://github.com/d3/d3-time-format#locale_format). UTC date format parsing is supported similarly (e.g., `{foo: \\\"utc:'%m%d%Y'\\\"}`). See more about [UTC time](https://vega.github.io/vega-lite/docs/timeunit.html#utc)\"\n                },\n                \"type\": {\n                    \"description\": \"Type of input data: `\\\"json\\\"`, `\\\"csv\\\"`, `\\\"tsv\\\"`, `\\\"dsv\\\"`.\\n\\n__Default value:__  The default format type is determined by the extension of the file URL. If no extension is detected, `\\\"json\\\"` will be used by default.\",\n                    \"enum\": [\n                        \"csv\",\n                        \"tsv\"\n                    ],\n                    \"type\": \"string\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"Cursor\": {\n            \"enum\": [\n                \"auto\",\n                \"default\",\n                \"none\",\n                \"context-menu\",\n                \"help\",\n                \"pointer\",\n                \"progress\",\n                \"wait\",\n                \"cell\",\n                \"crosshair\",\n                \"text\",\n                \"vertical-text\",\n                \"alias\",\n                \"copy\",\n                \"move\",\n                \"no-drop\",\n                \"not-allowed\",\n                \"e-resize\",\n                \"n-resize\",\n                \"ne-resize\",\n                \"nw-resize\",\n                \"s-resize\",\n                \"se-resize\",\n                \"sw-resize\",\n                \"w-resize\",\n                \"ew-resize\",\n                \"ns-resize\",\n                \"nesw-resize\",\n                \"nwse-resize\",\n                \"col-resize\",\n                \"row-resize\",\n                \"all-scroll\",\n                \"zoom-in\",\n                \"zoom-out\",\n                \"grab\",\n                \"grabbing\"\n            ],\n            \"type\": \"string\"\n        },\n        \"Cyclical\": {\n            \"enum\": [\n                \"rainbow\",\n                \"sinebow\"\n            ],\n            \"type\": \"string\"\n        },\n        \"Data\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/DataSource\"\n                },\n                {\n                    \"$ref\": \"#/definitions/Generator\"\n                }\n            ]\n        },\n        \"DataFormat\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/CsvDataFormat\"\n                },\n                {\n                    \"$ref\": \"#/definitions/DsvDataFormat\"\n                },\n                {\n                    \"$ref\": \"#/definitions/JsonDataFormat\"\n                },\n                {\n                    \"$ref\": \"#/definitions/TopoDataFormat\"\n                }\n            ]\n        },\n        \"DataSource\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/UrlData\"\n                },\n                {\n                    \"$ref\": \"#/definitions/InlineData\"\n                },\n                {\n                    \"$ref\": \"#/definitions/NamedData\"\n                }\n            ]\n        },\n        \"Datasets\": {\n            \"$ref\": \"#/definitions/Dict<InlineDataset>\"\n        },\n        \"DateTime\": {\n            \"additionalProperties\": false,\n            \"description\": \"Object for defining datetime in Vega-Lite Filter. If both month and quarter are provided, month has higher precedence. `day` cannot be combined with other date. We accept string for month and day names.\",\n            \"properties\": {\n                \"date\": {\n                    \"description\": \"Integer value representing the date (day of the month) from 1-31.\",\n                    \"maximum\": 31,\n                    \"minimum\": 1,\n                    \"type\": \"number\"\n                },\n                \"day\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Day\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        }\n                    ],\n                    \"description\": \"Value representing the day of a week. This can be one of: (1) integer value -- `1` represents Monday; (2) case-insensitive day name (e.g., `\\\"Monday\\\"`); (3) case-insensitive, 3-character short day name (e.g., `\\\"Mon\\\"`).\\n\\n**Warning:** A DateTime definition object with `day`** should not be combined with `year`, `quarter`, `month`, or `date`.\"\n                },\n                \"hours\": {\n                    \"description\": \"Integer value representing the hour of a day from 0-23.\",\n                    \"maximum\": 24,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"milliseconds\": {\n                    \"description\": \"Integer value representing the millisecond segment of time.\",\n                    \"maximum\": 1000,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"minutes\": {\n                    \"description\": \"Integer value representing the minute segment of time from 0-59.\",\n                    \"maximum\": 60,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"month\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Month\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        }\n                    ],\n                    \"description\": \"One of: (1) integer value representing the month from `1`-`12`. `1` represents January; (2) case-insensitive month name (e.g., `\\\"January\\\"`); (3) case-insensitive, 3-character short month name (e.g., `\\\"Jan\\\"`).\"\n                },\n                \"quarter\": {\n                    \"description\": \"Integer value representing the quarter of the year (from 1-4).\",\n                    \"maximum\": 4,\n                    \"minimum\": 1,\n                    \"type\": \"number\"\n                },\n                \"seconds\": {\n                    \"description\": \"Integer value representing the second segment (0-59) of a time value\",\n                    \"maximum\": 60,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"utc\": {\n                    \"description\": \"A boolean flag indicating if date time is in utc time. If false, the date time is in local time\",\n                    \"type\": \"boolean\"\n                },\n                \"year\": {\n                    \"description\": \"Integer value representing the year.\",\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"DatumDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"datum\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/PrimitiveValue\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/DateTime\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RepeatRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in data domain.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/Type\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"Day\": {\n            \"maximum\": 7,\n            \"minimum\": 1,\n            \"type\": \"number\"\n        },\n        \"DensityTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"as\": {\n                    \"description\": \"The output fields for the sample value and corresponding density estimate.\\n\\n__Default value:__ `[\\\"value\\\", \\\"density\\\"]`\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"maxItems\": 2,\n                    \"minItems\": 2,\n                    \"type\": \"array\"\n                },\n                \"bandwidth\": {\n                    \"description\": \"The bandwidth (standard deviation) of the Gaussian kernel. If unspecified or set to zero, the bandwidth value is automatically estimated from the input data using Scott’s rule.\",\n                    \"type\": \"number\"\n                },\n                \"counts\": {\n                    \"description\": \"A boolean flag indicating if the output values should be probability estimates (false) or smoothed counts (true).\\n\\n__Default value:__ `false`\",\n                    \"type\": \"boolean\"\n                },\n                \"cumulative\": {\n                    \"description\": \"A boolean flag indicating whether to produce density estimates (false) or cumulative density estimates (true).\\n\\n__Default value:__ `false`\",\n                    \"type\": \"boolean\"\n                },\n                \"density\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The data field for which to perform density estimation.\"\n                },\n                \"extent\": {\n                    \"description\": \"A [min, max] domain from which to sample the distribution. If unspecified, the extent will be determined by the observed minimum and maximum values of the density value field.\",\n                    \"items\": {\n                        \"type\": \"number\"\n                    },\n                    \"maxItems\": 2,\n                    \"minItems\": 2,\n                    \"type\": \"array\"\n                },\n                \"groupby\": {\n                    \"description\": \"The data fields to group by. If not specified, a single group containing all data objects will be used.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"maxsteps\": {\n                    \"description\": \"The maximum number of samples to take along the extent domain for plotting the density.\\n\\n__Default value:__ `200`\",\n                    \"type\": \"number\"\n                },\n                \"minsteps\": {\n                    \"description\": \"The minimum number of samples to take along the extent domain for plotting the density.\\n\\n__Default value:__ `25`\",\n                    \"type\": \"number\"\n                },\n                \"resolve\": {\n                    \"description\": \"Indicates how parameters for multiple densities should be resolved. If `\\\"independent\\\"`, each density may have its own domain extent and dynamic number of curve sample steps. If `\\\"shared\\\"`, the KDE transform will ensure that all densities are defined over a shared domain and curve steps, enabling stacking.\\n\\n__Default value:__ `\\\"shared\\\"`\",\n                    \"enum\": [\n                        \"independent\",\n                        \"shared\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"steps\": {\n                    \"description\": \"The exact number of samples to take along the extent domain for plotting the density. If specified, overrides both minsteps and maxsteps to set an exact number of uniform samples. Potentially useful in conjunction with a fixed extent to ensure consistent sample points for stacked densities.\",\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"density\"\n            ],\n            \"type\": \"object\"\n        },\n        \"DerivedStream\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"between\": {\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Stream\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"consume\": {\n                    \"type\": \"boolean\"\n                },\n                \"debounce\": {\n                    \"type\": \"number\"\n                },\n                \"filter\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Expr\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/Expr\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ]\n                },\n                \"markname\": {\n                    \"type\": \"string\"\n                },\n                \"marktype\": {\n                    \"$ref\": \"#/definitions/MarkType\"\n                },\n                \"stream\": {\n                    \"$ref\": \"#/definitions/Stream\"\n                },\n                \"throttle\": {\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"stream\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Dict<InlineDataset>\": {\n            \"additionalProperties\": {\n                \"$ref\": \"#/definitions/InlineDataset\"\n            },\n            \"type\": \"object\"\n        },\n        \"Dict<SelectionInit>\": {\n            \"additionalProperties\": {\n                \"$ref\": \"#/definitions/SelectionInit\"\n            },\n            \"type\": \"object\"\n        },\n        \"Dict<SelectionInitInterval>\": {\n            \"additionalProperties\": {\n                \"$ref\": \"#/definitions/SelectionInitInterval\"\n            },\n            \"type\": \"object\"\n        },\n        \"Dict\": {\n            \"additionalProperties\": {},\n            \"type\": \"object\"\n        },\n        \"Diverging\": {\n            \"enum\": [\n                \"blueorange\",\n                \"blueorange-3\",\n                \"blueorange-4\",\n                \"blueorange-5\",\n                \"blueorange-6\",\n                \"blueorange-7\",\n                \"blueorange-8\",\n                \"blueorange-9\",\n                \"blueorange-10\",\n                \"blueorange-11\",\n                \"brownbluegreen\",\n                \"brownbluegreen-3\",\n                \"brownbluegreen-4\",\n                \"brownbluegreen-5\",\n                \"brownbluegreen-6\",\n                \"brownbluegreen-7\",\n                \"brownbluegreen-8\",\n                \"brownbluegreen-9\",\n                \"brownbluegreen-10\",\n                \"brownbluegreen-11\",\n                \"purplegreen\",\n                \"purplegreen-3\",\n                \"purplegreen-4\",\n                \"purplegreen-5\",\n                \"purplegreen-6\",\n                \"purplegreen-7\",\n                \"purplegreen-8\",\n                \"purplegreen-9\",\n                \"purplegreen-10\",\n                \"purplegreen-11\",\n                \"pinkyellowgreen\",\n                \"pinkyellowgreen-3\",\n                \"pinkyellowgreen-4\",\n                \"pinkyellowgreen-5\",\n                \"pinkyellowgreen-6\",\n                \"pinkyellowgreen-7\",\n                \"pinkyellowgreen-8\",\n                \"pinkyellowgreen-9\",\n                \"pinkyellowgreen-10\",\n                \"pinkyellowgreen-11\",\n                \"purpleorange\",\n                \"purpleorange-3\",\n                \"purpleorange-4\",\n                \"purpleorange-5\",\n                \"purpleorange-6\",\n                \"purpleorange-7\",\n                \"purpleorange-8\",\n                \"purpleorange-9\",\n                \"purpleorange-10\",\n                \"purpleorange-11\",\n                \"redblue\",\n                \"redblue-3\",\n                \"redblue-4\",\n                \"redblue-5\",\n                \"redblue-6\",\n                \"redblue-7\",\n                \"redblue-8\",\n                \"redblue-9\",\n                \"redblue-10\",\n                \"redblue-11\",\n                \"redgrey\",\n                \"redgrey-3\",\n                \"redgrey-4\",\n                \"redgrey-5\",\n                \"redgrey-6\",\n                \"redgrey-7\",\n                \"redgrey-8\",\n                \"redgrey-9\",\n                \"redgrey-10\",\n                \"redgrey-11\",\n                \"redyellowblue\",\n                \"redyellowblue-3\",\n                \"redyellowblue-4\",\n                \"redyellowblue-5\",\n                \"redyellowblue-6\",\n                \"redyellowblue-7\",\n                \"redyellowblue-8\",\n                \"redyellowblue-9\",\n                \"redyellowblue-10\",\n                \"redyellowblue-11\",\n                \"redyellowgreen\",\n                \"redyellowgreen-3\",\n                \"redyellowgreen-4\",\n                \"redyellowgreen-5\",\n                \"redyellowgreen-6\",\n                \"redyellowgreen-7\",\n                \"redyellowgreen-8\",\n                \"redyellowgreen-9\",\n                \"redyellowgreen-10\",\n                \"redyellowgreen-11\",\n                \"spectral\",\n                \"spectral-3\",\n                \"spectral-4\",\n                \"spectral-5\",\n                \"spectral-6\",\n                \"spectral-7\",\n                \"spectral-8\",\n                \"spectral-9\",\n                \"spectral-10\",\n                \"spectral-11\"\n            ],\n            \"type\": \"string\"\n        },\n        \"DomainUnionWith\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"unionWith\": {\n                    \"description\": \"Customized domain values to be union with the field's values or explicitly defined domain. Should be an array of valid scale domain values.\",\n                    \"items\": {\n                        \"anyOf\": [\n                            {\n                                \"type\": \"number\"\n                            },\n                            {\n                                \"type\": \"string\"\n                            },\n                            {\n                                \"type\": \"boolean\"\n                            },\n                            {\n                                \"$ref\": \"#/definitions/DateTime\"\n                            }\n                        ]\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"unionWith\"\n            ],\n            \"type\": \"object\"\n        },\n        \"DsvDataFormat\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"delimiter\": {\n                    \"description\": \"The delimiter between records. The delimiter must be a single character (i.e., a single 16-bit code unit); so, ASCII delimiters are fine, but emoji delimiters are not.\",\n                    \"maxLength\": 1,\n                    \"minLength\": 1,\n                    \"type\": \"string\"\n                },\n                \"parse\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Parse\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"If set to `null`, disable type inference based on the spec and only use type inference based on the data. Alternatively, a parsing directive object can be provided for explicit data types. Each property of the object corresponds to a field name, and the value to the desired data type (one of `\\\"number\\\"`, `\\\"boolean\\\"`, `\\\"date\\\"`, or null (do not parse the field)). For example, `\\\"parse\\\": {\\\"modified_on\\\": \\\"date\\\"}` parses the `modified_on` field in each input record a Date value.\\n\\nFor `\\\"date\\\"`, we parse data based using JavaScript's [`Date.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse). For Specific date formats can be provided (e.g., `{foo: \\\"date:'%m%d%Y'\\\"}`), using the [d3-time-format syntax](https://github.com/d3/d3-time-format#locale_format). UTC date format parsing is supported similarly (e.g., `{foo: \\\"utc:'%m%d%Y'\\\"}`). See more about [UTC time](https://vega.github.io/vega-lite/docs/timeunit.html#utc)\"\n                },\n                \"type\": {\n                    \"const\": \"dsv\",\n                    \"description\": \"Type of input data: `\\\"json\\\"`, `\\\"csv\\\"`, `\\\"tsv\\\"`, `\\\"dsv\\\"`.\\n\\n__Default value:__  The default format type is determined by the extension of the file URL. If no extension is detected, `\\\"json\\\"` will be used by default.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"delimiter\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Element\": {\n            \"type\": \"string\"\n        },\n        \"EncodingSortField\": {\n            \"additionalProperties\": false,\n            \"description\": \"A sort definition for sorting a discrete scale in an encoding field definition.\",\n            \"properties\": {\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"The data [field](https://vega.github.io/vega-lite/docs/field.html) to sort by.\\n\\n__Default value:__ If unspecified, defaults to the field specified in the outer data reference.\"\n                },\n                \"op\": {\n                    \"$ref\": \"#/definitions/NonArgAggregateOp\",\n                    \"description\": \"An [aggregate operation](https://vega.github.io/vega-lite/docs/aggregate.html#ops) to perform on the field prior to sorting (e.g., `\\\"count\\\"`, `\\\"mean\\\"` and `\\\"median\\\"`). An aggregation is required when there are multiple values of the sort field for each encoded data field. The input data objects will be aggregated, grouped by the encoded data field.\\n\\nFor a full list of operations, please see the documentation for [aggregate](https://vega.github.io/vega-lite/docs/aggregate.html#ops).\\n\\n__Default value:__ `\\\"sum\\\"` for stacked plots. Otherwise, `\\\"min\\\"`.\"\n                },\n                \"order\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SortOrder\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"The sort order. One of `\\\"ascending\\\"` (default), `\\\"descending\\\"`, or `null` (no not sort).\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ErrorBand\": {\n            \"const\": \"errorband\",\n            \"type\": \"string\"\n        },\n        \"ErrorBandConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"band\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                },\n                \"borders\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                },\n                \"extent\": {\n                    \"$ref\": \"#/definitions/ErrorBarExtent\",\n                    \"description\": \"The extent of the band. Available options include:\\n- `\\\"ci\\\"`: Extend the band to the 95% bootstrapped confidence interval of the mean.\\n- `\\\"stderr\\\"`: The size of band are set to the value of standard error, extending from the mean.\\n- `\\\"stdev\\\"`: The size of band are set to the value of standard deviation, extending from the mean.\\n- `\\\"iqr\\\"`: Extend the band to the q1 and q3.\\n\\n__Default value:__ `\\\"stderr\\\"`.\"\n                },\n                \"interpolate\": {\n                    \"$ref\": \"#/definitions/Interpolate\",\n                    \"description\": \"The line interpolation method for the error band. One of the following:\\n- `\\\"linear\\\"`: piecewise linear segments, as in a polyline.\\n- `\\\"linear-closed\\\"`: close the linear segments to form a polygon.\\n- `\\\"step\\\"`: a piecewise constant function (a step function) consisting of alternating horizontal and vertical lines. The y-value changes at the midpoint of each pair of adjacent x-values.\\n- `\\\"step-before\\\"`: a piecewise constant function (a step function) consisting of alternating horizontal and vertical lines. The y-value changes before the x-value.\\n- `\\\"step-after\\\"`: a piecewise constant function (a step function) consisting of alternating horizontal and vertical lines. The y-value changes after the x-value.\\n- `\\\"basis\\\"`: a B-spline, with control point duplication on the ends.\\n- `\\\"basis-open\\\"`: an open B-spline; may not intersect the start or end.\\n- `\\\"basis-closed\\\"`: a closed B-spline, as in a loop.\\n- `\\\"cardinal\\\"`: a Cardinal spline, with control point duplication on the ends.\\n- `\\\"cardinal-open\\\"`: an open Cardinal spline; may not intersect the start or end, but will intersect other control points.\\n- `\\\"cardinal-closed\\\"`: a closed Cardinal spline, as in a loop.\\n- `\\\"bundle\\\"`: equivalent to basis, except the tension parameter is used to straighten the spline.\\n- `\\\"monotone\\\"`: cubic interpolation that preserves monotonicity in y.\"\n                },\n                \"tension\": {\n                    \"description\": \"The tension parameter for the interpolation type of the error band.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ErrorBandDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"band\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                },\n                \"borders\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                },\n                \"clip\": {\n                    \"description\": \"Whether a composite mark be clipped to the enclosing group’s width and height.\",\n                    \"type\": \"boolean\"\n                },\n                \"color\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default color.\\n\\n__Default value:__ <span style=\\\"color: #4682b4;\\\">&#9632;</span> `\\\"#4682b4\\\"`\\n\\n__Note:__\\n- This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\\n- The `fill` and `stroke` properties have higher precedence than `color` and will override `color`.\"\n                },\n                \"extent\": {\n                    \"$ref\": \"#/definitions/ErrorBarExtent\",\n                    \"description\": \"The extent of the band. Available options include:\\n- `\\\"ci\\\"`: Extend the band to the 95% bootstrapped confidence interval of the mean.\\n- `\\\"stderr\\\"`: The size of band are set to the value of standard error, extending from the mean.\\n- `\\\"stdev\\\"`: The size of band are set to the value of standard deviation, extending from the mean.\\n- `\\\"iqr\\\"`: Extend the band to the q1 and q3.\\n\\n__Default value:__ `\\\"stderr\\\"`.\"\n                },\n                \"interpolate\": {\n                    \"$ref\": \"#/definitions/Interpolate\",\n                    \"description\": \"The line interpolation method for the error band. One of the following:\\n- `\\\"linear\\\"`: piecewise linear segments, as in a polyline.\\n- `\\\"linear-closed\\\"`: close the linear segments to form a polygon.\\n- `\\\"step\\\"`: a piecewise constant function (a step function) consisting of alternating horizontal and vertical lines. The y-value changes at the midpoint of each pair of adjacent x-values.\\n- `\\\"step-before\\\"`: a piecewise constant function (a step function) consisting of alternating horizontal and vertical lines. The y-value changes before the x-value.\\n- `\\\"step-after\\\"`: a piecewise constant function (a step function) consisting of alternating horizontal and vertical lines. The y-value changes after the x-value.\\n- `\\\"basis\\\"`: a B-spline, with control point duplication on the ends.\\n- `\\\"basis-open\\\"`: an open B-spline; may not intersect the start or end.\\n- `\\\"basis-closed\\\"`: a closed B-spline, as in a loop.\\n- `\\\"cardinal\\\"`: a Cardinal spline, with control point duplication on the ends.\\n- `\\\"cardinal-open\\\"`: an open Cardinal spline; may not intersect the start or end, but will intersect other control points.\\n- `\\\"cardinal-closed\\\"`: a closed Cardinal spline, as in a loop.\\n- `\\\"bundle\\\"`: equivalent to basis, except the tension parameter is used to straighten the spline.\\n- `\\\"monotone\\\"`: cubic interpolation that preserves monotonicity in y.\"\n                },\n                \"opacity\": {\n                    \"description\": \"The opacity (value between [0,1]) of the mark.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"orient\": {\n                    \"$ref\": \"#/definitions/Orientation\",\n                    \"description\": \"Orientation of the error band. This is normally automatically determined, but can be specified when the orientation is ambiguous and cannot be automatically determined.\"\n                },\n                \"tension\": {\n                    \"description\": \"The tension parameter for the interpolation type of the error band.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/ErrorBand\",\n                    \"description\": \"The mark type. This could a primitive mark type (one of `\\\"bar\\\"`, `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"tick\\\"`, `\\\"line\\\"`, `\\\"area\\\"`, `\\\"point\\\"`, `\\\"geoshape\\\"`, `\\\"rule\\\"`, and `\\\"text\\\"`) or a composite mark type (`\\\"boxplot\\\"`, `\\\"errorband\\\"`, `\\\"errorbar\\\"`).\"\n                }\n            },\n            \"required\": [\n                \"type\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ErrorBar\": {\n            \"const\": \"errorbar\",\n            \"type\": \"string\"\n        },\n        \"ErrorBarConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"extent\": {\n                    \"$ref\": \"#/definitions/ErrorBarExtent\",\n                    \"description\": \"The extent of the rule. Available options include:\\n- `\\\"ci\\\"`: Extend the rule to the 95% bootstrapped confidence interval of the mean.\\n- `\\\"stderr\\\"`: The size of rule are set to the value of standard error, extending from the mean.\\n- `\\\"stdev\\\"`: The size of rule are set to the value of standard deviation, extending from the mean.\\n- `\\\"iqr\\\"`: Extend the rule to the q1 and q3.\\n\\n__Default value:__ `\\\"stderr\\\"`.\"\n                },\n                \"rule\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                },\n                \"size\": {\n                    \"description\": \"Size of the ticks of an error bar\",\n                    \"type\": \"number\"\n                },\n                \"thickness\": {\n                    \"description\": \"Thickness of the ticks and the bar of an error bar\",\n                    \"type\": \"number\"\n                },\n                \"ticks\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ErrorBarDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"clip\": {\n                    \"description\": \"Whether a composite mark be clipped to the enclosing group’s width and height.\",\n                    \"type\": \"boolean\"\n                },\n                \"color\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default color.\\n\\n__Default value:__ <span style=\\\"color: #4682b4;\\\">&#9632;</span> `\\\"#4682b4\\\"`\\n\\n__Note:__\\n- This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\\n- The `fill` and `stroke` properties have higher precedence than `color` and will override `color`.\"\n                },\n                \"extent\": {\n                    \"$ref\": \"#/definitions/ErrorBarExtent\",\n                    \"description\": \"The extent of the rule. Available options include:\\n- `\\\"ci\\\"`: Extend the rule to the 95% bootstrapped confidence interval of the mean.\\n- `\\\"stderr\\\"`: The size of rule are set to the value of standard error, extending from the mean.\\n- `\\\"stdev\\\"`: The size of rule are set to the value of standard deviation, extending from the mean.\\n- `\\\"iqr\\\"`: Extend the rule to the q1 and q3.\\n\\n__Default value:__ `\\\"stderr\\\"`.\"\n                },\n                \"opacity\": {\n                    \"description\": \"The opacity (value between [0,1]) of the mark.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"orient\": {\n                    \"$ref\": \"#/definitions/Orientation\",\n                    \"description\": \"Orientation of the error bar. This is normally automatically determined, but can be specified when the orientation is ambiguous and cannot be automatically determined.\"\n                },\n                \"rule\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                },\n                \"size\": {\n                    \"description\": \"Size of the ticks of an error bar\",\n                    \"type\": \"number\"\n                },\n                \"thickness\": {\n                    \"description\": \"Thickness of the ticks and the bar of an error bar\",\n                    \"type\": \"number\"\n                },\n                \"ticks\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AnyMarkConfig\"\n                        }\n                    ]\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/ErrorBar\",\n                    \"description\": \"The mark type. This could a primitive mark type (one of `\\\"bar\\\"`, `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"tick\\\"`, `\\\"line\\\"`, `\\\"area\\\"`, `\\\"point\\\"`, `\\\"geoshape\\\"`, `\\\"rule\\\"`, and `\\\"text\\\"`) or a composite mark type (`\\\"boxplot\\\"`, `\\\"errorband\\\"`, `\\\"errorbar\\\"`).\"\n                }\n            },\n            \"required\": [\n                \"type\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ErrorBarExtent\": {\n            \"enum\": [\n                \"ci\",\n                \"iqr\",\n                \"stderr\",\n                \"stdev\"\n            ],\n            \"type\": \"string\"\n        },\n        \"EventStream\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"between\": {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/Stream\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        \"consume\": {\n                            \"type\": \"boolean\"\n                        },\n                        \"debounce\": {\n                            \"type\": \"number\"\n                        },\n                        \"filter\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Expr\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/Expr\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"markname\": {\n                            \"type\": \"string\"\n                        },\n                        \"marktype\": {\n                            \"$ref\": \"#/definitions/MarkType\"\n                        },\n                        \"source\": {\n                            \"enum\": [\n                                \"view\",\n                                \"scope\"\n                            ],\n                            \"type\": \"string\"\n                        },\n                        \"throttle\": {\n                            \"type\": \"number\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/EventType\"\n                        }\n                    },\n                    \"required\": [\n                        \"type\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"between\": {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/Stream\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        \"consume\": {\n                            \"type\": \"boolean\"\n                        },\n                        \"debounce\": {\n                            \"type\": \"number\"\n                        },\n                        \"filter\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Expr\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"$ref\": \"#/definitions/Expr\"\n                                    },\n                                    \"type\": \"array\"\n                                }\n                            ]\n                        },\n                        \"markname\": {\n                            \"type\": \"string\"\n                        },\n                        \"marktype\": {\n                            \"$ref\": \"#/definitions/MarkType\"\n                        },\n                        \"source\": {\n                            \"const\": \"window\",\n                            \"type\": \"string\"\n                        },\n                        \"throttle\": {\n                            \"type\": \"number\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/WindowEventType\"\n                        }\n                    },\n                    \"required\": [\n                        \"source\",\n                        \"type\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"EventType\": {\n            \"enum\": [\n                \"click\",\n                \"dblclick\",\n                \"dragenter\",\n                \"dragleave\",\n                \"dragover\",\n                \"keydown\",\n                \"keypress\",\n                \"keyup\",\n                \"mousedown\",\n                \"mousemove\",\n                \"mouseout\",\n                \"mouseover\",\n                \"mouseup\",\n                \"mousewheel\",\n                \"pointerdown\",\n                \"pointermove\",\n                \"pointerout\",\n                \"pointerover\",\n                \"pointerup\",\n                \"timer\",\n                \"touchend\",\n                \"touchmove\",\n                \"touchstart\",\n                \"wheel\"\n            ],\n            \"type\": \"string\"\n        },\n        \"Expr\": {\n            \"type\": \"string\"\n        },\n        \"ExprRef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"expr\": {\n                    \"description\": \"Vega expression (which can refer to Vega-Lite parameters).\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"expr\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ExtentTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"extent\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The field of which to get the extent.\"\n                },\n                \"param\": {\n                    \"$ref\": \"#/definitions/ParameterName\",\n                    \"description\": \"The output parameter produced by the extent transform.\"\n                }\n            },\n            \"required\": [\n                \"extent\",\n                \"param\"\n            ],\n            \"type\": \"object\"\n        },\n        \"FacetEncodingFieldDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LayoutAlign\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<LayoutAlign>\"\n                        }\n                    ],\n                    \"description\": \"The alignment to apply to grid rows and columns. The supported string values are `\\\"all\\\"`, `\\\"each\\\"`, and `\\\"none\\\"`.\\n\\n- For `\\\"none\\\"`, a flow layout will be used, in which adjacent subviews are simply placed one after the other.\\n- For `\\\"each\\\"`, subviews will be aligned into a clean grid structure, but each row or column may be of variable size.\\n- For `\\\"all\\\"`, subviews will be aligned and each row or column will be sized identically based on the maximum observed size. String values for this property will be applied to both grid rows and columns.\\n\\nAlternatively, an object value of the form `{\\\"row\\\": string, \\\"column\\\": string}` can be used to supply different alignments for rows and columns.\\n\\n__Default value:__ `\\\"all\\\"`.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"bounds\": {\n                    \"description\": \"The bounds calculation method to use for determining the extent of a sub-plot. One of `full` (the default) or `flush`.\\n\\n- If set to `full`, the entire calculated bounds (including axes, title, and legend) will be used.\\n- If set to `flush`, only the specified width and height values for the sub-view will be used. The `flush` setting can be useful when attempting to place sub-plots without axes or legends into a uniform grid structure.\\n\\n__Default value:__ `\\\"full\\\"`\",\n                    \"enum\": [\n                        \"full\",\n                        \"flush\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"center\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<boolean>\"\n                        }\n                    ],\n                    \"description\": \"Boolean flag indicating if subviews should be centered relative to their respective rows or columns.\\n\\nAn object value of the form `{\\\"row\\\": boolean, \\\"column\\\": boolean}` can be used to supply different centering values for rows and columns.\\n\\n__Default value:__ `false`\"\n                },\n                \"columns\": {\n                    \"description\": \"The number of columns to include in the view composition layout.\\n\\n__Default value__: `undefined` -- An infinite number of columns (a single row) will be assumed. This is equivalent to `hconcat` (for `concat`) and to using the `column` channel (for `facet` and `repeat`).\\n\\n__Note__:\\n\\n1) This property is only for:\\n- the general (wrappable) `concat` operator (not `hconcat`/`vconcat`)\\n- the `facet` and `repeat` operator with one field/repetition definition (without row/column nesting)\\n\\n2) Setting the `columns` to `1` is equivalent to `vconcat` (for `concat`) and to using the `row` channel (for `facet` and `repeat`).\",\n                    \"type\": \"number\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"header\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Header\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of a facet's header.\"\n                },\n                \"sort\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SortArray\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/SortOrder\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/EncodingSortField\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` is not supported for `row` and `column`.\"\n                },\n                \"spacing\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<number>\"\n                        }\n                    ],\n                    \"description\": \"The spacing in pixels between sub-views of the composition operator. An object of the form `{\\\"row\\\": number, \\\"column\\\": number}` can be used to set different spacing values for rows and columns.\\n\\n__Default value__: Depends on `\\\"spacing\\\"` property of [the view composition configuration](https://vega.github.io/vega-lite/docs/config.html#view-config) (`20` by default)\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/StandardType\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"FacetFieldDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"header\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Header\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of a facet's header.\"\n                },\n                \"sort\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SortArray\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/SortOrder\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/EncodingSortField\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` is not supported for `row` and `column`.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/StandardType\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"FacetMapping\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"column\": {\n                    \"$ref\": \"#/definitions/FacetFieldDef\",\n                    \"description\": \"A field definition for the horizontal facet of trellis plots.\"\n                },\n                \"row\": {\n                    \"$ref\": \"#/definitions/FacetFieldDef\",\n                    \"description\": \"A field definition for the vertical facet of trellis plots.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"FacetedEncoding\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"angle\": {\n                    \"$ref\": \"#/definitions/NumericMarkPropDef\",\n                    \"description\": \"Rotation angle of point and text marks.\"\n                },\n                \"color\": {\n                    \"$ref\": \"#/definitions/ColorDef\",\n                    \"description\": \"Color of the marks – either fill or stroke color based on  the `filled` property of mark definition. By default, `color` represents fill color for `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"tick\\\"`, `\\\"text\\\"`, `\\\"trail\\\"`, `\\\"circle\\\"`, and `\\\"square\\\"` / stroke color for `\\\"line\\\"` and `\\\"point\\\"`.\\n\\n__Default value:__ If undefined, the default color depends on [mark config](https://vega.github.io/vega-lite/docs/config.html#mark-config)'s `color` property.\\n\\n_Note:_ 1) For fine-grained control over both fill and stroke colors of the marks, please use the `fill` and `stroke` channels. The `fill` or `stroke` encodings have higher precedence than `color`, thus may override the `color` encoding if conflicting encodings are specified. 2) See the scale documentation for more information about customizing [color scheme](https://vega.github.io/vega-lite/docs/scale.html#scheme).\"\n                },\n                \"column\": {\n                    \"$ref\": \"#/definitions/RowColumnEncodingFieldDef\",\n                    \"description\": \"A field definition for the horizontal facet of trellis plots.\"\n                },\n                \"description\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StringFieldDefWithCondition\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/StringValueDefWithCondition\"\n                        }\n                    ],\n                    \"description\": \"A text description of this mark for ARIA accessibility (SVG output only). For SVG output the `\\\"aria-label\\\"` attribute will be set to this description.\"\n                },\n                \"detail\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FieldDefWithoutScale\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/FieldDefWithoutScale\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"Additional levels of detail for grouping data in aggregate views and in line, trail, and area marks without mapping data to a specific visual channel.\"\n                },\n                \"facet\": {\n                    \"$ref\": \"#/definitions/FacetEncodingFieldDef\",\n                    \"description\": \"A field definition for the (flexible) facet of trellis plots.\\n\\nIf either `row` or `column` is specified, this channel will be ignored.\"\n                },\n                \"fill\": {\n                    \"$ref\": \"#/definitions/ColorDef\",\n                    \"description\": \"Fill color of the marks. __Default value:__ If undefined, the default color depends on [mark config](https://vega.github.io/vega-lite/docs/config.html#mark-config)'s `color` property.\\n\\n_Note:_ The `fill` encoding has higher precedence than `color`, thus may override the `color` encoding if conflicting encodings are specified.\"\n                },\n                \"fillOpacity\": {\n                    \"$ref\": \"#/definitions/NumericMarkPropDef\",\n                    \"description\": \"Fill opacity of the marks.\\n\\n__Default value:__ If undefined, the default opacity depends on [mark config](https://vega.github.io/vega-lite/docs/config.html#mark-config)'s `fillOpacity` property.\"\n                },\n                \"href\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StringFieldDefWithCondition\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/StringValueDefWithCondition\"\n                        }\n                    ],\n                    \"description\": \"A URL to load upon mouse click.\"\n                },\n                \"key\": {\n                    \"$ref\": \"#/definitions/FieldDefWithoutScale\",\n                    \"description\": \"A data field to use as a unique key for data binding. When a visualization’s data is updated, the key value will be used to match data elements to existing mark instances. Use a key channel to enable object constancy for transitions over dynamic data.\"\n                },\n                \"latitude\": {\n                    \"$ref\": \"#/definitions/LatLongDef\",\n                    \"description\": \"Latitude position of geographically projected marks.\"\n                },\n                \"latitude2\": {\n                    \"$ref\": \"#/definitions/Position2Def\",\n                    \"description\": \"Latitude-2 position for geographically projected ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\"\n                },\n                \"longitude\": {\n                    \"$ref\": \"#/definitions/LatLongDef\",\n                    \"description\": \"Longitude position of geographically projected marks.\"\n                },\n                \"longitude2\": {\n                    \"$ref\": \"#/definitions/Position2Def\",\n                    \"description\": \"Longitude-2 position for geographically projected ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\"\n                },\n                \"opacity\": {\n                    \"$ref\": \"#/definitions/NumericMarkPropDef\",\n                    \"description\": \"Opacity of the marks.\\n\\n__Default value:__ If undefined, the default opacity depends on [mark config](https://vega.github.io/vega-lite/docs/config.html#mark-config)'s `opacity` property.\"\n                },\n                \"order\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/OrderFieldDef\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/OrderFieldDef\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/OrderValueDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/OrderOnlyDef\"\n                        }\n                    ],\n                    \"description\": \"Order of the marks.\\n- For stacked marks, this `order` channel encodes [stack order](https://vega.github.io/vega-lite/docs/stack.html#order).\\n- For line and trail marks, this `order` channel encodes order of data points in the lines. This can be useful for creating [a connected scatterplot](https://vega.github.io/vega-lite/examples/connected_scatterplot.html). Setting `order` to `{\\\"value\\\": null}` makes the line marks use the original order in the data sources.\\n- Otherwise, this `order` channel encodes layer order of the marks.\\n\\n__Note__: In aggregate plots, `order` field should be `aggregate`d to avoid creating additional aggregation grouping.\"\n                },\n                \"radius\": {\n                    \"$ref\": \"#/definitions/PolarDef\",\n                    \"description\": \"The outer radius in pixels of arc marks.\"\n                },\n                \"radius2\": {\n                    \"$ref\": \"#/definitions/Position2Def\",\n                    \"description\": \"The inner radius in pixels of arc marks.\"\n                },\n                \"row\": {\n                    \"$ref\": \"#/definitions/RowColumnEncodingFieldDef\",\n                    \"description\": \"A field definition for the vertical facet of trellis plots.\"\n                },\n                \"shape\": {\n                    \"$ref\": \"#/definitions/ShapeDef\",\n                    \"description\": \"Shape of the mark.\\n\\n1. For `point` marks the supported values include:   - plotting shapes: `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"cross\\\"`, `\\\"diamond\\\"`, `\\\"triangle-up\\\"`, `\\\"triangle-down\\\"`, `\\\"triangle-right\\\"`, or `\\\"triangle-left\\\"`.   - the line symbol `\\\"stroke\\\"`   - centered directional shapes `\\\"arrow\\\"`, `\\\"wedge\\\"`, or `\\\"triangle\\\"`   - a custom [SVG path string](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths) (For correct sizing, custom shape paths should be defined within a square bounding box with coordinates ranging from -1 to 1 along both the x and y dimensions.)\\n\\n2. For `geoshape` marks it should be a field definition of the geojson data\\n\\n__Default value:__ If undefined, the default shape depends on [mark config](https://vega.github.io/vega-lite/docs/config.html#point-config)'s `shape` property. (`\\\"circle\\\"` if unset.)\"\n                },\n                \"size\": {\n                    \"$ref\": \"#/definitions/NumericMarkPropDef\",\n                    \"description\": \"Size of the mark.\\n- For `\\\"point\\\"`, `\\\"square\\\"` and `\\\"circle\\\"`, – the symbol size, or pixel area of the mark.\\n- For `\\\"bar\\\"` and `\\\"tick\\\"` – the bar and tick's size.\\n- For `\\\"text\\\"` – the text's font size.\\n- Size is unsupported for `\\\"line\\\"`, `\\\"area\\\"`, and `\\\"rect\\\"`. (Use `\\\"trail\\\"` instead of line with varying size)\"\n                },\n                \"stroke\": {\n                    \"$ref\": \"#/definitions/ColorDef\",\n                    \"description\": \"Stroke color of the marks. __Default value:__ If undefined, the default color depends on [mark config](https://vega.github.io/vega-lite/docs/config.html#mark-config)'s `color` property.\\n\\n_Note:_ The `stroke` encoding has higher precedence than `color`, thus may override the `color` encoding if conflicting encodings are specified.\"\n                },\n                \"strokeDash\": {\n                    \"$ref\": \"#/definitions/NumericArrayMarkPropDef\",\n                    \"description\": \"Stroke dash of the marks.\\n\\n__Default value:__ `[1,0]` (No dash).\"\n                },\n                \"strokeOpacity\": {\n                    \"$ref\": \"#/definitions/NumericMarkPropDef\",\n                    \"description\": \"Stroke opacity of the marks.\\n\\n__Default value:__ If undefined, the default opacity depends on [mark config](https://vega.github.io/vega-lite/docs/config.html#mark-config)'s `strokeOpacity` property.\"\n                },\n                \"strokeWidth\": {\n                    \"$ref\": \"#/definitions/NumericMarkPropDef\",\n                    \"description\": \"Stroke width of the marks.\\n\\n__Default value:__ If undefined, the default stroke width depends on [mark config](https://vega.github.io/vega-lite/docs/config.html#mark-config)'s `strokeWidth` property.\"\n                },\n                \"text\": {\n                    \"$ref\": \"#/definitions/TextDef\",\n                    \"description\": \"Text of the `text` mark.\"\n                },\n                \"theta\": {\n                    \"$ref\": \"#/definitions/PolarDef\",\n                    \"description\": \"- For arc marks, the arc length in radians if theta2 is not specified, otherwise the start arc angle. (A value of 0 indicates up or “north”, increasing values proceed clockwise.)\\n\\n- For text marks, polar coordinate angle in radians.\"\n                },\n                \"theta2\": {\n                    \"$ref\": \"#/definitions/Position2Def\",\n                    \"description\": \"The end angle of arc marks in radians. A value of 0 indicates up or “north”, increasing values proceed clockwise.\"\n                },\n                \"time\": {\n                    \"$ref\": \"#/definitions/TimeDef\"\n                },\n                \"tooltip\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StringFieldDefWithCondition\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/StringValueDefWithCondition\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/StringFieldDef\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"The tooltip text to show upon mouse hover. Specifying `tooltip` encoding overrides [the `tooltip` property in the mark definition](https://vega.github.io/vega-lite/docs/mark.html#mark-def).\\n\\nSee the [`tooltip`](https://vega.github.io/vega-lite/docs/tooltip.html) documentation for a detailed discussion about tooltip in Vega-Lite.\"\n                },\n                \"url\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StringFieldDefWithCondition\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/StringValueDefWithCondition\"\n                        }\n                    ],\n                    \"description\": \"The URL of an image mark.\"\n                },\n                \"x\": {\n                    \"$ref\": \"#/definitions/PositionDef\",\n                    \"description\": \"X coordinates of the marks, or width of horizontal `\\\"bar\\\"` and `\\\"area\\\"` without specified `x2` or `width`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"x2\": {\n                    \"$ref\": \"#/definitions/Position2Def\",\n                    \"description\": \"X2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"xError\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SecondaryFieldDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ValueDef<number>\"\n                        }\n                    ],\n                    \"description\": \"Error value of x coordinates for error specified `\\\"errorbar\\\"` and `\\\"errorband\\\"`.\"\n                },\n                \"xError2\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SecondaryFieldDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ValueDef<number>\"\n                        }\n                    ],\n                    \"description\": \"Secondary error value of x coordinates for error specified `\\\"errorbar\\\"` and `\\\"errorband\\\"`.\"\n                },\n                \"xOffset\": {\n                    \"$ref\": \"#/definitions/OffsetDef\",\n                    \"description\": \"Offset of x-position of the marks\"\n                },\n                \"y\": {\n                    \"$ref\": \"#/definitions/PositionDef\",\n                    \"description\": \"Y coordinates of the marks, or height of vertical `\\\"bar\\\"` and `\\\"area\\\"` without specified `y2` or `height`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                },\n                \"y2\": {\n                    \"$ref\": \"#/definitions/Position2Def\",\n                    \"description\": \"Y2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                },\n                \"yError\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SecondaryFieldDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ValueDef<number>\"\n                        }\n                    ],\n                    \"description\": \"Error value of y coordinates for error specified `\\\"errorbar\\\"` and `\\\"errorband\\\"`.\"\n                },\n                \"yError2\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SecondaryFieldDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ValueDef<number>\"\n                        }\n                    ],\n                    \"description\": \"Secondary error value of y coordinates for error specified `\\\"errorbar\\\"` and `\\\"errorband\\\"`.\"\n                },\n                \"yOffset\": {\n                    \"$ref\": \"#/definitions/OffsetDef\",\n                    \"description\": \"Offset of y-position of the marks\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"FacetedUnitSpec\": {\n            \"additionalProperties\": false,\n            \"description\": \"Unit spec that can have a composite mark and row or column channels (shorthand for a facet spec).\",\n            \"properties\": {\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LayoutAlign\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<LayoutAlign>\"\n                        }\n                    ],\n                    \"description\": \"The alignment to apply to grid rows and columns. The supported string values are `\\\"all\\\"`, `\\\"each\\\"`, and `\\\"none\\\"`.\\n\\n- For `\\\"none\\\"`, a flow layout will be used, in which adjacent subviews are simply placed one after the other.\\n- For `\\\"each\\\"`, subviews will be aligned into a clean grid structure, but each row or column may be of variable size.\\n- For `\\\"all\\\"`, subviews will be aligned and each row or column will be sized identically based on the maximum observed size. String values for this property will be applied to both grid rows and columns.\\n\\nAlternatively, an object value of the form `{\\\"row\\\": string, \\\"column\\\": string}` can be used to supply different alignments for rows and columns.\\n\\n__Default value:__ `\\\"all\\\"`.\"\n                },\n                \"bounds\": {\n                    \"description\": \"The bounds calculation method to use for determining the extent of a sub-plot. One of `full` (the default) or `flush`.\\n\\n- If set to `full`, the entire calculated bounds (including axes, title, and legend) will be used.\\n- If set to `flush`, only the specified width and height values for the sub-view will be used. The `flush` setting can be useful when attempting to place sub-plots without axes or legends into a uniform grid structure.\\n\\n__Default value:__ `\\\"full\\\"`\",\n                    \"enum\": [\n                        \"full\",\n                        \"flush\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"center\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<boolean>\"\n                        }\n                    ],\n                    \"description\": \"Boolean flag indicating if subviews should be centered relative to their respective rows or columns.\\n\\nAn object value of the form `{\\\"row\\\": boolean, \\\"column\\\": boolean}` can be used to supply different centering values for rows and columns.\\n\\n__Default value:__ `false`\"\n                },\n                \"data\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Data\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                },\n                \"description\": {\n                    \"description\": \"Description of this mark for commenting purpose.\",\n                    \"type\": \"string\"\n                },\n                \"encoding\": {\n                    \"$ref\": \"#/definitions/FacetedEncoding\",\n                    \"description\": \"A key-value mapping between encoding channels and definition of fields.\"\n                },\n                \"height\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"container\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Step\"\n                        }\n                    ],\n                    \"description\": \"The height of a visualization.\\n\\n- For a plot with a continuous y-field, height should be a number.\\n- For a plot with either a discrete y-field or no y-field, height can be either a number indicating a fixed height or an object in the form of `{step: number}` defining the height per discrete step. (No y-field is equivalent to having one discrete step.)\\n- To enable responsive sizing on height, it should be set to `\\\"container\\\"`.\\n\\n__Default value:__ Based on `config.view.continuousHeight` for a plot with a continuous y-field and `config.view.discreteHeight` otherwise.\\n\\n__Note:__ For plots with [`row` and `column` channels](https://vega.github.io/vega-lite/docs/encoding.html#facet), this represents the height of a single view and the `\\\"container\\\"` option cannot be used.\\n\\n__See also:__ [`height`](https://vega.github.io/vega-lite/docs/size.html) documentation.\"\n                },\n                \"mark\": {\n                    \"$ref\": \"#/definitions/AnyMark\",\n                    \"description\": \"A string describing the mark type (one of `\\\"bar\\\"`, `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"tick\\\"`, `\\\"line\\\"`, `\\\"area\\\"`, `\\\"point\\\"`, `\\\"rule\\\"`, `\\\"geoshape\\\"`, and `\\\"text\\\"`) or a [mark definition object](https://vega.github.io/vega-lite/docs/mark.html#mark-def).\"\n                },\n                \"name\": {\n                    \"description\": \"Name of the visualization for later reference.\",\n                    \"type\": \"string\"\n                },\n                \"params\": {\n                    \"description\": \"An array of parameters that may either be simple variables, or more complex selections that map user input to data queries.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/SelectionParameter\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"projection\": {\n                    \"$ref\": \"#/definitions/Projection\",\n                    \"description\": \"An object defining properties of geographic projection, which will be applied to `shape` path for `\\\"geoshape\\\"` marks and to `latitude` and `\\\"longitude\\\"` channels for other marks.\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/Resolve\",\n                    \"description\": \"Scale, axis, and legend resolutions for view composition specifications.\"\n                },\n                \"spacing\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<number>\"\n                        }\n                    ],\n                    \"description\": \"The spacing in pixels between sub-views of the composition operator. An object of the form `{\\\"row\\\": number, \\\"column\\\": number}` can be used to set different spacing values for rows and columns.\\n\\n__Default value__: Depends on `\\\"spacing\\\"` property of [the view composition configuration](https://vega.github.io/vega-lite/docs/config.html#view-config) (`20` by default)\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TitleParams\"\n                        }\n                    ],\n                    \"description\": \"Title for the plot.\"\n                },\n                \"transform\": {\n                    \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Transform\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"view\": {\n                    \"$ref\": \"#/definitions/ViewBackground\",\n                    \"description\": \"An object defining the view background's fill and stroke.\\n\\n__Default value:__ none (transparent)\"\n                },\n                \"width\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"container\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Step\"\n                        }\n                    ],\n                    \"description\": \"The width of a visualization.\\n\\n- For a plot with a continuous x-field, width should be a number.\\n- For a plot with either a discrete x-field or no x-field, width can be either a number indicating a fixed width or an object in the form of `{step: number}` defining the width per discrete step. (No x-field is equivalent to having one discrete step.)\\n- To enable responsive sizing on width, it should be set to `\\\"container\\\"`.\\n\\n__Default value:__ Based on `config.view.continuousWidth` for a plot with a continuous x-field and `config.view.discreteWidth` otherwise.\\n\\n__Note:__ For plots with [`row` and `column` channels](https://vega.github.io/vega-lite/docs/encoding.html#facet), this represents the width of a single view and the `\\\"container\\\"` option cannot be used.\\n\\n__See also:__ [`width`](https://vega.github.io/vega-lite/docs/size.html) documentation.\"\n                }\n            },\n            \"required\": [\n                \"mark\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Feature\": {\n            \"additionalProperties\": false,\n            \"description\": \"A feature object which contains a geometry and associated properties. https://tools.ietf.org/html/rfc7946#section-3.2\",\n            \"properties\": {\n                \"bbox\": {\n                    \"$ref\": \"#/definitions/BBox\",\n                    \"description\": \"Bounding box of the coordinate range of the object's Geometries, Features, or Feature Collections. https://tools.ietf.org/html/rfc7946#section-5\"\n                },\n                \"geometry\": {\n                    \"$ref\": \"#/definitions/Geometry\",\n                    \"description\": \"The feature's geometry\"\n                },\n                \"id\": {\n                    \"description\": \"A value that uniquely identifies this feature in a https://tools.ietf.org/html/rfc7946#section-3.2.\",\n                    \"type\": [\n                        \"string\",\n                        \"number\"\n                    ]\n                },\n                \"properties\": {\n                    \"$ref\": \"#/definitions/GeoJsonProperties\",\n                    \"description\": \"Properties associated with this feature.\"\n                },\n                \"type\": {\n                    \"const\": \"Feature\",\n                    \"description\": \"Specifies the type of GeoJSON object.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"geometry\",\n                \"properties\",\n                \"type\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Feature<Geometry,GeoJsonProperties>\": {\n            \"additionalProperties\": false,\n            \"description\": \"A feature object which contains a geometry and associated properties. https://tools.ietf.org/html/rfc7946#section-3.2\",\n            \"properties\": {\n                \"bbox\": {\n                    \"$ref\": \"#/definitions/BBox\",\n                    \"description\": \"Bounding box of the coordinate range of the object's Geometries, Features, or Feature Collections. https://tools.ietf.org/html/rfc7946#section-5\"\n                },\n                \"geometry\": {\n                    \"$ref\": \"#/definitions/Geometry\",\n                    \"description\": \"The feature's geometry\"\n                },\n                \"id\": {\n                    \"description\": \"A value that uniquely identifies this feature in a https://tools.ietf.org/html/rfc7946#section-3.2.\",\n                    \"type\": [\n                        \"string\",\n                        \"number\"\n                    ]\n                },\n                \"properties\": {\n                    \"$ref\": \"#/definitions/GeoJsonProperties\",\n                    \"description\": \"Properties associated with this feature.\"\n                },\n                \"type\": {\n                    \"const\": \"Feature\",\n                    \"description\": \"Specifies the type of GeoJSON object.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"geometry\",\n                \"properties\",\n                \"type\"\n            ],\n            \"type\": \"object\"\n        },\n        \"FeatureCollection\": {\n            \"additionalProperties\": false,\n            \"description\": \"A collection of feature objects.  https://tools.ietf.org/html/rfc7946#section-3.3\",\n            \"properties\": {\n                \"bbox\": {\n                    \"$ref\": \"#/definitions/BBox\",\n                    \"description\": \"Bounding box of the coordinate range of the object's Geometries, Features, or Feature Collections. https://tools.ietf.org/html/rfc7946#section-5\"\n                },\n                \"features\": {\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Feature<Geometry,GeoJsonProperties>\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"type\": {\n                    \"const\": \"FeatureCollection\",\n                    \"description\": \"Specifies the type of GeoJSON object.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"features\",\n                \"type\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Field\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/FieldName\"\n                },\n                {\n                    \"$ref\": \"#/definitions/RepeatRef\"\n                }\n            ]\n        },\n        \"FieldDefWithoutScale\": {\n            \"$ref\": \"#/definitions/TypedFieldDef\",\n            \"description\": \"Field Def without scale (and without bin: \\\"binned\\\" support).\"\n        },\n        \"FieldEqualPredicate\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"equal\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/DateTime\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The value that the field should be equal to.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"Field to be tested.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit for the field to be tested.\"\n                }\n            },\n            \"required\": [\n                \"equal\",\n                \"field\"\n            ],\n            \"type\": \"object\"\n        },\n        \"FieldGTEPredicate\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"field\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"Field to be tested.\"\n                },\n                \"gte\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/DateTime\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The value that the field should be greater than or equals to.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit for the field to be tested.\"\n                }\n            },\n            \"required\": [\n                \"field\",\n                \"gte\"\n            ],\n            \"type\": \"object\"\n        },\n        \"FieldGTPredicate\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"field\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"Field to be tested.\"\n                },\n                \"gt\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/DateTime\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The value that the field should be greater than.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit for the field to be tested.\"\n                }\n            },\n            \"required\": [\n                \"field\",\n                \"gt\"\n            ],\n            \"type\": \"object\"\n        },\n        \"FieldLTEPredicate\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"field\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"Field to be tested.\"\n                },\n                \"lte\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/DateTime\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The value that the field should be less than or equals to.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit for the field to be tested.\"\n                }\n            },\n            \"required\": [\n                \"field\",\n                \"lte\"\n            ],\n            \"type\": \"object\"\n        },\n        \"FieldLTPredicate\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"field\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"Field to be tested.\"\n                },\n                \"lt\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/DateTime\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The value that the field should be less than.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit for the field to be tested.\"\n                }\n            },\n            \"required\": [\n                \"field\",\n                \"lt\"\n            ],\n            \"type\": \"object\"\n        },\n        \"FieldName\": {\n            \"type\": \"string\"\n        },\n        \"FieldOneOfPredicate\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"field\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"Field to be tested.\"\n                },\n                \"oneOf\": {\n                    \"anyOf\": [\n                        {\n                            \"items\": {\n                                \"type\": \"string\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"items\": {\n                                \"type\": \"boolean\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/DateTime\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"A set of values that the `field`'s value should be a member of, for a data item included in the filtered data.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit for the field to be tested.\"\n                }\n            },\n            \"required\": [\n                \"field\",\n                \"oneOf\"\n            ],\n            \"type\": \"object\"\n        },\n        \"FieldOrDatumDefWithCondition<DatumDef,(Gradient|string|null)>\": {\n            \"additionalProperties\": false,\n            \"description\": \"A FieldDef with Condition<ValueDef> {   condition: {value: ...},   field: ...,   ... }\",\n            \"properties\": {\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                },\n                \"datum\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/PrimitiveValue\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/DateTime\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RepeatRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in data domain.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/Type\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"FieldOrDatumDefWithCondition<DatumDef,(string|null)>\": {\n            \"additionalProperties\": false,\n            \"description\": \"A FieldDef with Condition<ValueDef> {   condition: {value: ...},   field: ...,   ... }\",\n            \"properties\": {\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                },\n                \"datum\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/PrimitiveValue\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/DateTime\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RepeatRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in data domain.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/Type\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"FieldOrDatumDefWithCondition<DatumDef,number>\": {\n            \"additionalProperties\": false,\n            \"description\": \"A FieldDef with Condition<ValueDef> {   condition: {value: ...},   field: ...,   ... }\",\n            \"properties\": {\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                },\n                \"datum\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/PrimitiveValue\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/DateTime\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RepeatRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in data domain.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/Type\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"FieldOrDatumDefWithCondition<DatumDef,number[]>\": {\n            \"additionalProperties\": false,\n            \"description\": \"A FieldDef with Condition<ValueDef> {   condition: {value: ...},   field: ...,   ... }\",\n            \"properties\": {\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<(number[]|ExprRef)>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<(number[]|ExprRef)>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                },\n                \"datum\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/PrimitiveValue\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/DateTime\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RepeatRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in data domain.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/Type\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"FieldOrDatumDefWithCondition<MarkPropFieldDef,(Gradient|string|null)>\": {\n            \"additionalProperties\": false,\n            \"description\": \"A FieldDef with Condition<ValueDef> {   condition: {value: ...},   field: ...,   ... }\",\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"legend\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Legend\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                },\n                \"scale\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Scale\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                },\n                \"sort\": {\n                    \"$ref\": \"#/definitions/Sort\",\n                    \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/StandardType\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"FieldOrDatumDefWithCondition<MarkPropFieldDef,number>\": {\n            \"additionalProperties\": false,\n            \"description\": \"A FieldDef with Condition<ValueDef> {   condition: {value: ...},   field: ...,   ... }\",\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"legend\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Legend\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                },\n                \"scale\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Scale\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                },\n                \"sort\": {\n                    \"$ref\": \"#/definitions/Sort\",\n                    \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/StandardType\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"FieldOrDatumDefWithCondition<MarkPropFieldDef,number[]>\": {\n            \"additionalProperties\": false,\n            \"description\": \"A FieldDef with Condition<ValueDef> {   condition: {value: ...},   field: ...,   ... }\",\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<(number[]|ExprRef)>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<(number[]|ExprRef)>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"legend\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Legend\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                },\n                \"scale\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Scale\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                },\n                \"sort\": {\n                    \"$ref\": \"#/definitions/Sort\",\n                    \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/StandardType\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"FieldOrDatumDefWithCondition<MarkPropFieldDef<TypeForShape>,(string|null)>\": {\n            \"additionalProperties\": false,\n            \"description\": \"A FieldDef with Condition<ValueDef> {   condition: {value: ...},   field: ...,   ... }\",\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"legend\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Legend\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                },\n                \"scale\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Scale\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                },\n                \"sort\": {\n                    \"$ref\": \"#/definitions/Sort\",\n                    \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/TypeForShape\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"FieldOrDatumDefWithCondition<StringDatumDef,Text>\": {\n            \"additionalProperties\": false,\n            \"description\": \"A FieldDef with Condition<ValueDef> {   condition: {value: ...},   field: ...,   ... }\",\n            \"properties\": {\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<(Text|ExprRef)>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<(Text|ExprRef)>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                },\n                \"datum\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/PrimitiveValue\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/DateTime\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RepeatRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in data domain.\"\n                },\n                \"format\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Dict\"\n                        }\n                    ],\n                    \"description\": \"When used with the default `\\\"number\\\"` and `\\\"time\\\"` format type, the text formatting pattern for labels of guides (axes, legends, headers) and text marks.\\n\\n- If the format type is `\\\"number\\\"` (e.g., for quantitative fields), this is D3's [number format pattern](https://github.com/d3/d3-format#locale_format).\\n- If the format type is `\\\"time\\\"` (e.g., for temporal fields), this is D3's [time format pattern](https://github.com/d3/d3-time-format#locale_format).\\n\\nSee the [format documentation](https://vega.github.io/vega-lite/docs/format.html) for more examples.\\n\\nWhen used with a [custom `formatType`](https://vega.github.io/vega-lite/docs/config.html#custom-format-type), this value will be passed as `format` alongside `datum.value` to the registered function.\\n\\n__Default value:__  Derived from [numberFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for number format and from [timeFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for time format.\"\n                },\n                \"formatType\": {\n                    \"description\": \"The format type for labels. One of `\\\"number\\\"`, `\\\"time\\\"`, or a [registered custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type).\\n\\n__Default value:__\\n- `\\\"time\\\"` for temporal fields and ordinal and nominal fields with `timeUnit`.\\n- `\\\"number\\\"` for quantitative fields as well as ordinal and nominal fields without `timeUnit`.\",\n                    \"type\": \"string\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/Type\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"FieldOrDatumDefWithCondition<StringFieldDef,Text>\": {\n            \"additionalProperties\": false,\n            \"description\": \"A FieldDef with Condition<ValueDef> {   condition: {value: ...},   field: ...,   ... }\",\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"const\": \"binned\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<(Text|ExprRef)>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<(Text|ExprRef)>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"format\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Dict\"\n                        }\n                    ],\n                    \"description\": \"When used with the default `\\\"number\\\"` and `\\\"time\\\"` format type, the text formatting pattern for labels of guides (axes, legends, headers) and text marks.\\n\\n- If the format type is `\\\"number\\\"` (e.g., for quantitative fields), this is D3's [number format pattern](https://github.com/d3/d3-format#locale_format).\\n- If the format type is `\\\"time\\\"` (e.g., for temporal fields), this is D3's [time format pattern](https://github.com/d3/d3-time-format#locale_format).\\n\\nSee the [format documentation](https://vega.github.io/vega-lite/docs/format.html) for more examples.\\n\\nWhen used with a [custom `formatType`](https://vega.github.io/vega-lite/docs/config.html#custom-format-type), this value will be passed as `format` alongside `datum.value` to the registered function.\\n\\n__Default value:__  Derived from [numberFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for number format and from [timeFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for time format.\"\n                },\n                \"formatType\": {\n                    \"description\": \"The format type for labels. One of `\\\"number\\\"`, `\\\"time\\\"`, or a [registered custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type).\\n\\n__Default value:__\\n- `\\\"time\\\"` for temporal fields and ordinal and nominal fields with `timeUnit`.\\n- `\\\"number\\\"` for quantitative fields as well as ordinal and nominal fields without `timeUnit`.\",\n                    \"type\": \"string\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/StandardType\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"FieldOrDatumDefWithCondition<StringFieldDef,string>\": {\n            \"additionalProperties\": false,\n            \"description\": \"A FieldDef with Condition<ValueDef> {   condition: {value: ...},   field: ...,   ... }\",\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"const\": \"binned\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<(string|ExprRef)>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<(string|ExprRef)>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"format\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Dict\"\n                        }\n                    ],\n                    \"description\": \"When used with the default `\\\"number\\\"` and `\\\"time\\\"` format type, the text formatting pattern for labels of guides (axes, legends, headers) and text marks.\\n\\n- If the format type is `\\\"number\\\"` (e.g., for quantitative fields), this is D3's [number format pattern](https://github.com/d3/d3-format#locale_format).\\n- If the format type is `\\\"time\\\"` (e.g., for temporal fields), this is D3's [time format pattern](https://github.com/d3/d3-time-format#locale_format).\\n\\nSee the [format documentation](https://vega.github.io/vega-lite/docs/format.html) for more examples.\\n\\nWhen used with a [custom `formatType`](https://vega.github.io/vega-lite/docs/config.html#custom-format-type), this value will be passed as `format` alongside `datum.value` to the registered function.\\n\\n__Default value:__  Derived from [numberFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for number format and from [timeFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for time format.\"\n                },\n                \"formatType\": {\n                    \"description\": \"The format type for labels. One of `\\\"number\\\"`, `\\\"time\\\"`, or a [registered custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type).\\n\\n__Default value:__\\n- `\\\"time\\\"` for temporal fields and ordinal and nominal fields with `timeUnit`.\\n- `\\\"number\\\"` for quantitative fields as well as ordinal and nominal fields without `timeUnit`.\",\n                    \"type\": \"string\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/StandardType\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"FieldRange\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"field\": {\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"field\"\n            ],\n            \"type\": \"object\"\n        },\n        \"FieldRangePredicate\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"field\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"Field to be tested.\"\n                },\n                \"range\": {\n                    \"anyOf\": [\n                        {\n                            \"items\": {\n                                \"anyOf\": [\n                                    {\n                                        \"type\": \"number\"\n                                    },\n                                    {\n                                        \"$ref\": \"#/definitions/DateTime\"\n                                    },\n                                    {\n                                        \"type\": \"null\"\n                                    },\n                                    {\n                                        \"$ref\": \"#/definitions/ExprRef\"\n                                    }\n                                ]\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"An array of inclusive minimum and maximum values for a field value of a data item to be included in the filtered data.\",\n                    \"maxItems\": 2,\n                    \"minItems\": 2\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit for the field to be tested.\"\n                }\n            },\n            \"required\": [\n                \"field\",\n                \"range\"\n            ],\n            \"type\": \"object\"\n        },\n        \"FieldValidPredicate\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"field\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"Field to be tested.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit for the field to be tested.\"\n                },\n                \"valid\": {\n                    \"description\": \"If set to true the field's value has to be valid, meaning both not `null` and not [`NaN`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN).\",\n                    \"type\": \"boolean\"\n                }\n            },\n            \"required\": [\n                \"field\",\n                \"valid\"\n            ],\n            \"type\": \"object\"\n        },\n        \"FilterTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"filter\": {\n                    \"$ref\": \"#/definitions/PredicateComposition\",\n                    \"description\": \"The `filter` property must be a predication definition, which can take one of the following forms:\\n\\n1) an [expression](https://vega.github.io/vega-lite/docs/types.html#expression) string, where `datum` can be used to refer to the current data object. For example, `{filter: \\\"datum.b2 > 60\\\"}` would make the output data includes only items that have values in the field `b2` over 60.\\n\\n2) one of the [field predicates](https://vega.github.io/vega-lite/docs/predicate.html#field-predicate): [`equal`](https://vega.github.io/vega-lite/docs/predicate.html#field-equal-predicate), [`lt`](https://vega.github.io/vega-lite/docs/predicate.html#lt-predicate), [`lte`](https://vega.github.io/vega-lite/docs/predicate.html#lte-predicate), [`gt`](https://vega.github.io/vega-lite/docs/predicate.html#gt-predicate), [`gte`](https://vega.github.io/vega-lite/docs/predicate.html#gte-predicate), [`range`](https://vega.github.io/vega-lite/docs/predicate.html#range-predicate), [`oneOf`](https://vega.github.io/vega-lite/docs/predicate.html#one-of-predicate), or [`valid`](https://vega.github.io/vega-lite/docs/predicate.html#valid-predicate),\\n\\n3) a [selection predicate](https://vega.github.io/vega-lite/docs/predicate.html#selection-predicate), which define the names of a selection that the data point should belong to (or a logical composition of selections).\\n\\n4) a [logical composition](https://vega.github.io/vega-lite/docs/predicate.html#composition) of (1), (2), or (3).\"\n                }\n            },\n            \"required\": [\n                \"filter\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Fit\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/GeoJsonFeature\"\n                },\n                {\n                    \"$ref\": \"#/definitions/GeoJsonFeatureCollection\"\n                },\n                {\n                    \"items\": {\n                        \"$ref\": \"#/definitions/GeoJsonFeature\"\n                    },\n                    \"type\": \"array\"\n                }\n            ]\n        },\n        \"FlattenTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"as\": {\n                    \"description\": \"The output field names for extracted array values.\\n\\n__Default value:__ The field name of the corresponding array field\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"flatten\": {\n                    \"description\": \"An array of one or more data fields containing arrays to flatten. If multiple fields are specified, their array values should have a parallel structure, ideally with the same length. If the lengths of parallel arrays do not match, the longest array will be used with `null` values added for missing entries.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"flatten\"\n            ],\n            \"type\": \"object\"\n        },\n        \"FoldTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"as\": {\n                    \"description\": \"The output field names for the key and value properties produced by the fold transform. __Default value:__ `[\\\"key\\\", \\\"value\\\"]`\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"maxItems\": 2,\n                    \"minItems\": 2,\n                    \"type\": \"array\"\n                },\n                \"fold\": {\n                    \"description\": \"An array of data fields indicating the properties to fold.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"fold\"\n            ],\n            \"type\": \"object\"\n        },\n        \"FontStyle\": {\n            \"type\": \"string\"\n        },\n        \"FontWeight\": {\n            \"enum\": [\n                \"normal\",\n                \"bold\",\n                \"lighter\",\n                \"bolder\",\n                100,\n                200,\n                300,\n                400,\n                500,\n                600,\n                700,\n                800,\n                900\n            ],\n            \"type\": [\n                \"string\",\n                \"number\"\n            ]\n        },\n        \"FormatConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"normalizedNumberFormat\": {\n                    \"description\": \"If normalizedNumberFormatType is not specified, D3 number format for axis labels, text marks, and tooltips of normalized stacked fields (fields with `stack: \\\"normalize\\\"`). For example `\\\"s\\\"` for SI units. Use [D3's number format pattern](https://github.com/d3/d3-format#locale_format).\\n\\nIf `config.normalizedNumberFormatType` is specified and `config.customFormatTypes` is `true`, this value will be passed as `format` alongside `datum.value` to the `config.numberFormatType` function. __Default value:__ `%`\",\n                    \"type\": \"string\"\n                },\n                \"normalizedNumberFormatType\": {\n                    \"description\": \"[Custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type) for `config.normalizedNumberFormat`.\\n\\n__Default value:__ `undefined` -- This is equilvalent to call D3-format, which is exposed as [`format` in Vega-Expression](https://vega.github.io/vega/docs/expressions/#format). __Note:__ You must also set `customFormatTypes` to `true` to use this feature.\",\n                    \"type\": \"string\"\n                },\n                \"numberFormat\": {\n                    \"description\": \"If numberFormatType is not specified, D3 number format for guide labels, text marks, and tooltips of non-normalized fields (fields *without* `stack: \\\"normalize\\\"`). For example `\\\"s\\\"` for SI units. Use [D3's number format pattern](https://github.com/d3/d3-format#locale_format).\\n\\nIf `config.numberFormatType` is specified and `config.customFormatTypes` is `true`, this value will be passed as `format` alongside `datum.value` to the `config.numberFormatType` function.\",\n                    \"type\": \"string\"\n                },\n                \"numberFormatType\": {\n                    \"description\": \"[Custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type) for `config.numberFormat`.\\n\\n__Default value:__ `undefined` -- This is equilvalent to call D3-format, which is exposed as [`format` in Vega-Expression](https://vega.github.io/vega/docs/expressions/#format). __Note:__ You must also set `customFormatTypes` to `true` to use this feature.\",\n                    \"type\": \"string\"\n                },\n                \"timeFormat\": {\n                    \"description\": \"Default time format for raw time values (without time units) in text marks, legend labels and header labels.\\n\\n__Default value:__ `\\\"%b %d, %Y\\\"` __Note:__ Axes automatically determine the format for each label automatically so this config does not affect axes.\",\n                    \"type\": \"string\"\n                },\n                \"timeFormatType\": {\n                    \"description\": \"[Custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type) for `config.timeFormat`.\\n\\n__Default value:__ `undefined` -- This is equilvalent to call D3-time-format, which is exposed as [`timeFormat` in Vega-Expression](https://vega.github.io/vega/docs/expressions/#timeFormat). __Note:__ You must also set `customFormatTypes` to `true` and there must *not* be a `timeUnit` defined to use this feature.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"Generator\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/SequenceGenerator\"\n                },\n                {\n                    \"$ref\": \"#/definitions/SphereGenerator\"\n                },\n                {\n                    \"$ref\": \"#/definitions/GraticuleGenerator\"\n                }\n            ]\n        },\n        \"ConcatSpec<GenericSpec>\": {\n            \"additionalProperties\": false,\n            \"description\": \"Base interface for a generalized concatenation specification.\",\n            \"properties\": {\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LayoutAlign\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<LayoutAlign>\"\n                        }\n                    ],\n                    \"description\": \"The alignment to apply to grid rows and columns. The supported string values are `\\\"all\\\"`, `\\\"each\\\"`, and `\\\"none\\\"`.\\n\\n- For `\\\"none\\\"`, a flow layout will be used, in which adjacent subviews are simply placed one after the other.\\n- For `\\\"each\\\"`, subviews will be aligned into a clean grid structure, but each row or column may be of variable size.\\n- For `\\\"all\\\"`, subviews will be aligned and each row or column will be sized identically based on the maximum observed size. String values for this property will be applied to both grid rows and columns.\\n\\nAlternatively, an object value of the form `{\\\"row\\\": string, \\\"column\\\": string}` can be used to supply different alignments for rows and columns.\\n\\n__Default value:__ `\\\"all\\\"`.\"\n                },\n                \"bounds\": {\n                    \"description\": \"The bounds calculation method to use for determining the extent of a sub-plot. One of `full` (the default) or `flush`.\\n\\n- If set to `full`, the entire calculated bounds (including axes, title, and legend) will be used.\\n- If set to `flush`, only the specified width and height values for the sub-view will be used. The `flush` setting can be useful when attempting to place sub-plots without axes or legends into a uniform grid structure.\\n\\n__Default value:__ `\\\"full\\\"`\",\n                    \"enum\": [\n                        \"full\",\n                        \"flush\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"center\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<boolean>\"\n                        }\n                    ],\n                    \"description\": \"Boolean flag indicating if subviews should be centered relative to their respective rows or columns.\\n\\nAn object value of the form `{\\\"row\\\": boolean, \\\"column\\\": boolean}` can be used to supply different centering values for rows and columns.\\n\\n__Default value:__ `false`\"\n                },\n                \"columns\": {\n                    \"description\": \"The number of columns to include in the view composition layout.\\n\\n__Default value__: `undefined` -- An infinite number of columns (a single row) will be assumed. This is equivalent to `hconcat` (for `concat`) and to using the `column` channel (for `facet` and `repeat`).\\n\\n__Note__:\\n\\n1) This property is only for:\\n- the general (wrappable) `concat` operator (not `hconcat`/`vconcat`)\\n- the `facet` and `repeat` operator with one field/repetition definition (without row/column nesting)\\n\\n2) Setting the `columns` to `1` is equivalent to `vconcat` (for `concat`) and to using the `row` channel (for `facet` and `repeat`).\",\n                    \"type\": \"number\"\n                },\n                \"concat\": {\n                    \"description\": \"A list of views to be concatenated.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Spec\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"data\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Data\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                },\n                \"description\": {\n                    \"description\": \"Description of this mark for commenting purpose.\",\n                    \"type\": \"string\"\n                },\n                \"name\": {\n                    \"description\": \"Name of the visualization for later reference.\",\n                    \"type\": \"string\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/Resolve\",\n                    \"description\": \"Scale, axis, and legend resolutions for view composition specifications.\"\n                },\n                \"spacing\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<number>\"\n                        }\n                    ],\n                    \"description\": \"The spacing in pixels between sub-views of the composition operator. An object of the form `{\\\"row\\\": number, \\\"column\\\": number}` can be used to set different spacing values for rows and columns.\\n\\n__Default value__: Depends on `\\\"spacing\\\"` property of [the view composition configuration](https://vega.github.io/vega-lite/docs/config.html#view-config) (`20` by default)\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TitleParams\"\n                        }\n                    ],\n                    \"description\": \"Title for the plot.\"\n                },\n                \"transform\": {\n                    \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Transform\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"concat\"\n            ],\n            \"type\": \"object\"\n        },\n        \"FacetSpec\": {\n            \"additionalProperties\": false,\n            \"description\": \"Base interface for a facet specification.\",\n            \"properties\": {\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LayoutAlign\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<LayoutAlign>\"\n                        }\n                    ],\n                    \"description\": \"The alignment to apply to grid rows and columns. The supported string values are `\\\"all\\\"`, `\\\"each\\\"`, and `\\\"none\\\"`.\\n\\n- For `\\\"none\\\"`, a flow layout will be used, in which adjacent subviews are simply placed one after the other.\\n- For `\\\"each\\\"`, subviews will be aligned into a clean grid structure, but each row or column may be of variable size.\\n- For `\\\"all\\\"`, subviews will be aligned and each row or column will be sized identically based on the maximum observed size. String values for this property will be applied to both grid rows and columns.\\n\\nAlternatively, an object value of the form `{\\\"row\\\": string, \\\"column\\\": string}` can be used to supply different alignments for rows and columns.\\n\\n__Default value:__ `\\\"all\\\"`.\"\n                },\n                \"bounds\": {\n                    \"description\": \"The bounds calculation method to use for determining the extent of a sub-plot. One of `full` (the default) or `flush`.\\n\\n- If set to `full`, the entire calculated bounds (including axes, title, and legend) will be used.\\n- If set to `flush`, only the specified width and height values for the sub-view will be used. The `flush` setting can be useful when attempting to place sub-plots without axes or legends into a uniform grid structure.\\n\\n__Default value:__ `\\\"full\\\"`\",\n                    \"enum\": [\n                        \"full\",\n                        \"flush\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"center\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<boolean>\"\n                        }\n                    ],\n                    \"description\": \"Boolean flag indicating if subviews should be centered relative to their respective rows or columns.\\n\\nAn object value of the form `{\\\"row\\\": boolean, \\\"column\\\": boolean}` can be used to supply different centering values for rows and columns.\\n\\n__Default value:__ `false`\"\n                },\n                \"columns\": {\n                    \"description\": \"The number of columns to include in the view composition layout.\\n\\n__Default value__: `undefined` -- An infinite number of columns (a single row) will be assumed. This is equivalent to `hconcat` (for `concat`) and to using the `column` channel (for `facet` and `repeat`).\\n\\n__Note__:\\n\\n1) This property is only for:\\n- the general (wrappable) `concat` operator (not `hconcat`/`vconcat`)\\n- the `facet` and `repeat` operator with one field/repetition definition (without row/column nesting)\\n\\n2) Setting the `columns` to `1` is equivalent to `vconcat` (for `concat`) and to using the `row` channel (for `facet` and `repeat`).\",\n                    \"type\": \"number\"\n                },\n                \"data\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Data\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                },\n                \"description\": {\n                    \"description\": \"Description of this mark for commenting purpose.\",\n                    \"type\": \"string\"\n                },\n                \"facet\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FacetFieldDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/FacetMapping\"\n                        }\n                    ],\n                    \"description\": \"Definition for how to facet the data. One of: 1) [a field definition for faceting the plot by one field](https://vega.github.io/vega-lite/docs/facet.html#field-def) 2) [An object that maps `row` and `column` channels to their field definitions](https://vega.github.io/vega-lite/docs/facet.html#mapping)\"\n                },\n                \"name\": {\n                    \"description\": \"Name of the visualization for later reference.\",\n                    \"type\": \"string\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/Resolve\",\n                    \"description\": \"Scale, axis, and legend resolutions for view composition specifications.\"\n                },\n                \"spacing\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<number>\"\n                        }\n                    ],\n                    \"description\": \"The spacing in pixels between sub-views of the composition operator. An object of the form `{\\\"row\\\": number, \\\"column\\\": number}` can be used to set different spacing values for rows and columns.\\n\\n__Default value__: Depends on `\\\"spacing\\\"` property of [the view composition configuration](https://vega.github.io/vega-lite/docs/config.html#view-config) (`20` by default)\"\n                },\n                \"spec\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LayerSpec\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/FacetedUnitSpec\"\n                        }\n                    ],\n                    \"description\": \"A specification of the view that gets faceted.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TitleParams\"\n                        }\n                    ],\n                    \"description\": \"Title for the plot.\"\n                },\n                \"transform\": {\n                    \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Transform\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"facet\",\n                \"spec\"\n            ],\n            \"type\": \"object\"\n        },\n        \"HConcatSpec<GenericSpec>\": {\n            \"additionalProperties\": false,\n            \"description\": \"Base interface for a horizontal concatenation specification.\",\n            \"properties\": {\n                \"bounds\": {\n                    \"description\": \"The bounds calculation method to use for determining the extent of a sub-plot. One of `full` (the default) or `flush`.\\n\\n- If set to `full`, the entire calculated bounds (including axes, title, and legend) will be used.\\n- If set to `flush`, only the specified width and height values for the sub-view will be used. The `flush` setting can be useful when attempting to place sub-plots without axes or legends into a uniform grid structure.\\n\\n__Default value:__ `\\\"full\\\"`\",\n                    \"enum\": [\n                        \"full\",\n                        \"flush\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"center\": {\n                    \"description\": \"Boolean flag indicating if subviews should be centered relative to their respective rows or columns.\\n\\n__Default value:__ `false`\",\n                    \"type\": \"boolean\"\n                },\n                \"data\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Data\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                },\n                \"description\": {\n                    \"description\": \"Description of this mark for commenting purpose.\",\n                    \"type\": \"string\"\n                },\n                \"hconcat\": {\n                    \"description\": \"A list of views to be concatenated and put into a row.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Spec\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"name\": {\n                    \"description\": \"Name of the visualization for later reference.\",\n                    \"type\": \"string\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/Resolve\",\n                    \"description\": \"Scale, axis, and legend resolutions for view composition specifications.\"\n                },\n                \"spacing\": {\n                    \"description\": \"The spacing in pixels between sub-views of the concat operator.\\n\\n__Default value__: `10`\",\n                    \"type\": \"number\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TitleParams\"\n                        }\n                    ],\n                    \"description\": \"Title for the plot.\"\n                },\n                \"transform\": {\n                    \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Transform\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"hconcat\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Spec\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/FacetedUnitSpec\"\n                },\n                {\n                    \"$ref\": \"#/definitions/LayerSpec\"\n                },\n                {\n                    \"$ref\": \"#/definitions/RepeatSpec\"\n                },\n                {\n                    \"$ref\": \"#/definitions/FacetSpec\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ConcatSpec<GenericSpec>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/VConcatSpec<GenericSpec>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/HConcatSpec<GenericSpec>\"\n                }\n            ],\n            \"description\": \"Any specification in Vega-Lite.\"\n        },\n        \"GenericUnitSpec<Encoding,AnyMark>\": {\n            \"additionalProperties\": false,\n            \"description\": \"Base interface for a unit (single-view) specification.\",\n            \"properties\": {\n                \"data\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Data\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                },\n                \"description\": {\n                    \"description\": \"Description of this mark for commenting purpose.\",\n                    \"type\": \"string\"\n                },\n                \"encoding\": {\n                    \"$ref\": \"#/definitions/Encoding\",\n                    \"description\": \"A key-value mapping between encoding channels and definition of fields.\"\n                },\n                \"mark\": {\n                    \"$ref\": \"#/definitions/AnyMark\",\n                    \"description\": \"A string describing the mark type (one of `\\\"bar\\\"`, `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"tick\\\"`, `\\\"line\\\"`, `\\\"area\\\"`, `\\\"point\\\"`, `\\\"rule\\\"`, `\\\"geoshape\\\"`, and `\\\"text\\\"`) or a [mark definition object](https://vega.github.io/vega-lite/docs/mark.html#mark-def).\"\n                },\n                \"name\": {\n                    \"description\": \"Name of the visualization for later reference.\",\n                    \"type\": \"string\"\n                },\n                \"params\": {\n                    \"description\": \"An array of parameters that may either be simple variables, or more complex selections that map user input to data queries.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/SelectionParameter\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"projection\": {\n                    \"$ref\": \"#/definitions/Projection\",\n                    \"description\": \"An object defining properties of geographic projection, which will be applied to `shape` path for `\\\"geoshape\\\"` marks and to `latitude` and `\\\"longitude\\\"` channels for other marks.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TitleParams\"\n                        }\n                    ],\n                    \"description\": \"Title for the plot.\"\n                },\n                \"transform\": {\n                    \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Transform\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"mark\"\n            ],\n            \"type\": \"object\"\n        },\n        \"VConcatSpec<GenericSpec>\": {\n            \"additionalProperties\": false,\n            \"description\": \"Base interface for a vertical concatenation specification.\",\n            \"properties\": {\n                \"bounds\": {\n                    \"description\": \"The bounds calculation method to use for determining the extent of a sub-plot. One of `full` (the default) or `flush`.\\n\\n- If set to `full`, the entire calculated bounds (including axes, title, and legend) will be used.\\n- If set to `flush`, only the specified width and height values for the sub-view will be used. The `flush` setting can be useful when attempting to place sub-plots without axes or legends into a uniform grid structure.\\n\\n__Default value:__ `\\\"full\\\"`\",\n                    \"enum\": [\n                        \"full\",\n                        \"flush\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"center\": {\n                    \"description\": \"Boolean flag indicating if subviews should be centered relative to their respective rows or columns.\\n\\n__Default value:__ `false`\",\n                    \"type\": \"boolean\"\n                },\n                \"data\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Data\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                },\n                \"description\": {\n                    \"description\": \"Description of this mark for commenting purpose.\",\n                    \"type\": \"string\"\n                },\n                \"name\": {\n                    \"description\": \"Name of the visualization for later reference.\",\n                    \"type\": \"string\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/Resolve\",\n                    \"description\": \"Scale, axis, and legend resolutions for view composition specifications.\"\n                },\n                \"spacing\": {\n                    \"description\": \"The spacing in pixels between sub-views of the concat operator.\\n\\n__Default value__: `10`\",\n                    \"type\": \"number\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TitleParams\"\n                        }\n                    ],\n                    \"description\": \"Title for the plot.\"\n                },\n                \"transform\": {\n                    \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Transform\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"vconcat\": {\n                    \"description\": \"A list of views to be concatenated and put into a column.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Spec\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"vconcat\"\n            ],\n            \"type\": \"object\"\n        },\n        \"GeoJsonFeature\": {\n            \"$ref\": \"#/definitions/Feature\"\n        },\n        \"GeoJsonFeatureCollection\": {\n            \"$ref\": \"#/definitions/FeatureCollection\"\n        },\n        \"GeoJsonProperties\": {\n            \"anyOf\": [\n                {\n                    \"type\": \"object\"\n                },\n                {\n                    \"type\": \"null\"\n                }\n            ]\n        },\n        \"Geometry\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/Point\"\n                },\n                {\n                    \"$ref\": \"#/definitions/MultiPoint\"\n                },\n                {\n                    \"$ref\": \"#/definitions/LineString\"\n                },\n                {\n                    \"$ref\": \"#/definitions/MultiLineString\"\n                },\n                {\n                    \"$ref\": \"#/definitions/Polygon\"\n                },\n                {\n                    \"$ref\": \"#/definitions/MultiPolygon\"\n                },\n                {\n                    \"$ref\": \"#/definitions/GeometryCollection\"\n                }\n            ],\n            \"description\": \"Union of geometry objects. https://tools.ietf.org/html/rfc7946#section-3\"\n        },\n        \"GeometryCollection\": {\n            \"additionalProperties\": false,\n            \"description\": \"Geometry Collection https://tools.ietf.org/html/rfc7946#section-3.1.8\",\n            \"properties\": {\n                \"bbox\": {\n                    \"$ref\": \"#/definitions/BBox\",\n                    \"description\": \"Bounding box of the coordinate range of the object's Geometries, Features, or Feature Collections. https://tools.ietf.org/html/rfc7946#section-5\"\n                },\n                \"geometries\": {\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Geometry\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"type\": {\n                    \"const\": \"GeometryCollection\",\n                    \"description\": \"Specifies the type of GeoJSON object.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"geometries\",\n                \"type\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Gradient\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/LinearGradient\"\n                },\n                {\n                    \"$ref\": \"#/definitions/RadialGradient\"\n                }\n            ]\n        },\n        \"GradientStop\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"color\": {\n                    \"$ref\": \"#/definitions/Color\",\n                    \"description\": \"The color value at this point in the gradient.\"\n                },\n                \"offset\": {\n                    \"description\": \"The offset fraction for the color stop, indicating its position within the gradient.\",\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"offset\",\n                \"color\"\n            ],\n            \"type\": \"object\"\n        },\n        \"GraticuleGenerator\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"graticule\": {\n                    \"anyOf\": [\n                        {\n                            \"const\": true,\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/GraticuleParams\"\n                        }\n                    ],\n                    \"description\": \"Generate graticule GeoJSON data for geographic reference lines.\"\n                },\n                \"name\": {\n                    \"description\": \"Provide a placeholder name and bind data at runtime.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"graticule\"\n            ],\n            \"type\": \"object\"\n        },\n        \"GraticuleParams\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"extent\": {\n                    \"$ref\": \"#/definitions/Vector2<Vector2<number>>\",\n                    \"description\": \"Sets both the major and minor extents to the same values.\"\n                },\n                \"extentMajor\": {\n                    \"$ref\": \"#/definitions/Vector2<Vector2<number>>\",\n                    \"description\": \"The major extent of the graticule as a two-element array of coordinates.\"\n                },\n                \"extentMinor\": {\n                    \"$ref\": \"#/definitions/Vector2<Vector2<number>>\",\n                    \"description\": \"The minor extent of the graticule as a two-element array of coordinates.\"\n                },\n                \"precision\": {\n                    \"description\": \"The precision of the graticule in degrees.\\n\\n__Default value:__ `2.5`\",\n                    \"type\": \"number\"\n                },\n                \"step\": {\n                    \"$ref\": \"#/definitions/Vector2<number>\",\n                    \"description\": \"Sets both the major and minor step angles to the same values.\"\n                },\n                \"stepMajor\": {\n                    \"$ref\": \"#/definitions/Vector2<number>\",\n                    \"description\": \"The major step angles of the graticule.\\n\\n\\n__Default value:__ `[90, 360]`\"\n                },\n                \"stepMinor\": {\n                    \"$ref\": \"#/definitions/Vector2<number>\",\n                    \"description\": \"The minor step angles of the graticule.\\n\\n__Default value:__ `[10, 10]`\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"Header\": {\n            \"additionalProperties\": false,\n            \"description\": \"Headers of row / column channels for faceted plots.\",\n            \"properties\": {\n                \"format\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Dict\"\n                        }\n                    ],\n                    \"description\": \"When used with the default `\\\"number\\\"` and `\\\"time\\\"` format type, the text formatting pattern for labels of guides (axes, legends, headers) and text marks.\\n\\n- If the format type is `\\\"number\\\"` (e.g., for quantitative fields), this is D3's [number format pattern](https://github.com/d3/d3-format#locale_format).\\n- If the format type is `\\\"time\\\"` (e.g., for temporal fields), this is D3's [time format pattern](https://github.com/d3/d3-time-format#locale_format).\\n\\nSee the [format documentation](https://vega.github.io/vega-lite/docs/format.html) for more examples.\\n\\nWhen used with a [custom `formatType`](https://vega.github.io/vega-lite/docs/config.html#custom-format-type), this value will be passed as `format` alongside `datum.value` to the registered function.\\n\\n__Default value:__  Derived from [numberFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for number format and from [timeFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for time format.\"\n                },\n                \"formatType\": {\n                    \"description\": \"The format type for labels. One of `\\\"number\\\"`, `\\\"time\\\"`, or a [registered custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type).\\n\\n__Default value:__\\n- `\\\"time\\\"` for temporal fields and ordinal and nominal fields with `timeUnit`.\\n- `\\\"number\\\"` for quantitative fields as well as ordinal and nominal fields without `timeUnit`.\",\n                    \"type\": \"string\"\n                },\n                \"labelAlign\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Horizontal text alignment of header labels. One of `\\\"left\\\"`, `\\\"center\\\"`, or `\\\"right\\\"`.\"\n                },\n                \"labelAnchor\": {\n                    \"$ref\": \"#/definitions/TitleAnchor\",\n                    \"description\": \"The anchor position for placing the labels. One of `\\\"start\\\"`, `\\\"middle\\\"`, or `\\\"end\\\"`. For example, with a label orientation of top these anchor positions map to a left-, center-, or right-aligned label.\"\n                },\n                \"labelAngle\": {\n                    \"description\": \"The rotation angle of the header labels.\\n\\n__Default value:__ `0` for column header, `-90` for row header.\",\n                    \"maximum\": 360,\n                    \"minimum\": -360,\n                    \"type\": \"number\"\n                },\n                \"labelBaseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The vertical text baseline for the header labels. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, or `\\\"line-bottom\\\"`. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the `titleLineHeight` rather than `titleFontSize` alone.\"\n                },\n                \"labelColor\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The color of the header label, can be in hex color code or regular color name.\"\n                },\n                \"labelExpr\": {\n                    \"description\": \"[Vega expression](https://vega.github.io/vega/docs/expressions/) for customizing labels.\\n\\n__Note:__ The label text and value can be assessed via the `label` and `value` properties of the header's backing `datum` object.\",\n                    \"type\": \"string\"\n                },\n                \"labelFont\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The font of the header label.\"\n                },\n                \"labelFontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The font size of the header label, in pixels.\",\n                    \"minimum\": 0\n                },\n                \"labelFontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The font style of the header label.\"\n                },\n                \"labelFontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The font weight of the header label.\"\n                },\n                \"labelLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The maximum length of the header label in pixels. The text value will be automatically truncated if the rendered size exceeds the limit.\\n\\n__Default value:__ `0`, indicating no limit\"\n                },\n                \"labelLineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Line height in pixels for multi-line header labels or title text with `\\\"line-top\\\"` or `\\\"line-bottom\\\"` baseline.\"\n                },\n                \"labelOrient\": {\n                    \"$ref\": \"#/definitions/Orient\",\n                    \"description\": \"The orientation of the header label. One of `\\\"top\\\"`, `\\\"bottom\\\"`, `\\\"left\\\"` or `\\\"right\\\"`.\"\n                },\n                \"labelPadding\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The padding, in pixel, between facet header's label and the plot.\\n\\n__Default value:__ `10`\"\n                },\n                \"labels\": {\n                    \"description\": \"A boolean flag indicating if labels should be included as part of the header.\\n\\n__Default value:__ `true`.\",\n                    \"type\": \"boolean\"\n                },\n                \"orient\": {\n                    \"$ref\": \"#/definitions/Orient\",\n                    \"description\": \"Shortcut for setting both labelOrient and titleOrient.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"titleAlign\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Horizontal text alignment (to the anchor) of header titles.\"\n                },\n                \"titleAnchor\": {\n                    \"$ref\": \"#/definitions/TitleAnchor\",\n                    \"description\": \"The anchor position for placing the title. One of `\\\"start\\\"`, `\\\"middle\\\"`, or `\\\"end\\\"`. For example, with an orientation of top these anchor positions map to a left-, center-, or right-aligned title.\"\n                },\n                \"titleAngle\": {\n                    \"description\": \"The rotation angle of the header title.\\n\\n__Default value:__ `0`.\",\n                    \"maximum\": 360,\n                    \"minimum\": -360,\n                    \"type\": \"number\"\n                },\n                \"titleBaseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The vertical text baseline for the header title. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, or `\\\"line-bottom\\\"`. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the `titleLineHeight` rather than `titleFontSize` alone.\\n\\n__Default value:__ `\\\"middle\\\"`\"\n                },\n                \"titleColor\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Color of the header title, can be in hex color code or regular color name.\"\n                },\n                \"titleFont\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Font of the header title. (e.g., `\\\"Helvetica Neue\\\"`).\"\n                },\n                \"titleFontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Font size of the header title.\",\n                    \"minimum\": 0\n                },\n                \"titleFontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The font style of the header title.\"\n                },\n                \"titleFontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Font weight of the header title. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                },\n                \"titleLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The maximum length of the header title in pixels. The text value will be automatically truncated if the rendered size exceeds the limit.\\n\\n__Default value:__ `0`, indicating no limit\"\n                },\n                \"titleLineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Line height in pixels for multi-line header title text or title text with `\\\"line-top\\\"` or `\\\"line-bottom\\\"` baseline.\"\n                },\n                \"titleOrient\": {\n                    \"$ref\": \"#/definitions/Orient\",\n                    \"description\": \"The orientation of the header title. One of `\\\"top\\\"`, `\\\"bottom\\\"`, `\\\"left\\\"` or `\\\"right\\\"`.\"\n                },\n                \"titlePadding\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The padding, in pixel, between facet header's title and the label.\\n\\n__Default value:__ `10`\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"HeaderConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"format\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Dict\"\n                        }\n                    ],\n                    \"description\": \"When used with the default `\\\"number\\\"` and `\\\"time\\\"` format type, the text formatting pattern for labels of guides (axes, legends, headers) and text marks.\\n\\n- If the format type is `\\\"number\\\"` (e.g., for quantitative fields), this is D3's [number format pattern](https://github.com/d3/d3-format#locale_format).\\n- If the format type is `\\\"time\\\"` (e.g., for temporal fields), this is D3's [time format pattern](https://github.com/d3/d3-time-format#locale_format).\\n\\nSee the [format documentation](https://vega.github.io/vega-lite/docs/format.html) for more examples.\\n\\nWhen used with a [custom `formatType`](https://vega.github.io/vega-lite/docs/config.html#custom-format-type), this value will be passed as `format` alongside `datum.value` to the registered function.\\n\\n__Default value:__  Derived from [numberFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for number format and from [timeFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for time format.\"\n                },\n                \"formatType\": {\n                    \"description\": \"The format type for labels. One of `\\\"number\\\"`, `\\\"time\\\"`, or a [registered custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type).\\n\\n__Default value:__\\n- `\\\"time\\\"` for temporal fields and ordinal and nominal fields with `timeUnit`.\\n- `\\\"number\\\"` for quantitative fields as well as ordinal and nominal fields without `timeUnit`.\",\n                    \"type\": \"string\"\n                },\n                \"labelAlign\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Horizontal text alignment of header labels. One of `\\\"left\\\"`, `\\\"center\\\"`, or `\\\"right\\\"`.\"\n                },\n                \"labelAnchor\": {\n                    \"$ref\": \"#/definitions/TitleAnchor\",\n                    \"description\": \"The anchor position for placing the labels. One of `\\\"start\\\"`, `\\\"middle\\\"`, or `\\\"end\\\"`. For example, with a label orientation of top these anchor positions map to a left-, center-, or right-aligned label.\"\n                },\n                \"labelAngle\": {\n                    \"description\": \"The rotation angle of the header labels.\\n\\n__Default value:__ `0` for column header, `-90` for row header.\",\n                    \"maximum\": 360,\n                    \"minimum\": -360,\n                    \"type\": \"number\"\n                },\n                \"labelBaseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The vertical text baseline for the header labels. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, or `\\\"line-bottom\\\"`. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the `titleLineHeight` rather than `titleFontSize` alone.\"\n                },\n                \"labelColor\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The color of the header label, can be in hex color code or regular color name.\"\n                },\n                \"labelExpr\": {\n                    \"description\": \"[Vega expression](https://vega.github.io/vega/docs/expressions/) for customizing labels.\\n\\n__Note:__ The label text and value can be assessed via the `label` and `value` properties of the header's backing `datum` object.\",\n                    \"type\": \"string\"\n                },\n                \"labelFont\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The font of the header label.\"\n                },\n                \"labelFontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The font size of the header label, in pixels.\",\n                    \"minimum\": 0\n                },\n                \"labelFontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The font style of the header label.\"\n                },\n                \"labelFontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The font weight of the header label.\"\n                },\n                \"labelLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The maximum length of the header label in pixels. The text value will be automatically truncated if the rendered size exceeds the limit.\\n\\n__Default value:__ `0`, indicating no limit\"\n                },\n                \"labelLineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Line height in pixels for multi-line header labels or title text with `\\\"line-top\\\"` or `\\\"line-bottom\\\"` baseline.\"\n                },\n                \"labelOrient\": {\n                    \"$ref\": \"#/definitions/Orient\",\n                    \"description\": \"The orientation of the header label. One of `\\\"top\\\"`, `\\\"bottom\\\"`, `\\\"left\\\"` or `\\\"right\\\"`.\"\n                },\n                \"labelPadding\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The padding, in pixel, between facet header's label and the plot.\\n\\n__Default value:__ `10`\"\n                },\n                \"labels\": {\n                    \"description\": \"A boolean flag indicating if labels should be included as part of the header.\\n\\n__Default value:__ `true`.\",\n                    \"type\": \"boolean\"\n                },\n                \"orient\": {\n                    \"$ref\": \"#/definitions/Orient\",\n                    \"description\": \"Shortcut for setting both labelOrient and titleOrient.\"\n                },\n                \"title\": {\n                    \"description\": \"Set to null to disable title for the axis, legend, or header.\",\n                    \"type\": \"null\"\n                },\n                \"titleAlign\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Horizontal text alignment (to the anchor) of header titles.\"\n                },\n                \"titleAnchor\": {\n                    \"$ref\": \"#/definitions/TitleAnchor\",\n                    \"description\": \"The anchor position for placing the title. One of `\\\"start\\\"`, `\\\"middle\\\"`, or `\\\"end\\\"`. For example, with an orientation of top these anchor positions map to a left-, center-, or right-aligned title.\"\n                },\n                \"titleAngle\": {\n                    \"description\": \"The rotation angle of the header title.\\n\\n__Default value:__ `0`.\",\n                    \"maximum\": 360,\n                    \"minimum\": -360,\n                    \"type\": \"number\"\n                },\n                \"titleBaseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The vertical text baseline for the header title. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, or `\\\"line-bottom\\\"`. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the `titleLineHeight` rather than `titleFontSize` alone.\\n\\n__Default value:__ `\\\"middle\\\"`\"\n                },\n                \"titleColor\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Color of the header title, can be in hex color code or regular color name.\"\n                },\n                \"titleFont\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Font of the header title. (e.g., `\\\"Helvetica Neue\\\"`).\"\n                },\n                \"titleFontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Font size of the header title.\",\n                    \"minimum\": 0\n                },\n                \"titleFontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The font style of the header title.\"\n                },\n                \"titleFontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Font weight of the header title. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                },\n                \"titleLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The maximum length of the header title in pixels. The text value will be automatically truncated if the rendered size exceeds the limit.\\n\\n__Default value:__ `0`, indicating no limit\"\n                },\n                \"titleLineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Line height in pixels for multi-line header title text or title text with `\\\"line-top\\\"` or `\\\"line-bottom\\\"` baseline.\"\n                },\n                \"titleOrient\": {\n                    \"$ref\": \"#/definitions/Orient\",\n                    \"description\": \"The orientation of the header title. One of `\\\"top\\\"`, `\\\"bottom\\\"`, `\\\"left\\\"` or `\\\"right\\\"`.\"\n                },\n                \"titlePadding\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The padding, in pixel, between facet header's title and the label.\\n\\n__Default value:__ `10`\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"HexColor\": {\n            \"format\": \"color-hex\",\n            \"type\": \"string\"\n        },\n        \"ImputeMethod\": {\n            \"enum\": [\n                \"value\",\n                \"median\",\n                \"max\",\n                \"min\",\n                \"mean\"\n            ],\n            \"type\": \"string\"\n        },\n        \"ImputeParams\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"frame\": {\n                    \"description\": \"A frame specification as a two-element array used to control the window over which the specified method is applied. The array entries should either be a number indicating the offset from the current data object, or null to indicate unbounded rows preceding or following the current data object. For example, the value `[-5, 5]` indicates that the window should include five objects preceding and five objects following the current object.\\n\\n__Default value:__:  `[null, null]` indicating that the window includes all objects.\",\n                    \"items\": {\n                        \"type\": [\n                            \"null\",\n                            \"number\"\n                        ]\n                    },\n                    \"maxItems\": 2,\n                    \"minItems\": 2,\n                    \"type\": \"array\"\n                },\n                \"keyvals\": {\n                    \"anyOf\": [\n                        {\n                            \"items\": {},\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ImputeSequence\"\n                        }\n                    ],\n                    \"description\": \"Defines the key values that should be considered for imputation. An array of key values or an object defining a [number sequence](https://vega.github.io/vega-lite/docs/impute.html#sequence-def).\\n\\nIf provided, this will be used in addition to the key values observed within the input data. If not provided, the values will be derived from all unique values of the `key` field. For `impute` in `encoding`, the key field is the x-field if the y-field is imputed, or vice versa.\\n\\nIf there is no impute grouping, this property _must_ be specified.\"\n                },\n                \"method\": {\n                    \"$ref\": \"#/definitions/ImputeMethod\",\n                    \"description\": \"The imputation method to use for the field value of imputed data objects. One of `\\\"value\\\"`, `\\\"mean\\\"`, `\\\"median\\\"`, `\\\"max\\\"` or `\\\"min\\\"`.\\n\\n__Default value:__  `\\\"value\\\"`\"\n                },\n                \"value\": {\n                    \"description\": \"The field value to use when the imputation `method` is `\\\"value\\\"`.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ImputeSequence\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"start\": {\n                    \"description\": \"The starting value of the sequence. __Default value:__ `0`\",\n                    \"type\": \"number\"\n                },\n                \"step\": {\n                    \"description\": \"The step value between sequence entries. __Default value:__ `1` or `-1` if `stop < start`\",\n                    \"type\": \"number\"\n                },\n                \"stop\": {\n                    \"description\": \"The ending value(exclusive) of the sequence.\",\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"stop\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ImputeTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"frame\": {\n                    \"description\": \"A frame specification as a two-element array used to control the window over which the specified method is applied. The array entries should either be a number indicating the offset from the current data object, or null to indicate unbounded rows preceding or following the current data object. For example, the value `[-5, 5]` indicates that the window should include five objects preceding and five objects following the current object.\\n\\n__Default value:__:  `[null, null]` indicating that the window includes all objects.\",\n                    \"items\": {\n                        \"type\": [\n                            \"null\",\n                            \"number\"\n                        ]\n                    },\n                    \"maxItems\": 2,\n                    \"minItems\": 2,\n                    \"type\": \"array\"\n                },\n                \"groupby\": {\n                    \"description\": \"An optional array of fields by which to group the values. Imputation will then be performed on a per-group basis.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"impute\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The data field for which the missing values should be imputed.\"\n                },\n                \"key\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"A key field that uniquely identifies data objects within a group. Missing key values (those occurring in the data but not in the current group) will be imputed.\"\n                },\n                \"keyvals\": {\n                    \"anyOf\": [\n                        {\n                            \"items\": {},\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ImputeSequence\"\n                        }\n                    ],\n                    \"description\": \"Defines the key values that should be considered for imputation. An array of key values or an object defining a [number sequence](https://vega.github.io/vega-lite/docs/impute.html#sequence-def).\\n\\nIf provided, this will be used in addition to the key values observed within the input data. If not provided, the values will be derived from all unique values of the `key` field. For `impute` in `encoding`, the key field is the x-field if the y-field is imputed, or vice versa.\\n\\nIf there is no impute grouping, this property _must_ be specified.\"\n                },\n                \"method\": {\n                    \"$ref\": \"#/definitions/ImputeMethod\",\n                    \"description\": \"The imputation method to use for the field value of imputed data objects. One of `\\\"value\\\"`, `\\\"mean\\\"`, `\\\"median\\\"`, `\\\"max\\\"` or `\\\"min\\\"`.\\n\\n__Default value:__  `\\\"value\\\"`\"\n                },\n                \"value\": {\n                    \"description\": \"The field value to use when the imputation `method` is `\\\"value\\\"`.\"\n                }\n            },\n            \"required\": [\n                \"impute\",\n                \"key\"\n            ],\n            \"type\": \"object\"\n        },\n        \"InlineData\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"format\": {\n                    \"$ref\": \"#/definitions/DataFormat\",\n                    \"description\": \"An object that specifies the format for parsing the data.\"\n                },\n                \"name\": {\n                    \"description\": \"Provide a placeholder name and bind data at runtime.\",\n                    \"type\": \"string\"\n                },\n                \"values\": {\n                    \"$ref\": \"#/definitions/InlineDataset\",\n                    \"description\": \"The full data set, included inline. This can be an array of objects or primitive values, an object, or a string. Arrays of primitive values are ingested as objects with a `data` property. Strings are parsed according to the specified format type.\"\n                }\n            },\n            \"required\": [\n                \"values\"\n            ],\n            \"type\": \"object\"\n        },\n        \"InlineDataset\": {\n            \"anyOf\": [\n                {\n                    \"items\": {\n                        \"type\": \"number\"\n                    },\n                    \"type\": \"array\"\n                },\n                {\n                    \"items\": {\n                        \"type\": \"string\"\n                    },\n                    \"type\": \"array\"\n                },\n                {\n                    \"items\": {\n                        \"type\": \"boolean\"\n                    },\n                    \"type\": \"array\"\n                },\n                {\n                    \"items\": {\n                        \"type\": \"object\"\n                    },\n                    \"type\": \"array\"\n                },\n                {\n                    \"type\": \"string\"\n                },\n                {\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"Interpolate\": {\n            \"enum\": [\n                \"basis\",\n                \"basis-open\",\n                \"basis-closed\",\n                \"bundle\",\n                \"cardinal\",\n                \"cardinal-open\",\n                \"cardinal-closed\",\n                \"catmull-rom\",\n                \"linear\",\n                \"linear-closed\",\n                \"monotone\",\n                \"natural\",\n                \"step\",\n                \"step-before\",\n                \"step-after\"\n            ],\n            \"type\": \"string\"\n        },\n        \"IntervalSelectionConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"clear\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Stream\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        }\n                    ],\n                    \"description\": \"Clears the selection, emptying it of all values. This property can be a [Event Stream](https://vega.github.io/vega/docs/event-streams/) or `false` to disable clear.\\n\\n__Default value:__ `dblclick`.\\n\\n__See also:__ [`clear` examples ](https://vega.github.io/vega-lite/docs/selection.html#clear) in the documentation.\"\n                },\n                \"encodings\": {\n                    \"description\": \"An array of encoding channels. The corresponding data field values must match for a data tuple to fall within the selection.\\n\\n__See also:__ The [projection with `encodings` and `fields` section](https://vega.github.io/vega-lite/docs/selection.html#project) in the documentation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/SingleDefUnitChannel\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"fields\": {\n                    \"description\": \"An array of field names whose values must match for a data tuple to fall within the selection.\\n\\n__See also:__ The [projection with `encodings` and `fields` section](https://vega.github.io/vega-lite/docs/selection.html#project) in the documentation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"mark\": {\n                    \"$ref\": \"#/definitions/BrushConfig\",\n                    \"description\": \"An interval selection also adds a rectangle mark to depict the extents of the interval. The `mark` property can be used to customize the appearance of the mark.\\n\\n__See also:__ [`mark` examples](https://vega.github.io/vega-lite/docs/selection.html#mark) in the documentation.\"\n                },\n                \"on\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Stream\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        }\n                    ],\n                    \"description\": \"A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or selector) that triggers the selection. For interval selections, the event stream must specify a [start and end](https://vega.github.io/vega/docs/event-streams/#between-filters).\\n\\n__See also:__ [`on` examples](https://vega.github.io/vega-lite/docs/selection.html#on) in the documentation.\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/SelectionResolution\",\n                    \"description\": \"With layered and multi-view displays, a strategy that determines how selections' data queries are resolved when applied in a filter transform, conditional encoding rule, or scale domain.\\n\\nOne of:\\n- `\\\"global\\\"` -- only one brush exists for the entire SPLOM. When the user begins to drag, any previous brushes are cleared, and a new one is constructed.\\n- `\\\"union\\\"` -- each cell contains its own brush, and points are highlighted if they lie within _any_ of these individual brushes.\\n- `\\\"intersect\\\"` -- each cell contains its own brush, and points are highlighted only if they fall within _all_ of these individual brushes.\\n\\n__Default value:__ `global`.\\n\\n__See also:__ [`resolve` examples](https://vega.github.io/vega-lite/docs/selection.html#resolve) in the documentation.\"\n                },\n                \"translate\": {\n                    \"description\": \"When truthy, allows a user to interactively move an interval selection back-and-forth. Can be `true`, `false` (to disable panning), or a [Vega event stream definition](https://vega.github.io/vega/docs/event-streams/) which must include a start and end event to trigger continuous panning. Discrete panning (e.g., pressing the left/right arrow keys) will be supported in future versions.\\n\\n__Default value:__ `true`, which corresponds to `[pointerdown, window:pointerup] > window:pointermove!`. This default allows users to clicks and drags within an interval selection to reposition it.\\n\\n__See also:__ [`translate` examples](https://vega.github.io/vega-lite/docs/selection.html#translate) in the documentation.\",\n                    \"type\": [\n                        \"string\",\n                        \"boolean\"\n                    ]\n                },\n                \"type\": {\n                    \"const\": \"interval\",\n                    \"description\": \"Determines the default event processing and data query for the selection. Vega-Lite currently supports two selection types:\\n\\n- `\\\"point\\\"` -- to select multiple discrete data values; the first value is selected on `click` and additional values toggled on shift-click.\\n- `\\\"interval\\\"` -- to select a continuous range of data values on `drag`.\",\n                    \"type\": \"string\"\n                },\n                \"zoom\": {\n                    \"description\": \"When truthy, allows a user to interactively resize an interval selection. Can be `true`, `false` (to disable zooming), or a [Vega event stream definition](https://vega.github.io/vega/docs/event-streams/). Currently, only `wheel` events are supported, but custom event streams can still be used to specify filters, debouncing, and throttling. Future versions will expand the set of events that can trigger this transformation.\\n\\n__Default value:__ `true`, which corresponds to `wheel!`. This default allows users to use the mouse wheel to resize an interval selection.\\n\\n__See also:__ [`zoom` examples](https://vega.github.io/vega-lite/docs/selection.html#zoom) in the documentation.\",\n                    \"type\": [\n                        \"string\",\n                        \"boolean\"\n                    ]\n                }\n            },\n            \"required\": [\n                \"type\"\n            ],\n            \"type\": \"object\"\n        },\n        \"IntervalSelectionConfigWithoutType\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"clear\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Stream\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        }\n                    ],\n                    \"description\": \"Clears the selection, emptying it of all values. This property can be a [Event Stream](https://vega.github.io/vega/docs/event-streams/) or `false` to disable clear.\\n\\n__Default value:__ `dblclick`.\\n\\n__See also:__ [`clear` examples ](https://vega.github.io/vega-lite/docs/selection.html#clear) in the documentation.\"\n                },\n                \"encodings\": {\n                    \"description\": \"An array of encoding channels. The corresponding data field values must match for a data tuple to fall within the selection.\\n\\n__See also:__ The [projection with `encodings` and `fields` section](https://vega.github.io/vega-lite/docs/selection.html#project) in the documentation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/SingleDefUnitChannel\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"fields\": {\n                    \"description\": \"An array of field names whose values must match for a data tuple to fall within the selection.\\n\\n__See also:__ The [projection with `encodings` and `fields` section](https://vega.github.io/vega-lite/docs/selection.html#project) in the documentation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"mark\": {\n                    \"$ref\": \"#/definitions/BrushConfig\",\n                    \"description\": \"An interval selection also adds a rectangle mark to depict the extents of the interval. The `mark` property can be used to customize the appearance of the mark.\\n\\n__See also:__ [`mark` examples](https://vega.github.io/vega-lite/docs/selection.html#mark) in the documentation.\"\n                },\n                \"on\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Stream\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        }\n                    ],\n                    \"description\": \"A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or selector) that triggers the selection. For interval selections, the event stream must specify a [start and end](https://vega.github.io/vega/docs/event-streams/#between-filters).\\n\\n__See also:__ [`on` examples](https://vega.github.io/vega-lite/docs/selection.html#on) in the documentation.\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/SelectionResolution\",\n                    \"description\": \"With layered and multi-view displays, a strategy that determines how selections' data queries are resolved when applied in a filter transform, conditional encoding rule, or scale domain.\\n\\nOne of:\\n- `\\\"global\\\"` -- only one brush exists for the entire SPLOM. When the user begins to drag, any previous brushes are cleared, and a new one is constructed.\\n- `\\\"union\\\"` -- each cell contains its own brush, and points are highlighted if they lie within _any_ of these individual brushes.\\n- `\\\"intersect\\\"` -- each cell contains its own brush, and points are highlighted only if they fall within _all_ of these individual brushes.\\n\\n__Default value:__ `global`.\\n\\n__See also:__ [`resolve` examples](https://vega.github.io/vega-lite/docs/selection.html#resolve) in the documentation.\"\n                },\n                \"translate\": {\n                    \"description\": \"When truthy, allows a user to interactively move an interval selection back-and-forth. Can be `true`, `false` (to disable panning), or a [Vega event stream definition](https://vega.github.io/vega/docs/event-streams/) which must include a start and end event to trigger continuous panning. Discrete panning (e.g., pressing the left/right arrow keys) will be supported in future versions.\\n\\n__Default value:__ `true`, which corresponds to `[pointerdown, window:pointerup] > window:pointermove!`. This default allows users to clicks and drags within an interval selection to reposition it.\\n\\n__See also:__ [`translate` examples](https://vega.github.io/vega-lite/docs/selection.html#translate) in the documentation.\",\n                    \"type\": [\n                        \"string\",\n                        \"boolean\"\n                    ]\n                },\n                \"zoom\": {\n                    \"description\": \"When truthy, allows a user to interactively resize an interval selection. Can be `true`, `false` (to disable zooming), or a [Vega event stream definition](https://vega.github.io/vega/docs/event-streams/). Currently, only `wheel` events are supported, but custom event streams can still be used to specify filters, debouncing, and throttling. Future versions will expand the set of events that can trigger this transformation.\\n\\n__Default value:__ `true`, which corresponds to `wheel!`. This default allows users to use the mouse wheel to resize an interval selection.\\n\\n__See also:__ [`zoom` examples](https://vega.github.io/vega-lite/docs/selection.html#zoom) in the documentation.\",\n                    \"type\": [\n                        \"string\",\n                        \"boolean\"\n                    ]\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"JoinAggregateFieldDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"as\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The output name for the join aggregate operation.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The data field for which to compute the aggregate function. This can be omitted for functions that do not operate over a field such as `\\\"count\\\"`.\"\n                },\n                \"op\": {\n                    \"$ref\": \"#/definitions/AggregateOp\",\n                    \"description\": \"The aggregation operation to apply (e.g., `\\\"sum\\\"`, `\\\"average\\\"` or `\\\"count\\\"`). See the list of all supported operations [here](https://vega.github.io/vega-lite/docs/aggregate.html#ops).\"\n                }\n            },\n            \"required\": [\n                \"op\",\n                \"as\"\n            ],\n            \"type\": \"object\"\n        },\n        \"JoinAggregateTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"groupby\": {\n                    \"description\": \"The data fields for partitioning the data objects into separate groups. If unspecified, all data points will be in a single group.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"joinaggregate\": {\n                    \"description\": \"The definition of the fields in the join aggregate, and what calculations to use.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/JoinAggregateFieldDef\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"joinaggregate\"\n            ],\n            \"type\": \"object\"\n        },\n        \"JsonDataFormat\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"parse\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Parse\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"If set to `null`, disable type inference based on the spec and only use type inference based on the data. Alternatively, a parsing directive object can be provided for explicit data types. Each property of the object corresponds to a field name, and the value to the desired data type (one of `\\\"number\\\"`, `\\\"boolean\\\"`, `\\\"date\\\"`, or null (do not parse the field)). For example, `\\\"parse\\\": {\\\"modified_on\\\": \\\"date\\\"}` parses the `modified_on` field in each input record a Date value.\\n\\nFor `\\\"date\\\"`, we parse data based using JavaScript's [`Date.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse). For Specific date formats can be provided (e.g., `{foo: \\\"date:'%m%d%Y'\\\"}`), using the [d3-time-format syntax](https://github.com/d3/d3-time-format#locale_format). UTC date format parsing is supported similarly (e.g., `{foo: \\\"utc:'%m%d%Y'\\\"}`). See more about [UTC time](https://vega.github.io/vega-lite/docs/timeunit.html#utc)\"\n                },\n                \"property\": {\n                    \"description\": \"The JSON property containing the desired data. This parameter can be used when the loaded JSON file may have surrounding structure or meta-data. For example `\\\"property\\\": \\\"values.features\\\"` is equivalent to retrieving `json.values.features` from the loaded JSON object.\",\n                    \"type\": \"string\"\n                },\n                \"type\": {\n                    \"const\": \"json\",\n                    \"description\": \"Type of input data: `\\\"json\\\"`, `\\\"csv\\\"`, `\\\"tsv\\\"`, `\\\"dsv\\\"`.\\n\\n__Default value:__  The default format type is determined by the extension of the file URL. If no extension is detected, `\\\"json\\\"` will be used by default.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"LabelOverlap\": {\n            \"anyOf\": [\n                {\n                    \"type\": \"boolean\"\n                },\n                {\n                    \"const\": \"parity\",\n                    \"type\": \"string\"\n                },\n                {\n                    \"const\": \"greedy\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"LatLongDef\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/LatLongFieldDef\"\n                },\n                {\n                    \"$ref\": \"#/definitions/DatumDef\"\n                }\n            ]\n        },\n        \"LatLongFieldDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\",\n                    \"type\": \"null\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"const\": \"quantitative\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"LayerRepeatMapping\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"column\": {\n                    \"description\": \"An array of fields to be repeated horizontally.\",\n                    \"items\": {\n                        \"type\": \"string\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"layer\": {\n                    \"description\": \"An array of fields to be repeated as layers.\",\n                    \"items\": {\n                        \"type\": \"string\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"row\": {\n                    \"description\": \"An array of fields to be repeated vertically.\",\n                    \"items\": {\n                        \"type\": \"string\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"layer\"\n            ],\n            \"type\": \"object\"\n        },\n        \"LayerRepeatSpec\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LayoutAlign\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<LayoutAlign>\"\n                        }\n                    ],\n                    \"description\": \"The alignment to apply to grid rows and columns. The supported string values are `\\\"all\\\"`, `\\\"each\\\"`, and `\\\"none\\\"`.\\n\\n- For `\\\"none\\\"`, a flow layout will be used, in which adjacent subviews are simply placed one after the other.\\n- For `\\\"each\\\"`, subviews will be aligned into a clean grid structure, but each row or column may be of variable size.\\n- For `\\\"all\\\"`, subviews will be aligned and each row or column will be sized identically based on the maximum observed size. String values for this property will be applied to both grid rows and columns.\\n\\nAlternatively, an object value of the form `{\\\"row\\\": string, \\\"column\\\": string}` can be used to supply different alignments for rows and columns.\\n\\n__Default value:__ `\\\"all\\\"`.\"\n                },\n                \"bounds\": {\n                    \"description\": \"The bounds calculation method to use for determining the extent of a sub-plot. One of `full` (the default) or `flush`.\\n\\n- If set to `full`, the entire calculated bounds (including axes, title, and legend) will be used.\\n- If set to `flush`, only the specified width and height values for the sub-view will be used. The `flush` setting can be useful when attempting to place sub-plots without axes or legends into a uniform grid structure.\\n\\n__Default value:__ `\\\"full\\\"`\",\n                    \"enum\": [\n                        \"full\",\n                        \"flush\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"center\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<boolean>\"\n                        }\n                    ],\n                    \"description\": \"Boolean flag indicating if subviews should be centered relative to their respective rows or columns.\\n\\nAn object value of the form `{\\\"row\\\": boolean, \\\"column\\\": boolean}` can be used to supply different centering values for rows and columns.\\n\\n__Default value:__ `false`\"\n                },\n                \"columns\": {\n                    \"description\": \"The number of columns to include in the view composition layout.\\n\\n__Default value__: `undefined` -- An infinite number of columns (a single row) will be assumed. This is equivalent to `hconcat` (for `concat`) and to using the `column` channel (for `facet` and `repeat`).\\n\\n__Note__:\\n\\n1) This property is only for:\\n- the general (wrappable) `concat` operator (not `hconcat`/`vconcat`)\\n- the `facet` and `repeat` operator with one field/repetition definition (without row/column nesting)\\n\\n2) Setting the `columns` to `1` is equivalent to `vconcat` (for `concat`) and to using the `row` channel (for `facet` and `repeat`).\",\n                    \"type\": \"number\"\n                },\n                \"data\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Data\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                },\n                \"description\": {\n                    \"description\": \"Description of this mark for commenting purpose.\",\n                    \"type\": \"string\"\n                },\n                \"name\": {\n                    \"description\": \"Name of the visualization for later reference.\",\n                    \"type\": \"string\"\n                },\n                \"repeat\": {\n                    \"$ref\": \"#/definitions/LayerRepeatMapping\",\n                    \"description\": \"Definition for fields to be repeated. One of: 1) An array of fields to be repeated. If `\\\"repeat\\\"` is an array, the field can be referred to as `{\\\"repeat\\\": \\\"repeat\\\"}`. The repeated views are laid out in a wrapped row. You can set the number of columns to control the wrapping. 2) An object that maps `\\\"row\\\"` and/or `\\\"column\\\"` to the listed fields to be repeated along the particular orientations. The objects `{\\\"repeat\\\": \\\"row\\\"}` and `{\\\"repeat\\\": \\\"column\\\"}` can be used to refer to the repeated field respectively.\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/Resolve\",\n                    \"description\": \"Scale, axis, and legend resolutions for view composition specifications.\"\n                },\n                \"spacing\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<number>\"\n                        }\n                    ],\n                    \"description\": \"The spacing in pixels between sub-views of the composition operator. An object of the form `{\\\"row\\\": number, \\\"column\\\": number}` can be used to set different spacing values for rows and columns.\\n\\n__Default value__: Depends on `\\\"spacing\\\"` property of [the view composition configuration](https://vega.github.io/vega-lite/docs/config.html#view-config) (`20` by default)\"\n                },\n                \"spec\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LayerSpec\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/UnitSpecWithFrame\"\n                        }\n                    ],\n                    \"description\": \"A specification of the view that gets repeated.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TitleParams\"\n                        }\n                    ],\n                    \"description\": \"Title for the plot.\"\n                },\n                \"transform\": {\n                    \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Transform\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"repeat\",\n                \"spec\"\n            ],\n            \"type\": \"object\"\n        },\n        \"LayerSpec\": {\n            \"additionalProperties\": false,\n            \"description\": \"A full layered plot specification, which may contains `encoding` and `projection` properties that will be applied to underlying unit (single-view) specifications.\",\n            \"properties\": {\n                \"data\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Data\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                },\n                \"description\": {\n                    \"description\": \"Description of this mark for commenting purpose.\",\n                    \"type\": \"string\"\n                },\n                \"encoding\": {\n                    \"$ref\": \"#/definitions/SharedEncoding\",\n                    \"description\": \"A shared key-value mapping between encoding channels and definition of fields in the underlying layers.\"\n                },\n                \"height\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"container\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Step\"\n                        }\n                    ],\n                    \"description\": \"The height of a visualization.\\n\\n- For a plot with a continuous y-field, height should be a number.\\n- For a plot with either a discrete y-field or no y-field, height can be either a number indicating a fixed height or an object in the form of `{step: number}` defining the height per discrete step. (No y-field is equivalent to having one discrete step.)\\n- To enable responsive sizing on height, it should be set to `\\\"container\\\"`.\\n\\n__Default value:__ Based on `config.view.continuousHeight` for a plot with a continuous y-field and `config.view.discreteHeight` otherwise.\\n\\n__Note:__ For plots with [`row` and `column` channels](https://vega.github.io/vega-lite/docs/encoding.html#facet), this represents the height of a single view and the `\\\"container\\\"` option cannot be used.\\n\\n__See also:__ [`height`](https://vega.github.io/vega-lite/docs/size.html) documentation.\"\n                },\n                \"layer\": {\n                    \"description\": \"Layer or single view specifications to be layered.\\n\\n__Note__: Specifications inside `layer` cannot use `row` and `column` channels as layering facet specifications is not allowed. Instead, use the [facet operator](https://vega.github.io/vega-lite/docs/facet.html) and place a layer inside a facet.\",\n                    \"items\": {\n                        \"anyOf\": [\n                            {\n                                \"$ref\": \"#/definitions/LayerSpec\"\n                            },\n                            {\n                                \"$ref\": \"#/definitions/UnitSpec\"\n                            }\n                        ]\n                    },\n                    \"type\": \"array\"\n                },\n                \"name\": {\n                    \"description\": \"Name of the visualization for later reference.\",\n                    \"type\": \"string\"\n                },\n                \"projection\": {\n                    \"$ref\": \"#/definitions/Projection\",\n                    \"description\": \"An object defining properties of the geographic projection shared by underlying layers.\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/Resolve\",\n                    \"description\": \"Scale, axis, and legend resolutions for view composition specifications.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TitleParams\"\n                        }\n                    ],\n                    \"description\": \"Title for the plot.\"\n                },\n                \"transform\": {\n                    \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Transform\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"view\": {\n                    \"$ref\": \"#/definitions/ViewBackground\",\n                    \"description\": \"An object defining the view background's fill and stroke.\\n\\n__Default value:__ none (transparent)\"\n                },\n                \"width\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"container\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Step\"\n                        }\n                    ],\n                    \"description\": \"The width of a visualization.\\n\\n- For a plot with a continuous x-field, width should be a number.\\n- For a plot with either a discrete x-field or no x-field, width can be either a number indicating a fixed width or an object in the form of `{step: number}` defining the width per discrete step. (No x-field is equivalent to having one discrete step.)\\n- To enable responsive sizing on width, it should be set to `\\\"container\\\"`.\\n\\n__Default value:__ Based on `config.view.continuousWidth` for a plot with a continuous x-field and `config.view.discreteWidth` otherwise.\\n\\n__Note:__ For plots with [`row` and `column` channels](https://vega.github.io/vega-lite/docs/encoding.html#facet), this represents the width of a single view and the `\\\"container\\\"` option cannot be used.\\n\\n__See also:__ [`width`](https://vega.github.io/vega-lite/docs/size.html) documentation.\"\n                }\n            },\n            \"required\": [\n                \"layer\"\n            ],\n            \"type\": \"object\"\n        },\n        \"LayoutAlign\": {\n            \"enum\": [\n                \"all\",\n                \"each\",\n                \"none\"\n            ],\n            \"type\": \"string\"\n        },\n        \"Legend\": {\n            \"additionalProperties\": false,\n            \"description\": \"Properties of a legend or boolean flag for determining whether to show it.\",\n            \"properties\": {\n                \"aria\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag indicating if [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) should be included (SVG output only). If `false`, the \\\"aria-hidden\\\" attribute will be set on the output SVG group, removing the legend from the ARIA accessibility tree.\\n\\n__Default value:__ `true`\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"clipHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The height in pixels to clip symbol legend entries and limit their size.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"columnPadding\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The horizontal padding in pixels between symbol legend entries.\\n\\n__Default value:__ `10`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"columns\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The number of columns in which to arrange symbol legend entries. A value of `0` or lower indicates a single row with one column per entry.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Corner radius for the full legend.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"description\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A text description of this legend for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If the `aria` property is true, for SVG output the [\\\"aria-label\\\" attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute) will be set to this description. If the description is unspecified it will be automatically generated.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"direction\": {\n                    \"$ref\": \"#/definitions/Orientation\",\n                    \"description\": \"The direction of the legend, one of `\\\"vertical\\\"` or `\\\"horizontal\\\"`.\\n\\n__Default value:__\\n- For top-/bottom-`orient`ed legends, `\\\"horizontal\\\"`\\n- For left-/right-`orient`ed legends, `\\\"vertical\\\"`\\n- For top/bottom-left/right-`orient`ed legends, `\\\"horizontal\\\"` for gradient legends and `\\\"vertical\\\"` for symbol legends.\"\n                },\n                \"fillColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Background fill color for the full legend.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"format\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Dict\"\n                        }\n                    ],\n                    \"description\": \"When used with the default `\\\"number\\\"` and `\\\"time\\\"` format type, the text formatting pattern for labels of guides (axes, legends, headers) and text marks.\\n\\n- If the format type is `\\\"number\\\"` (e.g., for quantitative fields), this is D3's [number format pattern](https://github.com/d3/d3-format#locale_format).\\n- If the format type is `\\\"time\\\"` (e.g., for temporal fields), this is D3's [time format pattern](https://github.com/d3/d3-time-format#locale_format).\\n\\nSee the [format documentation](https://vega.github.io/vega-lite/docs/format.html) for more examples.\\n\\nWhen used with a [custom `formatType`](https://vega.github.io/vega-lite/docs/config.html#custom-format-type), this value will be passed as `format` alongside `datum.value` to the registered function.\\n\\n__Default value:__  Derived from [numberFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for number format and from [timeFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for time format.\"\n                },\n                \"formatType\": {\n                    \"description\": \"The format type for labels. One of `\\\"number\\\"`, `\\\"time\\\"`, or a [registered custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type).\\n\\n__Default value:__\\n- `\\\"time\\\"` for temporal fields and ordinal and nominal fields with `timeUnit`.\\n- `\\\"number\\\"` for quantitative fields as well as ordinal and nominal fields without `timeUnit`.\",\n                    \"type\": \"string\"\n                },\n                \"gradientLength\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The length in pixels of the primary axis of a color gradient. This value corresponds to the height of a vertical gradient or the width of a horizontal gradient.\\n\\n__Default value:__ `200`.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"gradientOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Opacity of the color gradient.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"gradientStrokeColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"The color of the gradient stroke, can be in hex color code or regular color name.\\n\\n__Default value:__ `\\\"lightGray\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"gradientStrokeWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The width of the gradient stroke, in pixels.\\n\\n__Default value:__ `0`.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"gradientThickness\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The thickness in pixels of the color gradient. This value corresponds to the width of a vertical gradient or the height of a horizontal gradient.\\n\\n__Default value:__ `16`.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"gridAlign\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LayoutAlign\",\n                            \"description\": \"The alignment to apply to symbol legends rows and columns. The supported string values are `\\\"all\\\"`, `\\\"each\\\"` (the default), and `none`. For more information, see the [grid layout documentation](https://vega.github.io/vega/docs/layout).\\n\\n__Default value:__ `\\\"each\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelAlign\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\",\n                            \"description\": \"The alignment of the legend label, can be left, center, or right.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelBaseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\",\n                            \"description\": \"The position of the baseline of legend label, can be `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, or `\\\"alphabetic\\\"`.\\n\\n__Default value:__ `\\\"middle\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"The color of the legend label, can be in hex color code or regular color name.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelExpr\": {\n                    \"description\": \"[Vega expression](https://vega.github.io/vega/docs/expressions/) for customizing labels.\\n\\n__Note:__ The label text and value can be assessed via the `label` and `value` properties of the legend's backing `datum` object.\",\n                    \"type\": \"string\"\n                },\n                \"labelFont\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font of the legend label.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelFontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font size of legend label.\\n\\n__Default value:__ `10`.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelFontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"The font style of legend label.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelFontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"The font weight of legend label.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Maximum allowed pixel width of legend tick labels.\\n\\n__Default value:__ `160`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset of the legend label.\\n\\n__Default value:__ `4`.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Opacity of labels.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelOverlap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LabelOverlap\",\n                            \"description\": \"The strategy to use for resolving overlap of labels in gradient legends. If `false`, no overlap reduction is attempted. If set to `true` (default) or `\\\"parity\\\"`, a strategy of removing every other label is used. If set to `\\\"greedy\\\"`, a linear scan of the labels is performed, removing any label that overlaps with the last visible label (this often works better for log-scaled axes).\\n\\n__Default value:__ `true`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelPadding\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Padding in pixels between the legend and legend labels.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelSeparation\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The minimum separation that must be between label bounding boxes for them to be considered non-overlapping (default `0`). This property is ignored if *labelOverlap* resolution is not enabled.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"legendX\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Custom x-position for legend with orient \\\"none\\\".\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"legendY\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Custom y-position for legend with orient \\\"none\\\".\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"offset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset in pixels by which to displace the legend from the data rectangle and axes.\\n\\n__Default value:__ `18`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"orient\": {\n                    \"$ref\": \"#/definitions/LegendOrient\",\n                    \"description\": \"The orientation of the legend, which determines how the legend is positioned within the scene. One of `\\\"left\\\"`, `\\\"right\\\"`, `\\\"top\\\"`, `\\\"bottom\\\"`, `\\\"top-left\\\"`, `\\\"top-right\\\"`, `\\\"bottom-left\\\"`, `\\\"bottom-right\\\"`, `\\\"none\\\"`.\\n\\n__Default value:__ `\\\"right\\\"`\"\n                },\n                \"padding\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The padding between the border and content of the legend group.\\n\\n__Default value:__ `0`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"rowPadding\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The vertical padding in pixels between symbol legend entries.\\n\\n__Default value:__ `2`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Border stroke color for the full legend.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating [stroke, space] lengths for dashed symbol strokes.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The pixel offset at which to start drawing with the symbol stroke dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolFillColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"The color of the legend symbol,\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The maximum number of allowed entries for a symbol legend. Additional entries will be dropped.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Horizontal pixel offset for legend symbols.\\n\\n__Default value:__ `0`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Opacity of the legend symbols.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The size of the legend symbol, in pixels.\\n\\n__Default value:__ `100`.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolStrokeColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Stroke color for legend symbols.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolStrokeWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The width of the symbol's stroke.\\n\\n__Default value:__ `1.5`.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolType\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SymbolShape\",\n                            \"description\": \"The symbol shape. One of the plotting shapes `circle` (default), `square`, `cross`, `diamond`, `triangle-up`, `triangle-down`, `triangle-right`, or `triangle-left`, the line symbol `stroke`, or one of the centered directional shapes `arrow`, `wedge`, or `triangle`. Alternatively, a custom [SVG path string](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths) can be provided. For correct sizing, custom shape paths should be defined within a square bounding box with coordinates ranging from -1 to 1 along both the x and y dimensions.\\n\\n__Default value:__ `\\\"circle\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"tickCount\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TickCount\",\n                            \"description\": \"The desired number of tick values for quantitative legends.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"tickMinStep\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The minimum desired step between legend ticks, in terms of scale domain values. For example, a value of `1` indicates that ticks should not be less than 1 unit apart. If `tickMinStep` is specified, the `tickCount` value will be adjusted, if necessary, to enforce the minimum step value.\\n\\n__Default value__: `undefined`\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"titleAlign\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\",\n                            \"description\": \"Horizontal text alignment for legend titles.\\n\\n__Default value:__ `\\\"left\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleAnchor\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TitleAnchor\",\n                            \"description\": \"Text anchor position for placing legend titles.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleBaseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\",\n                            \"description\": \"Vertical text baseline for legend titles.  One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, or `\\\"line-bottom\\\"`. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the *lineHeight* rather than *fontSize* alone.\\n\\n__Default value:__ `\\\"top\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"The color of the legend title, can be in hex color code or regular color name.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleFont\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font of the legend title.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleFontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font size of the legend title.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleFontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"The font style of the legend title.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleFontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"The font weight of the legend title. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Maximum allowed pixel width of legend titles.\\n\\n__Default value:__ `180`.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleLineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Line height in pixels for multi-line title text or title text with `\\\"line-top\\\"` or `\\\"line-bottom\\\"` baseline.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Opacity of the legend title.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleOrient\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Orient\",\n                            \"description\": \"Orientation of the legend title.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titlePadding\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The padding, in pixels, between title and legend.\\n\\n__Default value:__ `5`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"type\": {\n                    \"description\": \"The type of the legend. Use `\\\"symbol\\\"` to create a discrete legend and `\\\"gradient\\\"` for a continuous color gradient.\\n\\n__Default value:__ `\\\"gradient\\\"` for non-binned quantitative fields and temporal fields; `\\\"symbol\\\"` otherwise.\",\n                    \"enum\": [\n                        \"symbol\",\n                        \"gradient\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"values\": {\n                    \"anyOf\": [\n                        {\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"items\": {\n                                \"type\": \"string\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"items\": {\n                                \"type\": \"boolean\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/DateTime\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Explicitly set the visible legend values.\"\n                },\n                \"zindex\": {\n                    \"description\": \"A non-negative integer indicating the z-index of the legend. If zindex is 0, legend should be drawn behind all chart elements. To put them in front, use zindex = 1.\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"LegendBinding\": {\n            \"anyOf\": [\n                {\n                    \"const\": \"legend\",\n                    \"type\": \"string\"\n                },\n                {\n                    \"$ref\": \"#/definitions/LegendStreamBinding\"\n                }\n            ]\n        },\n        \"LegendConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"aria\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag indicating if [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) should be included (SVG output only). If `false`, the \\\"aria-hidden\\\" attribute will be set on the output SVG group, removing the legend from the ARIA accessibility tree.\\n\\n__Default value:__ `true`\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"clipHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The height in pixels to clip symbol legend entries and limit their size.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"columnPadding\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The horizontal padding in pixels between symbol legend entries.\\n\\n__Default value:__ `10`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"columns\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The number of columns in which to arrange symbol legend entries. A value of `0` or lower indicates a single row with one column per entry.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Corner radius for the full legend.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"description\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A text description of this legend for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If the `aria` property is true, for SVG output the [\\\"aria-label\\\" attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute) will be set to this description. If the description is unspecified it will be automatically generated.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"direction\": {\n                    \"$ref\": \"#/definitions/Orientation\",\n                    \"description\": \"The direction of the legend, one of `\\\"vertical\\\"` or `\\\"horizontal\\\"`.\\n\\n__Default value:__\\n- For top-/bottom-`orient`ed legends, `\\\"horizontal\\\"`\\n- For left-/right-`orient`ed legends, `\\\"vertical\\\"`\\n- For top/bottom-left/right-`orient`ed legends, `\\\"horizontal\\\"` for gradient legends and `\\\"vertical\\\"` for symbol legends.\"\n                },\n                \"disable\": {\n                    \"description\": \"Disable legend by default\",\n                    \"type\": \"boolean\"\n                },\n                \"fillColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Background fill color for the full legend.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"gradientDirection\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Orientation\",\n                            \"description\": \"The default direction (`\\\"horizontal\\\"` or `\\\"vertical\\\"`) for gradient legends.\\n\\n__Default value:__ `\\\"vertical\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"gradientHorizontalMaxLength\": {\n                    \"description\": \"Max legend length for a horizontal gradient when `config.legend.gradientLength` is undefined.\\n\\n__Default value:__ `200`\",\n                    \"type\": \"number\"\n                },\n                \"gradientHorizontalMinLength\": {\n                    \"description\": \"Min legend length for a horizontal gradient when `config.legend.gradientLength` is undefined.\\n\\n__Default value:__ `100`\",\n                    \"type\": \"number\"\n                },\n                \"gradientLabelLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The maximum allowed length in pixels of color ramp gradient labels.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"gradientLabelOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Vertical offset in pixels for color ramp gradient labels.\\n\\n__Default value:__ `2`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"gradientLength\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The length in pixels of the primary axis of a color gradient. This value corresponds to the height of a vertical gradient or the width of a horizontal gradient.\\n\\n__Default value:__ `200`.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"gradientOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Opacity of the color gradient.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"gradientStrokeColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"The color of the gradient stroke, can be in hex color code or regular color name.\\n\\n__Default value:__ `\\\"lightGray\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"gradientStrokeWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The width of the gradient stroke, in pixels.\\n\\n__Default value:__ `0`.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"gradientThickness\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The thickness in pixels of the color gradient. This value corresponds to the width of a vertical gradient or the height of a horizontal gradient.\\n\\n__Default value:__ `16`.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"gradientVerticalMaxLength\": {\n                    \"description\": \"Max legend length for a vertical gradient when `config.legend.gradientLength` is undefined.\\n\\n__Default value:__ `200`\",\n                    \"type\": \"number\"\n                },\n                \"gradientVerticalMinLength\": {\n                    \"description\": \"Min legend length for a vertical gradient when `config.legend.gradientLength` is undefined.\\n\\n__Default value:__ `100`\",\n                    \"type\": \"number\"\n                },\n                \"gridAlign\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LayoutAlign\",\n                            \"description\": \"The alignment to apply to symbol legends rows and columns. The supported string values are `\\\"all\\\"`, `\\\"each\\\"` (the default), and `none`. For more information, see the [grid layout documentation](https://vega.github.io/vega/docs/layout).\\n\\n__Default value:__ `\\\"each\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelAlign\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\",\n                            \"description\": \"The alignment of the legend label, can be left, center, or right.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelBaseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\",\n                            \"description\": \"The position of the baseline of legend label, can be `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, or `\\\"alphabetic\\\"`.\\n\\n__Default value:__ `\\\"middle\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"The color of the legend label, can be in hex color code or regular color name.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelFont\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font of the legend label.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelFontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font size of legend label.\\n\\n__Default value:__ `10`.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelFontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"The font style of legend label.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelFontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"The font weight of legend label.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Maximum allowed pixel width of legend tick labels.\\n\\n__Default value:__ `160`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset of the legend label.\\n\\n__Default value:__ `4`.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Opacity of labels.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelOverlap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LabelOverlap\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The strategy to use for resolving overlap of labels in gradient legends. If `false`, no overlap reduction is attempted. If set to `true` or `\\\"parity\\\"`, a strategy of removing every other label is used. If set to `\\\"greedy\\\"`, a linear scan of the labels is performed, removing any label that overlaps with the last visible label (this often works better for log-scaled axes).\\n\\n__Default value:__ `\\\"greedy\\\"` for `log scales otherwise `true`.\"\n                },\n                \"labelPadding\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Padding in pixels between the legend and legend labels.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"labelSeparation\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The minimum separation that must be between label bounding boxes for them to be considered non-overlapping (default `0`). This property is ignored if *labelOverlap* resolution is not enabled.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"layout\": {\n                    \"$ref\": \"#/definitions/ExprRef\"\n                },\n                \"legendX\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Custom x-position for legend with orient \\\"none\\\".\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"legendY\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Custom y-position for legend with orient \\\"none\\\".\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"offset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset in pixels by which to displace the legend from the data rectangle and axes.\\n\\n__Default value:__ `18`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"orient\": {\n                    \"$ref\": \"#/definitions/LegendOrient\",\n                    \"description\": \"The orientation of the legend, which determines how the legend is positioned within the scene. One of `\\\"left\\\"`, `\\\"right\\\"`, `\\\"top\\\"`, `\\\"bottom\\\"`, `\\\"top-left\\\"`, `\\\"top-right\\\"`, `\\\"bottom-left\\\"`, `\\\"bottom-right\\\"`, `\\\"none\\\"`.\\n\\n__Default value:__ `\\\"right\\\"`\"\n                },\n                \"padding\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The padding between the border and content of the legend group.\\n\\n__Default value:__ `0`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"rowPadding\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The vertical padding in pixels between symbol legend entries.\\n\\n__Default value:__ `2`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Border stroke color for the full legend.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Border stroke dash pattern for the full legend.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Border stroke width for the full legend.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolBaseFillColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Default fill color for legend symbols. Only applied if there is no `\\\"fill\\\"` scale color encoding for the legend.\\n\\n__Default value:__ `\\\"transparent\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolBaseStrokeColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Default stroke color for legend symbols. Only applied if there is no `\\\"fill\\\"` scale color encoding for the legend.\\n\\n__Default value:__ `\\\"gray\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating [stroke, space] lengths for dashed symbol strokes.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The pixel offset at which to start drawing with the symbol stroke dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolDirection\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Orientation\",\n                            \"description\": \"The default direction (`\\\"horizontal\\\"` or `\\\"vertical\\\"`) for symbol legends.\\n\\n__Default value:__ `\\\"vertical\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolFillColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"The color of the legend symbol,\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The maximum number of allowed entries for a symbol legend. Additional entries will be dropped.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Horizontal pixel offset for legend symbols.\\n\\n__Default value:__ `0`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Opacity of the legend symbols.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The size of the legend symbol, in pixels.\\n\\n__Default value:__ `100`.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolStrokeColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Stroke color for legend symbols.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolStrokeWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The width of the symbol's stroke.\\n\\n__Default value:__ `1.5`.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"symbolType\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SymbolShape\",\n                            \"description\": \"The symbol shape. One of the plotting shapes `circle` (default), `square`, `cross`, `diamond`, `triangle-up`, `triangle-down`, `triangle-right`, or `triangle-left`, the line symbol `stroke`, or one of the centered directional shapes `arrow`, `wedge`, or `triangle`. Alternatively, a custom [SVG path string](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths) can be provided. For correct sizing, custom shape paths should be defined within a square bounding box with coordinates ranging from -1 to 1 along both the x and y dimensions.\\n\\n__Default value:__ `\\\"circle\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"tickCount\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TickCount\",\n                            \"description\": \"The desired number of tick values for quantitative legends.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"title\": {\n                    \"description\": \"Set to null to disable title for the axis, legend, or header.\",\n                    \"type\": \"null\"\n                },\n                \"titleAlign\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\",\n                            \"description\": \"Horizontal text alignment for legend titles.\\n\\n__Default value:__ `\\\"left\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleAnchor\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TitleAnchor\",\n                            \"description\": \"Text anchor position for placing legend titles.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleBaseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\",\n                            \"description\": \"Vertical text baseline for legend titles.  One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, or `\\\"line-bottom\\\"`. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the *lineHeight* rather than *fontSize* alone.\\n\\n__Default value:__ `\\\"top\\\"`.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"The color of the legend title, can be in hex color code or regular color name.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleFont\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font of the legend title.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleFontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font size of the legend title.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleFontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"The font style of the legend title.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleFontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"The font weight of the legend title. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Maximum allowed pixel width of legend titles.\\n\\n__Default value:__ `180`.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleLineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Line height in pixels for multi-line title text or title text with `\\\"line-top\\\"` or `\\\"line-bottom\\\"` baseline.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Opacity of the legend title.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titleOrient\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Orient\",\n                            \"description\": \"Orientation of the legend title.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"titlePadding\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The padding, in pixels, between title and legend.\\n\\n__Default value:__ `5`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"unselectedOpacity\": {\n                    \"description\": \"The opacity of unselected legend entries.\\n\\n__Default value:__ 0.35.\",\n                    \"type\": \"number\"\n                },\n                \"zindex\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The integer z-index indicating the layering of the legend group relative to other axis, mark, and legend groups.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"LegendOrient\": {\n            \"enum\": [\n                \"none\",\n                \"left\",\n                \"right\",\n                \"top\",\n                \"bottom\",\n                \"top-left\",\n                \"top-right\",\n                \"bottom-left\",\n                \"bottom-right\"\n            ],\n            \"type\": \"string\"\n        },\n        \"LegendResolveMap\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"angle\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"color\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"fill\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"fillOpacity\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"opacity\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"shape\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"size\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"stroke\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"strokeDash\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"strokeOpacity\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"strokeWidth\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"time\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"LegendStreamBinding\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"legend\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Stream\"\n                        }\n                    ]\n                }\n            },\n            \"required\": [\n                \"legend\"\n            ],\n            \"type\": \"object\"\n        },\n        \"LineConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The horizontal alignment of the text or ranged marks (area, bar, image, rect, rule). One of `\\\"left\\\"`, `\\\"right\\\"`, `\\\"center\\\"`.\\n\\n__Note:__ Expression reference is *not* supported for range marks.\"\n                },\n                \"angle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The rotation angle of the text, in degrees.\",\n                            \"maximum\": 360,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aria\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag indicating if [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) should be included (SVG output only). If `false`, the \\\"aria-hidden\\\" attribute will be set on the output SVG element, removing the mark item from the ARIA accessibility tree.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ariaRole\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Sets the type of user interface element of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the \\\"role\\\" attribute. Warning: this property is experimental and may be changed in the future.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ariaRoleDescription\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A human-readable, author-localized description for the role of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the \\\"aria-roledescription\\\" attribute. Warning: this property is experimental and may be changed in the future.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aspect\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Whether to keep aspect ratio of image marks.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"baseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"For text marks, the vertical text baseline. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, `\\\"line-bottom\\\"`, or an expression reference that provides one of the valid values. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the `lineHeight` rather than `fontSize` alone.\\n\\nFor range marks, the vertical alignment of the marks. One of `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`.\\n\\n__Note:__ Expression reference is *not* supported for range marks.\"\n                },\n                \"blend\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Blend\",\n                            \"description\": \"The color blend mode for drawing an item on its current background. Any valid [CSS mix-blend-mode](https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode) value can be used.\\n\\n__Default value: `\\\"source-over\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"color\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default color.\\n\\n__Default value:__ <span style=\\\"color: #4682b4;\\\">&#9632;</span> `\\\"#4682b4\\\"`\\n\\n__Note:__\\n- This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\\n- The `fill` and `stroke` properties have higher precedence than `color` and will override `color`.\"\n                },\n                \"cornerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles or arcs' corners.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusBottomLeft\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' bottom left corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusBottomRight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' bottom right corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusTopLeft\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' top right corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusTopRight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' top left corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cursor\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Cursor\",\n                            \"description\": \"The mouse cursor used over the mark. Any valid [CSS cursor type](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"description\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A text description of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the [\\\"aria-label\\\" attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dir\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextDirection\",\n                            \"description\": \"The direction of the text. One of `\\\"ltr\\\"` (left-to-right) or `\\\"rtl\\\"` (right-to-left). This property determines on which side is truncated in response to the limit parameter.\\n\\n__Default value:__ `\\\"ltr\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dx\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The horizontal offset, in pixels, between the text label and its anchor point. The offset is applied after rotation by the _angle_ property.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dy\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The vertical offset, in pixels, between the text label and its anchor point. The offset is applied after rotation by the _angle_ property.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ellipsis\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The ellipsis string for text truncated in response to the limit parameter.\\n\\n__Default value:__ `\\\"…\\\"`\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"endAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The end angle in radians for arc marks. A value of `0` indicates up (north), increasing values proceed clockwise.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fill\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default fill color. This property has higher precedence than `config.color`. Set to `null` to remove fill.\\n\\n__Default value:__ (None)\"\n                },\n                \"fillOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The fill opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"filled\": {\n                    \"description\": \"Whether the mark's color should be used as fill color instead of stroke color.\\n\\n__Default value:__ `false` for all `point`, `line`, and `rule` marks as well as `geoshape` marks for [`graticule`](https://vega.github.io/vega-lite/docs/data.html#graticule) data sources; otherwise, `true`.\\n\\n__Note:__ This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\",\n                    \"type\": \"boolean\"\n                },\n                \"font\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The typeface to set the text in (e.g., `\\\"Helvetica Neue\\\"`).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font size, in pixels.\\n\\n__Default value:__ `11`\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"The font style (e.g., `\\\"italic\\\"`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"The font weight. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"height\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Height of the marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"href\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/URI\",\n                            \"description\": \"A URL to load upon mouse click. If defined, the mark acts as a hyperlink.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"innerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The inner radius in pixels of arc marks. `innerRadius` is an alias for `radius2`.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"interpolate\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Interpolate\",\n                            \"description\": \"The line interpolation method to use for line and area marks. One of the following:\\n- `\\\"linear\\\"`: piecewise linear segments, as in a polyline.\\n- `\\\"linear-closed\\\"`: close the linear segments to form a polygon.\\n- `\\\"step\\\"`: alternate between horizontal and vertical segments, as in a step function.\\n- `\\\"step-before\\\"`: alternate between vertical and horizontal segments, as in a step function.\\n- `\\\"step-after\\\"`: alternate between horizontal and vertical segments, as in a step function.\\n- `\\\"basis\\\"`: a B-spline, with control point duplication on the ends.\\n- `\\\"basis-open\\\"`: an open B-spline; may not intersect the start or end.\\n- `\\\"basis-closed\\\"`: a closed B-spline, as in a loop.\\n- `\\\"cardinal\\\"`: a Cardinal spline, with control point duplication on the ends.\\n- `\\\"cardinal-open\\\"`: an open Cardinal spline; may not intersect the start or end, but will intersect other control points.\\n- `\\\"cardinal-closed\\\"`: a closed Cardinal spline, as in a loop.\\n- `\\\"bundle\\\"`: equivalent to basis, except the tension parameter is used to straighten the spline.\\n- `\\\"monotone\\\"`: cubic interpolation that preserves monotonicity in y.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"invalid\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/MarkInvalidDataMode\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"Invalid data mode, which defines how the marks and corresponding scales should represent invalid values (`null` and `NaN` in continuous scales *without* defined output for invalid values).\\n\\n- `\\\"filter\\\"` — *Exclude* all invalid values from the visualization's *marks* and *scales*. For path marks (for line, area, trail), this option will create paths that connect valid points, as if the data rows with invalid values do not exist.\\n\\n- `\\\"break-paths-filter-domains\\\"` — Break path marks (for line, area, trail) at invalid values.  For non-path marks, this is equivalent to `\\\"filter\\\"`. All *scale* domains will *exclude* these filtered data points.\\n\\n- `\\\"break-paths-show-domains\\\"` — Break paths (for line, area, trail) at invalid values.  Hide invalid values for non-path marks. All *scale* domains will *include* these filtered data points (for both path and non-path marks).\\n\\n- `\\\"show\\\"` or `null` — Show all data points in the marks and scale domains. Each scale will use the output for invalid values defined in `config.scale.invalid` or, if unspecified, by default invalid values will produce the same visual values as zero (if the scale includes zero) or the minimum value (if the scale does not include zero).\\n\\n- `\\\"break-paths-show-path-domains\\\"` (default) — This is equivalent to `\\\"break-paths-show-domains\\\"` for path-based marks (line/area/trail) and `\\\"filter\\\"` for non-path marks.\\n\\n__Note__: If any channel's scale has an output for invalid values defined in `config.scale.invalid`, all values for the scales will be considered \\\"valid\\\" since they can produce a reasonable output for the scales. Thus, fields for such channels will not be filtered and will not cause path breaks.\"\n                },\n                \"limit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The maximum length of the text mark in pixels. The text value will be automatically truncated if the rendered size exceeds the limit.\\n\\n__Default value:__ `0` -- indicating no limit\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"lineBreak\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A delimiter, such as a newline character, upon which to break text strings into multiple lines. This property is ignored if the text is array-valued.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"lineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The line height in pixels (the spacing between subsequent lines of text) for multi-line text marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"opacity\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The overall opacity (value between [0,1]).\\n\\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or `square` marks or layered `bar` charts and `1` otherwise.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"order\": {\n                    \"description\": \"For line and trail marks, this `order` property can be set to `null` or `false` to make the lines use the original order in the data sources.\",\n                    \"type\": [\n                        \"null\",\n                        \"boolean\"\n                    ]\n                },\n                \"orient\": {\n                    \"$ref\": \"#/definitions/Orientation\",\n                    \"description\": \"The orientation of a non-stacked bar, tick, area, and line charts. The value is either horizontal (default) or vertical.\\n- For bar, rule and tick, this determines whether the size of the bar and tick should be applied to x or y dimension.\\n- For area, this property determines the orient property of the Vega output.\\n- For line and trail marks, this property determines the sort order of the points in the line if `config.sortLineBy` is not specified. For stacked charts, this is always determined by the orientation of the stack; therefore explicitly specified value will be ignored.\"\n                },\n                \"outerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The outer radius in pixels of arc marks. `outerRadius` is an alias for `radius`.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"padAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The angular padding applied to sides of the arc, in radians.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"point\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/OverlayMarkDef\"\n                        },\n                        {\n                            \"const\": \"transparent\",\n                            \"type\": \"string\"\n                        }\n                    ],\n                    \"description\": \"A flag for overlaying points on top of line or area marks, or an object defining the properties of the overlayed points.\\n\\n- If this property is `\\\"transparent\\\"`, transparent points will be used (for enhancing tooltips and selections).\\n\\n- If this property is an empty object (`{}`) or `true`, filled points with default properties will be used.\\n\\n- If this property is `false`, no points would be automatically added to line or area marks.\\n\\n__Default value:__ `false`.\"\n                },\n                \"radius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"For arc mark, the primary (outer) radius in pixels.\\n\\nFor text marks, polar coordinate radial offset, in pixels, of the text from the origin determined by the `x` and `y` properties.\\n\\n__Default value:__ `min(plot_width, plot_height)/2`\",\n                    \"minimum\": 0\n                },\n                \"radius2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The secondary (inner) radius in pixels of arc marks.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"shape\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/SymbolShape\"\n                                },\n                                {\n                                    \"type\": \"string\"\n                                }\n                            ],\n                            \"description\": \"Shape of the point marks. Supported values include:\\n- plotting shapes: `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"cross\\\"`, `\\\"diamond\\\"`, `\\\"triangle-up\\\"`, `\\\"triangle-down\\\"`, `\\\"triangle-right\\\"`, or `\\\"triangle-left\\\"`.\\n- the line symbol `\\\"stroke\\\"`\\n- centered directional shapes `\\\"arrow\\\"`, `\\\"wedge\\\"`, or `\\\"triangle\\\"`\\n- a custom [SVG path string](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths) (For correct sizing, custom shape paths should be defined within a square bounding box with coordinates ranging from -1 to 1 along both the x and y dimensions.)\\n\\n__Default value:__ `\\\"circle\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"size\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default size for marks.\\n- For `point`/`circle`/`square`, this represents the pixel area of the marks. Note that this value sets the area of the symbol; the side lengths will increase with the square root of this value.\\n- For `bar`, this represents the band size of the bar, in pixels.\\n- For `text`, this represents the font size, in pixels.\\n\\n__Default value:__\\n- `30` for point, circle, square marks; width/height's `step`\\n- `2` for bar marks with discrete dimensions;\\n- `5` for bar marks with continuous dimensions;\\n- `11` for text marks.\",\n                    \"minimum\": 0\n                },\n                \"smooth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag (default true) indicating if the image should be smoothed when resized. If false, individual pixels should be scaled directly rather than interpolated with smoothing. For SVG rendering, this option may not work in some browsers due to lack of standardization.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"startAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The start angle in radians for arc marks. A value of `0` indicates up (north), increasing values proceed clockwise.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"stroke\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default stroke color. This property has higher precedence than `config.color`. Set to `null` to remove stroke.\\n\\n__Default value:__ (None)\"\n                },\n                \"strokeCap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeCap\",\n                            \"description\": \"The stroke cap for line ending style. One of `\\\"butt\\\"`, `\\\"round\\\"`, or `\\\"square\\\"`.\\n\\n__Default value:__ `\\\"butt\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating stroke, space lengths for creating dashed or dotted lines.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset (in pixels) into which to begin drawing with the stroke dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeJoin\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeJoin\",\n                            \"description\": \"The stroke line join method. One of `\\\"miter\\\"`, `\\\"round\\\"` or `\\\"bevel\\\"`.\\n\\n__Default value:__ `\\\"miter\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeMiterLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The miter limit at which to bevel a line join.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset in pixels at which to draw the group stroke and fill. If unspecified, the default behavior is to dynamically offset stroked groups such that 1 pixel stroke widths align with the pixel grid.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke width, in pixels.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"tension\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Depending on the interpolation type, sets the tension parameter (for line and area marks).\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"text\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\",\n                            \"description\": \"Placeholder text if the `text` channel is not specified\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"theta\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"- For arc marks, the arc length in radians if theta2 is not specified, otherwise the start arc angle. (A value of 0 indicates up or “north”, increasing values proceed clockwise.)\\n\\n- For text marks, polar coordinate angle in radians.\",\n                    \"maximum\": 360,\n                    \"minimum\": 0\n                },\n                \"theta2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The end angle of arc marks in radians. A value of 0 indicates up or “north”, increasing values proceed clockwise.\"\n                },\n                \"time\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"timeUnitBandPosition\": {\n                    \"description\": \"Default relative band position for a time unit. If set to `0`, the marks will be positioned at the beginning of the time unit band step. If set to `0.5`, the marks will be positioned in the middle of the time unit band step.\",\n                    \"type\": \"number\"\n                },\n                \"timeUnitBandSize\": {\n                    \"description\": \"Default relative band size for a time unit. If set to `1`, the bandwidth of the marks will be equal to the time unit band step. If set to `0.5`, bandwidth of the marks will be half of the time unit band step.\",\n                    \"type\": \"number\"\n                },\n                \"tooltip\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TooltipContent\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"The tooltip text string to show upon mouse hover or an object defining which fields should the tooltip be derived from.\\n\\n- If `tooltip` is `true` or `{\\\"content\\\": \\\"encoding\\\"}`, then all fields from `encoding` will be used.\\n- If `tooltip` is `{\\\"content\\\": \\\"data\\\"}`, then all fields that appear in the highlighted data point will be used.\\n- If set to `null` or `false`, then no tooltip will be used.\\n\\nSee the [`tooltip`](https://vega.github.io/vega-lite/docs/tooltip.html) documentation for a detailed discussion about tooltip  in Vega-Lite.\\n\\n__Default value:__ `null`\"\n                },\n                \"url\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/URI\",\n                            \"description\": \"The URL of the image file for image marks.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"width\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Width of the marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"x\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"X coordinates of the marks, or width of horizontal `\\\"bar\\\"` and `\\\"area\\\"` without specified `x2` or `width`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"x2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"X2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"y\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Y coordinates of the marks, or height of vertical `\\\"bar\\\"` and `\\\"area\\\"` without specified `y2` or `height`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                },\n                \"y2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Y2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"LineString\": {\n            \"additionalProperties\": false,\n            \"description\": \"LineString geometry object. https://tools.ietf.org/html/rfc7946#section-3.1.4\",\n            \"properties\": {\n                \"bbox\": {\n                    \"$ref\": \"#/definitions/BBox\",\n                    \"description\": \"Bounding box of the coordinate range of the object's Geometries, Features, or Feature Collections. https://tools.ietf.org/html/rfc7946#section-5\"\n                },\n                \"coordinates\": {\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Position\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"type\": {\n                    \"const\": \"LineString\",\n                    \"description\": \"Specifies the type of GeoJSON object.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"coordinates\",\n                \"type\"\n            ],\n            \"type\": \"object\"\n        },\n        \"LinearGradient\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"gradient\": {\n                    \"const\": \"linear\",\n                    \"description\": \"The type of gradient. Use `\\\"linear\\\"` for a linear gradient.\",\n                    \"type\": \"string\"\n                },\n                \"id\": {\n                    \"type\": \"string\"\n                },\n                \"stops\": {\n                    \"description\": \"An array of gradient stops defining the gradient color sequence.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/GradientStop\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"x1\": {\n                    \"description\": \"The starting x-coordinate, in normalized [0, 1] coordinates, of the linear gradient.\\n\\n__Default value:__ `0`\",\n                    \"type\": \"number\"\n                },\n                \"x2\": {\n                    \"description\": \"The ending x-coordinate, in normalized [0, 1] coordinates, of the linear gradient.\\n\\n__Default value:__ `1`\",\n                    \"type\": \"number\"\n                },\n                \"y1\": {\n                    \"description\": \"The starting y-coordinate, in normalized [0, 1] coordinates, of the linear gradient.\\n\\n__Default value:__ `0`\",\n                    \"type\": \"number\"\n                },\n                \"y2\": {\n                    \"description\": \"The ending y-coordinate, in normalized [0, 1] coordinates, of the linear gradient.\\n\\n__Default value:__ `0`\",\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"gradient\",\n                \"stops\"\n            ],\n            \"type\": \"object\"\n        },\n        \"LocalMultiTimeUnit\": {\n            \"enum\": [\n                \"yearquarter\",\n                \"yearquartermonth\",\n                \"yearmonth\",\n                \"yearmonthdate\",\n                \"yearmonthdatehours\",\n                \"yearmonthdatehoursminutes\",\n                \"yearmonthdatehoursminutesseconds\",\n                \"yearweek\",\n                \"yearweekday\",\n                \"yearweekdayhours\",\n                \"yearweekdayhoursminutes\",\n                \"yearweekdayhoursminutesseconds\",\n                \"yeardayofyear\",\n                \"quartermonth\",\n                \"monthdate\",\n                \"monthdatehours\",\n                \"monthdatehoursminutes\",\n                \"monthdatehoursminutesseconds\",\n                \"weekday\",\n                \"weekdayhours\",\n                \"weekdayhoursminutes\",\n                \"weekdayhoursminutesseconds\",\n                \"dayhours\",\n                \"dayhoursminutes\",\n                \"dayhoursminutesseconds\",\n                \"hoursminutes\",\n                \"hoursminutesseconds\",\n                \"minutesseconds\",\n                \"secondsmilliseconds\"\n            ],\n            \"type\": \"string\"\n        },\n        \"LocalSingleTimeUnit\": {\n            \"enum\": [\n                \"year\",\n                \"quarter\",\n                \"month\",\n                \"week\",\n                \"day\",\n                \"dayofyear\",\n                \"date\",\n                \"hours\",\n                \"minutes\",\n                \"seconds\",\n                \"milliseconds\"\n            ],\n            \"type\": \"string\"\n        },\n        \"Locale\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"number\": {\n                    \"$ref\": \"#/definitions/NumberLocale\"\n                },\n                \"time\": {\n                    \"$ref\": \"#/definitions/TimeLocale\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"LoessTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"as\": {\n                    \"description\": \"The output field names for the smoothed points generated by the loess transform.\\n\\n__Default value:__ The field names of the input x and y values.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"maxItems\": 2,\n                    \"minItems\": 2,\n                    \"type\": \"array\"\n                },\n                \"bandwidth\": {\n                    \"description\": \"A bandwidth parameter in the range `[0, 1]` that determines the amount of smoothing.\\n\\n__Default value:__ `0.3`\",\n                    \"type\": \"number\"\n                },\n                \"groupby\": {\n                    \"description\": \"The data fields to group by. If not specified, a single group containing all data objects will be used.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"loess\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The data field of the dependent variable to smooth.\"\n                },\n                \"on\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The data field of the independent variable to use a predictor.\"\n                }\n            },\n            \"required\": [\n                \"loess\",\n                \"on\"\n            ],\n            \"type\": \"object\"\n        },\n        \"LogicalAnd<Predicate>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"and\": {\n                    \"items\": {\n                        \"$ref\": \"#/definitions/PredicateComposition\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"and\"\n            ],\n            \"type\": \"object\"\n        },\n        \"PredicateComposition\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/LogicalNot<Predicate>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/LogicalAnd<Predicate>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/LogicalOr<Predicate>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/Predicate\"\n                }\n            ]\n        },\n        \"LogicalNot<Predicate>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"not\": {\n                    \"$ref\": \"#/definitions/PredicateComposition\"\n                }\n            },\n            \"required\": [\n                \"not\"\n            ],\n            \"type\": \"object\"\n        },\n        \"LogicalOr<Predicate>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"or\": {\n                    \"items\": {\n                        \"$ref\": \"#/definitions/PredicateComposition\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"or\"\n            ],\n            \"type\": \"object\"\n        },\n        \"LookupData\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"data\": {\n                    \"$ref\": \"#/definitions/Data\",\n                    \"description\": \"Secondary data source to lookup in.\"\n                },\n                \"fields\": {\n                    \"description\": \"Fields in foreign data or selection to lookup. If not specified, the entire object is queried.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"key\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"Key in data to lookup.\"\n                }\n            },\n            \"required\": [\n                \"data\",\n                \"key\"\n            ],\n            \"type\": \"object\"\n        },\n        \"LookupSelection\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"fields\": {\n                    \"description\": \"Fields in foreign data or selection to lookup. If not specified, the entire object is queried.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"key\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"Key in data to lookup.\"\n                },\n                \"param\": {\n                    \"$ref\": \"#/definitions/ParameterName\",\n                    \"description\": \"Selection parameter name to look up.\"\n                }\n            },\n            \"required\": [\n                \"key\",\n                \"param\"\n            ],\n            \"type\": \"object\"\n        },\n        \"LookupTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"as\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FieldName\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/FieldName\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"The output fields on which to store the looked up data values.\\n\\nFor data lookups, this property may be left blank if `from.fields` has been specified (those field names will be used); if `from.fields` has not been specified, `as` must be a string.\\n\\nFor selection lookups, this property is optional: if unspecified, looked up values will be stored under a property named for the selection; and if specified, it must correspond to `from.fields`.\"\n                },\n                \"default\": {\n                    \"description\": \"The default value to use if lookup fails.\\n\\n__Default value:__ `null`\"\n                },\n                \"from\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LookupData\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/LookupSelection\"\n                        }\n                    ],\n                    \"description\": \"Data source or selection for secondary data reference.\"\n                },\n                \"lookup\": {\n                    \"description\": \"Key in primary data source.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"lookup\",\n                \"from\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Mark\": {\n            \"description\": \"All types of primitive marks.\",\n            \"enum\": [\n                \"arc\",\n                \"area\",\n                \"bar\",\n                \"image\",\n                \"line\",\n                \"point\",\n                \"rect\",\n                \"rule\",\n                \"text\",\n                \"tick\",\n                \"trail\",\n                \"circle\",\n                \"square\",\n                \"geoshape\"\n            ],\n            \"type\": \"string\"\n        },\n        \"MarkConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The horizontal alignment of the text or ranged marks (area, bar, image, rect, rule). One of `\\\"left\\\"`, `\\\"right\\\"`, `\\\"center\\\"`.\\n\\n__Note:__ Expression reference is *not* supported for range marks.\"\n                },\n                \"angle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The rotation angle of the text, in degrees.\",\n                            \"maximum\": 360,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aria\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag indicating if [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) should be included (SVG output only). If `false`, the \\\"aria-hidden\\\" attribute will be set on the output SVG element, removing the mark item from the ARIA accessibility tree.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ariaRole\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Sets the type of user interface element of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the \\\"role\\\" attribute. Warning: this property is experimental and may be changed in the future.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ariaRoleDescription\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A human-readable, author-localized description for the role of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the \\\"aria-roledescription\\\" attribute. Warning: this property is experimental and may be changed in the future.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aspect\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Whether to keep aspect ratio of image marks.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"baseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"For text marks, the vertical text baseline. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, `\\\"line-bottom\\\"`, or an expression reference that provides one of the valid values. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the `lineHeight` rather than `fontSize` alone.\\n\\nFor range marks, the vertical alignment of the marks. One of `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`.\\n\\n__Note:__ Expression reference is *not* supported for range marks.\"\n                },\n                \"blend\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Blend\",\n                            \"description\": \"The color blend mode for drawing an item on its current background. Any valid [CSS mix-blend-mode](https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode) value can be used.\\n\\n__Default value: `\\\"source-over\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"color\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default color.\\n\\n__Default value:__ <span style=\\\"color: #4682b4;\\\">&#9632;</span> `\\\"#4682b4\\\"`\\n\\n__Note:__\\n- This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\\n- The `fill` and `stroke` properties have higher precedence than `color` and will override `color`.\"\n                },\n                \"cornerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles or arcs' corners.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusBottomLeft\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' bottom left corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusBottomRight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' bottom right corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusTopLeft\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' top right corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusTopRight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' top left corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cursor\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Cursor\",\n                            \"description\": \"The mouse cursor used over the mark. Any valid [CSS cursor type](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"description\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A text description of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the [\\\"aria-label\\\" attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dir\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextDirection\",\n                            \"description\": \"The direction of the text. One of `\\\"ltr\\\"` (left-to-right) or `\\\"rtl\\\"` (right-to-left). This property determines on which side is truncated in response to the limit parameter.\\n\\n__Default value:__ `\\\"ltr\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dx\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The horizontal offset, in pixels, between the text label and its anchor point. The offset is applied after rotation by the _angle_ property.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dy\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The vertical offset, in pixels, between the text label and its anchor point. The offset is applied after rotation by the _angle_ property.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ellipsis\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The ellipsis string for text truncated in response to the limit parameter.\\n\\n__Default value:__ `\\\"…\\\"`\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"endAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The end angle in radians for arc marks. A value of `0` indicates up (north), increasing values proceed clockwise.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fill\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default fill color. This property has higher precedence than `config.color`. Set to `null` to remove fill.\\n\\n__Default value:__ (None)\"\n                },\n                \"fillOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The fill opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"filled\": {\n                    \"description\": \"Whether the mark's color should be used as fill color instead of stroke color.\\n\\n__Default value:__ `false` for all `point`, `line`, and `rule` marks as well as `geoshape` marks for [`graticule`](https://vega.github.io/vega-lite/docs/data.html#graticule) data sources; otherwise, `true`.\\n\\n__Note:__ This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\",\n                    \"type\": \"boolean\"\n                },\n                \"font\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The typeface to set the text in (e.g., `\\\"Helvetica Neue\\\"`).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font size, in pixels.\\n\\n__Default value:__ `11`\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"The font style (e.g., `\\\"italic\\\"`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"The font weight. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"height\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Height of the marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"href\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/URI\",\n                            \"description\": \"A URL to load upon mouse click. If defined, the mark acts as a hyperlink.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"innerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The inner radius in pixels of arc marks. `innerRadius` is an alias for `radius2`.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"interpolate\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Interpolate\",\n                            \"description\": \"The line interpolation method to use for line and area marks. One of the following:\\n- `\\\"linear\\\"`: piecewise linear segments, as in a polyline.\\n- `\\\"linear-closed\\\"`: close the linear segments to form a polygon.\\n- `\\\"step\\\"`: alternate between horizontal and vertical segments, as in a step function.\\n- `\\\"step-before\\\"`: alternate between vertical and horizontal segments, as in a step function.\\n- `\\\"step-after\\\"`: alternate between horizontal and vertical segments, as in a step function.\\n- `\\\"basis\\\"`: a B-spline, with control point duplication on the ends.\\n- `\\\"basis-open\\\"`: an open B-spline; may not intersect the start or end.\\n- `\\\"basis-closed\\\"`: a closed B-spline, as in a loop.\\n- `\\\"cardinal\\\"`: a Cardinal spline, with control point duplication on the ends.\\n- `\\\"cardinal-open\\\"`: an open Cardinal spline; may not intersect the start or end, but will intersect other control points.\\n- `\\\"cardinal-closed\\\"`: a closed Cardinal spline, as in a loop.\\n- `\\\"bundle\\\"`: equivalent to basis, except the tension parameter is used to straighten the spline.\\n- `\\\"monotone\\\"`: cubic interpolation that preserves monotonicity in y.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"invalid\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/MarkInvalidDataMode\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"Invalid data mode, which defines how the marks and corresponding scales should represent invalid values (`null` and `NaN` in continuous scales *without* defined output for invalid values).\\n\\n- `\\\"filter\\\"` — *Exclude* all invalid values from the visualization's *marks* and *scales*. For path marks (for line, area, trail), this option will create paths that connect valid points, as if the data rows with invalid values do not exist.\\n\\n- `\\\"break-paths-filter-domains\\\"` — Break path marks (for line, area, trail) at invalid values.  For non-path marks, this is equivalent to `\\\"filter\\\"`. All *scale* domains will *exclude* these filtered data points.\\n\\n- `\\\"break-paths-show-domains\\\"` — Break paths (for line, area, trail) at invalid values.  Hide invalid values for non-path marks. All *scale* domains will *include* these filtered data points (for both path and non-path marks).\\n\\n- `\\\"show\\\"` or `null` — Show all data points in the marks and scale domains. Each scale will use the output for invalid values defined in `config.scale.invalid` or, if unspecified, by default invalid values will produce the same visual values as zero (if the scale includes zero) or the minimum value (if the scale does not include zero).\\n\\n- `\\\"break-paths-show-path-domains\\\"` (default) — This is equivalent to `\\\"break-paths-show-domains\\\"` for path-based marks (line/area/trail) and `\\\"filter\\\"` for non-path marks.\\n\\n__Note__: If any channel's scale has an output for invalid values defined in `config.scale.invalid`, all values for the scales will be considered \\\"valid\\\" since they can produce a reasonable output for the scales. Thus, fields for such channels will not be filtered and will not cause path breaks.\"\n                },\n                \"limit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The maximum length of the text mark in pixels. The text value will be automatically truncated if the rendered size exceeds the limit.\\n\\n__Default value:__ `0` -- indicating no limit\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"lineBreak\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A delimiter, such as a newline character, upon which to break text strings into multiple lines. This property is ignored if the text is array-valued.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"lineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The line height in pixels (the spacing between subsequent lines of text) for multi-line text marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"opacity\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The overall opacity (value between [0,1]).\\n\\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or `square` marks or layered `bar` charts and `1` otherwise.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"order\": {\n                    \"description\": \"For line and trail marks, this `order` property can be set to `null` or `false` to make the lines use the original order in the data sources.\",\n                    \"type\": [\n                        \"null\",\n                        \"boolean\"\n                    ]\n                },\n                \"orient\": {\n                    \"$ref\": \"#/definitions/Orientation\",\n                    \"description\": \"The orientation of a non-stacked bar, tick, area, and line charts. The value is either horizontal (default) or vertical.\\n- For bar, rule and tick, this determines whether the size of the bar and tick should be applied to x or y dimension.\\n- For area, this property determines the orient property of the Vega output.\\n- For line and trail marks, this property determines the sort order of the points in the line if `config.sortLineBy` is not specified. For stacked charts, this is always determined by the orientation of the stack; therefore explicitly specified value will be ignored.\"\n                },\n                \"outerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The outer radius in pixels of arc marks. `outerRadius` is an alias for `radius`.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"padAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The angular padding applied to sides of the arc, in radians.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"radius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"For arc mark, the primary (outer) radius in pixels.\\n\\nFor text marks, polar coordinate radial offset, in pixels, of the text from the origin determined by the `x` and `y` properties.\\n\\n__Default value:__ `min(plot_width, plot_height)/2`\",\n                    \"minimum\": 0\n                },\n                \"radius2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The secondary (inner) radius in pixels of arc marks.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"shape\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/SymbolShape\"\n                                },\n                                {\n                                    \"type\": \"string\"\n                                }\n                            ],\n                            \"description\": \"Shape of the point marks. Supported values include:\\n- plotting shapes: `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"cross\\\"`, `\\\"diamond\\\"`, `\\\"triangle-up\\\"`, `\\\"triangle-down\\\"`, `\\\"triangle-right\\\"`, or `\\\"triangle-left\\\"`.\\n- the line symbol `\\\"stroke\\\"`\\n- centered directional shapes `\\\"arrow\\\"`, `\\\"wedge\\\"`, or `\\\"triangle\\\"`\\n- a custom [SVG path string](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths) (For correct sizing, custom shape paths should be defined within a square bounding box with coordinates ranging from -1 to 1 along both the x and y dimensions.)\\n\\n__Default value:__ `\\\"circle\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"size\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default size for marks.\\n- For `point`/`circle`/`square`, this represents the pixel area of the marks. Note that this value sets the area of the symbol; the side lengths will increase with the square root of this value.\\n- For `bar`, this represents the band size of the bar, in pixels.\\n- For `text`, this represents the font size, in pixels.\\n\\n__Default value:__\\n- `30` for point, circle, square marks; width/height's `step`\\n- `2` for bar marks with discrete dimensions;\\n- `5` for bar marks with continuous dimensions;\\n- `11` for text marks.\",\n                    \"minimum\": 0\n                },\n                \"smooth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag (default true) indicating if the image should be smoothed when resized. If false, individual pixels should be scaled directly rather than interpolated with smoothing. For SVG rendering, this option may not work in some browsers due to lack of standardization.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"startAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The start angle in radians for arc marks. A value of `0` indicates up (north), increasing values proceed clockwise.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"stroke\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default stroke color. This property has higher precedence than `config.color`. Set to `null` to remove stroke.\\n\\n__Default value:__ (None)\"\n                },\n                \"strokeCap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeCap\",\n                            \"description\": \"The stroke cap for line ending style. One of `\\\"butt\\\"`, `\\\"round\\\"`, or `\\\"square\\\"`.\\n\\n__Default value:__ `\\\"butt\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating stroke, space lengths for creating dashed or dotted lines.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset (in pixels) into which to begin drawing with the stroke dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeJoin\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeJoin\",\n                            \"description\": \"The stroke line join method. One of `\\\"miter\\\"`, `\\\"round\\\"` or `\\\"bevel\\\"`.\\n\\n__Default value:__ `\\\"miter\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeMiterLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The miter limit at which to bevel a line join.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset in pixels at which to draw the group stroke and fill. If unspecified, the default behavior is to dynamically offset stroked groups such that 1 pixel stroke widths align with the pixel grid.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke width, in pixels.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"tension\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Depending on the interpolation type, sets the tension parameter (for line and area marks).\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"text\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\",\n                            \"description\": \"Placeholder text if the `text` channel is not specified\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"theta\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"- For arc marks, the arc length in radians if theta2 is not specified, otherwise the start arc angle. (A value of 0 indicates up or “north”, increasing values proceed clockwise.)\\n\\n- For text marks, polar coordinate angle in radians.\",\n                    \"maximum\": 360,\n                    \"minimum\": 0\n                },\n                \"theta2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The end angle of arc marks in radians. A value of 0 indicates up or “north”, increasing values proceed clockwise.\"\n                },\n                \"time\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"timeUnitBandPosition\": {\n                    \"description\": \"Default relative band position for a time unit. If set to `0`, the marks will be positioned at the beginning of the time unit band step. If set to `0.5`, the marks will be positioned in the middle of the time unit band step.\",\n                    \"type\": \"number\"\n                },\n                \"timeUnitBandSize\": {\n                    \"description\": \"Default relative band size for a time unit. If set to `1`, the bandwidth of the marks will be equal to the time unit band step. If set to `0.5`, bandwidth of the marks will be half of the time unit band step.\",\n                    \"type\": \"number\"\n                },\n                \"tooltip\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TooltipContent\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"The tooltip text string to show upon mouse hover or an object defining which fields should the tooltip be derived from.\\n\\n- If `tooltip` is `true` or `{\\\"content\\\": \\\"encoding\\\"}`, then all fields from `encoding` will be used.\\n- If `tooltip` is `{\\\"content\\\": \\\"data\\\"}`, then all fields that appear in the highlighted data point will be used.\\n- If set to `null` or `false`, then no tooltip will be used.\\n\\nSee the [`tooltip`](https://vega.github.io/vega-lite/docs/tooltip.html) documentation for a detailed discussion about tooltip  in Vega-Lite.\\n\\n__Default value:__ `null`\"\n                },\n                \"url\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/URI\",\n                            \"description\": \"The URL of the image file for image marks.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"width\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Width of the marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"x\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"X coordinates of the marks, or width of horizontal `\\\"bar\\\"` and `\\\"area\\\"` without specified `x2` or `width`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"x2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"X2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"y\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Y coordinates of the marks, or height of vertical `\\\"bar\\\"` and `\\\"area\\\"` without specified `y2` or `height`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                },\n                \"y2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Y2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"MarkDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The horizontal alignment of the text or ranged marks (area, bar, image, rect, rule). One of `\\\"left\\\"`, `\\\"right\\\"`, `\\\"center\\\"`.\\n\\n__Note:__ Expression reference is *not* supported for range marks.\"\n                },\n                \"angle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The rotation angle of the text, in degrees.\",\n                            \"maximum\": 360,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aria\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag indicating if [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) should be included (SVG output only). If `false`, the \\\"aria-hidden\\\" attribute will be set on the output SVG element, removing the mark item from the ARIA accessibility tree.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ariaRole\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Sets the type of user interface element of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the \\\"role\\\" attribute. Warning: this property is experimental and may be changed in the future.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ariaRoleDescription\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A human-readable, author-localized description for the role of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the \\\"aria-roledescription\\\" attribute. Warning: this property is experimental and may be changed in the future.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aspect\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Whether to keep aspect ratio of image marks.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"bandSize\": {\n                    \"description\": \"The width of the ticks.\\n\\n__Default value:__  3/4 of step (width step for horizontal ticks and height step for vertical ticks).\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"baseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"For text marks, the vertical text baseline. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, `\\\"line-bottom\\\"`, or an expression reference that provides one of the valid values. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the `lineHeight` rather than `fontSize` alone.\\n\\nFor range marks, the vertical alignment of the marks. One of `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`.\\n\\n__Note:__ Expression reference is *not* supported for range marks.\"\n                },\n                \"binSpacing\": {\n                    \"description\": \"Offset between bars for binned field. The ideal value for this is either 0 (preferred by statisticians) or 1 (Vega-Lite default, D3 example style).\\n\\n__Default value:__ `1`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"blend\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Blend\",\n                            \"description\": \"The color blend mode for drawing an item on its current background. Any valid [CSS mix-blend-mode](https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode) value can be used.\\n\\n__Default value: `\\\"source-over\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"clip\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Whether a mark be clipped to the enclosing group’s width and height.\"\n                },\n                \"color\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default color.\\n\\n__Default value:__ <span style=\\\"color: #4682b4;\\\">&#9632;</span> `\\\"#4682b4\\\"`\\n\\n__Note:__\\n- This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\\n- The `fill` and `stroke` properties have higher precedence than `color` and will override `color`.\"\n                },\n                \"continuousBandSize\": {\n                    \"description\": \"The default size of the bars on continuous scales.\\n\\n__Default value:__ `5`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"cornerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles or arcs' corners.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusBottomLeft\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' bottom left corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusBottomRight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' bottom right corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusEnd\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"- For vertical bars, top-left and top-right corner radius.\\n\\n- For horizontal bars, top-right and bottom-right corner radius.\"\n                },\n                \"cornerRadiusTopLeft\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' top right corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusTopRight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' top left corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cursor\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Cursor\",\n                            \"description\": \"The mouse cursor used over the mark. Any valid [CSS cursor type](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"description\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A text description of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the [\\\"aria-label\\\" attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dir\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextDirection\",\n                            \"description\": \"The direction of the text. One of `\\\"ltr\\\"` (left-to-right) or `\\\"rtl\\\"` (right-to-left). This property determines on which side is truncated in response to the limit parameter.\\n\\n__Default value:__ `\\\"ltr\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"discreteBandSize\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RelativeBandSize\"\n                        }\n                    ],\n                    \"description\": \"The default size of the bars with discrete dimensions. If unspecified, the default size is  `step-2`, which provides 2 pixel offset between bars.\",\n                    \"minimum\": 0\n                },\n                \"dx\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The horizontal offset, in pixels, between the text label and its anchor point. The offset is applied after rotation by the _angle_ property.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dy\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The vertical offset, in pixels, between the text label and its anchor point. The offset is applied after rotation by the _angle_ property.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ellipsis\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The ellipsis string for text truncated in response to the limit parameter.\\n\\n__Default value:__ `\\\"…\\\"`\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fill\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default fill color. This property has higher precedence than `config.color`. Set to `null` to remove fill.\\n\\n__Default value:__ (None)\"\n                },\n                \"fillOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The fill opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"filled\": {\n                    \"description\": \"Whether the mark's color should be used as fill color instead of stroke color.\\n\\n__Default value:__ `false` for all `point`, `line`, and `rule` marks as well as `geoshape` marks for [`graticule`](https://vega.github.io/vega-lite/docs/data.html#graticule) data sources; otherwise, `true`.\\n\\n__Note:__ This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\",\n                    \"type\": \"boolean\"\n                },\n                \"font\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The typeface to set the text in (e.g., `\\\"Helvetica Neue\\\"`).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font size, in pixels.\\n\\n__Default value:__ `11`\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"The font style (e.g., `\\\"italic\\\"`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"The font weight. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"height\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RelativeBandSize\"\n                        }\n                    ],\n                    \"description\": \"Height of the marks.  One of:\\n\\n- A number representing a fixed pixel height.\\n\\n- A relative band size definition.  For example, `{band: 0.5}` represents half of the band\"\n                },\n                \"href\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/URI\",\n                            \"description\": \"A URL to load upon mouse click. If defined, the mark acts as a hyperlink.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"innerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The inner radius in pixels of arc marks. `innerRadius` is an alias for `radius2`.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"interpolate\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Interpolate\",\n                            \"description\": \"The line interpolation method to use for line and area marks. One of the following:\\n- `\\\"linear\\\"`: piecewise linear segments, as in a polyline.\\n- `\\\"linear-closed\\\"`: close the linear segments to form a polygon.\\n- `\\\"step\\\"`: alternate between horizontal and vertical segments, as in a step function.\\n- `\\\"step-before\\\"`: alternate between vertical and horizontal segments, as in a step function.\\n- `\\\"step-after\\\"`: alternate between horizontal and vertical segments, as in a step function.\\n- `\\\"basis\\\"`: a B-spline, with control point duplication on the ends.\\n- `\\\"basis-open\\\"`: an open B-spline; may not intersect the start or end.\\n- `\\\"basis-closed\\\"`: a closed B-spline, as in a loop.\\n- `\\\"cardinal\\\"`: a Cardinal spline, with control point duplication on the ends.\\n- `\\\"cardinal-open\\\"`: an open Cardinal spline; may not intersect the start or end, but will intersect other control points.\\n- `\\\"cardinal-closed\\\"`: a closed Cardinal spline, as in a loop.\\n- `\\\"bundle\\\"`: equivalent to basis, except the tension parameter is used to straighten the spline.\\n- `\\\"monotone\\\"`: cubic interpolation that preserves monotonicity in y.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"invalid\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/MarkInvalidDataMode\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"Invalid data mode, which defines how the marks and corresponding scales should represent invalid values (`null` and `NaN` in continuous scales *without* defined output for invalid values).\\n\\n- `\\\"filter\\\"` — *Exclude* all invalid values from the visualization's *marks* and *scales*. For path marks (for line, area, trail), this option will create paths that connect valid points, as if the data rows with invalid values do not exist.\\n\\n- `\\\"break-paths-filter-domains\\\"` — Break path marks (for line, area, trail) at invalid values.  For non-path marks, this is equivalent to `\\\"filter\\\"`. All *scale* domains will *exclude* these filtered data points.\\n\\n- `\\\"break-paths-show-domains\\\"` — Break paths (for line, area, trail) at invalid values.  Hide invalid values for non-path marks. All *scale* domains will *include* these filtered data points (for both path and non-path marks).\\n\\n- `\\\"show\\\"` or `null` — Show all data points in the marks and scale domains. Each scale will use the output for invalid values defined in `config.scale.invalid` or, if unspecified, by default invalid values will produce the same visual values as zero (if the scale includes zero) or the minimum value (if the scale does not include zero).\\n\\n- `\\\"break-paths-show-path-domains\\\"` (default) — This is equivalent to `\\\"break-paths-show-domains\\\"` for path-based marks (line/area/trail) and `\\\"filter\\\"` for non-path marks.\\n\\n__Note__: If any channel's scale has an output for invalid values defined in `config.scale.invalid`, all values for the scales will be considered \\\"valid\\\" since they can produce a reasonable output for the scales. Thus, fields for such channels will not be filtered and will not cause path breaks.\"\n                },\n                \"limit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The maximum length of the text mark in pixels. The text value will be automatically truncated if the rendered size exceeds the limit.\\n\\n__Default value:__ `0` -- indicating no limit\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"line\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/OverlayMarkDef\"\n                        }\n                    ],\n                    \"description\": \"A flag for overlaying line on top of area marks, or an object defining the properties of the overlayed lines.\\n\\n- If this value is an empty object (`{}`) or `true`, lines with default properties will be used.\\n\\n- If this value is `false`, no lines would be automatically added to area marks.\\n\\n__Default value:__ `false`.\"\n                },\n                \"lineBreak\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A delimiter, such as a newline character, upon which to break text strings into multiple lines. This property is ignored if the text is array-valued.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"lineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The line height in pixels (the spacing between subsequent lines of text) for multi-line text marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"minBandSize\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The minimum band size for bar and rectangle marks. __Default value:__ `0.25`\"\n                },\n                \"opacity\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The overall opacity (value between [0,1]).\\n\\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or `square` marks or layered `bar` charts and `1` otherwise.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"order\": {\n                    \"description\": \"For line and trail marks, this `order` property can be set to `null` or `false` to make the lines use the original order in the data sources.\",\n                    \"type\": [\n                        \"null\",\n                        \"boolean\"\n                    ]\n                },\n                \"orient\": {\n                    \"$ref\": \"#/definitions/Orientation\",\n                    \"description\": \"The orientation of a non-stacked bar, tick, area, and line charts. The value is either horizontal (default) or vertical.\\n- For bar, rule and tick, this determines whether the size of the bar and tick should be applied to x or y dimension.\\n- For area, this property determines the orient property of the Vega output.\\n- For line and trail marks, this property determines the sort order of the points in the line if `config.sortLineBy` is not specified. For stacked charts, this is always determined by the orientation of the stack; therefore explicitly specified value will be ignored.\"\n                },\n                \"outerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The outer radius in pixels of arc marks. `outerRadius` is an alias for `radius`.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"padAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The angular padding applied to sides of the arc, in radians.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"point\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/OverlayMarkDef\"\n                        },\n                        {\n                            \"const\": \"transparent\",\n                            \"type\": \"string\"\n                        }\n                    ],\n                    \"description\": \"A flag for overlaying points on top of line or area marks, or an object defining the properties of the overlayed points.\\n\\n- If this property is `\\\"transparent\\\"`, transparent points will be used (for enhancing tooltips and selections).\\n\\n- If this property is an empty object (`{}`) or `true`, filled points with default properties will be used.\\n\\n- If this property is `false`, no points would be automatically added to line or area marks.\\n\\n__Default value:__ `false`.\"\n                },\n                \"radius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"For arc mark, the primary (outer) radius in pixels.\\n\\nFor text marks, polar coordinate radial offset, in pixels, of the text from the origin determined by the `x` and `y` properties.\\n\\n__Default value:__ `min(plot_width, plot_height)/2`\",\n                    \"minimum\": 0\n                },\n                \"radius2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The secondary (inner) radius in pixels of arc marks.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"radius2Offset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Offset for radius2.\"\n                },\n                \"radiusOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Offset for radius.\"\n                },\n                \"shape\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/SymbolShape\"\n                                },\n                                {\n                                    \"type\": \"string\"\n                                }\n                            ],\n                            \"description\": \"Shape of the point marks. Supported values include:\\n- plotting shapes: `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"cross\\\"`, `\\\"diamond\\\"`, `\\\"triangle-up\\\"`, `\\\"triangle-down\\\"`, `\\\"triangle-right\\\"`, or `\\\"triangle-left\\\"`.\\n- the line symbol `\\\"stroke\\\"`\\n- centered directional shapes `\\\"arrow\\\"`, `\\\"wedge\\\"`, or `\\\"triangle\\\"`\\n- a custom [SVG path string](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths) (For correct sizing, custom shape paths should be defined within a square bounding box with coordinates ranging from -1 to 1 along both the x and y dimensions.)\\n\\n__Default value:__ `\\\"circle\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"size\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default size for marks.\\n- For `point`/`circle`/`square`, this represents the pixel area of the marks. Note that this value sets the area of the symbol; the side lengths will increase with the square root of this value.\\n- For `bar`, this represents the band size of the bar, in pixels.\\n- For `text`, this represents the font size, in pixels.\\n\\n__Default value:__\\n- `30` for point, circle, square marks; width/height's `step`\\n- `2` for bar marks with discrete dimensions;\\n- `5` for bar marks with continuous dimensions;\\n- `11` for text marks.\",\n                    \"minimum\": 0\n                },\n                \"smooth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag (default true) indicating if the image should be smoothed when resized. If false, individual pixels should be scaled directly rather than interpolated with smoothing. For SVG rendering, this option may not work in some browsers due to lack of standardization.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"stroke\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default stroke color. This property has higher precedence than `config.color`. Set to `null` to remove stroke.\\n\\n__Default value:__ (None)\"\n                },\n                \"strokeCap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeCap\",\n                            \"description\": \"The stroke cap for line ending style. One of `\\\"butt\\\"`, `\\\"round\\\"`, or `\\\"square\\\"`.\\n\\n__Default value:__ `\\\"butt\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating stroke, space lengths for creating dashed or dotted lines.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset (in pixels) into which to begin drawing with the stroke dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeJoin\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeJoin\",\n                            \"description\": \"The stroke line join method. One of `\\\"miter\\\"`, `\\\"round\\\"` or `\\\"bevel\\\"`.\\n\\n__Default value:__ `\\\"miter\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeMiterLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The miter limit at which to bevel a line join.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset in pixels at which to draw the group stroke and fill. If unspecified, the default behavior is to dynamically offset stroked groups such that 1 pixel stroke widths align with the pixel grid.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke width, in pixels.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"style\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"items\": {\n                                \"type\": \"string\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"A string or array of strings indicating the name of custom styles to apply to the mark. A style is a named collection of mark property defaults defined within the [style configuration](https://vega.github.io/vega-lite/docs/mark.html#style-config). If style is an array, later styles will override earlier styles. Any [mark properties](https://vega.github.io/vega-lite/docs/encoding.html#mark-prop) explicitly defined within the `encoding` will override a style default.\\n\\n__Default value:__ The mark's name. For example, a bar mark will have style `\\\"bar\\\"` by default. __Note:__ Any specified style will augment the default style. For example, a bar mark with `\\\"style\\\": \\\"foo\\\"` will receive from `config.style.bar` and `config.style.foo` (the specified style `\\\"foo\\\"` has higher precedence).\"\n                },\n                \"tension\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Depending on the interpolation type, sets the tension parameter (for line and area marks).\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"text\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\",\n                            \"description\": \"Placeholder text if the `text` channel is not specified\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"theta\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"- For arc marks, the arc length in radians if theta2 is not specified, otherwise the start arc angle. (A value of 0 indicates up or “north”, increasing values proceed clockwise.)\\n\\n- For text marks, polar coordinate angle in radians.\",\n                    \"maximum\": 360,\n                    \"minimum\": 0\n                },\n                \"theta2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The end angle of arc marks in radians. A value of 0 indicates up or “north”, increasing values proceed clockwise.\"\n                },\n                \"theta2Offset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Offset for theta2.\"\n                },\n                \"thetaOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Offset for theta.\"\n                },\n                \"thickness\": {\n                    \"description\": \"Thickness of the tick mark.\\n\\n__Default value:__  `1`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"time\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"timeUnitBandPosition\": {\n                    \"description\": \"Default relative band position for a time unit. If set to `0`, the marks will be positioned at the beginning of the time unit band step. If set to `0.5`, the marks will be positioned in the middle of the time unit band step.\",\n                    \"type\": \"number\"\n                },\n                \"timeUnitBandSize\": {\n                    \"description\": \"Default relative band size for a time unit. If set to `1`, the bandwidth of the marks will be equal to the time unit band step. If set to `0.5`, bandwidth of the marks will be half of the time unit band step.\",\n                    \"type\": \"number\"\n                },\n                \"tooltip\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TooltipContent\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"The tooltip text string to show upon mouse hover or an object defining which fields should the tooltip be derived from.\\n\\n- If `tooltip` is `true` or `{\\\"content\\\": \\\"encoding\\\"}`, then all fields from `encoding` will be used.\\n- If `tooltip` is `{\\\"content\\\": \\\"data\\\"}`, then all fields that appear in the highlighted data point will be used.\\n- If set to `null` or `false`, then no tooltip will be used.\\n\\nSee the [`tooltip`](https://vega.github.io/vega-lite/docs/tooltip.html) documentation for a detailed discussion about tooltip  in Vega-Lite.\\n\\n__Default value:__ `null`\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/Mark\",\n                    \"description\": \"The mark type. This could a primitive mark type (one of `\\\"bar\\\"`, `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"tick\\\"`, `\\\"line\\\"`, `\\\"area\\\"`, `\\\"point\\\"`, `\\\"geoshape\\\"`, `\\\"rule\\\"`, and `\\\"text\\\"`) or a composite mark type (`\\\"boxplot\\\"`, `\\\"errorband\\\"`, `\\\"errorbar\\\"`).\"\n                },\n                \"url\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/URI\",\n                            \"description\": \"The URL of the image file for image marks.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"width\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RelativeBandSize\"\n                        }\n                    ],\n                    \"description\": \"Width of the marks.  One of:\\n\\n- A number representing a fixed pixel width.\\n\\n- A relative band size definition.  For example, `{band: 0.5}` represents half of the band.\"\n                },\n                \"x\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"X coordinates of the marks, or width of horizontal `\\\"bar\\\"` and `\\\"area\\\"` without specified `x2` or `width`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"x2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"X2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"x2Offset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Offset for x2-position.\"\n                },\n                \"xOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Offset for x-position.\"\n                },\n                \"y\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Y coordinates of the marks, or height of vertical `\\\"bar\\\"` and `\\\"area\\\"` without specified `y2` or `height`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                },\n                \"y2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Y2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                },\n                \"y2Offset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Offset for y2-position.\"\n                },\n                \"yOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Offset for y-position.\"\n                }\n            },\n            \"required\": [\n                \"type\"\n            ],\n            \"type\": \"object\"\n        },\n        \"MarkInvalidDataMode\": {\n            \"enum\": [\n                \"filter\",\n                \"break-paths-filter-domains\",\n                \"break-paths-show-domains\",\n                \"break-paths-show-path-domains\",\n                \"show\"\n            ],\n            \"type\": \"string\"\n        },\n        \"MarkPropDef<(Gradient|string|null)>\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/FieldOrDatumDefWithCondition<MarkPropFieldDef,(Gradient|string|null)>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/FieldOrDatumDefWithCondition<DatumDef,(Gradient|string|null)>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ValueDefWithCondition<MarkPropFieldOrDatumDef,(Gradient|string|null)>\"\n                }\n            ]\n        },\n        \"MarkPropDef<(string|null),TypeForShape>\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/FieldOrDatumDefWithCondition<MarkPropFieldDef<TypeForShape>,(string|null)>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/FieldOrDatumDefWithCondition<DatumDef,(string|null)>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ValueDefWithCondition<MarkPropFieldOrDatumDef<TypeForShape>,(string|null)>\"\n                }\n            ]\n        },\n        \"MarkPropDef<number>\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/FieldOrDatumDefWithCondition<MarkPropFieldDef,number>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/FieldOrDatumDefWithCondition<DatumDef,number>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ValueDefWithCondition<MarkPropFieldOrDatumDef,number>\"\n                }\n            ]\n        },\n        \"MarkPropDef<number[]>\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/FieldOrDatumDefWithCondition<MarkPropFieldDef,number[]>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/FieldOrDatumDefWithCondition<DatumDef,number[]>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ValueDefWithCondition<MarkPropFieldOrDatumDef,number[]>\"\n                }\n            ]\n        },\n        \"MarkType\": {\n            \"enum\": [\n                \"arc\",\n                \"area\",\n                \"image\",\n                \"group\",\n                \"line\",\n                \"path\",\n                \"rect\",\n                \"rule\",\n                \"shape\",\n                \"symbol\",\n                \"text\",\n                \"trail\"\n            ],\n            \"type\": \"string\"\n        },\n        \"MergedStream\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"between\": {\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Stream\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"consume\": {\n                    \"type\": \"boolean\"\n                },\n                \"debounce\": {\n                    \"type\": \"number\"\n                },\n                \"filter\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Expr\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/Expr\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ]\n                },\n                \"markname\": {\n                    \"type\": \"string\"\n                },\n                \"marktype\": {\n                    \"$ref\": \"#/definitions/MarkType\"\n                },\n                \"merge\": {\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Stream\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"throttle\": {\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"merge\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Month\": {\n            \"maximum\": 12,\n            \"minimum\": 1,\n            \"type\": \"number\"\n        },\n        \"MultiLineString\": {\n            \"additionalProperties\": false,\n            \"description\": \"MultiLineString geometry object. https://tools.ietf.org/html/rfc7946#section-3.1.5\",\n            \"properties\": {\n                \"bbox\": {\n                    \"$ref\": \"#/definitions/BBox\",\n                    \"description\": \"Bounding box of the coordinate range of the object's Geometries, Features, or Feature Collections. https://tools.ietf.org/html/rfc7946#section-5\"\n                },\n                \"coordinates\": {\n                    \"items\": {\n                        \"items\": {\n                            \"$ref\": \"#/definitions/Position\"\n                        },\n                        \"type\": \"array\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"type\": {\n                    \"const\": \"MultiLineString\",\n                    \"description\": \"Specifies the type of GeoJSON object.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"coordinates\",\n                \"type\"\n            ],\n            \"type\": \"object\"\n        },\n        \"MultiPoint\": {\n            \"additionalProperties\": false,\n            \"description\": \"MultiPoint geometry object.  https://tools.ietf.org/html/rfc7946#section-3.1.3\",\n            \"properties\": {\n                \"bbox\": {\n                    \"$ref\": \"#/definitions/BBox\",\n                    \"description\": \"Bounding box of the coordinate range of the object's Geometries, Features, or Feature Collections. https://tools.ietf.org/html/rfc7946#section-5\"\n                },\n                \"coordinates\": {\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Position\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"type\": {\n                    \"const\": \"MultiPoint\",\n                    \"description\": \"Specifies the type of GeoJSON object.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"coordinates\",\n                \"type\"\n            ],\n            \"type\": \"object\"\n        },\n        \"MultiPolygon\": {\n            \"additionalProperties\": false,\n            \"description\": \"MultiPolygon geometry object. https://tools.ietf.org/html/rfc7946#section-3.1.7\",\n            \"properties\": {\n                \"bbox\": {\n                    \"$ref\": \"#/definitions/BBox\",\n                    \"description\": \"Bounding box of the coordinate range of the object's Geometries, Features, or Feature Collections. https://tools.ietf.org/html/rfc7946#section-5\"\n                },\n                \"coordinates\": {\n                    \"items\": {\n                        \"items\": {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/Position\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        \"type\": \"array\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"type\": {\n                    \"const\": \"MultiPolygon\",\n                    \"description\": \"Specifies the type of GeoJSON object.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"coordinates\",\n                \"type\"\n            ],\n            \"type\": \"object\"\n        },\n        \"MultiTimeUnit\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/LocalMultiTimeUnit\"\n                },\n                {\n                    \"$ref\": \"#/definitions/UtcMultiTimeUnit\"\n                }\n            ]\n        },\n        \"NamedData\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"format\": {\n                    \"$ref\": \"#/definitions/DataFormat\",\n                    \"description\": \"An object that specifies the format for parsing the data.\"\n                },\n                \"name\": {\n                    \"description\": \"Provide a placeholder name and bind data at runtime.\\n\\nNew data may change the layout but Vega does not always resize the chart. To update the layout when the data updates, set [autosize](https://vega.github.io/vega-lite/docs/size.html#autosize) or explicitly use [view.resize](https://vega.github.io/vega/docs/api/view/#view_resize).\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"name\"\n            ],\n            \"type\": \"object\"\n        },\n        \"NonArgAggregateOp\": {\n            \"enum\": [\n                \"average\",\n                \"count\",\n                \"distinct\",\n                \"max\",\n                \"mean\",\n                \"median\",\n                \"min\",\n                \"missing\",\n                \"product\",\n                \"q1\",\n                \"q3\",\n                \"ci0\",\n                \"ci1\",\n                \"stderr\",\n                \"stdev\",\n                \"stdevp\",\n                \"sum\",\n                \"valid\",\n                \"values\",\n                \"variance\",\n                \"variancep\",\n                \"exponential\",\n                \"exponentialb\"\n            ],\n            \"type\": \"string\"\n        },\n        \"NonLayerRepeatSpec\": {\n            \"additionalProperties\": false,\n            \"description\": \"Base interface for a repeat specification.\",\n            \"properties\": {\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LayoutAlign\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<LayoutAlign>\"\n                        }\n                    ],\n                    \"description\": \"The alignment to apply to grid rows and columns. The supported string values are `\\\"all\\\"`, `\\\"each\\\"`, and `\\\"none\\\"`.\\n\\n- For `\\\"none\\\"`, a flow layout will be used, in which adjacent subviews are simply placed one after the other.\\n- For `\\\"each\\\"`, subviews will be aligned into a clean grid structure, but each row or column may be of variable size.\\n- For `\\\"all\\\"`, subviews will be aligned and each row or column will be sized identically based on the maximum observed size. String values for this property will be applied to both grid rows and columns.\\n\\nAlternatively, an object value of the form `{\\\"row\\\": string, \\\"column\\\": string}` can be used to supply different alignments for rows and columns.\\n\\n__Default value:__ `\\\"all\\\"`.\"\n                },\n                \"bounds\": {\n                    \"description\": \"The bounds calculation method to use for determining the extent of a sub-plot. One of `full` (the default) or `flush`.\\n\\n- If set to `full`, the entire calculated bounds (including axes, title, and legend) will be used.\\n- If set to `flush`, only the specified width and height values for the sub-view will be used. The `flush` setting can be useful when attempting to place sub-plots without axes or legends into a uniform grid structure.\\n\\n__Default value:__ `\\\"full\\\"`\",\n                    \"enum\": [\n                        \"full\",\n                        \"flush\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"center\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<boolean>\"\n                        }\n                    ],\n                    \"description\": \"Boolean flag indicating if subviews should be centered relative to their respective rows or columns.\\n\\nAn object value of the form `{\\\"row\\\": boolean, \\\"column\\\": boolean}` can be used to supply different centering values for rows and columns.\\n\\n__Default value:__ `false`\"\n                },\n                \"columns\": {\n                    \"description\": \"The number of columns to include in the view composition layout.\\n\\n__Default value__: `undefined` -- An infinite number of columns (a single row) will be assumed. This is equivalent to `hconcat` (for `concat`) and to using the `column` channel (for `facet` and `repeat`).\\n\\n__Note__:\\n\\n1) This property is only for:\\n- the general (wrappable) `concat` operator (not `hconcat`/`vconcat`)\\n- the `facet` and `repeat` operator with one field/repetition definition (without row/column nesting)\\n\\n2) Setting the `columns` to `1` is equivalent to `vconcat` (for `concat`) and to using the `row` channel (for `facet` and `repeat`).\",\n                    \"type\": \"number\"\n                },\n                \"data\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Data\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                },\n                \"description\": {\n                    \"description\": \"Description of this mark for commenting purpose.\",\n                    \"type\": \"string\"\n                },\n                \"name\": {\n                    \"description\": \"Name of the visualization for later reference.\",\n                    \"type\": \"string\"\n                },\n                \"repeat\": {\n                    \"anyOf\": [\n                        {\n                            \"items\": {\n                                \"type\": \"string\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RepeatMapping\"\n                        }\n                    ],\n                    \"description\": \"Definition for fields to be repeated. One of: 1) An array of fields to be repeated. If `\\\"repeat\\\"` is an array, the field can be referred to as `{\\\"repeat\\\": \\\"repeat\\\"}`. The repeated views are laid out in a wrapped row. You can set the number of columns to control the wrapping. 2) An object that maps `\\\"row\\\"` and/or `\\\"column\\\"` to the listed fields to be repeated along the particular orientations. The objects `{\\\"repeat\\\": \\\"row\\\"}` and `{\\\"repeat\\\": \\\"column\\\"}` can be used to refer to the repeated field respectively.\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/Resolve\",\n                    \"description\": \"Scale, axis, and legend resolutions for view composition specifications.\"\n                },\n                \"spacing\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<number>\"\n                        }\n                    ],\n                    \"description\": \"The spacing in pixels between sub-views of the composition operator. An object of the form `{\\\"row\\\": number, \\\"column\\\": number}` can be used to set different spacing values for rows and columns.\\n\\n__Default value__: Depends on `\\\"spacing\\\"` property of [the view composition configuration](https://vega.github.io/vega-lite/docs/config.html#view-config) (`20` by default)\"\n                },\n                \"spec\": {\n                    \"$ref\": \"#/definitions/NonNormalizedSpec\",\n                    \"description\": \"A specification of the view that gets repeated.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TitleParams\"\n                        }\n                    ],\n                    \"description\": \"Title for the plot.\"\n                },\n                \"transform\": {\n                    \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Transform\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"repeat\",\n                \"spec\"\n            ],\n            \"type\": \"object\"\n        },\n        \"NonNormalizedSpec\": {\n            \"$ref\": \"#/definitions/Spec\"\n        },\n        \"NumberLocale\": {\n            \"additionalProperties\": false,\n            \"description\": \"Locale definition for formatting numbers.\",\n            \"properties\": {\n                \"currency\": {\n                    \"$ref\": \"#/definitions/Vector2<string>\",\n                    \"description\": \"The currency prefix and suffix (e.g., [\\\"$\\\", \\\"\\\"]).\"\n                },\n                \"decimal\": {\n                    \"description\": \"The decimal point (e.g., \\\".\\\").\",\n                    \"type\": \"string\"\n                },\n                \"grouping\": {\n                    \"description\": \"The array of group sizes (e.g., [3]), cycled as needed.\",\n                    \"items\": {\n                        \"type\": \"number\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"minus\": {\n                    \"description\": \"The minus sign (defaults to hyphen-minus, \\\"-\\\").\",\n                    \"type\": \"string\"\n                },\n                \"nan\": {\n                    \"description\": \"The not-a-number value (defaults to \\\"NaN\\\").\",\n                    \"type\": \"string\"\n                },\n                \"numerals\": {\n                    \"$ref\": \"#/definitions/Vector10<string>\",\n                    \"description\": \"An array of ten strings to replace the numerals 0-9.\"\n                },\n                \"percent\": {\n                    \"description\": \"The percent sign (defaults to \\\"%\\\").\",\n                    \"type\": \"string\"\n                },\n                \"thousands\": {\n                    \"description\": \"The group separator (e.g., \\\",\\\").\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"decimal\",\n                \"thousands\",\n                \"grouping\",\n                \"currency\"\n            ],\n            \"type\": \"object\"\n        },\n        \"NumericArrayMarkPropDef\": {\n            \"$ref\": \"#/definitions/MarkPropDef<number[]>\"\n        },\n        \"NumericMarkPropDef\": {\n            \"$ref\": \"#/definitions/MarkPropDef<number>\"\n        },\n        \"OffsetDef\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleFieldDef\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ScaleDatumDef\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ValueDef<number>\"\n                }\n            ]\n        },\n        \"OrderFieldDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"const\": \"binned\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"sort\": {\n                    \"$ref\": \"#/definitions/SortOrder\",\n                    \"description\": \"The sort order. One of `\\\"ascending\\\"` (default) or `\\\"descending\\\"`.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/StandardType\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"OrderOnlyDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"sort\": {\n                    \"$ref\": \"#/definitions/SortOrder\",\n                    \"description\": \"The sort order. One of `\\\"ascending\\\"` (default) or `\\\"descending\\\"`.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"OrderValueDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<number>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<number>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"required\": [\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Orient\": {\n            \"enum\": [\n                \"left\",\n                \"right\",\n                \"top\",\n                \"bottom\"\n            ],\n            \"type\": \"string\"\n        },\n        \"Orientation\": {\n            \"enum\": [\n                \"horizontal\",\n                \"vertical\"\n            ],\n            \"type\": \"string\"\n        },\n        \"OverlayMarkDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The horizontal alignment of the text or ranged marks (area, bar, image, rect, rule). One of `\\\"left\\\"`, `\\\"right\\\"`, `\\\"center\\\"`.\\n\\n__Note:__ Expression reference is *not* supported for range marks.\"\n                },\n                \"angle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The rotation angle of the text, in degrees.\",\n                            \"maximum\": 360,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aria\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag indicating if [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) should be included (SVG output only). If `false`, the \\\"aria-hidden\\\" attribute will be set on the output SVG element, removing the mark item from the ARIA accessibility tree.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ariaRole\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Sets the type of user interface element of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the \\\"role\\\" attribute. Warning: this property is experimental and may be changed in the future.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ariaRoleDescription\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A human-readable, author-localized description for the role of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the \\\"aria-roledescription\\\" attribute. Warning: this property is experimental and may be changed in the future.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aspect\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Whether to keep aspect ratio of image marks.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"baseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"For text marks, the vertical text baseline. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, `\\\"line-bottom\\\"`, or an expression reference that provides one of the valid values. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the `lineHeight` rather than `fontSize` alone.\\n\\nFor range marks, the vertical alignment of the marks. One of `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`.\\n\\n__Note:__ Expression reference is *not* supported for range marks.\"\n                },\n                \"blend\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Blend\",\n                            \"description\": \"The color blend mode for drawing an item on its current background. Any valid [CSS mix-blend-mode](https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode) value can be used.\\n\\n__Default value: `\\\"source-over\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"clip\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Whether a mark be clipped to the enclosing group’s width and height.\"\n                },\n                \"color\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default color.\\n\\n__Default value:__ <span style=\\\"color: #4682b4;\\\">&#9632;</span> `\\\"#4682b4\\\"`\\n\\n__Note:__\\n- This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\\n- The `fill` and `stroke` properties have higher precedence than `color` and will override `color`.\"\n                },\n                \"cornerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles or arcs' corners.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusBottomLeft\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' bottom left corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusBottomRight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' bottom right corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusTopLeft\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' top right corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusTopRight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' top left corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cursor\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Cursor\",\n                            \"description\": \"The mouse cursor used over the mark. Any valid [CSS cursor type](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"description\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A text description of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the [\\\"aria-label\\\" attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dir\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextDirection\",\n                            \"description\": \"The direction of the text. One of `\\\"ltr\\\"` (left-to-right) or `\\\"rtl\\\"` (right-to-left). This property determines on which side is truncated in response to the limit parameter.\\n\\n__Default value:__ `\\\"ltr\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dx\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The horizontal offset, in pixels, between the text label and its anchor point. The offset is applied after rotation by the _angle_ property.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dy\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The vertical offset, in pixels, between the text label and its anchor point. The offset is applied after rotation by the _angle_ property.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ellipsis\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The ellipsis string for text truncated in response to the limit parameter.\\n\\n__Default value:__ `\\\"…\\\"`\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"endAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The end angle in radians for arc marks. A value of `0` indicates up (north), increasing values proceed clockwise.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fill\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default fill color. This property has higher precedence than `config.color`. Set to `null` to remove fill.\\n\\n__Default value:__ (None)\"\n                },\n                \"fillOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The fill opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"filled\": {\n                    \"description\": \"Whether the mark's color should be used as fill color instead of stroke color.\\n\\n__Default value:__ `false` for all `point`, `line`, and `rule` marks as well as `geoshape` marks for [`graticule`](https://vega.github.io/vega-lite/docs/data.html#graticule) data sources; otherwise, `true`.\\n\\n__Note:__ This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\",\n                    \"type\": \"boolean\"\n                },\n                \"font\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The typeface to set the text in (e.g., `\\\"Helvetica Neue\\\"`).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font size, in pixels.\\n\\n__Default value:__ `11`\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"The font style (e.g., `\\\"italic\\\"`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"The font weight. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"height\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Height of the marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"href\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/URI\",\n                            \"description\": \"A URL to load upon mouse click. If defined, the mark acts as a hyperlink.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"innerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The inner radius in pixels of arc marks. `innerRadius` is an alias for `radius2`.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"interpolate\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Interpolate\",\n                            \"description\": \"The line interpolation method to use for line and area marks. One of the following:\\n- `\\\"linear\\\"`: piecewise linear segments, as in a polyline.\\n- `\\\"linear-closed\\\"`: close the linear segments to form a polygon.\\n- `\\\"step\\\"`: alternate between horizontal and vertical segments, as in a step function.\\n- `\\\"step-before\\\"`: alternate between vertical and horizontal segments, as in a step function.\\n- `\\\"step-after\\\"`: alternate between horizontal and vertical segments, as in a step function.\\n- `\\\"basis\\\"`: a B-spline, with control point duplication on the ends.\\n- `\\\"basis-open\\\"`: an open B-spline; may not intersect the start or end.\\n- `\\\"basis-closed\\\"`: a closed B-spline, as in a loop.\\n- `\\\"cardinal\\\"`: a Cardinal spline, with control point duplication on the ends.\\n- `\\\"cardinal-open\\\"`: an open Cardinal spline; may not intersect the start or end, but will intersect other control points.\\n- `\\\"cardinal-closed\\\"`: a closed Cardinal spline, as in a loop.\\n- `\\\"bundle\\\"`: equivalent to basis, except the tension parameter is used to straighten the spline.\\n- `\\\"monotone\\\"`: cubic interpolation that preserves monotonicity in y.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"invalid\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/MarkInvalidDataMode\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"Invalid data mode, which defines how the marks and corresponding scales should represent invalid values (`null` and `NaN` in continuous scales *without* defined output for invalid values).\\n\\n- `\\\"filter\\\"` — *Exclude* all invalid values from the visualization's *marks* and *scales*. For path marks (for line, area, trail), this option will create paths that connect valid points, as if the data rows with invalid values do not exist.\\n\\n- `\\\"break-paths-filter-domains\\\"` — Break path marks (for line, area, trail) at invalid values.  For non-path marks, this is equivalent to `\\\"filter\\\"`. All *scale* domains will *exclude* these filtered data points.\\n\\n- `\\\"break-paths-show-domains\\\"` — Break paths (for line, area, trail) at invalid values.  Hide invalid values for non-path marks. All *scale* domains will *include* these filtered data points (for both path and non-path marks).\\n\\n- `\\\"show\\\"` or `null` — Show all data points in the marks and scale domains. Each scale will use the output for invalid values defined in `config.scale.invalid` or, if unspecified, by default invalid values will produce the same visual values as zero (if the scale includes zero) or the minimum value (if the scale does not include zero).\\n\\n- `\\\"break-paths-show-path-domains\\\"` (default) — This is equivalent to `\\\"break-paths-show-domains\\\"` for path-based marks (line/area/trail) and `\\\"filter\\\"` for non-path marks.\\n\\n__Note__: If any channel's scale has an output for invalid values defined in `config.scale.invalid`, all values for the scales will be considered \\\"valid\\\" since they can produce a reasonable output for the scales. Thus, fields for such channels will not be filtered and will not cause path breaks.\"\n                },\n                \"limit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The maximum length of the text mark in pixels. The text value will be automatically truncated if the rendered size exceeds the limit.\\n\\n__Default value:__ `0` -- indicating no limit\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"lineBreak\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A delimiter, such as a newline character, upon which to break text strings into multiple lines. This property is ignored if the text is array-valued.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"lineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The line height in pixels (the spacing between subsequent lines of text) for multi-line text marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"opacity\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The overall opacity (value between [0,1]).\\n\\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or `square` marks or layered `bar` charts and `1` otherwise.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"order\": {\n                    \"description\": \"For line and trail marks, this `order` property can be set to `null` or `false` to make the lines use the original order in the data sources.\",\n                    \"type\": [\n                        \"null\",\n                        \"boolean\"\n                    ]\n                },\n                \"orient\": {\n                    \"$ref\": \"#/definitions/Orientation\",\n                    \"description\": \"The orientation of a non-stacked bar, tick, area, and line charts. The value is either horizontal (default) or vertical.\\n- For bar, rule and tick, this determines whether the size of the bar and tick should be applied to x or y dimension.\\n- For area, this property determines the orient property of the Vega output.\\n- For line and trail marks, this property determines the sort order of the points in the line if `config.sortLineBy` is not specified. For stacked charts, this is always determined by the orientation of the stack; therefore explicitly specified value will be ignored.\"\n                },\n                \"outerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The outer radius in pixels of arc marks. `outerRadius` is an alias for `radius`.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"padAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The angular padding applied to sides of the arc, in radians.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"radius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"For arc mark, the primary (outer) radius in pixels.\\n\\nFor text marks, polar coordinate radial offset, in pixels, of the text from the origin determined by the `x` and `y` properties.\\n\\n__Default value:__ `min(plot_width, plot_height)/2`\",\n                    \"minimum\": 0\n                },\n                \"radius2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The secondary (inner) radius in pixels of arc marks.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"radius2Offset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Offset for radius2.\"\n                },\n                \"radiusOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Offset for radius.\"\n                },\n                \"shape\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/SymbolShape\"\n                                },\n                                {\n                                    \"type\": \"string\"\n                                }\n                            ],\n                            \"description\": \"Shape of the point marks. Supported values include:\\n- plotting shapes: `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"cross\\\"`, `\\\"diamond\\\"`, `\\\"triangle-up\\\"`, `\\\"triangle-down\\\"`, `\\\"triangle-right\\\"`, or `\\\"triangle-left\\\"`.\\n- the line symbol `\\\"stroke\\\"`\\n- centered directional shapes `\\\"arrow\\\"`, `\\\"wedge\\\"`, or `\\\"triangle\\\"`\\n- a custom [SVG path string](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths) (For correct sizing, custom shape paths should be defined within a square bounding box with coordinates ranging from -1 to 1 along both the x and y dimensions.)\\n\\n__Default value:__ `\\\"circle\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"size\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default size for marks.\\n- For `point`/`circle`/`square`, this represents the pixel area of the marks. Note that this value sets the area of the symbol; the side lengths will increase with the square root of this value.\\n- For `bar`, this represents the band size of the bar, in pixels.\\n- For `text`, this represents the font size, in pixels.\\n\\n__Default value:__\\n- `30` for point, circle, square marks; width/height's `step`\\n- `2` for bar marks with discrete dimensions;\\n- `5` for bar marks with continuous dimensions;\\n- `11` for text marks.\",\n                    \"minimum\": 0\n                },\n                \"smooth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag (default true) indicating if the image should be smoothed when resized. If false, individual pixels should be scaled directly rather than interpolated with smoothing. For SVG rendering, this option may not work in some browsers due to lack of standardization.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"startAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The start angle in radians for arc marks. A value of `0` indicates up (north), increasing values proceed clockwise.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"stroke\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default stroke color. This property has higher precedence than `config.color`. Set to `null` to remove stroke.\\n\\n__Default value:__ (None)\"\n                },\n                \"strokeCap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeCap\",\n                            \"description\": \"The stroke cap for line ending style. One of `\\\"butt\\\"`, `\\\"round\\\"`, or `\\\"square\\\"`.\\n\\n__Default value:__ `\\\"butt\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating stroke, space lengths for creating dashed or dotted lines.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset (in pixels) into which to begin drawing with the stroke dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeJoin\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeJoin\",\n                            \"description\": \"The stroke line join method. One of `\\\"miter\\\"`, `\\\"round\\\"` or `\\\"bevel\\\"`.\\n\\n__Default value:__ `\\\"miter\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeMiterLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The miter limit at which to bevel a line join.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset in pixels at which to draw the group stroke and fill. If unspecified, the default behavior is to dynamically offset stroked groups such that 1 pixel stroke widths align with the pixel grid.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke width, in pixels.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"style\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"items\": {\n                                \"type\": \"string\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"A string or array of strings indicating the name of custom styles to apply to the mark. A style is a named collection of mark property defaults defined within the [style configuration](https://vega.github.io/vega-lite/docs/mark.html#style-config). If style is an array, later styles will override earlier styles. Any [mark properties](https://vega.github.io/vega-lite/docs/encoding.html#mark-prop) explicitly defined within the `encoding` will override a style default.\\n\\n__Default value:__ The mark's name. For example, a bar mark will have style `\\\"bar\\\"` by default. __Note:__ Any specified style will augment the default style. For example, a bar mark with `\\\"style\\\": \\\"foo\\\"` will receive from `config.style.bar` and `config.style.foo` (the specified style `\\\"foo\\\"` has higher precedence).\"\n                },\n                \"tension\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Depending on the interpolation type, sets the tension parameter (for line and area marks).\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"text\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\",\n                            \"description\": \"Placeholder text if the `text` channel is not specified\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"theta\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"- For arc marks, the arc length in radians if theta2 is not specified, otherwise the start arc angle. (A value of 0 indicates up or “north”, increasing values proceed clockwise.)\\n\\n- For text marks, polar coordinate angle in radians.\",\n                    \"maximum\": 360,\n                    \"minimum\": 0\n                },\n                \"theta2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The end angle of arc marks in radians. A value of 0 indicates up or “north”, increasing values proceed clockwise.\"\n                },\n                \"theta2Offset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Offset for theta2.\"\n                },\n                \"thetaOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Offset for theta.\"\n                },\n                \"time\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"timeUnitBandPosition\": {\n                    \"description\": \"Default relative band position for a time unit. If set to `0`, the marks will be positioned at the beginning of the time unit band step. If set to `0.5`, the marks will be positioned in the middle of the time unit band step.\",\n                    \"type\": \"number\"\n                },\n                \"timeUnitBandSize\": {\n                    \"description\": \"Default relative band size for a time unit. If set to `1`, the bandwidth of the marks will be equal to the time unit band step. If set to `0.5`, bandwidth of the marks will be half of the time unit band step.\",\n                    \"type\": \"number\"\n                },\n                \"tooltip\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TooltipContent\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"The tooltip text string to show upon mouse hover or an object defining which fields should the tooltip be derived from.\\n\\n- If `tooltip` is `true` or `{\\\"content\\\": \\\"encoding\\\"}`, then all fields from `encoding` will be used.\\n- If `tooltip` is `{\\\"content\\\": \\\"data\\\"}`, then all fields that appear in the highlighted data point will be used.\\n- If set to `null` or `false`, then no tooltip will be used.\\n\\nSee the [`tooltip`](https://vega.github.io/vega-lite/docs/tooltip.html) documentation for a detailed discussion about tooltip  in Vega-Lite.\\n\\n__Default value:__ `null`\"\n                },\n                \"url\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/URI\",\n                            \"description\": \"The URL of the image file for image marks.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"width\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Width of the marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"x\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"X coordinates of the marks, or width of horizontal `\\\"bar\\\"` and `\\\"area\\\"` without specified `x2` or `width`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"x2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"X2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"x2Offset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Offset for x2-position.\"\n                },\n                \"xOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Offset for x-position.\"\n                },\n                \"y\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Y coordinates of the marks, or height of vertical `\\\"bar\\\"` and `\\\"area\\\"` without specified `y2` or `height`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                },\n                \"y2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Y2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                },\n                \"y2Offset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Offset for y2-position.\"\n                },\n                \"yOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Offset for y-position.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"Padding\": {\n            \"anyOf\": [\n                {\n                    \"type\": \"number\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"bottom\": {\n                            \"type\": \"number\"\n                        },\n                        \"left\": {\n                            \"type\": \"number\"\n                        },\n                        \"right\": {\n                            \"type\": \"number\"\n                        },\n                        \"top\": {\n                            \"type\": \"number\"\n                        }\n                    },\n                    \"type\": \"object\"\n                }\n            ],\n            \"minimum\": 0\n        },\n        \"ParameterExtent\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"field\": {\n                            \"$ref\": \"#/definitions/FieldName\",\n                            \"description\": \"If a selection parameter is specified, the field name to extract selected values for when the selection is [projected](https://vega.github.io/vega-lite/docs/selection.html#project) over multiple fields or encodings.\"\n                        },\n                        \"param\": {\n                            \"$ref\": \"#/definitions/ParameterName\",\n                            \"description\": \"The name of a parameter.\"\n                        }\n                    },\n                    \"required\": [\n                        \"param\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"encoding\": {\n                            \"$ref\": \"#/definitions/SingleDefUnitChannel\",\n                            \"description\": \"If a selection parameter is specified, the encoding channel to extract selected values for when a selection is [projected](https://vega.github.io/vega-lite/docs/selection.html#project) over multiple fields or encodings.\"\n                        },\n                        \"param\": {\n                            \"$ref\": \"#/definitions/ParameterName\",\n                            \"description\": \"The name of a parameter.\"\n                        }\n                    },\n                    \"required\": [\n                        \"param\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"ParameterName\": {\n            \"type\": \"string\"\n        },\n        \"ParameterPredicate\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"empty\": {\n                    \"description\": \"For selection parameters, the predicate of empty selections returns true by default. Override this behavior, by setting this property `empty: false`.\",\n                    \"type\": \"boolean\"\n                },\n                \"param\": {\n                    \"$ref\": \"#/definitions/ParameterName\",\n                    \"description\": \"Filter using a parameter name.\"\n                }\n            },\n            \"required\": [\n                \"param\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Parse\": {\n            \"additionalProperties\": {\n                \"$ref\": \"#/definitions/ParseValue\"\n            },\n            \"type\": \"object\"\n        },\n        \"ParseValue\": {\n            \"type\": [\n                \"string\",\n                \"null\"\n            ]\n        },\n        \"PivotTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"groupby\": {\n                    \"description\": \"The optional data fields to group by. If not specified, a single group containing all data objects will be used.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"limit\": {\n                    \"description\": \"An optional parameter indicating the maximum number of pivoted fields to generate. The default (`0`) applies no limit. The pivoted `pivot` names are sorted in ascending order prior to enforcing the limit. __Default value:__ `0`\",\n                    \"type\": \"number\"\n                },\n                \"op\": {\n                    \"$ref\": \"#/definitions/AggregateOp\",\n                    \"description\": \"The aggregation operation to apply to grouped `value` field values. __Default value:__ `sum`\"\n                },\n                \"pivot\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The data field to pivot on. The unique values of this field become new field names in the output stream.\"\n                },\n                \"value\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The data field to populate pivoted fields. The aggregate values of this field become the values of the new pivoted fields.\"\n                }\n            },\n            \"required\": [\n                \"pivot\",\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Point\": {\n            \"additionalProperties\": false,\n            \"description\": \"Point geometry object. https://tools.ietf.org/html/rfc7946#section-3.1.2\",\n            \"properties\": {\n                \"bbox\": {\n                    \"$ref\": \"#/definitions/BBox\",\n                    \"description\": \"Bounding box of the coordinate range of the object's Geometries, Features, or Feature Collections. https://tools.ietf.org/html/rfc7946#section-5\"\n                },\n                \"coordinates\": {\n                    \"$ref\": \"#/definitions/Position\"\n                },\n                \"type\": {\n                    \"const\": \"Point\",\n                    \"description\": \"Specifies the type of GeoJSON object.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"coordinates\",\n                \"type\"\n            ],\n            \"type\": \"object\"\n        },\n        \"PointSelectionConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"clear\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Stream\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        }\n                    ],\n                    \"description\": \"Clears the selection, emptying it of all values. This property can be a [Event Stream](https://vega.github.io/vega/docs/event-streams/) or `false` to disable clear.\\n\\n__Default value:__ `dblclick`.\\n\\n__See also:__ [`clear` examples ](https://vega.github.io/vega-lite/docs/selection.html#clear) in the documentation.\"\n                },\n                \"encodings\": {\n                    \"description\": \"An array of encoding channels. The corresponding data field values must match for a data tuple to fall within the selection.\\n\\n__See also:__ The [projection with `encodings` and `fields` section](https://vega.github.io/vega-lite/docs/selection.html#project) in the documentation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/SingleDefUnitChannel\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"fields\": {\n                    \"description\": \"An array of field names whose values must match for a data tuple to fall within the selection.\\n\\n__See also:__ The [projection with `encodings` and `fields` section](https://vega.github.io/vega-lite/docs/selection.html#project) in the documentation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"nearest\": {\n                    \"description\": \"When true, an invisible voronoi diagram is computed to accelerate discrete selection. The data value _nearest_ the mouse cursor is added to the selection.\\n\\n__Default value:__ `false`, which means that data values must be interacted with directly (e.g., clicked on) to be added to the selection.\\n\\n__See also:__ [`nearest` examples](https://vega.github.io/vega-lite/docs/selection.html#nearest) documentation.\",\n                    \"type\": \"boolean\"\n                },\n                \"on\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Stream\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        }\n                    ],\n                    \"description\": \"A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or selector) that triggers the selection. For interval selections, the event stream must specify a [start and end](https://vega.github.io/vega/docs/event-streams/#between-filters).\\n\\n__See also:__ [`on` examples](https://vega.github.io/vega-lite/docs/selection.html#on) in the documentation.\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/SelectionResolution\",\n                    \"description\": \"With layered and multi-view displays, a strategy that determines how selections' data queries are resolved when applied in a filter transform, conditional encoding rule, or scale domain.\\n\\nOne of:\\n- `\\\"global\\\"` -- only one brush exists for the entire SPLOM. When the user begins to drag, any previous brushes are cleared, and a new one is constructed.\\n- `\\\"union\\\"` -- each cell contains its own brush, and points are highlighted if they lie within _any_ of these individual brushes.\\n- `\\\"intersect\\\"` -- each cell contains its own brush, and points are highlighted only if they fall within _all_ of these individual brushes.\\n\\n__Default value:__ `global`.\\n\\n__See also:__ [`resolve` examples](https://vega.github.io/vega-lite/docs/selection.html#resolve) in the documentation.\"\n                },\n                \"toggle\": {\n                    \"description\": \"Controls whether data values should be toggled (inserted or removed from a point selection) or only ever inserted into point selections.\\n\\nOne of:\\n- `true` -- the default behavior, which corresponds to `\\\"event.shiftKey\\\"`.  As a result, data values are toggled when the user interacts with the shift-key pressed.\\n- `false` -- disables toggling behaviour; the selection will only ever contain a single data value corresponding to the most recent interaction.\\n- A [Vega expression](https://vega.github.io/vega/docs/expressions/) which is re-evaluated as the user interacts. If the expression evaluates to `true`, the data value is toggled into or out of the point selection. If the expression evaluates to `false`, the point selection is first cleared, and the data value is then inserted. For example, setting the value to the Vega expression `\\\"true\\\"` will toggle data values without the user pressing the shift-key.\\n\\n__Default value:__ `true`\\n\\n__See also:__ [`toggle` examples](https://vega.github.io/vega-lite/docs/selection.html#toggle) in the documentation.\",\n                    \"type\": [\n                        \"string\",\n                        \"boolean\"\n                    ]\n                },\n                \"type\": {\n                    \"const\": \"point\",\n                    \"description\": \"Determines the default event processing and data query for the selection. Vega-Lite currently supports two selection types:\\n\\n- `\\\"point\\\"` -- to select multiple discrete data values; the first value is selected on `click` and additional values toggled on shift-click.\\n- `\\\"interval\\\"` -- to select a continuous range of data values on `drag`.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"type\"\n            ],\n            \"type\": \"object\"\n        },\n        \"PointSelectionConfigWithoutType\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"clear\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Stream\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        }\n                    ],\n                    \"description\": \"Clears the selection, emptying it of all values. This property can be a [Event Stream](https://vega.github.io/vega/docs/event-streams/) or `false` to disable clear.\\n\\n__Default value:__ `dblclick`.\\n\\n__See also:__ [`clear` examples ](https://vega.github.io/vega-lite/docs/selection.html#clear) in the documentation.\"\n                },\n                \"encodings\": {\n                    \"description\": \"An array of encoding channels. The corresponding data field values must match for a data tuple to fall within the selection.\\n\\n__See also:__ The [projection with `encodings` and `fields` section](https://vega.github.io/vega-lite/docs/selection.html#project) in the documentation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/SingleDefUnitChannel\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"fields\": {\n                    \"description\": \"An array of field names whose values must match for a data tuple to fall within the selection.\\n\\n__See also:__ The [projection with `encodings` and `fields` section](https://vega.github.io/vega-lite/docs/selection.html#project) in the documentation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"nearest\": {\n                    \"description\": \"When true, an invisible voronoi diagram is computed to accelerate discrete selection. The data value _nearest_ the mouse cursor is added to the selection.\\n\\n__Default value:__ `false`, which means that data values must be interacted with directly (e.g., clicked on) to be added to the selection.\\n\\n__See also:__ [`nearest` examples](https://vega.github.io/vega-lite/docs/selection.html#nearest) documentation.\",\n                    \"type\": \"boolean\"\n                },\n                \"on\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Stream\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        }\n                    ],\n                    \"description\": \"A [Vega event stream](https://vega.github.io/vega/docs/event-streams/) (object or selector) that triggers the selection. For interval selections, the event stream must specify a [start and end](https://vega.github.io/vega/docs/event-streams/#between-filters).\\n\\n__See also:__ [`on` examples](https://vega.github.io/vega-lite/docs/selection.html#on) in the documentation.\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/SelectionResolution\",\n                    \"description\": \"With layered and multi-view displays, a strategy that determines how selections' data queries are resolved when applied in a filter transform, conditional encoding rule, or scale domain.\\n\\nOne of:\\n- `\\\"global\\\"` -- only one brush exists for the entire SPLOM. When the user begins to drag, any previous brushes are cleared, and a new one is constructed.\\n- `\\\"union\\\"` -- each cell contains its own brush, and points are highlighted if they lie within _any_ of these individual brushes.\\n- `\\\"intersect\\\"` -- each cell contains its own brush, and points are highlighted only if they fall within _all_ of these individual brushes.\\n\\n__Default value:__ `global`.\\n\\n__See also:__ [`resolve` examples](https://vega.github.io/vega-lite/docs/selection.html#resolve) in the documentation.\"\n                },\n                \"toggle\": {\n                    \"description\": \"Controls whether data values should be toggled (inserted or removed from a point selection) or only ever inserted into point selections.\\n\\nOne of:\\n- `true` -- the default behavior, which corresponds to `\\\"event.shiftKey\\\"`.  As a result, data values are toggled when the user interacts with the shift-key pressed.\\n- `false` -- disables toggling behaviour; the selection will only ever contain a single data value corresponding to the most recent interaction.\\n- A [Vega expression](https://vega.github.io/vega/docs/expressions/) which is re-evaluated as the user interacts. If the expression evaluates to `true`, the data value is toggled into or out of the point selection. If the expression evaluates to `false`, the point selection is first cleared, and the data value is then inserted. For example, setting the value to the Vega expression `\\\"true\\\"` will toggle data values without the user pressing the shift-key.\\n\\n__Default value:__ `true`\\n\\n__See also:__ [`toggle` examples](https://vega.github.io/vega-lite/docs/selection.html#toggle) in the documentation.\",\n                    \"type\": [\n                        \"string\",\n                        \"boolean\"\n                    ]\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"PolarDef\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/PositionFieldDefBase\"\n                },\n                {\n                    \"$ref\": \"#/definitions/PositionDatumDefBase\"\n                },\n                {\n                    \"$ref\": \"#/definitions/PositionValueDef\"\n                }\n            ]\n        },\n        \"Polygon\": {\n            \"additionalProperties\": false,\n            \"description\": \"Polygon geometry object. https://tools.ietf.org/html/rfc7946#section-3.1.6\",\n            \"properties\": {\n                \"bbox\": {\n                    \"$ref\": \"#/definitions/BBox\",\n                    \"description\": \"Bounding box of the coordinate range of the object's Geometries, Features, or Feature Collections. https://tools.ietf.org/html/rfc7946#section-5\"\n                },\n                \"coordinates\": {\n                    \"items\": {\n                        \"items\": {\n                            \"$ref\": \"#/definitions/Position\"\n                        },\n                        \"type\": \"array\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"type\": {\n                    \"const\": \"Polygon\",\n                    \"description\": \"Specifies the type of GeoJSON object.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"coordinates\",\n                \"type\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Position\": {\n            \"description\": \"A Position is an array of coordinates. https://tools.ietf.org/html/rfc7946#section-3.1.1 Array should contain between two and three elements. The previous GeoJSON specification allowed more elements (e.g., which could be used to represent M values), but the current specification only allows X, Y, and (optionally) Z to be defined.\",\n            \"items\": {\n                \"type\": \"number\"\n            },\n            \"type\": \"array\"\n        },\n        \"Position2Def\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/SecondaryFieldDef\"\n                },\n                {\n                    \"$ref\": \"#/definitions/DatumDef\"\n                },\n                {\n                    \"$ref\": \"#/definitions/PositionValueDef\"\n                }\n            ]\n        },\n        \"PositionDatumDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"axis\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Axis\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of axis's gridlines, ticks and labels. If `null`, the axis for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [axis properties](https://vega.github.io/vega-lite/docs/axis.html) are applied.\\n\\n__See also:__ [`axis`](https://vega.github.io/vega-lite/docs/axis.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"datum\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/PrimitiveValue\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/DateTime\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RepeatRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in data domain.\"\n                },\n                \"impute\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ImputeParams\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining the properties of the Impute Operation to be applied. The field value of the other positional channel is taken as `key` of the `Impute` Operation. The field of the `color` channel if specified is used as `groupby` of the `Impute` Operation.\\n\\n__See also:__ [`impute`](https://vega.github.io/vega-lite/docs/impute.html) documentation.\"\n                },\n                \"scale\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Scale\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                },\n                \"stack\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StackOffset\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        }\n                    ],\n                    \"description\": \"Type of stacking offset if the field should be stacked. `stack` is only applicable for `x`, `y`, `theta`, and `radius` channels with continuous domains. For example, `stack` of `y` can be used to customize stacking for a vertical bar chart.\\n\\n`stack` can be one of the following values:\\n- `\\\"zero\\\"` or `true`: stacking with baseline offset at zero value of the scale (for creating typical stacked [bar](https://vega.github.io/vega-lite/docs/stack.html#bar) and [area](https://vega.github.io/vega-lite/docs/stack.html#area) chart).\\n- `\\\"normalize\\\"` - stacking with normalized domain (for creating [normalized stacked bar and area charts](https://vega.github.io/vega-lite/docs/stack.html#normalized) and pie charts [with percentage tooltip](https://vega.github.io/vega-lite/docs/arc.html#tooltip)). <br/>\\n-`\\\"center\\\"` - stacking with center baseline (for [streamgraph](https://vega.github.io/vega-lite/docs/stack.html#streamgraph)).\\n- `null` or `false` - No-stacking. This will produce layered [bar](https://vega.github.io/vega-lite/docs/stack.html#layered-bar-chart) and area chart.\\n\\n__Default value:__ `zero` for plots with all of the following conditions are true: (1) the mark is `bar`, `area`, or `arc`; (2) the stacked measure channel (x or y) has a linear scale; (3) At least one of non-position channels mapped to an unaggregated field that is different from x and y. Otherwise, `null` by default.\\n\\n__See also:__ [`stack`](https://vega.github.io/vega-lite/docs/stack.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/Type\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"PositionDatumDefBase\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"datum\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/PrimitiveValue\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/DateTime\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RepeatRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in data domain.\"\n                },\n                \"scale\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Scale\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                },\n                \"stack\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StackOffset\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        }\n                    ],\n                    \"description\": \"Type of stacking offset if the field should be stacked. `stack` is only applicable for `x`, `y`, `theta`, and `radius` channels with continuous domains. For example, `stack` of `y` can be used to customize stacking for a vertical bar chart.\\n\\n`stack` can be one of the following values:\\n- `\\\"zero\\\"` or `true`: stacking with baseline offset at zero value of the scale (for creating typical stacked [bar](https://vega.github.io/vega-lite/docs/stack.html#bar) and [area](https://vega.github.io/vega-lite/docs/stack.html#area) chart).\\n- `\\\"normalize\\\"` - stacking with normalized domain (for creating [normalized stacked bar and area charts](https://vega.github.io/vega-lite/docs/stack.html#normalized) and pie charts [with percentage tooltip](https://vega.github.io/vega-lite/docs/arc.html#tooltip)). <br/>\\n-`\\\"center\\\"` - stacking with center baseline (for [streamgraph](https://vega.github.io/vega-lite/docs/stack.html#streamgraph)).\\n- `null` or `false` - No-stacking. This will produce layered [bar](https://vega.github.io/vega-lite/docs/stack.html#layered-bar-chart) and area chart.\\n\\n__Default value:__ `zero` for plots with all of the following conditions are true: (1) the mark is `bar`, `area`, or `arc`; (2) the stacked measure channel (x or y) has a linear scale; (3) At least one of non-position channels mapped to an unaggregated field that is different from x and y. Otherwise, `null` by default.\\n\\n__See also:__ [`stack`](https://vega.github.io/vega-lite/docs/stack.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/Type\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"PositionDef\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/PositionFieldDef\"\n                },\n                {\n                    \"$ref\": \"#/definitions/PositionDatumDef\"\n                },\n                {\n                    \"$ref\": \"#/definitions/PositionValueDef\"\n                }\n            ]\n        },\n        \"PositionFieldDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"axis\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Axis\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of axis's gridlines, ticks and labels. If `null`, the axis for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [axis properties](https://vega.github.io/vega-lite/docs/axis.html) are applied.\\n\\n__See also:__ [`axis`](https://vega.github.io/vega-lite/docs/axis.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"const\": \"binned\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"impute\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ImputeParams\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining the properties of the Impute Operation to be applied. The field value of the other positional channel is taken as `key` of the `Impute` Operation. The field of the `color` channel if specified is used as `groupby` of the `Impute` Operation.\\n\\n__See also:__ [`impute`](https://vega.github.io/vega-lite/docs/impute.html) documentation.\"\n                },\n                \"scale\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Scale\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                },\n                \"sort\": {\n                    \"$ref\": \"#/definitions/Sort\",\n                    \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                },\n                \"stack\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StackOffset\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        }\n                    ],\n                    \"description\": \"Type of stacking offset if the field should be stacked. `stack` is only applicable for `x`, `y`, `theta`, and `radius` channels with continuous domains. For example, `stack` of `y` can be used to customize stacking for a vertical bar chart.\\n\\n`stack` can be one of the following values:\\n- `\\\"zero\\\"` or `true`: stacking with baseline offset at zero value of the scale (for creating typical stacked [bar](https://vega.github.io/vega-lite/docs/stack.html#bar) and [area](https://vega.github.io/vega-lite/docs/stack.html#area) chart).\\n- `\\\"normalize\\\"` - stacking with normalized domain (for creating [normalized stacked bar and area charts](https://vega.github.io/vega-lite/docs/stack.html#normalized) and pie charts [with percentage tooltip](https://vega.github.io/vega-lite/docs/arc.html#tooltip)). <br/>\\n-`\\\"center\\\"` - stacking with center baseline (for [streamgraph](https://vega.github.io/vega-lite/docs/stack.html#streamgraph)).\\n- `null` or `false` - No-stacking. This will produce layered [bar](https://vega.github.io/vega-lite/docs/stack.html#layered-bar-chart) and area chart.\\n\\n__Default value:__ `zero` for plots with all of the following conditions are true: (1) the mark is `bar`, `area`, or `arc`; (2) the stacked measure channel (x or y) has a linear scale; (3) At least one of non-position channels mapped to an unaggregated field that is different from x and y. Otherwise, `null` by default.\\n\\n__See also:__ [`stack`](https://vega.github.io/vega-lite/docs/stack.html) documentation.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/StandardType\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"PositionFieldDefBase\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"const\": \"binned\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"scale\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Scale\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                },\n                \"sort\": {\n                    \"$ref\": \"#/definitions/Sort\",\n                    \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                },\n                \"stack\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StackOffset\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        }\n                    ],\n                    \"description\": \"Type of stacking offset if the field should be stacked. `stack` is only applicable for `x`, `y`, `theta`, and `radius` channels with continuous domains. For example, `stack` of `y` can be used to customize stacking for a vertical bar chart.\\n\\n`stack` can be one of the following values:\\n- `\\\"zero\\\"` or `true`: stacking with baseline offset at zero value of the scale (for creating typical stacked [bar](https://vega.github.io/vega-lite/docs/stack.html#bar) and [area](https://vega.github.io/vega-lite/docs/stack.html#area) chart).\\n- `\\\"normalize\\\"` - stacking with normalized domain (for creating [normalized stacked bar and area charts](https://vega.github.io/vega-lite/docs/stack.html#normalized) and pie charts [with percentage tooltip](https://vega.github.io/vega-lite/docs/arc.html#tooltip)). <br/>\\n-`\\\"center\\\"` - stacking with center baseline (for [streamgraph](https://vega.github.io/vega-lite/docs/stack.html#streamgraph)).\\n- `null` or `false` - No-stacking. This will produce layered [bar](https://vega.github.io/vega-lite/docs/stack.html#layered-bar-chart) and area chart.\\n\\n__Default value:__ `zero` for plots with all of the following conditions are true: (1) the mark is `bar`, `area`, or `arc`; (2) the stacked measure channel (x or y) has a linear scale; (3) At least one of non-position channels mapped to an unaggregated field that is different from x and y. Otherwise, `null` by default.\\n\\n__See also:__ [`stack`](https://vega.github.io/vega-lite/docs/stack.html) documentation.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/StandardType\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"PositionValueDef\": {\n            \"$ref\": \"#/definitions/ValueDef<(number|\\\"width\\\"|\\\"height\\\"|ExprRef)>\"\n        },\n        \"Predicate\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/FieldEqualPredicate\"\n                },\n                {\n                    \"$ref\": \"#/definitions/FieldRangePredicate\"\n                },\n                {\n                    \"$ref\": \"#/definitions/FieldOneOfPredicate\"\n                },\n                {\n                    \"$ref\": \"#/definitions/FieldLTPredicate\"\n                },\n                {\n                    \"$ref\": \"#/definitions/FieldGTPredicate\"\n                },\n                {\n                    \"$ref\": \"#/definitions/FieldLTEPredicate\"\n                },\n                {\n                    \"$ref\": \"#/definitions/FieldGTEPredicate\"\n                },\n                {\n                    \"$ref\": \"#/definitions/FieldValidPredicate\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ParameterPredicate\"\n                },\n                {\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"PrimitiveValue\": {\n            \"type\": [\n                \"number\",\n                \"string\",\n                \"boolean\",\n                \"null\"\n            ]\n        },\n        \"Projection\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"center\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Vector2<number>\",\n                            \"description\": \"The projection's center, a two-element array of longitude and latitude in degrees.\\n\\n__Default value:__ `[0, 0]`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"clipAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The projection's clipping circle radius to the specified angle in degrees. If `null`, switches to [antimeridian](http://bl.ocks.org/mbostock/3788999) cutting rather than small-circle clipping.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"clipExtent\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Vector2<Vector2<number>>\",\n                            \"description\": \"The projection's viewport clip extent to the specified bounds in pixels. The extent bounds are specified as an array `[[x0, y0], [x1, y1]]`, where `x0` is the left-side of the viewport, `y0` is the top, `x1` is the right and `y1` is the bottom. If `null`, no viewport clipping is performed.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"coefficient\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The coefficient parameter for the `hammer` projection.\\n\\n__Default value:__ `2`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"distance\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"For the `satellite` projection, the distance from the center of the sphere to the point of view, as a proportion of the sphere’s radius. The recommended maximum clip angle for a given `distance` is acos(1 / distance) converted to degrees. If tilt is also applied, then more conservative clipping may be necessary.\\n\\n__Default value:__ `2.0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"extent\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Vector2<Vector2<number>>\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Fit\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/Fit\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fraction\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The fraction parameter for the `bottomley` projection.\\n\\n__Default value:__ `0.5`, corresponding to a sin(ψ) where ψ = π/6.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"lobes\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The number of lobes in projections that support multi-lobe views: `berghaus`, `gingery`, or `healpix`. The default value varies based on the projection type.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"parallel\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The parallel parameter for projections that support it: `armadillo`, `bonne`, `craig`, `cylindricalEqualArea`, `cylindricalStereographic`, `hammerRetroazimuthal`, `loximuthal`, or `rectangularPolyconic`. The default value varies based on the projection type.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"parallels\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"For conic projections, the [two standard parallels](https://en.wikipedia.org/wiki/Map_projection#Conic) that define the map layout. The default depends on the specific conic projection used.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"pointRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The default radius (in pixels) to use when drawing GeoJSON `Point` and `MultiPoint` geometries. This parameter sets a constant default value. To modify the point radius in response to data, see the corresponding parameter of the GeoPath and GeoShape transforms.\\n\\n__Default value:__ `4.5`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"precision\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The threshold for the projection's [adaptive resampling](http://bl.ocks.org/mbostock/3795544) to the specified value in pixels. This value corresponds to the [Douglas–Peucker distance](http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm). If precision is not specified, returns the projection's current resampling precision which defaults to `√0.5 ≅ 0.70710…`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"radius\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius parameter for the `airy` or `gingery` projection. The default value varies based on the projection type.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ratio\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The ratio parameter for the `hill`, `hufnagel`, or `wagner` projections. The default value varies based on the projection type.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"reflectX\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Sets whether or not the x-dimension is reflected (negated) in the output.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"reflectY\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Sets whether or not the y-dimension is reflected (negated) in the output.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"rotate\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Vector2<number>\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Vector3<number>\"\n                                }\n                            ],\n                            \"description\": \"The projection's three-axis rotation to the specified angles, which must be a two- or three-element array of numbers [`lambda`, `phi`, `gamma`] specifying the rotation angles in degrees about each spherical axis. (These correspond to yaw, pitch and roll.)\\n\\n__Default value:__ `[0, 0, 0]`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"scale\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The projection’s scale (zoom) factor, overriding automatic fitting. The default scale is projection-specific. The scale factor corresponds linearly to the distance between projected points; however, scale factor values are not equivalent across projections.\"\n                },\n                \"size\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Vector2<number>\",\n                            \"description\": \"Used in conjunction with fit, provides the width and height in pixels of the area to which the projection should be automatically fit.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"spacing\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The spacing parameter for the `lagrange` projection.\\n\\n__Default value:__ `0.5`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"tilt\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The tilt angle (in degrees) for the `satellite` projection.\\n\\n__Default value:__ `0`.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"translate\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Vector2<number>\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The projection’s translation offset as a two-element array `[tx, ty]`.\"\n                },\n                \"type\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ProjectionType\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The cartographic projection to use. This value is case-insensitive, for example `\\\"albers\\\"` and `\\\"Albers\\\"` indicate the same projection type. You can find all valid projection types [in the documentation](https://vega.github.io/vega-lite/docs/projection.html#projection-types).\\n\\n__Default value:__ `equalEarth`\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ProjectionConfig\": {\n            \"$ref\": \"#/definitions/Projection\",\n            \"description\": \"Any property of Projection can be in config\"\n        },\n        \"ProjectionType\": {\n            \"enum\": [\n                \"albers\",\n                \"albersUsa\",\n                \"azimuthalEqualArea\",\n                \"azimuthalEquidistant\",\n                \"conicConformal\",\n                \"conicEqualArea\",\n                \"conicEquidistant\",\n                \"equalEarth\",\n                \"equirectangular\",\n                \"gnomonic\",\n                \"identity\",\n                \"mercator\",\n                \"naturalEarth1\",\n                \"orthographic\",\n                \"stereographic\",\n                \"transverseMercator\"\n            ],\n            \"type\": \"string\"\n        },\n        \"QuantileTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"as\": {\n                    \"description\": \"The output field names for the probability and quantile values.\\n\\n__Default value:__ `[\\\"prob\\\", \\\"value\\\"]`\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"maxItems\": 2,\n                    \"minItems\": 2,\n                    \"type\": \"array\"\n                },\n                \"groupby\": {\n                    \"description\": \"The data fields to group by. If not specified, a single group containing all data objects will be used.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"probs\": {\n                    \"description\": \"An array of probabilities in the range (0, 1) for which to compute quantile values. If not specified, the *step* parameter will be used.\",\n                    \"items\": {\n                        \"type\": \"number\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"quantile\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The data field for which to perform quantile estimation.\"\n                },\n                \"step\": {\n                    \"description\": \"A probability step size (default 0.01) for sampling quantile values. All values from one-half the step size up to 1 (exclusive) will be sampled. This parameter is only used if the *probs* parameter is not provided.\",\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"quantile\"\n            ],\n            \"type\": \"object\"\n        },\n        \"RadialGradient\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"gradient\": {\n                    \"const\": \"radial\",\n                    \"description\": \"The type of gradient. Use `\\\"radial\\\"` for a radial gradient.\",\n                    \"type\": \"string\"\n                },\n                \"id\": {\n                    \"type\": \"string\"\n                },\n                \"r1\": {\n                    \"description\": \"The radius length, in normalized [0, 1] coordinates, of the inner circle for the gradient.\\n\\n__Default value:__ `0`\",\n                    \"type\": \"number\"\n                },\n                \"r2\": {\n                    \"description\": \"The radius length, in normalized [0, 1] coordinates, of the outer circle for the gradient.\\n\\n__Default value:__ `0.5`\",\n                    \"type\": \"number\"\n                },\n                \"stops\": {\n                    \"description\": \"An array of gradient stops defining the gradient color sequence.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/GradientStop\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"x1\": {\n                    \"description\": \"The x-coordinate, in normalized [0, 1] coordinates, for the center of the inner circle for the gradient.\\n\\n__Default value:__ `0.5`\",\n                    \"type\": \"number\"\n                },\n                \"x2\": {\n                    \"description\": \"The x-coordinate, in normalized [0, 1] coordinates, for the center of the outer circle for the gradient.\\n\\n__Default value:__ `0.5`\",\n                    \"type\": \"number\"\n                },\n                \"y1\": {\n                    \"description\": \"The y-coordinate, in normalized [0, 1] coordinates, for the center of the inner circle for the gradient.\\n\\n__Default value:__ `0.5`\",\n                    \"type\": \"number\"\n                },\n                \"y2\": {\n                    \"description\": \"The y-coordinate, in normalized [0, 1] coordinates, for the center of the outer circle for the gradient.\\n\\n__Default value:__ `0.5`\",\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"gradient\",\n                \"stops\"\n            ],\n            \"type\": \"object\"\n        },\n        \"RangeConfig\": {\n            \"additionalProperties\": {\n                \"anyOf\": [\n                    {\n                        \"$ref\": \"#/definitions/RangeScheme\"\n                    },\n                    {\n                        \"type\": \"array\"\n                    }\n                ]\n            },\n            \"properties\": {\n                \"category\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/RangeScheme\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/Color\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"Default [color scheme](https://vega.github.io/vega/docs/schemes/) for categorical data.\"\n                },\n                \"diverging\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/RangeScheme\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/Color\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"Default [color scheme](https://vega.github.io/vega/docs/schemes/) for diverging quantitative ramps.\"\n                },\n                \"heatmap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/RangeScheme\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/Color\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"Default [color scheme](https://vega.github.io/vega/docs/schemes/) for quantitative heatmaps.\"\n                },\n                \"ordinal\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/RangeScheme\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/Color\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"Default [color scheme](https://vega.github.io/vega/docs/schemes/) for rank-ordered data.\"\n                },\n                \"ramp\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/RangeScheme\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/Color\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"Default [color scheme](https://vega.github.io/vega/docs/schemes/) for sequential quantitative ramps.\"\n                },\n                \"symbol\": {\n                    \"description\": \"Array of [symbol](https://vega.github.io/vega/docs/marks/symbol/) names or paths for the default shape palette.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/SymbolShape\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"RangeEnum\": {\n            \"enum\": [\n                \"width\",\n                \"height\",\n                \"symbol\",\n                \"category\",\n                \"ordinal\",\n                \"ramp\",\n                \"diverging\",\n                \"heatmap\"\n            ],\n            \"type\": \"string\"\n        },\n        \"RangeRaw\": {\n            \"items\": {\n                \"anyOf\": [\n                    {\n                        \"type\": \"null\"\n                    },\n                    {\n                        \"type\": \"boolean\"\n                    },\n                    {\n                        \"type\": \"string\"\n                    },\n                    {\n                        \"type\": \"number\"\n                    },\n                    {\n                        \"$ref\": \"#/definitions/RangeRawArray\"\n                    }\n                ]\n            },\n            \"type\": \"array\"\n        },\n        \"RangeRawArray\": {\n            \"items\": {\n                \"type\": \"number\"\n            },\n            \"type\": \"array\"\n        },\n        \"RangeScheme\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/RangeEnum\"\n                },\n                {\n                    \"$ref\": \"#/definitions/RangeRaw\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"count\": {\n                            \"type\": \"number\"\n                        },\n                        \"extent\": {\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        \"scheme\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"items\": {\n                                        \"type\": \"string\"\n                                    },\n                                    \"type\": \"array\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ColorScheme\"\n                                }\n                            ]\n                        }\n                    },\n                    \"required\": [\n                        \"scheme\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"RectConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The horizontal alignment of the text or ranged marks (area, bar, image, rect, rule). One of `\\\"left\\\"`, `\\\"right\\\"`, `\\\"center\\\"`.\\n\\n__Note:__ Expression reference is *not* supported for range marks.\"\n                },\n                \"angle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The rotation angle of the text, in degrees.\",\n                            \"maximum\": 360,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aria\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag indicating if [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) should be included (SVG output only). If `false`, the \\\"aria-hidden\\\" attribute will be set on the output SVG element, removing the mark item from the ARIA accessibility tree.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ariaRole\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Sets the type of user interface element of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the \\\"role\\\" attribute. Warning: this property is experimental and may be changed in the future.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ariaRoleDescription\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A human-readable, author-localized description for the role of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the \\\"aria-roledescription\\\" attribute. Warning: this property is experimental and may be changed in the future.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aspect\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Whether to keep aspect ratio of image marks.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"baseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"For text marks, the vertical text baseline. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, `\\\"line-bottom\\\"`, or an expression reference that provides one of the valid values. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the `lineHeight` rather than `fontSize` alone.\\n\\nFor range marks, the vertical alignment of the marks. One of `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`.\\n\\n__Note:__ Expression reference is *not* supported for range marks.\"\n                },\n                \"binSpacing\": {\n                    \"description\": \"Offset between bars for binned field. The ideal value for this is either 0 (preferred by statisticians) or 1 (Vega-Lite default, D3 example style).\\n\\n__Default value:__ `1`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"blend\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Blend\",\n                            \"description\": \"The color blend mode for drawing an item on its current background. Any valid [CSS mix-blend-mode](https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode) value can be used.\\n\\n__Default value: `\\\"source-over\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"color\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default color.\\n\\n__Default value:__ <span style=\\\"color: #4682b4;\\\">&#9632;</span> `\\\"#4682b4\\\"`\\n\\n__Note:__\\n- This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\\n- The `fill` and `stroke` properties have higher precedence than `color` and will override `color`.\"\n                },\n                \"continuousBandSize\": {\n                    \"description\": \"The default size of the bars on continuous scales.\\n\\n__Default value:__ `5`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"cornerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles or arcs' corners.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusBottomLeft\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' bottom left corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusBottomRight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' bottom right corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusTopLeft\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' top right corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusTopRight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' top left corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cursor\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Cursor\",\n                            \"description\": \"The mouse cursor used over the mark. Any valid [CSS cursor type](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"description\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A text description of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the [\\\"aria-label\\\" attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dir\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextDirection\",\n                            \"description\": \"The direction of the text. One of `\\\"ltr\\\"` (left-to-right) or `\\\"rtl\\\"` (right-to-left). This property determines on which side is truncated in response to the limit parameter.\\n\\n__Default value:__ `\\\"ltr\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"discreteBandSize\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RelativeBandSize\"\n                        }\n                    ],\n                    \"description\": \"The default size of the bars with discrete dimensions. If unspecified, the default size is  `step-2`, which provides 2 pixel offset between bars.\",\n                    \"minimum\": 0\n                },\n                \"dx\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The horizontal offset, in pixels, between the text label and its anchor point. The offset is applied after rotation by the _angle_ property.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dy\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The vertical offset, in pixels, between the text label and its anchor point. The offset is applied after rotation by the _angle_ property.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ellipsis\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The ellipsis string for text truncated in response to the limit parameter.\\n\\n__Default value:__ `\\\"…\\\"`\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"endAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The end angle in radians for arc marks. A value of `0` indicates up (north), increasing values proceed clockwise.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fill\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default fill color. This property has higher precedence than `config.color`. Set to `null` to remove fill.\\n\\n__Default value:__ (None)\"\n                },\n                \"fillOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The fill opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"filled\": {\n                    \"description\": \"Whether the mark's color should be used as fill color instead of stroke color.\\n\\n__Default value:__ `false` for all `point`, `line`, and `rule` marks as well as `geoshape` marks for [`graticule`](https://vega.github.io/vega-lite/docs/data.html#graticule) data sources; otherwise, `true`.\\n\\n__Note:__ This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\",\n                    \"type\": \"boolean\"\n                },\n                \"font\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The typeface to set the text in (e.g., `\\\"Helvetica Neue\\\"`).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font size, in pixels.\\n\\n__Default value:__ `11`\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"The font style (e.g., `\\\"italic\\\"`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"The font weight. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"height\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Height of the marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"href\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/URI\",\n                            \"description\": \"A URL to load upon mouse click. If defined, the mark acts as a hyperlink.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"innerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The inner radius in pixels of arc marks. `innerRadius` is an alias for `radius2`.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"interpolate\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Interpolate\",\n                            \"description\": \"The line interpolation method to use for line and area marks. One of the following:\\n- `\\\"linear\\\"`: piecewise linear segments, as in a polyline.\\n- `\\\"linear-closed\\\"`: close the linear segments to form a polygon.\\n- `\\\"step\\\"`: alternate between horizontal and vertical segments, as in a step function.\\n- `\\\"step-before\\\"`: alternate between vertical and horizontal segments, as in a step function.\\n- `\\\"step-after\\\"`: alternate between horizontal and vertical segments, as in a step function.\\n- `\\\"basis\\\"`: a B-spline, with control point duplication on the ends.\\n- `\\\"basis-open\\\"`: an open B-spline; may not intersect the start or end.\\n- `\\\"basis-closed\\\"`: a closed B-spline, as in a loop.\\n- `\\\"cardinal\\\"`: a Cardinal spline, with control point duplication on the ends.\\n- `\\\"cardinal-open\\\"`: an open Cardinal spline; may not intersect the start or end, but will intersect other control points.\\n- `\\\"cardinal-closed\\\"`: a closed Cardinal spline, as in a loop.\\n- `\\\"bundle\\\"`: equivalent to basis, except the tension parameter is used to straighten the spline.\\n- `\\\"monotone\\\"`: cubic interpolation that preserves monotonicity in y.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"invalid\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/MarkInvalidDataMode\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"Invalid data mode, which defines how the marks and corresponding scales should represent invalid values (`null` and `NaN` in continuous scales *without* defined output for invalid values).\\n\\n- `\\\"filter\\\"` — *Exclude* all invalid values from the visualization's *marks* and *scales*. For path marks (for line, area, trail), this option will create paths that connect valid points, as if the data rows with invalid values do not exist.\\n\\n- `\\\"break-paths-filter-domains\\\"` — Break path marks (for line, area, trail) at invalid values.  For non-path marks, this is equivalent to `\\\"filter\\\"`. All *scale* domains will *exclude* these filtered data points.\\n\\n- `\\\"break-paths-show-domains\\\"` — Break paths (for line, area, trail) at invalid values.  Hide invalid values for non-path marks. All *scale* domains will *include* these filtered data points (for both path and non-path marks).\\n\\n- `\\\"show\\\"` or `null` — Show all data points in the marks and scale domains. Each scale will use the output for invalid values defined in `config.scale.invalid` or, if unspecified, by default invalid values will produce the same visual values as zero (if the scale includes zero) or the minimum value (if the scale does not include zero).\\n\\n- `\\\"break-paths-show-path-domains\\\"` (default) — This is equivalent to `\\\"break-paths-show-domains\\\"` for path-based marks (line/area/trail) and `\\\"filter\\\"` for non-path marks.\\n\\n__Note__: If any channel's scale has an output for invalid values defined in `config.scale.invalid`, all values for the scales will be considered \\\"valid\\\" since they can produce a reasonable output for the scales. Thus, fields for such channels will not be filtered and will not cause path breaks.\"\n                },\n                \"limit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The maximum length of the text mark in pixels. The text value will be automatically truncated if the rendered size exceeds the limit.\\n\\n__Default value:__ `0` -- indicating no limit\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"lineBreak\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A delimiter, such as a newline character, upon which to break text strings into multiple lines. This property is ignored if the text is array-valued.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"lineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The line height in pixels (the spacing between subsequent lines of text) for multi-line text marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"minBandSize\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The minimum band size for bar and rectangle marks. __Default value:__ `0.25`\"\n                },\n                \"opacity\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The overall opacity (value between [0,1]).\\n\\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or `square` marks or layered `bar` charts and `1` otherwise.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"order\": {\n                    \"description\": \"For line and trail marks, this `order` property can be set to `null` or `false` to make the lines use the original order in the data sources.\",\n                    \"type\": [\n                        \"null\",\n                        \"boolean\"\n                    ]\n                },\n                \"orient\": {\n                    \"$ref\": \"#/definitions/Orientation\",\n                    \"description\": \"The orientation of a non-stacked bar, tick, area, and line charts. The value is either horizontal (default) or vertical.\\n- For bar, rule and tick, this determines whether the size of the bar and tick should be applied to x or y dimension.\\n- For area, this property determines the orient property of the Vega output.\\n- For line and trail marks, this property determines the sort order of the points in the line if `config.sortLineBy` is not specified. For stacked charts, this is always determined by the orientation of the stack; therefore explicitly specified value will be ignored.\"\n                },\n                \"outerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The outer radius in pixels of arc marks. `outerRadius` is an alias for `radius`.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"padAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The angular padding applied to sides of the arc, in radians.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"radius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"For arc mark, the primary (outer) radius in pixels.\\n\\nFor text marks, polar coordinate radial offset, in pixels, of the text from the origin determined by the `x` and `y` properties.\\n\\n__Default value:__ `min(plot_width, plot_height)/2`\",\n                    \"minimum\": 0\n                },\n                \"radius2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The secondary (inner) radius in pixels of arc marks.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"shape\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/SymbolShape\"\n                                },\n                                {\n                                    \"type\": \"string\"\n                                }\n                            ],\n                            \"description\": \"Shape of the point marks. Supported values include:\\n- plotting shapes: `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"cross\\\"`, `\\\"diamond\\\"`, `\\\"triangle-up\\\"`, `\\\"triangle-down\\\"`, `\\\"triangle-right\\\"`, or `\\\"triangle-left\\\"`.\\n- the line symbol `\\\"stroke\\\"`\\n- centered directional shapes `\\\"arrow\\\"`, `\\\"wedge\\\"`, or `\\\"triangle\\\"`\\n- a custom [SVG path string](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths) (For correct sizing, custom shape paths should be defined within a square bounding box with coordinates ranging from -1 to 1 along both the x and y dimensions.)\\n\\n__Default value:__ `\\\"circle\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"size\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default size for marks.\\n- For `point`/`circle`/`square`, this represents the pixel area of the marks. Note that this value sets the area of the symbol; the side lengths will increase with the square root of this value.\\n- For `bar`, this represents the band size of the bar, in pixels.\\n- For `text`, this represents the font size, in pixels.\\n\\n__Default value:__\\n- `30` for point, circle, square marks; width/height's `step`\\n- `2` for bar marks with discrete dimensions;\\n- `5` for bar marks with continuous dimensions;\\n- `11` for text marks.\",\n                    \"minimum\": 0\n                },\n                \"smooth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag (default true) indicating if the image should be smoothed when resized. If false, individual pixels should be scaled directly rather than interpolated with smoothing. For SVG rendering, this option may not work in some browsers due to lack of standardization.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"startAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The start angle in radians for arc marks. A value of `0` indicates up (north), increasing values proceed clockwise.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"stroke\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default stroke color. This property has higher precedence than `config.color`. Set to `null` to remove stroke.\\n\\n__Default value:__ (None)\"\n                },\n                \"strokeCap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeCap\",\n                            \"description\": \"The stroke cap for line ending style. One of `\\\"butt\\\"`, `\\\"round\\\"`, or `\\\"square\\\"`.\\n\\n__Default value:__ `\\\"butt\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating stroke, space lengths for creating dashed or dotted lines.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset (in pixels) into which to begin drawing with the stroke dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeJoin\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeJoin\",\n                            \"description\": \"The stroke line join method. One of `\\\"miter\\\"`, `\\\"round\\\"` or `\\\"bevel\\\"`.\\n\\n__Default value:__ `\\\"miter\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeMiterLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The miter limit at which to bevel a line join.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset in pixels at which to draw the group stroke and fill. If unspecified, the default behavior is to dynamically offset stroked groups such that 1 pixel stroke widths align with the pixel grid.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke width, in pixels.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"tension\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Depending on the interpolation type, sets the tension parameter (for line and area marks).\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"text\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\",\n                            \"description\": \"Placeholder text if the `text` channel is not specified\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"theta\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"- For arc marks, the arc length in radians if theta2 is not specified, otherwise the start arc angle. (A value of 0 indicates up or “north”, increasing values proceed clockwise.)\\n\\n- For text marks, polar coordinate angle in radians.\",\n                    \"maximum\": 360,\n                    \"minimum\": 0\n                },\n                \"theta2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The end angle of arc marks in radians. A value of 0 indicates up or “north”, increasing values proceed clockwise.\"\n                },\n                \"time\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"timeUnitBandPosition\": {\n                    \"description\": \"Default relative band position for a time unit. If set to `0`, the marks will be positioned at the beginning of the time unit band step. If set to `0.5`, the marks will be positioned in the middle of the time unit band step.\",\n                    \"type\": \"number\"\n                },\n                \"timeUnitBandSize\": {\n                    \"description\": \"Default relative band size for a time unit. If set to `1`, the bandwidth of the marks will be equal to the time unit band step. If set to `0.5`, bandwidth of the marks will be half of the time unit band step.\",\n                    \"type\": \"number\"\n                },\n                \"tooltip\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TooltipContent\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"The tooltip text string to show upon mouse hover or an object defining which fields should the tooltip be derived from.\\n\\n- If `tooltip` is `true` or `{\\\"content\\\": \\\"encoding\\\"}`, then all fields from `encoding` will be used.\\n- If `tooltip` is `{\\\"content\\\": \\\"data\\\"}`, then all fields that appear in the highlighted data point will be used.\\n- If set to `null` or `false`, then no tooltip will be used.\\n\\nSee the [`tooltip`](https://vega.github.io/vega-lite/docs/tooltip.html) documentation for a detailed discussion about tooltip  in Vega-Lite.\\n\\n__Default value:__ `null`\"\n                },\n                \"url\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/URI\",\n                            \"description\": \"The URL of the image file for image marks.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"width\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Width of the marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"x\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"X coordinates of the marks, or width of horizontal `\\\"bar\\\"` and `\\\"area\\\"` without specified `x2` or `width`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"x2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"X2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"y\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Y coordinates of the marks, or height of vertical `\\\"bar\\\"` and `\\\"area\\\"` without specified `y2` or `height`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                },\n                \"y2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Y2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"RegressionTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"as\": {\n                    \"description\": \"The output field names for the smoothed points generated by the regression transform.\\n\\n__Default value:__ The field names of the input x and y values.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"maxItems\": 2,\n                    \"minItems\": 2,\n                    \"type\": \"array\"\n                },\n                \"extent\": {\n                    \"description\": \"A [min, max] domain over the independent (x) field for the starting and ending points of the generated trend line.\",\n                    \"items\": {\n                        \"type\": \"number\"\n                    },\n                    \"maxItems\": 2,\n                    \"minItems\": 2,\n                    \"type\": \"array\"\n                },\n                \"groupby\": {\n                    \"description\": \"The data fields to group by. If not specified, a single group containing all data objects will be used.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"method\": {\n                    \"description\": \"The functional form of the regression model. One of `\\\"linear\\\"`, `\\\"log\\\"`, `\\\"exp\\\"`, `\\\"pow\\\"`, `\\\"quad\\\"`, or `\\\"poly\\\"`.\\n\\n__Default value:__ `\\\"linear\\\"`\",\n                    \"enum\": [\n                        \"linear\",\n                        \"log\",\n                        \"exp\",\n                        \"pow\",\n                        \"quad\",\n                        \"poly\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"on\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The data field of the independent variable to use a predictor.\"\n                },\n                \"order\": {\n                    \"description\": \"The polynomial order (number of coefficients) for the 'poly' method.\\n\\n__Default value:__ `3`\",\n                    \"type\": \"number\"\n                },\n                \"params\": {\n                    \"description\": \"A boolean flag indicating if the transform should return the regression model parameters (one object per group), rather than trend line points. The resulting objects include a `coef` array of fitted coefficient values (starting with the intercept term and then including terms of increasing order) and an `rSquared` value (indicating the total variance explained by the model).\\n\\n__Default value:__ `false`\",\n                    \"type\": \"boolean\"\n                },\n                \"regression\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The data field of the dependent variable to predict.\"\n                }\n            },\n            \"required\": [\n                \"regression\",\n                \"on\"\n            ],\n            \"type\": \"object\"\n        },\n        \"RelativeBandSize\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"band\": {\n                    \"description\": \"The relative band size.  For example `0.5` means half of the band scale's band width.\",\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"band\"\n            ],\n            \"type\": \"object\"\n        },\n        \"RepeatMapping\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"column\": {\n                    \"description\": \"An array of fields to be repeated horizontally.\",\n                    \"items\": {\n                        \"type\": \"string\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"row\": {\n                    \"description\": \"An array of fields to be repeated vertically.\",\n                    \"items\": {\n                        \"type\": \"string\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"RepeatRef\": {\n            \"additionalProperties\": false,\n            \"description\": \"Reference to a repeated value.\",\n            \"properties\": {\n                \"repeat\": {\n                    \"enum\": [\n                        \"row\",\n                        \"column\",\n                        \"repeat\",\n                        \"layer\"\n                    ],\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"repeat\"\n            ],\n            \"type\": \"object\"\n        },\n        \"RepeatSpec\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/NonLayerRepeatSpec\"\n                },\n                {\n                    \"$ref\": \"#/definitions/LayerRepeatSpec\"\n                }\n            ]\n        },\n        \"Resolve\": {\n            \"additionalProperties\": false,\n            \"description\": \"Defines how scales, axes, and legends from different specs should be combined. Resolve is a mapping from `scale`, `axis`, and `legend` to a mapping from channels to resolutions. Scales and guides can be resolved to be `\\\"independent\\\"` or `\\\"shared\\\"`.\",\n            \"properties\": {\n                \"axis\": {\n                    \"$ref\": \"#/definitions/AxisResolveMap\"\n                },\n                \"legend\": {\n                    \"$ref\": \"#/definitions/LegendResolveMap\"\n                },\n                \"scale\": {\n                    \"$ref\": \"#/definitions/ScaleResolveMap\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ResolveMode\": {\n            \"enum\": [\n                \"independent\",\n                \"shared\"\n            ],\n            \"type\": \"string\"\n        },\n        \"RowCol<LayoutAlign>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"column\": {\n                    \"$ref\": \"#/definitions/LayoutAlign\"\n                },\n                \"row\": {\n                    \"$ref\": \"#/definitions/LayoutAlign\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"RowCol<boolean>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"column\": {\n                    \"type\": \"boolean\"\n                },\n                \"row\": {\n                    \"type\": \"boolean\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"RowCol<number>\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"column\": {\n                    \"type\": \"number\"\n                },\n                \"row\": {\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"RowColumnEncodingFieldDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"align\": {\n                    \"$ref\": \"#/definitions/LayoutAlign\",\n                    \"description\": \"The alignment to apply to row/column facet's subplot. The supported string values are `\\\"all\\\"`, `\\\"each\\\"`, and `\\\"none\\\"`.\\n\\n- For `\\\"none\\\"`, a flow layout will be used, in which adjacent subviews are simply placed one after the other.\\n- For `\\\"each\\\"`, subviews will be aligned into a clean grid structure, but each row or column may be of variable size.\\n- For `\\\"all\\\"`, subviews will be aligned and each row or column will be sized identically based on the maximum observed size. String values for this property will be applied to both grid rows and columns.\\n\\n__Default value:__ `\\\"all\\\"`.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"center\": {\n                    \"description\": \"Boolean flag indicating if facet's subviews should be centered relative to their respective rows or columns.\\n\\n__Default value:__ `false`\",\n                    \"type\": \"boolean\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"header\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Header\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of a facet's header.\"\n                },\n                \"sort\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SortArray\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/SortOrder\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/EncodingSortField\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` is not supported for `row` and `column`.\"\n                },\n                \"spacing\": {\n                    \"description\": \"The spacing in pixels between facet's sub-views.\\n\\n__Default value__: Depends on `\\\"spacing\\\"` property of [the view composition configuration](https://vega.github.io/vega-lite/docs/config.html#view-config) (`20` by default)\",\n                    \"type\": \"number\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/StandardType\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"SampleTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"sample\": {\n                    \"description\": \"The maximum number of data objects to include in the sample.\\n\\n__Default value:__ `1000`\",\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"sample\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Scale\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The alignment of the steps within the scale range.\\n\\nThis value must lie in the range `[0,1]`. A value of `0.5` indicates that the steps should be centered within the range. A value of `0` or `1` may be used to shift the bands to one side, say to position them adjacent to an axis.\\n\\n__Default value:__ `0.5`\"\n                },\n                \"base\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The logarithm base of the `log` scale (default `10`).\"\n                },\n                \"bins\": {\n                    \"$ref\": \"#/definitions/ScaleBins\",\n                    \"description\": \"Bin boundaries can be provided to scales as either an explicit array of bin boundaries or as a bin specification object. The legal values are:\\n- An [array](../types/#Array) literal of bin boundary values. For example, `[0, 5, 10, 15, 20]`. The array must include both starting and ending boundaries. The previous example uses five values to indicate a total of four bin intervals: [0-5), [5-10), [10-15), [15-20]. Array literals may include signal references as elements.\\n- A [bin specification object](https://vega.github.io/vega-lite/docs/scale.html#bins) that indicates the bin _step_ size, and optionally the _start_ and _stop_ boundaries.\\n- An array of bin boundaries over the scale domain. If provided, axes and legends will use the bin boundaries to inform the choice of tick marks and text labels.\"\n                },\n                \"clamp\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"If `true`, values that exceed the data domain are clamped to either the minimum or maximum range value\\n\\n__Default value:__ derived from the [scale config](https://vega.github.io/vega-lite/docs/config.html#scale-config)'s `clamp` (`true` by default).\"\n                },\n                \"constant\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant determining the slope of the symlog function around zero. Only used for `symlog` scales.\\n\\n__Default value:__ `1`\"\n                },\n                \"domain\": {\n                    \"anyOf\": [\n                        {\n                            \"items\": {\n                                \"anyOf\": [\n                                    {\n                                        \"type\": \"null\"\n                                    },\n                                    {\n                                        \"type\": \"string\"\n                                    },\n                                    {\n                                        \"type\": \"number\"\n                                    },\n                                    {\n                                        \"type\": \"boolean\"\n                                    },\n                                    {\n                                        \"$ref\": \"#/definitions/DateTime\"\n                                    },\n                                    {\n                                        \"$ref\": \"#/definitions/ExprRef\"\n                                    }\n                                ]\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"const\": \"unaggregated\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ParameterExtent\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/DomainUnionWith\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Customized domain values in the form of constant values or dynamic values driven by a parameter.\\n\\n1) Constant `domain` for _quantitative_ fields can take one of the following forms:\\n\\n- A two-element array with minimum and maximum values. To create a diverging scale, this two-element array can be combined with the `domainMid` property.\\n- An array with more than two entries, for [Piecewise quantitative scales](https://vega.github.io/vega-lite/docs/scale.html#piecewise).\\n- A string value `\\\"unaggregated\\\"`, if the input field is aggregated, to indicate that the domain should include the raw data values prior to the aggregation.\\n\\n2) Constant `domain` for _temporal_ fields can be a two-element array with minimum and maximum values, in the form of either timestamps or the [DateTime definition objects](https://vega.github.io/vega-lite/docs/types.html#datetime).\\n\\n3) Constant `domain` for _ordinal_ and _nominal_ fields can be an array that lists valid input values.\\n\\n4) To combine (union) specified constant domain with the field's values, `domain` can be an object with a `unionWith` property that specify constant domain to be combined. For example, `domain: {unionWith: [0, 100]}` for a quantitative scale means that the scale domain always includes `[0, 100]`, but will include other values in the fields beyond `[0, 100]`.\\n\\n5) Domain can also takes an object defining a field or encoding of a parameter that [interactively determines](https://vega.github.io/vega-lite/docs/selection.html#scale-domains) the scale domain.\"\n                },\n                \"domainMax\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/DateTime\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Sets the maximum value in the scale domain, overriding the `domain` property. This property is only intended for use with scales having continuous domains.\"\n                },\n                \"domainMid\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Inserts a single mid-point value into a two-element domain. The mid-point value must lie between the domain minimum and maximum values. This property can be useful for setting a midpoint for [diverging color scales](https://vega.github.io/vega-lite/docs/scale.html#piecewise). The domainMid property is only intended for use with scales supporting continuous, piecewise domains.\"\n                },\n                \"domainMin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/DateTime\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Sets the minimum value in the scale domain, overriding the domain property. This property is only intended for use with scales having continuous domains.\"\n                },\n                \"domainRaw\": {\n                    \"$ref\": \"#/definitions/ExprRef\",\n                    \"description\": \"An expression for an array of raw values that, if non-null, directly overrides the _domain_ property. This is useful for supporting interactions such as panning or zooming a scale. The scale may be initially determined using a data-driven domain, then modified in response to user input by setting the rawDomain value.\"\n                },\n                \"exponent\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The exponent of the `pow` scale.\"\n                },\n                \"interpolate\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ScaleInterpolateEnum\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ScaleInterpolateParams\"\n                        }\n                    ],\n                    \"description\": \"The interpolation method for range values. By default, a general interpolator for numbers, dates, strings and colors (in HCL space) is used. For color ranges, this property allows interpolation in alternative color spaces. Legal values include `rgb`, `hsl`, `hsl-long`, `lab`, `hcl`, `hcl-long`, `cubehelix` and `cubehelix-long` ('-long' variants use longer paths in polar coordinate spaces). If object-valued, this property accepts an object with a string-valued _type_ property and an optional numeric _gamma_ property applicable to rgb and cubehelix interpolators. For more, see the [d3-interpolate documentation](https://github.com/d3/d3-interpolate).\\n\\n* __Default value:__ `hcl`\"\n                },\n                \"nice\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeInterval\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeIntervalStep\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Extending the domain so that it starts and ends on nice round values. This method typically modifies the scale’s domain, and may only extend the bounds to the nearest round value. Nicing is useful if the domain is computed from data and may be irregular. For example, for a domain of _[0.201479…, 0.996679…]_, a nice domain might be _[0.2, 1.0]_.\\n\\nFor quantitative scales such as linear, `nice` can be either a boolean flag or a number. If `nice` is a number, it will represent a desired tick count. This allows greater control over the step size used to extend the bounds, guaranteeing that the returned ticks will exactly cover the domain.\\n\\nFor temporal fields with time and utc scales, the `nice` value can be a string indicating the desired time interval. Legal values are `\\\"millisecond\\\"`, `\\\"second\\\"`, `\\\"minute\\\"`, `\\\"hour\\\"`, `\\\"day\\\"`, `\\\"week\\\"`, `\\\"month\\\"`, and `\\\"year\\\"`. Alternatively, `time` and `utc` scales can accept an object-valued interval specifier of the form `{\\\"interval\\\": \\\"month\\\", \\\"step\\\": 3}`, which includes a desired number of interval steps. Here, the domain would snap to quarter (Jan, Apr, Jul, Oct) boundaries.\\n\\n__Default value:__ `true` for unbinned _quantitative_ fields without explicit domain bounds; `false` otherwise.\"\n                },\n                \"padding\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"For _[continuous](https://vega.github.io/vega-lite/docs/scale.html#continuous)_ scales, expands the scale domain to accommodate the specified number of pixels on each of the scale range. The scale range must represent pixels for this parameter to function as intended. Padding adjustment is performed prior to all other adjustments, including the effects of the `zero`, `nice`, `domainMin`, and `domainMax` properties.\\n\\nFor _[band](https://vega.github.io/vega-lite/docs/scale.html#band)_ scales, shortcut for setting `paddingInner` and `paddingOuter` to the same value.\\n\\nFor _[point](https://vega.github.io/vega-lite/docs/scale.html#point)_ scales, alias for `paddingOuter`.\\n\\n__Default value:__ For _continuous_ scales, derived from the [scale config](https://vega.github.io/vega-lite/docs/scale.html#config)'s `continuousPadding`. For _band and point_ scales, see `paddingInner` and `paddingOuter`. By default, Vega-Lite sets padding such that _width/height = number of unique values * step_.\",\n                    \"minimum\": 0\n                },\n                \"paddingInner\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The inner padding (spacing) within each band step of band scales, as a fraction of the step size. This value must lie in the range [0,1].\\n\\nFor point scale, this property is invalid as point scales do not have internal band widths (only step sizes between bands).\\n\\n__Default value:__ derived from the [scale config](https://vega.github.io/vega-lite/docs/scale.html#config)'s `bandPaddingInner`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"paddingOuter\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The outer padding (spacing) at the ends of the range of band and point scales, as a fraction of the step size. This value must lie in the range [0,1].\\n\\n__Default value:__ derived from the [scale config](https://vega.github.io/vega-lite/docs/scale.html#config)'s `bandPaddingOuter` for band scales and `pointPadding` for point scales. By default, Vega-Lite sets outer padding such that _width/height = number of unique values * step_.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"range\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/RangeEnum\"\n                        },\n                        {\n                            \"items\": {\n                                \"anyOf\": [\n                                    {\n                                        \"type\": \"number\"\n                                    },\n                                    {\n                                        \"type\": \"string\"\n                                    },\n                                    {\n                                        \"items\": {\n                                            \"type\": \"number\"\n                                        },\n                                        \"type\": \"array\"\n                                    },\n                                    {\n                                        \"$ref\": \"#/definitions/ExprRef\"\n                                    }\n                                ]\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/FieldRange\"\n                        }\n                    ],\n                    \"description\": \"The range of the scale. One of:\\n\\n- A string indicating a [pre-defined named scale range](https://vega.github.io/vega-lite/docs/scale.html#range-config) (e.g., example, `\\\"symbol\\\"`, or `\\\"diverging\\\"`).\\n\\n- For [continuous scales](https://vega.github.io/vega-lite/docs/scale.html#continuous), two-element array indicating  minimum and maximum values, or an array with more than two entries for specifying a [piecewise scale](https://vega.github.io/vega-lite/docs/scale.html#piecewise).\\n\\n- For [discrete](https://vega.github.io/vega-lite/docs/scale.html#discrete) and [discretizing](https://vega.github.io/vega-lite/docs/scale.html#discretizing) scales, an array of desired output values or an object with a `field` property representing the range values.  For example, if a field `color` contains CSS color names, we can set `range` to `{field: \\\"color\\\"}`.\\n\\n__Notes:__\\n\\n1) For color scales you can also specify a color [`scheme`](https://vega.github.io/vega-lite/docs/scale.html#scheme) instead of `range`.\\n\\n2) Any directly specified `range` for `x` and `y` channels will be ignored. Range can be customized via the view's corresponding [size](https://vega.github.io/vega-lite/docs/size.html) (`width` and `height`).\"\n                },\n                \"rangeMax\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Sets the maximum value in the scale range, overriding the `range` property or the default range. This property is only intended for use with scales having continuous ranges.\"\n                },\n                \"rangeMin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Sets the minimum value in the scale range, overriding the `range` property or the default range. This property is only intended for use with scales having continuous ranges.\"\n                },\n                \"reverse\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"If true, reverses the order of the scale range. __Default value:__ `false`.\"\n                },\n                \"round\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"If `true`, rounds numeric output values to integers. This can be helpful for snapping to the pixel grid.\\n\\n__Default value:__ `false`.\"\n                },\n                \"scheme\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ColorScheme\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/SchemeParams\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A string indicating a color [scheme](https://vega.github.io/vega-lite/docs/scale.html#scheme) name (e.g., `\\\"category10\\\"` or `\\\"blues\\\"`) or a [scheme parameter object](https://vega.github.io/vega-lite/docs/scale.html#scheme-params).\\n\\nDiscrete color schemes may be used with [discrete](https://vega.github.io/vega-lite/docs/scale.html#discrete) or [discretizing](https://vega.github.io/vega-lite/docs/scale.html#discretizing) scales. Continuous color schemes are intended for use with color scales.\\n\\nTo set a custom scheme, instead set the list of values [as the scale range](https://vega.github.io/vega-lite/docs/scale.html#2-setting-the-range-property-to-an-array-of-valid-css-color-strings).\\n\\nFor the full list of supported schemes, please refer to the [Vega Scheme](https://vega.github.io/vega/docs/schemes/#reference) reference.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/ScaleType\",\n                    \"description\": \"The type of scale. Vega-Lite supports the following categories of scale types:\\n\\n1) [**Continuous Scales**](https://vega.github.io/vega-lite/docs/scale.html#continuous) -- mapping continuous domains to continuous output ranges ([`\\\"linear\\\"`](https://vega.github.io/vega-lite/docs/scale.html#linear), [`\\\"pow\\\"`](https://vega.github.io/vega-lite/docs/scale.html#pow), [`\\\"sqrt\\\"`](https://vega.github.io/vega-lite/docs/scale.html#sqrt), [`\\\"symlog\\\"`](https://vega.github.io/vega-lite/docs/scale.html#symlog), [`\\\"log\\\"`](https://vega.github.io/vega-lite/docs/scale.html#log), [`\\\"time\\\"`](https://vega.github.io/vega-lite/docs/scale.html#time), [`\\\"utc\\\"`](https://vega.github.io/vega-lite/docs/scale.html#utc).\\n\\n2) [**Discrete Scales**](https://vega.github.io/vega-lite/docs/scale.html#discrete) -- mapping discrete domains to discrete ([`\\\"ordinal\\\"`](https://vega.github.io/vega-lite/docs/scale.html#ordinal)) or continuous ([`\\\"band\\\"`](https://vega.github.io/vega-lite/docs/scale.html#band) and [`\\\"point\\\"`](https://vega.github.io/vega-lite/docs/scale.html#point)) output ranges.\\n\\n3) [**Discretizing Scales**](https://vega.github.io/vega-lite/docs/scale.html#discretizing) -- mapping continuous domains to discrete output ranges [`\\\"bin-ordinal\\\"`](https://vega.github.io/vega-lite/docs/scale.html#bin-ordinal), [`\\\"quantile\\\"`](https://vega.github.io/vega-lite/docs/scale.html#quantile), [`\\\"quantize\\\"`](https://vega.github.io/vega-lite/docs/scale.html#quantize) and [`\\\"threshold\\\"`](https://vega.github.io/vega-lite/docs/scale.html#threshold).\\n\\n__Default value:__ please see the [scale type table](https://vega.github.io/vega-lite/docs/scale.html#type).\"\n                },\n                \"zero\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"If `true`, ensures that a zero baseline value is included in the scale domain.\\n\\n__Default value:__ `true` for x and y channels if the quantitative field is not binned and no custom `domain` is provided; `false` otherwise.\\n\\n__Note:__ Log, time, and utc scales do not support `zero`.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleBinParams\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"start\": {\n                    \"description\": \"The starting (lowest-valued) bin boundary.\\n\\n__Default value:__ The lowest value of the scale domain will be used.\",\n                    \"type\": \"number\"\n                },\n                \"step\": {\n                    \"description\": \"The step size defining the bin interval width.\",\n                    \"type\": \"number\"\n                },\n                \"stop\": {\n                    \"description\": \"The stopping (highest-valued) bin boundary.\\n\\n__Default value:__ The highest value of the scale domain will be used.\",\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"step\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ScaleBins\": {\n            \"anyOf\": [\n                {\n                    \"items\": {\n                        \"type\": \"number\"\n                    },\n                    \"type\": \"array\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ScaleBinParams\"\n                }\n            ]\n        },\n        \"ScaleConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"animationDuration\": {\n                    \"description\": \"Default animation duration (in seconds) for time encodings, except for [`band`](https://vega.github.io/vega-lite/docs/scale.html#band) scales.\\n\\n__Default value:__ `5`\",\n                    \"type\": \"number\"\n                },\n                \"bandPaddingInner\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default inner padding for `x` and `y` band scales.\\n\\n__Default value:__\\n- `nestedOffsetPaddingInner` for x/y scales with nested x/y offset scales.\\n- `barBandPaddingInner` for bar marks (`0.1` by default)\\n- `rectBandPaddingInner` for rect and other marks (`0` by default)\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"bandPaddingOuter\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default outer padding for `x` and `y` band scales.\\n\\n__Default value:__ `paddingInner/2` (which makes _width/height = number of unique values * step_)\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"bandWithNestedOffsetPaddingInner\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default inner padding for `x` and `y` band scales with nested `xOffset` and `yOffset` encoding.\\n\\n__Default value:__ `0.2`\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"bandWithNestedOffsetPaddingOuter\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default outer padding for `x` and `y` band scales with nested `xOffset` and `yOffset` encoding.\\n\\n__Default value:__ `0.2`\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"barBandPaddingInner\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default inner padding for `x` and `y` band-ordinal scales of `\\\"bar\\\"` marks.\\n\\n__Default value:__ `0.1`\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"clamp\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"If true, values that exceed the data domain are clamped to either the minimum or maximum range value\"\n                },\n                \"continuousPadding\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default padding for continuous x/y scales.\\n\\n__Default:__ The bar width for continuous x-scale of a vertical bar and continuous y-scale of a horizontal bar.; `0` otherwise.\",\n                    \"minimum\": 0\n                },\n                \"framesPerSecond\": {\n                    \"description\": \"Default framerate (frames per second) for time [`band`](https://vega.github.io/vega-lite/docs/scale.html#band) scales.\\n\\n__Default value:__ `2`\",\n                    \"type\": \"number\"\n                },\n                \"invalid\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataConfig\",\n                    \"description\": \"An object that defines scale outputs per channel for invalid values (nulls and NaNs on a continuous scale).\\n- The keys in this object are the scale channels.\\n- The values is either `\\\"zero-or-min\\\"` (use zero if the scale includes zero or min value otherwise) or a value definition `{value: ...}`.\\n\\n_Example:_ Setting this `config.scale.invalid` property to `{color: {value: '#aaa'}}` will make the visualization color all invalid values with '#aaa'.\\n\\nSee [https://vega.github.io/vega-lite/docs/invalid-data.html](Invalid Data Docs) for more details.\"\n                },\n                \"maxBandSize\": {\n                    \"description\": \"The default max value for mapping quantitative fields to bar's size/bandSize.\\n\\nIf undefined (default), we will use the axis's size (width or height) - 1.\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"maxFontSize\": {\n                    \"description\": \"The default max value for mapping quantitative fields to text's size/fontSize scale.\\n\\n__Default value:__ `40`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"maxOpacity\": {\n                    \"description\": \"Default max opacity for mapping a field to opacity.\\n\\n__Default value:__ `0.8`\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"maxSize\": {\n                    \"description\": \"Default max value for point size scale.\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"maxStrokeWidth\": {\n                    \"description\": \"Default max strokeWidth for the scale of strokeWidth for rule and line marks and of size for trail marks.\\n\\n__Default value:__ `4`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"minBandSize\": {\n                    \"description\": \"The default min value for mapping quantitative fields to bar and tick's size/bandSize scale.\\n\\n__Default value:__ `2`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"minFontSize\": {\n                    \"description\": \"The default min value for mapping quantitative fields to text's size/fontSize scale.\\n\\n__Default value:__ `8`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"minOpacity\": {\n                    \"description\": \"Default minimum opacity for mapping a field to opacity.\\n\\n__Default value:__ `0.3`\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"minSize\": {\n                    \"description\": \"Default minimum value for point size scale.\\n\\n__Default value:__ `9`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"minStrokeWidth\": {\n                    \"description\": \"Default minimum strokeWidth for the scale of strokeWidth for rule and line marks and of size for trail marks.\\n\\n__Default value:__ `1`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"offsetBandPaddingInner\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default padding inner for xOffset/yOffset's band scales.\\n\\n__Default Value:__ `0`\"\n                },\n                \"offsetBandPaddingOuter\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default padding outer for xOffset/yOffset's band scales.\\n\\n__Default Value:__ `0`\"\n                },\n                \"pointPadding\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default outer padding for `x` and `y` point-ordinal scales.\\n\\n__Default value:__ `0.5` (which makes _width/height = number of unique values * step_)\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"quantileCount\": {\n                    \"description\": \"Default range cardinality for [`quantile`](https://vega.github.io/vega-lite/docs/scale.html#quantile) scale.\\n\\n__Default value:__ `4`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"quantizeCount\": {\n                    \"description\": \"Default range cardinality for [`quantize`](https://vega.github.io/vega-lite/docs/scale.html#quantize) scale.\\n\\n__Default value:__ `4`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"rectBandPaddingInner\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default inner padding for `x` and `y` band-ordinal scales of `\\\"rect\\\"` marks.\\n\\n__Default value:__ `0`\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"round\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"If true, rounds numeric output values to integers. This can be helpful for snapping to the pixel grid. (Only available for `x`, `y`, and `size` scales.)\"\n                },\n                \"tickBandPaddingInner\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default inner padding for `x` and `y` band-ordinal scales of `\\\"tick\\\"` marks.\\n\\n__Default value:__ `0.25`\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"useUnaggregatedDomain\": {\n                    \"description\": \"Use the source data range before aggregation as scale domain instead of aggregated data for aggregate axis.\\n\\nThis is equivalent to setting `domain` to `\\\"unaggregate\\\"` for aggregated _quantitative_ fields by default.\\n\\nThis property only works with aggregate functions that produce values within the raw data domain (`\\\"mean\\\"`, `\\\"average\\\"`, `\\\"median\\\"`, `\\\"q1\\\"`, `\\\"q3\\\"`, `\\\"min\\\"`, `\\\"max\\\"`). For other aggregations that produce values outside of the raw data domain (e.g. `\\\"count\\\"`, `\\\"sum\\\"`), this property is ignored.\\n\\n__Default value:__ `false`\",\n                    \"type\": \"boolean\"\n                },\n                \"xReverse\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Reverse x-scale by default (useful for right-to-left charts).\"\n                },\n                \"zero\": {\n                    \"description\": \"Default `scale.zero` for [`continuous`](https://vega.github.io/vega-lite/docs/scale.html#continuous) scales except for (1) x/y-scales of non-ranged bar or area charts and (2) size scales.\\n\\n__Default value:__ `true`\",\n                    \"type\": \"boolean\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleDatumDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"datum\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/PrimitiveValue\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/DateTime\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RepeatRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in data domain.\"\n                },\n                \"scale\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Scale\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/Type\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleFieldDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"scale\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Scale\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                },\n                \"sort\": {\n                    \"$ref\": \"#/definitions/Sort\",\n                    \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/StandardType\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInterpolateEnum\": {\n            \"enum\": [\n                \"rgb\",\n                \"lab\",\n                \"hcl\",\n                \"hsl\",\n                \"hsl-long\",\n                \"hcl-long\",\n                \"cubehelix\",\n                \"cubehelix-long\"\n            ],\n            \"type\": \"string\"\n        },\n        \"ScaleInterpolateParams\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"gamma\": {\n                    \"type\": \"number\"\n                },\n                \"type\": {\n                    \"enum\": [\n                        \"rgb\",\n                        \"cubehelix\",\n                        \"cubehelix-long\"\n                    ],\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"type\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"angle\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"angle\\\">\"\n                },\n                \"color\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"color\\\">\"\n                },\n                \"fill\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"fill\\\">\"\n                },\n                \"fillOpacity\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"fillOpacity\\\">\"\n                },\n                \"opacity\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"opacity\\\">\"\n                },\n                \"radius\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"radius\\\">\"\n                },\n                \"shape\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"shape\\\">\"\n                },\n                \"size\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"size\\\">\"\n                },\n                \"stroke\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"stroke\\\">\"\n                },\n                \"strokeDash\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"strokeDash\\\">\"\n                },\n                \"strokeOpacity\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"strokeOpacity\\\">\"\n                },\n                \"strokeWidth\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"strokeWidth\\\">\"\n                },\n                \"theta\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"theta\\\">\"\n                },\n                \"time\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"time\\\">\"\n                },\n                \"x\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"x\\\">\"\n                },\n                \"xOffset\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"xOffset\\\">\"\n                },\n                \"y\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"y\\\">\"\n                },\n                \"yOffset\": {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAs<\\\"yOffset\\\">\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAs<\\\"angle\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"angle\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAs<\\\"color\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"color\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAs<\\\"fill\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"fill\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAs<\\\"fillOpacity\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"fillOpacity\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAs<\\\"opacity\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"opacity\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAs<\\\"radius\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"radius\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAs<\\\"shape\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"shape\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAs<\\\"size\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"size\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAs<\\\"stroke\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"stroke\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAs<\\\"strokeDash\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"strokeDash\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAs<\\\"strokeOpacity\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"strokeOpacity\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAs<\\\"strokeWidth\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"strokeWidth\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAs<\\\"theta\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"theta\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAs<\\\"time\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"time\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAs<\\\"x\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"x\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAs<\\\"xOffset\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"xOffset\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAs<\\\"y\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"y\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAs<\\\"yOffset\\\">\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/ScaleInvalidDataShowAsValue<\\\"yOffset\\\">\"\n                },\n                {\n                    \"const\": \"zero-or-min\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"angle\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"description\": \"The rotation angle of the text, in degrees.\",\n                    \"maximum\": 360,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"color\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        }\n                    ],\n                    \"description\": \"Default color.\\n\\n__Default value:__ <span style=\\\"color: #4682b4;\\\">&#9632;</span> `\\\"#4682b4\\\"`\\n\\n__Note:__\\n- This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\\n- The `fill` and `stroke` properties have higher precedence than `color` and will override `color`.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"fill\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"Default fill color. This property has higher precedence than `config.color`. Set to `null` to remove fill.\\n\\n__Default value:__ (None)\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"fillOpacity\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"description\": \"The fill opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"opacity\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"description\": \"The overall opacity (value between [0,1]).\\n\\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or `square` marks or layered `bar` charts and `1` otherwise.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"radius\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"description\": \"For arc mark, the primary (outer) radius in pixels.\\n\\nFor text marks, polar coordinate radial offset, in pixels, of the text from the origin determined by the `x` and `y` properties.\\n\\n__Default value:__ `min(plot_width, plot_height)/2`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"shape\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SymbolShape\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        }\n                    ],\n                    \"description\": \"Shape of the point marks. Supported values include:\\n- plotting shapes: `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"cross\\\"`, `\\\"diamond\\\"`, `\\\"triangle-up\\\"`, `\\\"triangle-down\\\"`, `\\\"triangle-right\\\"`, or `\\\"triangle-left\\\"`.\\n- the line symbol `\\\"stroke\\\"`\\n- centered directional shapes `\\\"arrow\\\"`, `\\\"wedge\\\"`, or `\\\"triangle\\\"`\\n- a custom [SVG path string](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths) (For correct sizing, custom shape paths should be defined within a square bounding box with coordinates ranging from -1 to 1 along both the x and y dimensions.)\\n\\n__Default value:__ `\\\"circle\\\"`\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"size\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"description\": \"Default size for marks.\\n- For `point`/`circle`/`square`, this represents the pixel area of the marks. Note that this value sets the area of the symbol; the side lengths will increase with the square root of this value.\\n- For `bar`, this represents the band size of the bar, in pixels.\\n- For `text`, this represents the font size, in pixels.\\n\\n__Default value:__\\n- `30` for point, circle, square marks; width/height's `step`\\n- `2` for bar marks with discrete dimensions;\\n- `5` for bar marks with continuous dimensions;\\n- `11` for text marks.\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"stroke\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"Default stroke color. This property has higher precedence than `config.color`. Set to `null` to remove stroke.\\n\\n__Default value:__ (None)\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"strokeDash\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"description\": \"An array of alternating stroke, space lengths for creating dashed or dotted lines.\",\n                    \"items\": {\n                        \"type\": \"number\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"strokeOpacity\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"description\": \"The stroke opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"strokeWidth\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"description\": \"The stroke width, in pixels.\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"theta\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"description\": \"- For arc marks, the arc length in radians if theta2 is not specified, otherwise the start arc angle. (A value of 0 indicates up or “north”, increasing values proceed clockwise.)\\n\\n- For text marks, polar coordinate angle in radians.\",\n                    \"maximum\": 360,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"time\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"x\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        }\n                    ],\n                    \"description\": \"X coordinates of the marks, or width of horizontal `\\\"bar\\\"` and `\\\"area\\\"` without specified `x2` or `width`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"xOffset\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"description\": \"Offset for x-position.\",\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"y\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        }\n                    ],\n                    \"description\": \"Y coordinates of the marks, or height of vertical `\\\"bar\\\"` and `\\\"area\\\"` without specified `y2` or `height`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleInvalidDataShowAsValue<\\\"yOffset\\\">\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"value\": {\n                    \"description\": \"Offset for y-position.\",\n                    \"type\": \"number\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleResolveMap\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"angle\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"color\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"fill\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"fillOpacity\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"opacity\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"radius\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"shape\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"size\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"stroke\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"strokeDash\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"strokeOpacity\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"strokeWidth\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"theta\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"time\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"x\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"xOffset\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"y\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                },\n                \"yOffset\": {\n                    \"$ref\": \"#/definitions/ResolveMode\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ScaleType\": {\n            \"enum\": [\n                \"linear\",\n                \"log\",\n                \"pow\",\n                \"sqrt\",\n                \"symlog\",\n                \"identity\",\n                \"sequential\",\n                \"time\",\n                \"utc\",\n                \"quantile\",\n                \"quantize\",\n                \"threshold\",\n                \"bin-ordinal\",\n                \"ordinal\",\n                \"point\",\n                \"band\"\n            ],\n            \"type\": \"string\"\n        },\n        \"SchemeParams\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"count\": {\n                    \"description\": \"The number of colors to use in the scheme. This can be useful for scale types such as `\\\"quantize\\\"`, which use the length of the scale range to determine the number of discrete bins for the scale domain.\",\n                    \"type\": \"number\"\n                },\n                \"extent\": {\n                    \"description\": \"The extent of the color range to use. For example `[0.2, 1]` will rescale the color scheme such that color values in the range _[0, 0.2)_ are excluded from the scheme.\",\n                    \"items\": {\n                        \"type\": \"number\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"name\": {\n                    \"$ref\": \"#/definitions/ColorScheme\",\n                    \"description\": \"A color scheme name for ordinal scales (e.g., `\\\"category10\\\"` or `\\\"blues\\\"`).\\n\\nFor the full list of supported schemes, please refer to the [Vega Scheme](https://vega.github.io/vega/docs/schemes/#reference) reference.\"\n                }\n            },\n            \"required\": [\n                \"name\"\n            ],\n            \"type\": \"object\"\n        },\n        \"SecondaryFieldDef\": {\n            \"additionalProperties\": false,\n            \"description\": \"A field definition of a secondary channel that shares a scale with another primary channel. For example, `x2`, `xError` and `xError2` share the same scale with `x`.\",\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\",\n                    \"type\": \"null\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"SelectionConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"interval\": {\n                    \"$ref\": \"#/definitions/IntervalSelectionConfigWithoutType\",\n                    \"description\": \"The default definition for an [`interval`](https://vega.github.io/vega-lite/docs/parameter.html#select) selection. All properties and transformations for an interval selection definition (except `type`) may be specified here.\\n\\nFor instance, setting `interval` to `{\\\"translate\\\": false}` disables the ability to move interval selections by default.\"\n                },\n                \"point\": {\n                    \"$ref\": \"#/definitions/PointSelectionConfigWithoutType\",\n                    \"description\": \"The default definition for a [`point`](https://vega.github.io/vega-lite/docs/parameter.html#select) selection. All properties and transformations  for a point selection definition (except `type`) may be specified here.\\n\\nFor instance, setting `point` to `{\\\"on\\\": \\\"dblclick\\\"}` populates point selections on double-click by default.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"SelectionInit\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                },\n                {\n                    \"$ref\": \"#/definitions/DateTime\"\n                }\n            ]\n        },\n        \"SelectionInitInterval\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/Vector2<boolean>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/Vector2<number>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/Vector2<string>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/Vector2<DateTime>\"\n                }\n            ]\n        },\n        \"SelectionInitIntervalMapping\": {\n            \"$ref\": \"#/definitions/Dict<SelectionInitInterval>\"\n        },\n        \"SelectionInitMapping\": {\n            \"$ref\": \"#/definitions/Dict<SelectionInit>\"\n        },\n        \"SelectionParameter\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"bind\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Binding\"\n                        },\n                        {\n                            \"additionalProperties\": {\n                                \"$ref\": \"#/definitions/Binding\"\n                            },\n                            \"type\": \"object\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/LegendBinding\"\n                        },\n                        {\n                            \"const\": \"scales\",\n                            \"type\": \"string\"\n                        }\n                    ],\n                    \"description\": \"When set, a selection is populated by input elements (also known as dynamic query widgets) or by interacting with the corresponding legend. Direct manipulation interaction is disabled by default; to re-enable it, set the selection's [`on`](https://vega.github.io/vega-lite/docs/selection.html#common-selection-properties) property.\\n\\nLegend bindings are restricted to selections that only specify a single field or encoding.\\n\\nQuery widget binding takes the form of Vega's [input element binding definition](https://vega.github.io/vega/docs/signals/#bind) or can be a mapping between projected field/encodings and binding definitions.\\n\\n__See also:__ [`bind`](https://vega.github.io/vega-lite/docs/bind.html) documentation.\"\n                },\n                \"name\": {\n                    \"$ref\": \"#/definitions/ParameterName\",\n                    \"description\": \"Required. A unique name for the selection parameter. Selection names should be valid JavaScript identifiers: they should contain only alphanumeric characters (or \\\"$\\\", or \\\"_\\\") and may not start with a digit. Reserved keywords that may not be used as parameter names are \\\"datum\\\", \\\"event\\\", \\\"item\\\", and \\\"parent\\\".\"\n                },\n                \"select\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SelectionType\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/PointSelectionConfig\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/IntervalSelectionConfig\"\n                        }\n                    ],\n                    \"description\": \"Determines the default event processing and data query for the selection. Vega-Lite currently supports two selection types:\\n\\n- `\\\"point\\\"` -- to select multiple discrete data values; the first value is selected on `click` and additional values toggled on shift-click.\\n- `\\\"interval\\\"` -- to select a continuous range of data values on `drag`.\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SelectionInit\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/SelectionInitMapping\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/SelectionInitIntervalMapping\"\n                        }\n                    ],\n                    \"description\": \"Initialize the selection with a mapping between [projected channels or field names](https://vega.github.io/vega-lite/docs/selection.html#project) and initial values.\\n\\n__See also:__ [`init`](https://vega.github.io/vega-lite/docs/value.html) documentation.\"\n                }\n            },\n            \"required\": [\n                \"name\",\n                \"select\"\n            ],\n            \"type\": \"object\"\n        },\n        \"SelectionResolution\": {\n            \"enum\": [\n                \"global\",\n                \"union\",\n                \"intersect\"\n            ],\n            \"type\": \"string\"\n        },\n        \"SelectionType\": {\n            \"enum\": [\n                \"point\",\n                \"interval\"\n            ],\n            \"type\": \"string\"\n        },\n        \"SequenceGenerator\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"name\": {\n                    \"description\": \"Provide a placeholder name and bind data at runtime.\",\n                    \"type\": \"string\"\n                },\n                \"sequence\": {\n                    \"$ref\": \"#/definitions/SequenceParams\",\n                    \"description\": \"Generate a sequence of numbers.\"\n                }\n            },\n            \"required\": [\n                \"sequence\"\n            ],\n            \"type\": \"object\"\n        },\n        \"SequenceParams\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"as\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The name of the generated sequence field.\\n\\n__Default value:__ `\\\"data\\\"`\"\n                },\n                \"start\": {\n                    \"description\": \"The starting value of the sequence (inclusive).\",\n                    \"type\": \"number\"\n                },\n                \"step\": {\n                    \"description\": \"The step value between sequence entries.\\n\\n__Default value:__ `1`\",\n                    \"type\": \"number\"\n                },\n                \"stop\": {\n                    \"description\": \"The ending value of the sequence (exclusive).\",\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"start\",\n                \"stop\"\n            ],\n            \"type\": \"object\"\n        },\n        \"SequentialMultiHue\": {\n            \"enum\": [\n                \"turbo\",\n                \"viridis\",\n                \"inferno\",\n                \"magma\",\n                \"plasma\",\n                \"cividis\",\n                \"bluegreen\",\n                \"bluegreen-3\",\n                \"bluegreen-4\",\n                \"bluegreen-5\",\n                \"bluegreen-6\",\n                \"bluegreen-7\",\n                \"bluegreen-8\",\n                \"bluegreen-9\",\n                \"bluepurple\",\n                \"bluepurple-3\",\n                \"bluepurple-4\",\n                \"bluepurple-5\",\n                \"bluepurple-6\",\n                \"bluepurple-7\",\n                \"bluepurple-8\",\n                \"bluepurple-9\",\n                \"goldgreen\",\n                \"goldgreen-3\",\n                \"goldgreen-4\",\n                \"goldgreen-5\",\n                \"goldgreen-6\",\n                \"goldgreen-7\",\n                \"goldgreen-8\",\n                \"goldgreen-9\",\n                \"goldorange\",\n                \"goldorange-3\",\n                \"goldorange-4\",\n                \"goldorange-5\",\n                \"goldorange-6\",\n                \"goldorange-7\",\n                \"goldorange-8\",\n                \"goldorange-9\",\n                \"goldred\",\n                \"goldred-3\",\n                \"goldred-4\",\n                \"goldred-5\",\n                \"goldred-6\",\n                \"goldred-7\",\n                \"goldred-8\",\n                \"goldred-9\",\n                \"greenblue\",\n                \"greenblue-3\",\n                \"greenblue-4\",\n                \"greenblue-5\",\n                \"greenblue-6\",\n                \"greenblue-7\",\n                \"greenblue-8\",\n                \"greenblue-9\",\n                \"orangered\",\n                \"orangered-3\",\n                \"orangered-4\",\n                \"orangered-5\",\n                \"orangered-6\",\n                \"orangered-7\",\n                \"orangered-8\",\n                \"orangered-9\",\n                \"purplebluegreen\",\n                \"purplebluegreen-3\",\n                \"purplebluegreen-4\",\n                \"purplebluegreen-5\",\n                \"purplebluegreen-6\",\n                \"purplebluegreen-7\",\n                \"purplebluegreen-8\",\n                \"purplebluegreen-9\",\n                \"purpleblue\",\n                \"purpleblue-3\",\n                \"purpleblue-4\",\n                \"purpleblue-5\",\n                \"purpleblue-6\",\n                \"purpleblue-7\",\n                \"purpleblue-8\",\n                \"purpleblue-9\",\n                \"purplered\",\n                \"purplered-3\",\n                \"purplered-4\",\n                \"purplered-5\",\n                \"purplered-6\",\n                \"purplered-7\",\n                \"purplered-8\",\n                \"purplered-9\",\n                \"redpurple\",\n                \"redpurple-3\",\n                \"redpurple-4\",\n                \"redpurple-5\",\n                \"redpurple-6\",\n                \"redpurple-7\",\n                \"redpurple-8\",\n                \"redpurple-9\",\n                \"yellowgreenblue\",\n                \"yellowgreenblue-3\",\n                \"yellowgreenblue-4\",\n                \"yellowgreenblue-5\",\n                \"yellowgreenblue-6\",\n                \"yellowgreenblue-7\",\n                \"yellowgreenblue-8\",\n                \"yellowgreenblue-9\",\n                \"yellowgreen\",\n                \"yellowgreen-3\",\n                \"yellowgreen-4\",\n                \"yellowgreen-5\",\n                \"yellowgreen-6\",\n                \"yellowgreen-7\",\n                \"yellowgreen-8\",\n                \"yellowgreen-9\",\n                \"yelloworangebrown\",\n                \"yelloworangebrown-3\",\n                \"yelloworangebrown-4\",\n                \"yelloworangebrown-5\",\n                \"yelloworangebrown-6\",\n                \"yelloworangebrown-7\",\n                \"yelloworangebrown-8\",\n                \"yelloworangebrown-9\",\n                \"yelloworangered\",\n                \"yelloworangered-3\",\n                \"yelloworangered-4\",\n                \"yelloworangered-5\",\n                \"yelloworangered-6\",\n                \"yelloworangered-7\",\n                \"yelloworangered-8\",\n                \"yelloworangered-9\",\n                \"darkblue\",\n                \"darkblue-3\",\n                \"darkblue-4\",\n                \"darkblue-5\",\n                \"darkblue-6\",\n                \"darkblue-7\",\n                \"darkblue-8\",\n                \"darkblue-9\",\n                \"darkgold\",\n                \"darkgold-3\",\n                \"darkgold-4\",\n                \"darkgold-5\",\n                \"darkgold-6\",\n                \"darkgold-7\",\n                \"darkgold-8\",\n                \"darkgold-9\",\n                \"darkgreen\",\n                \"darkgreen-3\",\n                \"darkgreen-4\",\n                \"darkgreen-5\",\n                \"darkgreen-6\",\n                \"darkgreen-7\",\n                \"darkgreen-8\",\n                \"darkgreen-9\",\n                \"darkmulti\",\n                \"darkmulti-3\",\n                \"darkmulti-4\",\n                \"darkmulti-5\",\n                \"darkmulti-6\",\n                \"darkmulti-7\",\n                \"darkmulti-8\",\n                \"darkmulti-9\",\n                \"darkred\",\n                \"darkred-3\",\n                \"darkred-4\",\n                \"darkred-5\",\n                \"darkred-6\",\n                \"darkred-7\",\n                \"darkred-8\",\n                \"darkred-9\",\n                \"lightgreyred\",\n                \"lightgreyred-3\",\n                \"lightgreyred-4\",\n                \"lightgreyred-5\",\n                \"lightgreyred-6\",\n                \"lightgreyred-7\",\n                \"lightgreyred-8\",\n                \"lightgreyred-9\",\n                \"lightgreyteal\",\n                \"lightgreyteal-3\",\n                \"lightgreyteal-4\",\n                \"lightgreyteal-5\",\n                \"lightgreyteal-6\",\n                \"lightgreyteal-7\",\n                \"lightgreyteal-8\",\n                \"lightgreyteal-9\",\n                \"lightmulti\",\n                \"lightmulti-3\",\n                \"lightmulti-4\",\n                \"lightmulti-5\",\n                \"lightmulti-6\",\n                \"lightmulti-7\",\n                \"lightmulti-8\",\n                \"lightmulti-9\",\n                \"lightorange\",\n                \"lightorange-3\",\n                \"lightorange-4\",\n                \"lightorange-5\",\n                \"lightorange-6\",\n                \"lightorange-7\",\n                \"lightorange-8\",\n                \"lightorange-9\",\n                \"lighttealblue\",\n                \"lighttealblue-3\",\n                \"lighttealblue-4\",\n                \"lighttealblue-5\",\n                \"lighttealblue-6\",\n                \"lighttealblue-7\",\n                \"lighttealblue-8\",\n                \"lighttealblue-9\"\n            ],\n            \"type\": \"string\"\n        },\n        \"SequentialSingleHue\": {\n            \"enum\": [\n                \"blues\",\n                \"tealblues\",\n                \"teals\",\n                \"greens\",\n                \"browns\",\n                \"greys\",\n                \"purples\",\n                \"warmgreys\",\n                \"reds\",\n                \"oranges\"\n            ],\n            \"type\": \"string\"\n        },\n        \"ShapeDef\": {\n            \"$ref\": \"#/definitions/MarkPropDef<(string|null),TypeForShape>\"\n        },\n        \"SharedEncoding\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"angle\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                                },\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef\"\n                                        },\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                                }\n                            ],\n                            \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StandardType\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"color\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                                },\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef\"\n                                        },\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                                }\n                            ],\n                            \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StandardType\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Gradient\"\n                                },\n                                {\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"description\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"const\": \"binned\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(string|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(string|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                                },\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef\"\n                                        },\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                                }\n                            ],\n                            \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"format\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Dict\"\n                                }\n                            ],\n                            \"description\": \"When used with the default `\\\"number\\\"` and `\\\"time\\\"` format type, the text formatting pattern for labels of guides (axes, legends, headers) and text marks.\\n\\n- If the format type is `\\\"number\\\"` (e.g., for quantitative fields), this is D3's [number format pattern](https://github.com/d3/d3-format#locale_format).\\n- If the format type is `\\\"time\\\"` (e.g., for temporal fields), this is D3's [time format pattern](https://github.com/d3/d3-time-format#locale_format).\\n\\nSee the [format documentation](https://vega.github.io/vega-lite/docs/format.html) for more examples.\\n\\nWhen used with a [custom `formatType`](https://vega.github.io/vega-lite/docs/config.html#custom-format-type), this value will be passed as `format` alongside `datum.value` to the registered function.\\n\\n__Default value:__  Derived from [numberFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for number format and from [timeFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for time format.\"\n                        },\n                        \"formatType\": {\n                            \"description\": \"The format type for labels. One of `\\\"number\\\"`, `\\\"time\\\"`, or a [registered custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type).\\n\\n__Default value:__\\n- `\\\"time\\\"` for temporal fields and ordinal and nominal fields with `timeUnit`.\\n- `\\\"number\\\"` for quantitative fields as well as ordinal and nominal fields without `timeUnit`.\",\n                            \"type\": \"string\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/StandardType\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"detail\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FieldDefWithoutScale\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/FieldDefWithoutScale\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"Additional levels of detail for grouping data in aggregate views and in line, trail, and area marks without mapping data to a specific visual channel.\"\n                },\n                \"fill\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                                },\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef\"\n                                        },\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                                }\n                            ],\n                            \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StandardType\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Gradient\"\n                                },\n                                {\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"fillOpacity\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                                },\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef\"\n                                        },\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                                }\n                            ],\n                            \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StandardType\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"href\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"const\": \"binned\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(string|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(string|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                                },\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef\"\n                                        },\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                                }\n                            ],\n                            \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"format\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Dict\"\n                                }\n                            ],\n                            \"description\": \"When used with the default `\\\"number\\\"` and `\\\"time\\\"` format type, the text formatting pattern for labels of guides (axes, legends, headers) and text marks.\\n\\n- If the format type is `\\\"number\\\"` (e.g., for quantitative fields), this is D3's [number format pattern](https://github.com/d3/d3-format#locale_format).\\n- If the format type is `\\\"time\\\"` (e.g., for temporal fields), this is D3's [time format pattern](https://github.com/d3/d3-time-format#locale_format).\\n\\nSee the [format documentation](https://vega.github.io/vega-lite/docs/format.html) for more examples.\\n\\nWhen used with a [custom `formatType`](https://vega.github.io/vega-lite/docs/config.html#custom-format-type), this value will be passed as `format` alongside `datum.value` to the registered function.\\n\\n__Default value:__  Derived from [numberFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for number format and from [timeFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for time format.\"\n                        },\n                        \"formatType\": {\n                            \"description\": \"The format type for labels. One of `\\\"number\\\"`, `\\\"time\\\"`, or a [registered custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type).\\n\\n__Default value:__\\n- `\\\"time\\\"` for temporal fields and ordinal and nominal fields with `timeUnit`.\\n- `\\\"number\\\"` for quantitative fields as well as ordinal and nominal fields without `timeUnit`.\",\n                            \"type\": \"string\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/StandardType\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"key\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"const\": \"binned\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/StandardType\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"latitude\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\",\n                            \"type\": \"null\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"const\": \"quantitative\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"latitude2\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\",\n                            \"type\": \"null\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/Type\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"const\": \"width\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"const\": \"height\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"longitude\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\",\n                            \"type\": \"null\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"const\": \"quantitative\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"longitude2\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\",\n                            \"type\": \"null\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/Type\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"const\": \"width\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"const\": \"height\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"opacity\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                                },\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef\"\n                                        },\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                                }\n                            ],\n                            \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StandardType\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"order\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/OrderFieldDef\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/OrderFieldDef\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/OrderValueDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/OrderOnlyDef\"\n                        }\n                    ],\n                    \"description\": \"Order of the marks.\\n- For stacked marks, this `order` channel encodes [stack order](https://vega.github.io/vega-lite/docs/stack.html#order).\\n- For line and trail marks, this `order` channel encodes order of data points in the lines. This can be useful for creating [a connected scatterplot](https://vega.github.io/vega-lite/examples/connected_scatterplot.html). Setting `order` to `{\\\"value\\\": null}` makes the line marks use the original order in the data sources.\\n- Otherwise, this `order` channel encodes layer order of the marks.\\n\\n__Note__: In aggregate plots, `order` field should be `aggregate`d to avoid creating additional aggregation grouping.\"\n                },\n                \"radius\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"const\": \"binned\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"stack\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StackOffset\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"type\": \"boolean\"\n                                }\n                            ],\n                            \"description\": \"Type of stacking offset if the field should be stacked. `stack` is only applicable for `x`, `y`, `theta`, and `radius` channels with continuous domains. For example, `stack` of `y` can be used to customize stacking for a vertical bar chart.\\n\\n`stack` can be one of the following values:\\n- `\\\"zero\\\"` or `true`: stacking with baseline offset at zero value of the scale (for creating typical stacked [bar](https://vega.github.io/vega-lite/docs/stack.html#bar) and [area](https://vega.github.io/vega-lite/docs/stack.html#area) chart).\\n- `\\\"normalize\\\"` - stacking with normalized domain (for creating [normalized stacked bar and area charts](https://vega.github.io/vega-lite/docs/stack.html#normalized) and pie charts [with percentage tooltip](https://vega.github.io/vega-lite/docs/arc.html#tooltip)). <br/>\\n-`\\\"center\\\"` - stacking with center baseline (for [streamgraph](https://vega.github.io/vega-lite/docs/stack.html#streamgraph)).\\n- `null` or `false` - No-stacking. This will produce layered [bar](https://vega.github.io/vega-lite/docs/stack.html#layered-bar-chart) and area chart.\\n\\n__Default value:__ `zero` for plots with all of the following conditions are true: (1) the mark is `bar`, `area`, or `arc`; (2) the stacked measure channel (x or y) has a linear scale; (3) At least one of non-position channels mapped to an unaggregated field that is different from x and y. Otherwise, `null` by default.\\n\\n__See also:__ [`stack`](https://vega.github.io/vega-lite/docs/stack.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StandardType\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"const\": \"width\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"const\": \"height\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"radius2\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\",\n                            \"type\": \"null\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/Type\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"const\": \"width\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"const\": \"height\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"shape\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                                },\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef<TypeForShape>\"\n                                        },\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                                }\n                            ],\n                            \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TypeForShape\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"size\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                                },\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef\"\n                                        },\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                                }\n                            ],\n                            \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StandardType\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"stroke\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                                },\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef\"\n                                        },\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                                }\n                            ],\n                            \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StandardType\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Gradient\"\n                                },\n                                {\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"strokeDash\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(number[]|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(number[]|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                                },\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef\"\n                                        },\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(number[]|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(number[]|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                                }\n                            ],\n                            \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StandardType\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"items\": {\n                                        \"type\": \"number\"\n                                    },\n                                    \"type\": \"array\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"strokeOpacity\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                                },\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef\"\n                                        },\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                                }\n                            ],\n                            \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StandardType\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"strokeWidth\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                                },\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef\"\n                                        },\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                                }\n                            ],\n                            \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"legend\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Legend\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the legend. If `null`, the legend for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [legend properties](https://vega.github.io/vega-lite/docs/legend.html) are applied.\\n\\n__See also:__ [`legend`](https://vega.github.io/vega-lite/docs/legend.html) documentation.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StandardType\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"text\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"const\": \"binned\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(Text|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(Text|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                                },\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalStringFieldDef\"\n                                        },\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(Text|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(Text|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                                }\n                            ],\n                            \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"format\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Dict\"\n                                }\n                            ],\n                            \"description\": \"When used with the default `\\\"number\\\"` and `\\\"time\\\"` format type, the text formatting pattern for labels of guides (axes, legends, headers) and text marks.\\n\\n- If the format type is `\\\"number\\\"` (e.g., for quantitative fields), this is D3's [number format pattern](https://github.com/d3/d3-format#locale_format).\\n- If the format type is `\\\"time\\\"` (e.g., for temporal fields), this is D3's [time format pattern](https://github.com/d3/d3-time-format#locale_format).\\n\\nSee the [format documentation](https://vega.github.io/vega-lite/docs/format.html) for more examples.\\n\\nWhen used with a [custom `formatType`](https://vega.github.io/vega-lite/docs/config.html#custom-format-type), this value will be passed as `format` alongside `datum.value` to the registered function.\\n\\n__Default value:__  Derived from [numberFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for number format and from [timeFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for time format.\"\n                        },\n                        \"formatType\": {\n                            \"description\": \"The format type for labels. One of `\\\"number\\\"`, `\\\"time\\\"`, or a [registered custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type).\\n\\n__Default value:__\\n- `\\\"time\\\"` for temporal fields and ordinal and nominal fields with `timeUnit`.\\n- `\\\"number\\\"` for quantitative fields as well as ordinal and nominal fields without `timeUnit`.\",\n                            \"type\": \"string\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StandardType\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"theta\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"const\": \"binned\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"stack\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StackOffset\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"type\": \"boolean\"\n                                }\n                            ],\n                            \"description\": \"Type of stacking offset if the field should be stacked. `stack` is only applicable for `x`, `y`, `theta`, and `radius` channels with continuous domains. For example, `stack` of `y` can be used to customize stacking for a vertical bar chart.\\n\\n`stack` can be one of the following values:\\n- `\\\"zero\\\"` or `true`: stacking with baseline offset at zero value of the scale (for creating typical stacked [bar](https://vega.github.io/vega-lite/docs/stack.html#bar) and [area](https://vega.github.io/vega-lite/docs/stack.html#area) chart).\\n- `\\\"normalize\\\"` - stacking with normalized domain (for creating [normalized stacked bar and area charts](https://vega.github.io/vega-lite/docs/stack.html#normalized) and pie charts [with percentage tooltip](https://vega.github.io/vega-lite/docs/arc.html#tooltip)). <br/>\\n-`\\\"center\\\"` - stacking with center baseline (for [streamgraph](https://vega.github.io/vega-lite/docs/stack.html#streamgraph)).\\n- `null` or `false` - No-stacking. This will produce layered [bar](https://vega.github.io/vega-lite/docs/stack.html#layered-bar-chart) and area chart.\\n\\n__Default value:__ `zero` for plots with all of the following conditions are true: (1) the mark is `bar`, `area`, or `arc`; (2) the stacked measure channel (x or y) has a linear scale; (3) At least one of non-position channels mapped to an unaggregated field that is different from x and y. Otherwise, `null` by default.\\n\\n__See also:__ [`stack`](https://vega.github.io/vega-lite/docs/stack.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StandardType\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"const\": \"width\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"const\": \"height\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"theta2\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\",\n                            \"type\": \"null\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/Type\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"const\": \"width\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"const\": \"height\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"time\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"rescale\": {\n                            \"type\": \"boolean\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/StandardType\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"tooltip\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StringFieldDefWithCondition\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/StringValueDefWithCondition\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/StringFieldDef\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"The tooltip text to show upon mouse hover. Specifying `tooltip` encoding overrides [the `tooltip` property in the mark definition](https://vega.github.io/vega-lite/docs/mark.html#mark-def).\\n\\nSee the [`tooltip`](https://vega.github.io/vega-lite/docs/tooltip.html) documentation for a detailed discussion about tooltip in Vega-Lite.\"\n                },\n                \"url\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"const\": \"binned\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"condition\": {\n                            \"anyOf\": [\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(string|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(string|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                                },\n                                {\n                                    \"anyOf\": [\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef\"\n                                        },\n                                        {\n                                            \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                                        },\n                                        {\n                                            \"items\": {\n                                                \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                                            },\n                                            \"type\": \"array\"\n                                        }\n                                    ],\n                                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                                }\n                            ],\n                            \"description\": \"One or more value definition(s) with [a parameter or a test predicate](https://vega.github.io/vega-lite/docs/condition.html).\\n\\n__Note:__ A field definition's `condition` property can only contain [conditional value definitions](https://vega.github.io/vega-lite/docs/condition.html#value) since Vega-Lite only allows at most one encoded field per encoding channel.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"format\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Dict\"\n                                }\n                            ],\n                            \"description\": \"When used with the default `\\\"number\\\"` and `\\\"time\\\"` format type, the text formatting pattern for labels of guides (axes, legends, headers) and text marks.\\n\\n- If the format type is `\\\"number\\\"` (e.g., for quantitative fields), this is D3's [number format pattern](https://github.com/d3/d3-format#locale_format).\\n- If the format type is `\\\"time\\\"` (e.g., for temporal fields), this is D3's [time format pattern](https://github.com/d3/d3-time-format#locale_format).\\n\\nSee the [format documentation](https://vega.github.io/vega-lite/docs/format.html) for more examples.\\n\\nWhen used with a [custom `formatType`](https://vega.github.io/vega-lite/docs/config.html#custom-format-type), this value will be passed as `format` alongside `datum.value` to the registered function.\\n\\n__Default value:__  Derived from [numberFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for number format and from [timeFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for time format.\"\n                        },\n                        \"formatType\": {\n                            \"description\": \"The format type for labels. One of `\\\"number\\\"`, `\\\"time\\\"`, or a [registered custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type).\\n\\n__Default value:__\\n- `\\\"time\\\"` for temporal fields and ordinal and nominal fields with `timeUnit`.\\n- `\\\"number\\\"` for quantitative fields as well as ordinal and nominal fields without `timeUnit`.\",\n                            \"type\": \"string\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/StandardType\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"x\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"axis\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Axis\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of axis's gridlines, ticks and labels. If `null`, the axis for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [axis properties](https://vega.github.io/vega-lite/docs/axis.html) are applied.\\n\\n__See also:__ [`axis`](https://vega.github.io/vega-lite/docs/axis.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"const\": \"binned\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"impute\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ImputeParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining the properties of the Impute Operation to be applied. The field value of the other positional channel is taken as `key` of the `Impute` Operation. The field of the `color` channel if specified is used as `groupby` of the `Impute` Operation.\\n\\n__See also:__ [`impute`](https://vega.github.io/vega-lite/docs/impute.html) documentation.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"stack\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StackOffset\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"type\": \"boolean\"\n                                }\n                            ],\n                            \"description\": \"Type of stacking offset if the field should be stacked. `stack` is only applicable for `x`, `y`, `theta`, and `radius` channels with continuous domains. For example, `stack` of `y` can be used to customize stacking for a vertical bar chart.\\n\\n`stack` can be one of the following values:\\n- `\\\"zero\\\"` or `true`: stacking with baseline offset at zero value of the scale (for creating typical stacked [bar](https://vega.github.io/vega-lite/docs/stack.html#bar) and [area](https://vega.github.io/vega-lite/docs/stack.html#area) chart).\\n- `\\\"normalize\\\"` - stacking with normalized domain (for creating [normalized stacked bar and area charts](https://vega.github.io/vega-lite/docs/stack.html#normalized) and pie charts [with percentage tooltip](https://vega.github.io/vega-lite/docs/arc.html#tooltip)). <br/>\\n-`\\\"center\\\"` - stacking with center baseline (for [streamgraph](https://vega.github.io/vega-lite/docs/stack.html#streamgraph)).\\n- `null` or `false` - No-stacking. This will produce layered [bar](https://vega.github.io/vega-lite/docs/stack.html#layered-bar-chart) and area chart.\\n\\n__Default value:__ `zero` for plots with all of the following conditions are true: (1) the mark is `bar`, `area`, or `arc`; (2) the stacked measure channel (x or y) has a linear scale; (3) At least one of non-position channels mapped to an unaggregated field that is different from x and y. Otherwise, `null` by default.\\n\\n__See also:__ [`stack`](https://vega.github.io/vega-lite/docs/stack.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StandardType\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"const\": \"width\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"const\": \"height\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"x2\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\",\n                            \"type\": \"null\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/Type\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"const\": \"width\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"const\": \"height\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"xError\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\",\n                            \"type\": \"null\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"value\": {\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\",\n                            \"type\": \"number\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"xError2\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\",\n                            \"type\": \"null\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"value\": {\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\",\n                            \"type\": \"number\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"xOffset\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StandardType\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\",\n                            \"type\": \"number\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"y\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"axis\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Axis\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of axis's gridlines, ticks and labels. If `null`, the axis for the encoding channel will be removed.\\n\\n__Default value:__ If undefined, default [axis properties](https://vega.github.io/vega-lite/docs/axis.html) are applied.\\n\\n__See also:__ [`axis`](https://vega.github.io/vega-lite/docs/axis.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"const\": \"binned\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"impute\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/ImputeParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining the properties of the Impute Operation to be applied. The field value of the other positional channel is taken as `key` of the `Impute` Operation. The field of the `color` channel if specified is used as `groupby` of the `Impute` Operation.\\n\\n__See also:__ [`impute`](https://vega.github.io/vega-lite/docs/impute.html) documentation.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"stack\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StackOffset\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"type\": \"boolean\"\n                                }\n                            ],\n                            \"description\": \"Type of stacking offset if the field should be stacked. `stack` is only applicable for `x`, `y`, `theta`, and `radius` channels with continuous domains. For example, `stack` of `y` can be used to customize stacking for a vertical bar chart.\\n\\n`stack` can be one of the following values:\\n- `\\\"zero\\\"` or `true`: stacking with baseline offset at zero value of the scale (for creating typical stacked [bar](https://vega.github.io/vega-lite/docs/stack.html#bar) and [area](https://vega.github.io/vega-lite/docs/stack.html#area) chart).\\n- `\\\"normalize\\\"` - stacking with normalized domain (for creating [normalized stacked bar and area charts](https://vega.github.io/vega-lite/docs/stack.html#normalized) and pie charts [with percentage tooltip](https://vega.github.io/vega-lite/docs/arc.html#tooltip)). <br/>\\n-`\\\"center\\\"` - stacking with center baseline (for [streamgraph](https://vega.github.io/vega-lite/docs/stack.html#streamgraph)).\\n- `null` or `false` - No-stacking. This will produce layered [bar](https://vega.github.io/vega-lite/docs/stack.html#layered-bar-chart) and area chart.\\n\\n__Default value:__ `zero` for plots with all of the following conditions are true: (1) the mark is `bar`, `area`, or `arc`; (2) the stacked measure channel (x or y) has a linear scale; (3) At least one of non-position channels mapped to an unaggregated field that is different from x and y. Otherwise, `null` by default.\\n\\n__See also:__ [`stack`](https://vega.github.io/vega-lite/docs/stack.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StandardType\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"const\": \"width\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"const\": \"height\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"y2\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\",\n                            \"type\": \"null\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"$ref\": \"#/definitions/Type\",\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"const\": \"width\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"const\": \"height\",\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"yError\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\",\n                            \"type\": \"null\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"value\": {\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\",\n                            \"type\": \"number\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"yError2\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\",\n                            \"type\": \"null\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"value\": {\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\",\n                            \"type\": \"number\"\n                        }\n                    },\n                    \"type\": \"object\"\n                },\n                \"yOffset\": {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"aggregate\": {\n                            \"$ref\": \"#/definitions/Aggregate\",\n                            \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                        },\n                        \"bandPosition\": {\n                            \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        \"bin\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinParams\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                        },\n                        \"datum\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/PrimitiveValue\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/DateTime\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatRef\"\n                                }\n                            ],\n                            \"description\": \"A constant value in data domain.\"\n                        },\n                        \"field\": {\n                            \"$ref\": \"#/definitions/Field\",\n                            \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                        },\n                        \"scale\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Scale\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                        },\n                        \"sort\": {\n                            \"$ref\": \"#/definitions/Sort\",\n                            \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                        },\n                        \"timeUnit\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TimeUnitParams\"\n                                }\n                            ],\n                            \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                        },\n                        \"type\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/StandardType\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Type\",\n                                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                                }\n                            ],\n                            \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                        },\n                        \"value\": {\n                            \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\",\n                            \"type\": \"number\"\n                        }\n                    },\n                    \"type\": \"object\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"SingleDefUnitChannel\": {\n            \"enum\": [\n                \"text\",\n                \"shape\",\n                \"x\",\n                \"y\",\n                \"xOffset\",\n                \"yOffset\",\n                \"x2\",\n                \"y2\",\n                \"longitude\",\n                \"latitude\",\n                \"longitude2\",\n                \"latitude2\",\n                \"theta\",\n                \"theta2\",\n                \"radius\",\n                \"radius2\",\n                \"time\",\n                \"color\",\n                \"fill\",\n                \"stroke\",\n                \"opacity\",\n                \"fillOpacity\",\n                \"strokeOpacity\",\n                \"strokeWidth\",\n                \"strokeDash\",\n                \"size\",\n                \"angle\",\n                \"key\",\n                \"href\",\n                \"url\",\n                \"description\"\n            ],\n            \"type\": \"string\"\n        },\n        \"SingleTimeUnit\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/LocalSingleTimeUnit\"\n                },\n                {\n                    \"$ref\": \"#/definitions/UtcSingleTimeUnit\"\n                }\n            ]\n        },\n        \"Sort\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/SortArray\"\n                },\n                {\n                    \"$ref\": \"#/definitions/AllSortString\"\n                },\n                {\n                    \"$ref\": \"#/definitions/EncodingSortField\"\n                },\n                {\n                    \"$ref\": \"#/definitions/SortByEncoding\"\n                },\n                {\n                    \"type\": \"null\"\n                }\n            ]\n        },\n        \"SortArray\": {\n            \"anyOf\": [\n                {\n                    \"items\": {\n                        \"type\": \"number\"\n                    },\n                    \"type\": \"array\"\n                },\n                {\n                    \"items\": {\n                        \"type\": \"string\"\n                    },\n                    \"type\": \"array\"\n                },\n                {\n                    \"items\": {\n                        \"type\": \"boolean\"\n                    },\n                    \"type\": \"array\"\n                },\n                {\n                    \"items\": {\n                        \"$ref\": \"#/definitions/DateTime\"\n                    },\n                    \"type\": \"array\"\n                }\n            ]\n        },\n        \"SortByChannel\": {\n            \"enum\": [\n                \"x\",\n                \"y\",\n                \"color\",\n                \"fill\",\n                \"stroke\",\n                \"strokeWidth\",\n                \"size\",\n                \"shape\",\n                \"fillOpacity\",\n                \"strokeOpacity\",\n                \"opacity\",\n                \"text\"\n            ],\n            \"type\": \"string\"\n        },\n        \"SortByChannelDesc\": {\n            \"enum\": [\n                \"-x\",\n                \"-y\",\n                \"-color\",\n                \"-fill\",\n                \"-stroke\",\n                \"-strokeWidth\",\n                \"-size\",\n                \"-shape\",\n                \"-fillOpacity\",\n                \"-strokeOpacity\",\n                \"-opacity\",\n                \"-text\"\n            ],\n            \"type\": \"string\"\n        },\n        \"SortByEncoding\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"encoding\": {\n                    \"$ref\": \"#/definitions/SortByChannel\",\n                    \"description\": \"The [encoding channel](https://vega.github.io/vega-lite/docs/encoding.html#channels) to sort by (e.g., `\\\"x\\\"`, `\\\"y\\\"`)\"\n                },\n                \"order\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SortOrder\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"The sort order. One of `\\\"ascending\\\"` (default), `\\\"descending\\\"`, or `null` (no not sort).\"\n                }\n            },\n            \"required\": [\n                \"encoding\"\n            ],\n            \"type\": \"object\"\n        },\n        \"SortField\": {\n            \"additionalProperties\": false,\n            \"description\": \"A sort definition for transform\",\n            \"properties\": {\n                \"field\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The name of the field to sort.\"\n                },\n                \"order\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SortOrder\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"Whether to sort the field in ascending or descending order. One of `\\\"ascending\\\"` (default), `\\\"descending\\\"`, or `null` (no not sort).\"\n                }\n            },\n            \"required\": [\n                \"field\"\n            ],\n            \"type\": \"object\"\n        },\n        \"SortOrder\": {\n            \"enum\": [\n                \"ascending\",\n                \"descending\"\n            ],\n            \"type\": \"string\"\n        },\n        \"SphereGenerator\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"name\": {\n                    \"description\": \"Provide a placeholder name and bind data at runtime.\",\n                    \"type\": \"string\"\n                },\n                \"sphere\": {\n                    \"anyOf\": [\n                        {\n                            \"const\": true,\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"additionalProperties\": false,\n                            \"type\": \"object\"\n                        }\n                    ],\n                    \"description\": \"Generate sphere GeoJSON data for the full globe.\"\n                }\n            },\n            \"required\": [\n                \"sphere\"\n            ],\n            \"type\": \"object\"\n        },\n        \"StackOffset\": {\n            \"enum\": [\n                \"zero\",\n                \"center\",\n                \"normalize\"\n            ],\n            \"type\": \"string\"\n        },\n        \"StackTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"as\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FieldName\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/FieldName\"\n                            },\n                            \"maxItems\": 2,\n                            \"minItems\": 2,\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"Output field names. This can be either a string or an array of strings with two elements denoting the name for the fields for stack start and stack end respectively. If a single string(e.g., `\\\"val\\\"`) is provided, the end field will be `\\\"val_end\\\"`.\"\n                },\n                \"groupby\": {\n                    \"description\": \"The data fields to group by.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"offset\": {\n                    \"description\": \"Mode for stacking marks. One of `\\\"zero\\\"` (default), `\\\"center\\\"`, or `\\\"normalize\\\"`. The `\\\"zero\\\"` offset will stack starting at `0`. The `\\\"center\\\"` offset will center the stacks. The `\\\"normalize\\\"` offset will compute percentage values for each stack point, with output values in the range `[0,1]`.\\n\\n__Default value:__ `\\\"zero\\\"`\",\n                    \"enum\": [\n                        \"zero\",\n                        \"center\",\n                        \"normalize\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"sort\": {\n                    \"description\": \"Field that determines the order of leaves in the stacked charts.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/SortField\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"stack\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The field which is stacked.\"\n                }\n            },\n            \"required\": [\n                \"stack\",\n                \"groupby\",\n                \"as\"\n            ],\n            \"type\": \"object\"\n        },\n        \"StandardType\": {\n            \"enum\": [\n                \"quantitative\",\n                \"ordinal\",\n                \"temporal\",\n                \"nominal\"\n            ],\n            \"type\": \"string\"\n        },\n        \"Step\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"for\": {\n                    \"$ref\": \"#/definitions/StepFor\",\n                    \"description\": \"Whether to apply the step to position scale or offset scale when there are both `x` and `xOffset` or both `y` and `yOffset` encodings.\"\n                },\n                \"step\": {\n                    \"description\": \"The size (width/height) per discrete step.\",\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"step\"\n            ],\n            \"type\": \"object\"\n        },\n        \"StepFor\": {\n            \"enum\": [\n                \"position\",\n                \"offset\"\n            ],\n            \"type\": \"string\"\n        },\n        \"Stream\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/EventStream\"\n                },\n                {\n                    \"$ref\": \"#/definitions/DerivedStream\"\n                },\n                {\n                    \"$ref\": \"#/definitions/MergedStream\"\n                }\n            ]\n        },\n        \"StringFieldDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"const\": \"binned\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"format\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Dict\"\n                        }\n                    ],\n                    \"description\": \"When used with the default `\\\"number\\\"` and `\\\"time\\\"` format type, the text formatting pattern for labels of guides (axes, legends, headers) and text marks.\\n\\n- If the format type is `\\\"number\\\"` (e.g., for quantitative fields), this is D3's [number format pattern](https://github.com/d3/d3-format#locale_format).\\n- If the format type is `\\\"time\\\"` (e.g., for temporal fields), this is D3's [time format pattern](https://github.com/d3/d3-time-format#locale_format).\\n\\nSee the [format documentation](https://vega.github.io/vega-lite/docs/format.html) for more examples.\\n\\nWhen used with a [custom `formatType`](https://vega.github.io/vega-lite/docs/config.html#custom-format-type), this value will be passed as `format` alongside `datum.value` to the registered function.\\n\\n__Default value:__  Derived from [numberFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for number format and from [timeFormat](https://vega.github.io/vega-lite/docs/config.html#format) config for time format.\"\n                },\n                \"formatType\": {\n                    \"description\": \"The format type for labels. One of `\\\"number\\\"`, `\\\"time\\\"`, or a [registered custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type).\\n\\n__Default value:__\\n- `\\\"time\\\"` for temporal fields and ordinal and nominal fields with `timeUnit`.\\n- `\\\"number\\\"` for quantitative fields as well as ordinal and nominal fields without `timeUnit`.\",\n                    \"type\": \"string\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/StandardType\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"StringFieldDefWithCondition\": {\n            \"$ref\": \"#/definitions/FieldOrDatumDefWithCondition<StringFieldDef,string>\"\n        },\n        \"StringValueDefWithCondition\": {\n            \"$ref\": \"#/definitions/ValueDefWithCondition<MarkPropFieldOrDatumDef,(string|null)>\"\n        },\n        \"StrokeCap\": {\n            \"enum\": [\n                \"butt\",\n                \"round\",\n                \"square\"\n            ],\n            \"type\": \"string\"\n        },\n        \"StrokeJoin\": {\n            \"enum\": [\n                \"miter\",\n                \"round\",\n                \"bevel\"\n            ],\n            \"type\": \"string\"\n        },\n        \"StyleConfigIndex\": {\n            \"additionalProperties\": {\n                \"anyOf\": [\n                    {\n                        \"$ref\": \"#/definitions/AnyMarkConfig\"\n                    },\n                    {\n                        \"$ref\": \"#/definitions/Axis\"\n                    }\n                ]\n            },\n            \"properties\": {\n                \"arc\": {\n                    \"$ref\": \"#/definitions/RectConfig\",\n                    \"description\": \"Arc-specific Config\"\n                },\n                \"area\": {\n                    \"$ref\": \"#/definitions/AreaConfig\",\n                    \"description\": \"Area-Specific Config\"\n                },\n                \"bar\": {\n                    \"$ref\": \"#/definitions/BarConfig\",\n                    \"description\": \"Bar-Specific Config\"\n                },\n                \"circle\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Circle-Specific Config\"\n                },\n                \"geoshape\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Geoshape-Specific Config\"\n                },\n                \"group-subtitle\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Default style for chart subtitles\"\n                },\n                \"group-title\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Default style for chart titles\"\n                },\n                \"guide-label\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Default style for axis, legend, and header labels.\"\n                },\n                \"guide-title\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Default style for axis, legend, and header titles.\"\n                },\n                \"image\": {\n                    \"$ref\": \"#/definitions/RectConfig\",\n                    \"description\": \"Image-specific Config\"\n                },\n                \"line\": {\n                    \"$ref\": \"#/definitions/LineConfig\",\n                    \"description\": \"Line-Specific Config\"\n                },\n                \"mark\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Mark Config\"\n                },\n                \"point\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Point-Specific Config\"\n                },\n                \"rect\": {\n                    \"$ref\": \"#/definitions/RectConfig\",\n                    \"description\": \"Rect-Specific Config\"\n                },\n                \"rule\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Rule-Specific Config\"\n                },\n                \"square\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Square-Specific Config\"\n                },\n                \"text\": {\n                    \"$ref\": \"#/definitions/MarkConfig\",\n                    \"description\": \"Text-Specific Config\"\n                },\n                \"tick\": {\n                    \"$ref\": \"#/definitions/TickConfig\",\n                    \"description\": \"Tick-Specific Config\"\n                },\n                \"trail\": {\n                    \"$ref\": \"#/definitions/LineConfig\",\n                    \"description\": \"Trail-Specific Config\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"SymbolShape\": {\n            \"type\": \"string\"\n        },\n        \"Text\": {\n            \"anyOf\": [\n                {\n                    \"type\": \"string\"\n                },\n                {\n                    \"items\": {\n                        \"type\": \"string\"\n                    },\n                    \"type\": \"array\"\n                }\n            ]\n        },\n        \"TextBaseline\": {\n            \"anyOf\": [\n                {\n                    \"const\": \"alphabetic\",\n                    \"type\": \"string\"\n                },\n                {\n                    \"$ref\": \"#/definitions/Baseline\"\n                },\n                {\n                    \"const\": \"line-top\",\n                    \"type\": \"string\"\n                },\n                {\n                    \"const\": \"line-bottom\",\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"TextDef\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/FieldOrDatumDefWithCondition<StringFieldDef,Text>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/FieldOrDatumDefWithCondition<StringDatumDef,Text>\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ValueDefWithCondition<StringFieldDef,Text>\"\n                }\n            ]\n        },\n        \"TextDirection\": {\n            \"enum\": [\n                \"ltr\",\n                \"rtl\"\n            ],\n            \"type\": \"string\"\n        },\n        \"TickConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Align\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The horizontal alignment of the text or ranged marks (area, bar, image, rect, rule). One of `\\\"left\\\"`, `\\\"right\\\"`, `\\\"center\\\"`.\\n\\n__Note:__ Expression reference is *not* supported for range marks.\"\n                },\n                \"angle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The rotation angle of the text, in degrees.\",\n                            \"maximum\": 360,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aria\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag indicating if [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) should be included (SVG output only). If `false`, the \\\"aria-hidden\\\" attribute will be set on the output SVG element, removing the mark item from the ARIA accessibility tree.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ariaRole\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Sets the type of user interface element of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the \\\"role\\\" attribute. Warning: this property is experimental and may be changed in the future.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ariaRoleDescription\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A human-readable, author-localized description for the role of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the \\\"aria-roledescription\\\" attribute. Warning: this property is experimental and may be changed in the future.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aspect\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Whether to keep aspect ratio of image marks.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"bandSize\": {\n                    \"description\": \"The width of the ticks.\\n\\n__Default value:__  3/4 of step (width step for horizontal ticks and height step for vertical ticks).\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"baseline\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextBaseline\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"For text marks, the vertical text baseline. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, `\\\"line-bottom\\\"`, or an expression reference that provides one of the valid values. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the `lineHeight` rather than `fontSize` alone.\\n\\nFor range marks, the vertical alignment of the marks. One of `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`.\\n\\n__Note:__ Expression reference is *not* supported for range marks.\"\n                },\n                \"binSpacing\": {\n                    \"description\": \"Offset between bars for binned field. The ideal value for this is either 0 (preferred by statisticians) or 1 (Vega-Lite default, D3 example style).\\n\\n__Default value:__ `1`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"blend\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Blend\",\n                            \"description\": \"The color blend mode for drawing an item on its current background. Any valid [CSS mix-blend-mode](https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode) value can be used.\\n\\n__Default value: `\\\"source-over\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"color\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default color.\\n\\n__Default value:__ <span style=\\\"color: #4682b4;\\\">&#9632;</span> `\\\"#4682b4\\\"`\\n\\n__Note:__\\n- This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\\n- The `fill` and `stroke` properties have higher precedence than `color` and will override `color`.\"\n                },\n                \"continuousBandSize\": {\n                    \"description\": \"The default size of the bars on continuous scales.\\n\\n__Default value:__ `5`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"cornerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles or arcs' corners.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusBottomLeft\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' bottom left corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusBottomRight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' bottom right corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusTopLeft\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' top right corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cornerRadiusTopRight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles' top left corner.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cursor\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Cursor\",\n                            \"description\": \"The mouse cursor used over the mark. Any valid [CSS cursor type](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"description\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A text description of the mark item for [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) (SVG output only). If specified, this property determines the [\\\"aria-label\\\" attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dir\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TextDirection\",\n                            \"description\": \"The direction of the text. One of `\\\"ltr\\\"` (left-to-right) or `\\\"rtl\\\"` (right-to-left). This property determines on which side is truncated in response to the limit parameter.\\n\\n__Default value:__ `\\\"ltr\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"discreteBandSize\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RelativeBandSize\"\n                        }\n                    ],\n                    \"description\": \"The default size of the bars with discrete dimensions. If unspecified, the default size is  `step-2`, which provides 2 pixel offset between bars.\",\n                    \"minimum\": 0\n                },\n                \"dx\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The horizontal offset, in pixels, between the text label and its anchor point. The offset is applied after rotation by the _angle_ property.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dy\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The vertical offset, in pixels, between the text label and its anchor point. The offset is applied after rotation by the _angle_ property.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"ellipsis\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The ellipsis string for text truncated in response to the limit parameter.\\n\\n__Default value:__ `\\\"…\\\"`\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"endAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The end angle in radians for arc marks. A value of `0` indicates up (north), increasing values proceed clockwise.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fill\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default fill color. This property has higher precedence than `config.color`. Set to `null` to remove fill.\\n\\n__Default value:__ (None)\"\n                },\n                \"fillOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The fill opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"filled\": {\n                    \"description\": \"Whether the mark's color should be used as fill color instead of stroke color.\\n\\n__Default value:__ `false` for all `point`, `line`, and `rule` marks as well as `geoshape` marks for [`graticule`](https://vega.github.io/vega-lite/docs/data.html#graticule) data sources; otherwise, `true`.\\n\\n__Note:__ This property cannot be used in a [style config](https://vega.github.io/vega-lite/docs/mark.html#style-config).\",\n                    \"type\": \"boolean\"\n                },\n                \"font\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The typeface to set the text in (e.g., `\\\"Helvetica Neue\\\"`).\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The font size, in pixels.\\n\\n__Default value:__ `11`\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"The font style (e.g., `\\\"italic\\\"`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"The font weight. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"height\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Height of the marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"href\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/URI\",\n                            \"description\": \"A URL to load upon mouse click. If defined, the mark acts as a hyperlink.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"innerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The inner radius in pixels of arc marks. `innerRadius` is an alias for `radius2`.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"interpolate\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Interpolate\",\n                            \"description\": \"The line interpolation method to use for line and area marks. One of the following:\\n- `\\\"linear\\\"`: piecewise linear segments, as in a polyline.\\n- `\\\"linear-closed\\\"`: close the linear segments to form a polygon.\\n- `\\\"step\\\"`: alternate between horizontal and vertical segments, as in a step function.\\n- `\\\"step-before\\\"`: alternate between vertical and horizontal segments, as in a step function.\\n- `\\\"step-after\\\"`: alternate between horizontal and vertical segments, as in a step function.\\n- `\\\"basis\\\"`: a B-spline, with control point duplication on the ends.\\n- `\\\"basis-open\\\"`: an open B-spline; may not intersect the start or end.\\n- `\\\"basis-closed\\\"`: a closed B-spline, as in a loop.\\n- `\\\"cardinal\\\"`: a Cardinal spline, with control point duplication on the ends.\\n- `\\\"cardinal-open\\\"`: an open Cardinal spline; may not intersect the start or end, but will intersect other control points.\\n- `\\\"cardinal-closed\\\"`: a closed Cardinal spline, as in a loop.\\n- `\\\"bundle\\\"`: equivalent to basis, except the tension parameter is used to straighten the spline.\\n- `\\\"monotone\\\"`: cubic interpolation that preserves monotonicity in y.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"invalid\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/MarkInvalidDataMode\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"Invalid data mode, which defines how the marks and corresponding scales should represent invalid values (`null` and `NaN` in continuous scales *without* defined output for invalid values).\\n\\n- `\\\"filter\\\"` — *Exclude* all invalid values from the visualization's *marks* and *scales*. For path marks (for line, area, trail), this option will create paths that connect valid points, as if the data rows with invalid values do not exist.\\n\\n- `\\\"break-paths-filter-domains\\\"` — Break path marks (for line, area, trail) at invalid values.  For non-path marks, this is equivalent to `\\\"filter\\\"`. All *scale* domains will *exclude* these filtered data points.\\n\\n- `\\\"break-paths-show-domains\\\"` — Break paths (for line, area, trail) at invalid values.  Hide invalid values for non-path marks. All *scale* domains will *include* these filtered data points (for both path and non-path marks).\\n\\n- `\\\"show\\\"` or `null` — Show all data points in the marks and scale domains. Each scale will use the output for invalid values defined in `config.scale.invalid` or, if unspecified, by default invalid values will produce the same visual values as zero (if the scale includes zero) or the minimum value (if the scale does not include zero).\\n\\n- `\\\"break-paths-show-path-domains\\\"` (default) — This is equivalent to `\\\"break-paths-show-domains\\\"` for path-based marks (line/area/trail) and `\\\"filter\\\"` for non-path marks.\\n\\n__Note__: If any channel's scale has an output for invalid values defined in `config.scale.invalid`, all values for the scales will be considered \\\"valid\\\" since they can produce a reasonable output for the scales. Thus, fields for such channels will not be filtered and will not cause path breaks.\"\n                },\n                \"limit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The maximum length of the text mark in pixels. The text value will be automatically truncated if the rendered size exceeds the limit.\\n\\n__Default value:__ `0` -- indicating no limit\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"lineBreak\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A delimiter, such as a newline character, upon which to break text strings into multiple lines. This property is ignored if the text is array-valued.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"lineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The line height in pixels (the spacing between subsequent lines of text) for multi-line text marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"minBandSize\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The minimum band size for bar and rectangle marks. __Default value:__ `0.25`\"\n                },\n                \"opacity\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The overall opacity (value between [0,1]).\\n\\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or `square` marks or layered `bar` charts and `1` otherwise.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"order\": {\n                    \"description\": \"For line and trail marks, this `order` property can be set to `null` or `false` to make the lines use the original order in the data sources.\",\n                    \"type\": [\n                        \"null\",\n                        \"boolean\"\n                    ]\n                },\n                \"orient\": {\n                    \"$ref\": \"#/definitions/Orientation\",\n                    \"description\": \"The orientation of a non-stacked bar, tick, area, and line charts. The value is either horizontal (default) or vertical.\\n- For bar, rule and tick, this determines whether the size of the bar and tick should be applied to x or y dimension.\\n- For area, this property determines the orient property of the Vega output.\\n- For line and trail marks, this property determines the sort order of the points in the line if `config.sortLineBy` is not specified. For stacked charts, this is always determined by the orientation of the stack; therefore explicitly specified value will be ignored.\"\n                },\n                \"outerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The outer radius in pixels of arc marks. `outerRadius` is an alias for `radius`.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"padAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The angular padding applied to sides of the arc, in radians.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"radius\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"For arc mark, the primary (outer) radius in pixels.\\n\\nFor text marks, polar coordinate radial offset, in pixels, of the text from the origin determined by the `x` and `y` properties.\\n\\n__Default value:__ `min(plot_width, plot_height)/2`\",\n                    \"minimum\": 0\n                },\n                \"radius2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The secondary (inner) radius in pixels of arc marks.\\n\\n__Default value:__ `0`\",\n                    \"minimum\": 0\n                },\n                \"shape\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/SymbolShape\"\n                                },\n                                {\n                                    \"type\": \"string\"\n                                }\n                            ],\n                            \"description\": \"Shape of the point marks. Supported values include:\\n- plotting shapes: `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"cross\\\"`, `\\\"diamond\\\"`, `\\\"triangle-up\\\"`, `\\\"triangle-down\\\"`, `\\\"triangle-right\\\"`, or `\\\"triangle-left\\\"`.\\n- the line symbol `\\\"stroke\\\"`\\n- centered directional shapes `\\\"arrow\\\"`, `\\\"wedge\\\"`, or `\\\"triangle\\\"`\\n- a custom [SVG path string](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths) (For correct sizing, custom shape paths should be defined within a square bounding box with coordinates ranging from -1 to 1 along both the x and y dimensions.)\\n\\n__Default value:__ `\\\"circle\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"size\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default size for marks.\\n- For `point`/`circle`/`square`, this represents the pixel area of the marks. Note that this value sets the area of the symbol; the side lengths will increase with the square root of this value.\\n- For `bar`, this represents the band size of the bar, in pixels.\\n- For `text`, this represents the font size, in pixels.\\n\\n__Default value:__\\n- `30` for point, circle, square marks; width/height's `step`\\n- `2` for bar marks with discrete dimensions;\\n- `5` for bar marks with continuous dimensions;\\n- `11` for text marks.\",\n                    \"minimum\": 0\n                },\n                \"smooth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag (default true) indicating if the image should be smoothed when resized. If false, individual pixels should be scaled directly rather than interpolated with smoothing. For SVG rendering, this option may not work in some browsers due to lack of standardization.\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"startAngle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The start angle in radians for arc marks. A value of `0` indicates up (north), increasing values proceed clockwise.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"stroke\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Default stroke color. This property has higher precedence than `config.color`. Set to `null` to remove stroke.\\n\\n__Default value:__ (None)\"\n                },\n                \"strokeCap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeCap\",\n                            \"description\": \"The stroke cap for line ending style. One of `\\\"butt\\\"`, `\\\"round\\\"`, or `\\\"square\\\"`.\\n\\n__Default value:__ `\\\"butt\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating stroke, space lengths for creating dashed or dotted lines.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset (in pixels) into which to begin drawing with the stroke dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeJoin\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeJoin\",\n                            \"description\": \"The stroke line join method. One of `\\\"miter\\\"`, `\\\"round\\\"` or `\\\"bevel\\\"`.\\n\\n__Default value:__ `\\\"miter\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeMiterLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The miter limit at which to bevel a line join.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset in pixels at which to draw the group stroke and fill. If unspecified, the default behavior is to dynamically offset stroked groups such that 1 pixel stroke widths align with the pixel grid.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke width, in pixels.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"tension\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Depending on the interpolation type, sets the tension parameter (for line and area marks).\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"text\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\",\n                            \"description\": \"Placeholder text if the `text` channel is not specified\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"theta\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"- For arc marks, the arc length in radians if theta2 is not specified, otherwise the start arc angle. (A value of 0 indicates up or “north”, increasing values proceed clockwise.)\\n\\n- For text marks, polar coordinate angle in radians.\",\n                    \"maximum\": 360,\n                    \"minimum\": 0\n                },\n                \"theta2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The end angle of arc marks in radians. A value of 0 indicates up or “north”, increasing values proceed clockwise.\"\n                },\n                \"thickness\": {\n                    \"description\": \"Thickness of the tick mark.\\n\\n__Default value:__  `1`\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"time\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"timeUnitBandPosition\": {\n                    \"description\": \"Default relative band position for a time unit. If set to `0`, the marks will be positioned at the beginning of the time unit band step. If set to `0.5`, the marks will be positioned in the middle of the time unit band step.\",\n                    \"type\": \"number\"\n                },\n                \"timeUnitBandSize\": {\n                    \"description\": \"Default relative band size for a time unit. If set to `1`, the bandwidth of the marks will be equal to the time unit band step. If set to `0.5`, bandwidth of the marks will be half of the time unit band step.\",\n                    \"type\": \"number\"\n                },\n                \"tooltip\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TooltipContent\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"The tooltip text string to show upon mouse hover or an object defining which fields should the tooltip be derived from.\\n\\n- If `tooltip` is `true` or `{\\\"content\\\": \\\"encoding\\\"}`, then all fields from `encoding` will be used.\\n- If `tooltip` is `{\\\"content\\\": \\\"data\\\"}`, then all fields that appear in the highlighted data point will be used.\\n- If set to `null` or `false`, then no tooltip will be used.\\n\\nSee the [`tooltip`](https://vega.github.io/vega-lite/docs/tooltip.html) documentation for a detailed discussion about tooltip  in Vega-Lite.\\n\\n__Default value:__ `null`\"\n                },\n                \"url\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/URI\",\n                            \"description\": \"The URL of the image file for image marks.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"width\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Width of the marks.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"x\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"X coordinates of the marks, or width of horizontal `\\\"bar\\\"` and `\\\"area\\\"` without specified `x2` or `width`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"x2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"X2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"width\\\"` for the width of the plot.\"\n                },\n                \"y\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Y coordinates of the marks, or height of vertical `\\\"bar\\\"` and `\\\"area\\\"` without specified `y2` or `height`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                },\n                \"y2\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"Y2 coordinates for ranged `\\\"area\\\"`, `\\\"bar\\\"`, `\\\"rect\\\"`, and  `\\\"rule\\\"`.\\n\\nThe `value` of this channel can be a number or a string `\\\"height\\\"` for the height of the plot.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"TickCount\": {\n            \"anyOf\": [\n                {\n                    \"type\": \"number\"\n                },\n                {\n                    \"$ref\": \"#/definitions/TimeInterval\"\n                },\n                {\n                    \"$ref\": \"#/definitions/TimeIntervalStep\"\n                }\n            ]\n        },\n        \"TimeDef\": {\n            \"$ref\": \"#/definitions/TimeFieldDef\"\n        },\n        \"TimeFieldDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"rescale\": {\n                    \"type\": \"boolean\"\n                },\n                \"scale\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Scale\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object defining properties of the channel's scale, which is the function that transforms values in the data domain (numbers, dates, strings, etc) to visual values (pixels, colors, sizes) of the encoding channels.\\n\\nIf `null`, the scale will be [disabled and the data value will be directly encoded](https://vega.github.io/vega-lite/docs/scale.html#disable).\\n\\n__Default value:__ If undefined, default [scale properties](https://vega.github.io/vega-lite/docs/scale.html) are applied.\\n\\n__See also:__ [`scale`](https://vega.github.io/vega-lite/docs/scale.html) documentation.\"\n                },\n                \"sort\": {\n                    \"$ref\": \"#/definitions/Sort\",\n                    \"description\": \"Sort order for the encoded field.\\n\\nFor continuous fields (quantitative or temporal), `sort` can be either `\\\"ascending\\\"` or `\\\"descending\\\"`.\\n\\nFor discrete fields, `sort` can be one of the following:\\n- `\\\"ascending\\\"` or `\\\"descending\\\"` -- for sorting by the values' natural order in JavaScript.\\n- [A string indicating an encoding channel name to sort by](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding) (e.g., `\\\"x\\\"` or `\\\"y\\\"`) with an optional minus prefix for descending sort (e.g., `\\\"-x\\\"` to sort by x-field, descending). This channel string is short-form of [a sort-by-encoding definition](https://vega.github.io/vega-lite/docs/sort.html#sort-by-encoding). For example, `\\\"sort\\\": \\\"-x\\\"` is equivalent to `\\\"sort\\\": {\\\"encoding\\\": \\\"x\\\", \\\"order\\\": \\\"descending\\\"}`.\\n- [A sort field definition](https://vega.github.io/vega-lite/docs/sort.html#sort-field) for sorting by another field.\\n- [An array specifying the field values in preferred order](https://vega.github.io/vega-lite/docs/sort.html#sort-array). In this case, the sort order will obey the values in the array, followed by any unspecified values in their original order. For discrete time field, values in the sort array can be [date-time definition objects](types#datetime). In addition, for time units `\\\"month\\\"` and `\\\"day\\\"`, the values can be the month or day names (case insensitive) or their 3-letter initials (e.g., `\\\"Mon\\\"`, `\\\"Tue\\\"`).\\n- `null` indicating no sort.\\n\\n__Default value:__ `\\\"ascending\\\"`\\n\\n__Note:__ `null` and sorting by another channel is not supported for `row` and `column`.\\n\\n__See also:__ [`sort`](https://vega.github.io/vega-lite/docs/sort.html) documentation.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/StandardType\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"TimeInterval\": {\n            \"enum\": [\n                \"millisecond\",\n                \"second\",\n                \"minute\",\n                \"hour\",\n                \"day\",\n                \"week\",\n                \"month\",\n                \"year\"\n            ],\n            \"type\": \"string\"\n        },\n        \"TimeIntervalStep\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"interval\": {\n                    \"$ref\": \"#/definitions/TimeInterval\"\n                },\n                \"step\": {\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"interval\",\n                \"step\"\n            ],\n            \"type\": \"object\"\n        },\n        \"TimeLocale\": {\n            \"additionalProperties\": false,\n            \"description\": \"Locale definition for formatting dates and times.\",\n            \"properties\": {\n                \"date\": {\n                    \"description\": \"The date (%x) format specifier (e.g., \\\"%m/%d/%Y\\\").\",\n                    \"type\": \"string\"\n                },\n                \"dateTime\": {\n                    \"description\": \"The date and time (%c) format specifier (e.g., \\\"%a %b %e %X %Y\\\").\",\n                    \"type\": \"string\"\n                },\n                \"days\": {\n                    \"$ref\": \"#/definitions/Vector7<string>\",\n                    \"description\": \"The full names of the weekdays, starting with Sunday.\"\n                },\n                \"months\": {\n                    \"$ref\": \"#/definitions/Vector12<string>\",\n                    \"description\": \"The full names of the months (starting with January).\"\n                },\n                \"periods\": {\n                    \"$ref\": \"#/definitions/Vector2<string>\",\n                    \"description\": \"The A.M. and P.M. equivalents (e.g., [\\\"AM\\\", \\\"PM\\\"]).\"\n                },\n                \"shortDays\": {\n                    \"$ref\": \"#/definitions/Vector7<string>\",\n                    \"description\": \"The abbreviated names of the weekdays, starting with Sunday.\"\n                },\n                \"shortMonths\": {\n                    \"$ref\": \"#/definitions/Vector12<string>\",\n                    \"description\": \"The abbreviated names of the months (starting with January).\"\n                },\n                \"time\": {\n                    \"description\": \"The time (%X) format specifier (e.g., \\\"%H:%M:%S\\\").\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"dateTime\",\n                \"date\",\n                \"time\",\n                \"periods\",\n                \"days\",\n                \"shortDays\",\n                \"months\",\n                \"shortMonths\"\n            ],\n            \"type\": \"object\"\n        },\n        \"TimeUnit\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/SingleTimeUnit\"\n                },\n                {\n                    \"$ref\": \"#/definitions/MultiTimeUnit\"\n                }\n            ]\n        },\n        \"TimeUnitParams\": {\n            \"additionalProperties\": false,\n            \"description\": \"Time Unit Params for encoding predicate, which can specified if the data is  already \\\"binned\\\".\",\n            \"properties\": {\n                \"binned\": {\n                    \"description\": \"Whether the data has already been binned to this time unit. If true, Vega-Lite will only format the data, marks, and guides, without applying the timeUnit transform to re-bin the data again.\",\n                    \"type\": \"boolean\"\n                },\n                \"maxbins\": {\n                    \"description\": \"If no `unit` is specified, maxbins is used to infer time units.\",\n                    \"type\": \"number\"\n                },\n                \"step\": {\n                    \"description\": \"The number of steps between bins, in terms of the least significant unit provided.\",\n                    \"type\": \"number\"\n                },\n                \"unit\": {\n                    \"$ref\": \"#/definitions/TimeUnit\",\n                    \"description\": \"Defines how date-time values should be binned.\"\n                },\n                \"utc\": {\n                    \"description\": \"True to use UTC timezone. Equivalent to using a `utc` prefixed `TimeUnit`.\",\n                    \"type\": \"boolean\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"TimeUnitTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"as\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The output field to write the timeUnit value.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The data field to apply time unit.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitTransformParams\"\n                        }\n                    ],\n                    \"description\": \"The timeUnit.\"\n                }\n            },\n            \"required\": [\n                \"timeUnit\",\n                \"field\",\n                \"as\"\n            ],\n            \"type\": \"object\"\n        },\n        \"TimeUnitTransformParams\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"maxbins\": {\n                    \"description\": \"If no `unit` is specified, maxbins is used to infer time units.\",\n                    \"type\": \"number\"\n                },\n                \"step\": {\n                    \"description\": \"The number of steps between bins, in terms of the least significant unit provided.\",\n                    \"type\": \"number\"\n                },\n                \"unit\": {\n                    \"$ref\": \"#/definitions/TimeUnit\",\n                    \"description\": \"Defines how date-time values should be binned.\"\n                },\n                \"utc\": {\n                    \"description\": \"True to use UTC timezone. Equivalent to using a `utc` prefixed `TimeUnit`.\",\n                    \"type\": \"boolean\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"TitleAnchor\": {\n            \"enum\": [\n                null,\n                \"start\",\n                \"middle\",\n                \"end\"\n            ],\n            \"type\": [\n                \"null\",\n                \"string\"\n            ]\n        },\n        \"TitleConfig\": {\n            \"$ref\": \"#/definitions/BaseTitleNoValueRefs\"\n        },\n        \"TitleFrame\": {\n            \"enum\": [\n                \"bounds\",\n                \"group\"\n            ],\n            \"type\": \"string\"\n        },\n        \"TitleOrient\": {\n            \"enum\": [\n                \"none\",\n                \"left\",\n                \"right\",\n                \"top\",\n                \"bottom\"\n            ],\n            \"type\": \"string\"\n        },\n        \"TitleParams\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"align\": {\n                    \"$ref\": \"#/definitions/Align\",\n                    \"description\": \"Horizontal text alignment for title text. One of `\\\"left\\\"`, `\\\"center\\\"`, or `\\\"right\\\"`.\"\n                },\n                \"anchor\": {\n                    \"$ref\": \"#/definitions/TitleAnchor\",\n                    \"description\": \"The anchor position for placing the title. One of `\\\"start\\\"`, `\\\"middle\\\"`, or `\\\"end\\\"`. For example, with an orientation of top these anchor positions map to a left-, center-, or right-aligned title.\\n\\n__Default value:__ `\\\"middle\\\"` for [single](https://vega.github.io/vega-lite/docs/spec.html) and [layered](https://vega.github.io/vega-lite/docs/layer.html) views. `\\\"start\\\"` for other composite views.\\n\\n__Note:__ [For now](https://github.com/vega/vega-lite/issues/2875), `anchor` is only customizable only for [single](https://vega.github.io/vega-lite/docs/spec.html) and [layered](https://vega.github.io/vega-lite/docs/layer.html) views. For other composite views, `anchor` is always `\\\"start\\\"`.\"\n                },\n                \"angle\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Angle in degrees of title and subtitle text.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"aria\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"A boolean flag indicating if [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) should be included (SVG output only). If `false`, the \\\"aria-hidden\\\" attribute will be set on the output SVG group, removing the title from the ARIA accessibility tree.\\n\\n__Default value:__ `true`\",\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"baseline\": {\n                    \"$ref\": \"#/definitions/TextBaseline\",\n                    \"description\": \"Vertical text baseline for title and subtitle text. One of `\\\"alphabetic\\\"` (default), `\\\"top\\\"`, `\\\"middle\\\"`, `\\\"bottom\\\"`, `\\\"line-top\\\"`, or `\\\"line-bottom\\\"`. The `\\\"line-top\\\"` and `\\\"line-bottom\\\"` values operate similarly to `\\\"top\\\"` and `\\\"bottom\\\"`, but are calculated relative to the *lineHeight* rather than *fontSize* alone.\"\n                },\n                \"color\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Text color for title text.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dx\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Delta offset for title and subtitle text x-coordinate.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"dy\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Delta offset for title and subtitle text y-coordinate.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"font\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Font name for title text.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Font size in pixels for title text.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"Font style for title text.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"fontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"Font weight for title text. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"frame\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/TitleFrame\"\n                                },\n                                {\n                                    \"type\": \"string\"\n                                }\n                            ],\n                            \"description\": \"The reference frame for the anchor position, one of `\\\"bounds\\\"` (to anchor relative to the full bounding box) or `\\\"group\\\"` (to anchor relative to the group width or height).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"limit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The maximum allowed length in pixels of title and subtitle text.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"lineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Line height in pixels for multi-line title text or title text with `\\\"line-top\\\"` or `\\\"line-bottom\\\"` baseline.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"offset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The orthogonal offset in pixels by which to displace the title group from its position along the edge of the chart.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"orient\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TitleOrient\",\n                            \"description\": \"Default title orientation (`\\\"top\\\"`, `\\\"bottom\\\"`, `\\\"left\\\"`, or `\\\"right\\\"`)\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"style\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"items\": {\n                                \"type\": \"string\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"A [mark style property](https://vega.github.io/vega-lite/docs/config.html#style) to apply to the title text mark.\\n\\n__Default value:__ `\\\"group-title\\\"`.\"\n                },\n                \"subtitle\": {\n                    \"$ref\": \"#/definitions/Text\",\n                    \"description\": \"The subtitle Text.\"\n                },\n                \"subtitleColor\": {\n                    \"anyOf\": [\n                        {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"null\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                }\n                            ],\n                            \"description\": \"Text color for subtitle text.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"subtitleFont\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Font name for subtitle text.\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"subtitleFontSize\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Font size in pixels for subtitle text.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"subtitleFontStyle\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontStyle\",\n                            \"description\": \"Font style for subtitle text.\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"subtitleFontWeight\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FontWeight\",\n                            \"description\": \"Font weight for subtitle text. This can be either a string (e.g `\\\"bold\\\"`, `\\\"normal\\\"`) or a number (`100`, `200`, `300`, ..., `900` where `\\\"normal\\\"` = `400` and `\\\"bold\\\"` = `700`).\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"subtitleLineHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"Line height in pixels for multi-line subtitle text.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"subtitlePadding\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The padding in pixels between title and subtitle text.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"text\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The title text.\"\n                },\n                \"zindex\": {\n                    \"description\": \"The integer z-index indicating the layering of the title group relative to other axis, mark and legend groups.\\n\\n__Default value:__ `0`.\",\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"text\"\n            ],\n            \"type\": \"object\"\n        },\n        \"TooltipContent\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"content\": {\n                    \"enum\": [\n                        \"encoding\",\n                        \"data\"\n                    ],\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"content\"\n            ],\n            \"type\": \"object\"\n        },\n        \"TopLevelConcatSpec\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"$schema\": {\n                    \"description\": \"URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you have a reason to change this, use `https://vega.github.io/schema/vega-lite/v5.json`. Setting the `$schema` property allows automatic validation and autocomplete in editors that support JSON schema.\",\n                    \"format\": \"uri\",\n                    \"type\": \"string\"\n                },\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LayoutAlign\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<LayoutAlign>\"\n                        }\n                    ],\n                    \"description\": \"The alignment to apply to grid rows and columns. The supported string values are `\\\"all\\\"`, `\\\"each\\\"`, and `\\\"none\\\"`.\\n\\n- For `\\\"none\\\"`, a flow layout will be used, in which adjacent subviews are simply placed one after the other.\\n- For `\\\"each\\\"`, subviews will be aligned into a clean grid structure, but each row or column may be of variable size.\\n- For `\\\"all\\\"`, subviews will be aligned and each row or column will be sized identically based on the maximum observed size. String values for this property will be applied to both grid rows and columns.\\n\\nAlternatively, an object value of the form `{\\\"row\\\": string, \\\"column\\\": string}` can be used to supply different alignments for rows and columns.\\n\\n__Default value:__ `\\\"all\\\"`.\"\n                },\n                \"autosize\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/AutosizeType\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AutoSizeParams\"\n                        }\n                    ],\n                    \"description\": \"How the visualization size should be determined. If a string, should be one of `\\\"pad\\\"`, `\\\"fit\\\"` or `\\\"none\\\"`. Object values can additionally specify parameters for content sizing and automatic resizing.\\n\\n__Default value__: `pad`\"\n                },\n                \"background\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"CSS color property to use as the background of the entire view.\\n\\n__Default value:__ `\\\"white\\\"`\"\n                },\n                \"bounds\": {\n                    \"description\": \"The bounds calculation method to use for determining the extent of a sub-plot. One of `full` (the default) or `flush`.\\n\\n- If set to `full`, the entire calculated bounds (including axes, title, and legend) will be used.\\n- If set to `flush`, only the specified width and height values for the sub-view will be used. The `flush` setting can be useful when attempting to place sub-plots without axes or legends into a uniform grid structure.\\n\\n__Default value:__ `\\\"full\\\"`\",\n                    \"enum\": [\n                        \"full\",\n                        \"flush\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"center\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<boolean>\"\n                        }\n                    ],\n                    \"description\": \"Boolean flag indicating if subviews should be centered relative to their respective rows or columns.\\n\\nAn object value of the form `{\\\"row\\\": boolean, \\\"column\\\": boolean}` can be used to supply different centering values for rows and columns.\\n\\n__Default value:__ `false`\"\n                },\n                \"columns\": {\n                    \"description\": \"The number of columns to include in the view composition layout.\\n\\n__Default value__: `undefined` -- An infinite number of columns (a single row) will be assumed. This is equivalent to `hconcat` (for `concat`) and to using the `column` channel (for `facet` and `repeat`).\\n\\n__Note__:\\n\\n1) This property is only for:\\n- the general (wrappable) `concat` operator (not `hconcat`/`vconcat`)\\n- the `facet` and `repeat` operator with one field/repetition definition (without row/column nesting)\\n\\n2) Setting the `columns` to `1` is equivalent to `vconcat` (for `concat`) and to using the `row` channel (for `facet` and `repeat`).\",\n                    \"type\": \"number\"\n                },\n                \"concat\": {\n                    \"description\": \"A list of views to be concatenated.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/NonNormalizedSpec\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"config\": {\n                    \"$ref\": \"#/definitions/Config\",\n                    \"description\": \"Vega-Lite configuration object. This property can only be defined at the top-level of a specification.\"\n                },\n                \"data\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Data\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                },\n                \"datasets\": {\n                    \"$ref\": \"#/definitions/Datasets\",\n                    \"description\": \"A global data store for named datasets. This is a mapping from names to inline datasets. This can be an array of objects or primitive values or a string. Arrays of primitive values are ingested as objects with a `data` property.\"\n                },\n                \"description\": {\n                    \"description\": \"Description of this mark for commenting purpose.\",\n                    \"type\": \"string\"\n                },\n                \"name\": {\n                    \"description\": \"Name of the visualization for later reference.\",\n                    \"type\": \"string\"\n                },\n                \"padding\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Padding\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The default visualization padding, in pixels, from the edge of the visualization canvas to the data rectangle. If a number, specifies padding for all sides. If an object, the value should have the format `{\\\"left\\\": 5, \\\"top\\\": 5, \\\"right\\\": 5, \\\"bottom\\\": 5}` to specify padding for each side of the visualization.\\n\\n__Default value__: `5`\"\n                },\n                \"params\": {\n                    \"description\": \"Dynamic variables or selections that parameterize a visualization.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/TopLevelParameter\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/Resolve\",\n                    \"description\": \"Scale, axis, and legend resolutions for view composition specifications.\"\n                },\n                \"spacing\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<number>\"\n                        }\n                    ],\n                    \"description\": \"The spacing in pixels between sub-views of the composition operator. An object of the form `{\\\"row\\\": number, \\\"column\\\": number}` can be used to set different spacing values for rows and columns.\\n\\n__Default value__: Depends on `\\\"spacing\\\"` property of [the view composition configuration](https://vega.github.io/vega-lite/docs/config.html#view-config) (`20` by default)\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TitleParams\"\n                        }\n                    ],\n                    \"description\": \"Title for the plot.\"\n                },\n                \"transform\": {\n                    \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Transform\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"usermeta\": {\n                    \"$ref\": \"#/definitions/Dict\",\n                    \"description\": \"Optional metadata that will be passed to Vega. This object is completely ignored by Vega and Vega-Lite and can be used for custom metadata.\"\n                }\n            },\n            \"required\": [\n                \"concat\"\n            ],\n            \"type\": \"object\"\n        },\n        \"TopLevelHConcatSpec\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"$schema\": {\n                    \"description\": \"URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you have a reason to change this, use `https://vega.github.io/schema/vega-lite/v5.json`. Setting the `$schema` property allows automatic validation and autocomplete in editors that support JSON schema.\",\n                    \"format\": \"uri\",\n                    \"type\": \"string\"\n                },\n                \"autosize\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/AutosizeType\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AutoSizeParams\"\n                        }\n                    ],\n                    \"description\": \"How the visualization size should be determined. If a string, should be one of `\\\"pad\\\"`, `\\\"fit\\\"` or `\\\"none\\\"`. Object values can additionally specify parameters for content sizing and automatic resizing.\\n\\n__Default value__: `pad`\"\n                },\n                \"background\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"CSS color property to use as the background of the entire view.\\n\\n__Default value:__ `\\\"white\\\"`\"\n                },\n                \"bounds\": {\n                    \"description\": \"The bounds calculation method to use for determining the extent of a sub-plot. One of `full` (the default) or `flush`.\\n\\n- If set to `full`, the entire calculated bounds (including axes, title, and legend) will be used.\\n- If set to `flush`, only the specified width and height values for the sub-view will be used. The `flush` setting can be useful when attempting to place sub-plots without axes or legends into a uniform grid structure.\\n\\n__Default value:__ `\\\"full\\\"`\",\n                    \"enum\": [\n                        \"full\",\n                        \"flush\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"center\": {\n                    \"description\": \"Boolean flag indicating if subviews should be centered relative to their respective rows or columns.\\n\\n__Default value:__ `false`\",\n                    \"type\": \"boolean\"\n                },\n                \"config\": {\n                    \"$ref\": \"#/definitions/Config\",\n                    \"description\": \"Vega-Lite configuration object. This property can only be defined at the top-level of a specification.\"\n                },\n                \"data\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Data\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                },\n                \"datasets\": {\n                    \"$ref\": \"#/definitions/Datasets\",\n                    \"description\": \"A global data store for named datasets. This is a mapping from names to inline datasets. This can be an array of objects or primitive values or a string. Arrays of primitive values are ingested as objects with a `data` property.\"\n                },\n                \"description\": {\n                    \"description\": \"Description of this mark for commenting purpose.\",\n                    \"type\": \"string\"\n                },\n                \"hconcat\": {\n                    \"description\": \"A list of views to be concatenated and put into a row.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/NonNormalizedSpec\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"name\": {\n                    \"description\": \"Name of the visualization for later reference.\",\n                    \"type\": \"string\"\n                },\n                \"padding\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Padding\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The default visualization padding, in pixels, from the edge of the visualization canvas to the data rectangle. If a number, specifies padding for all sides. If an object, the value should have the format `{\\\"left\\\": 5, \\\"top\\\": 5, \\\"right\\\": 5, \\\"bottom\\\": 5}` to specify padding for each side of the visualization.\\n\\n__Default value__: `5`\"\n                },\n                \"params\": {\n                    \"description\": \"Dynamic variables or selections that parameterize a visualization.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/TopLevelParameter\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/Resolve\",\n                    \"description\": \"Scale, axis, and legend resolutions for view composition specifications.\"\n                },\n                \"spacing\": {\n                    \"description\": \"The spacing in pixels between sub-views of the concat operator.\\n\\n__Default value__: `10`\",\n                    \"type\": \"number\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TitleParams\"\n                        }\n                    ],\n                    \"description\": \"Title for the plot.\"\n                },\n                \"transform\": {\n                    \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Transform\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"usermeta\": {\n                    \"$ref\": \"#/definitions/Dict\",\n                    \"description\": \"Optional metadata that will be passed to Vega. This object is completely ignored by Vega and Vega-Lite and can be used for custom metadata.\"\n                }\n            },\n            \"required\": [\n                \"hconcat\"\n            ],\n            \"type\": \"object\"\n        },\n        \"TopLevelVConcatSpec\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"$schema\": {\n                    \"description\": \"URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you have a reason to change this, use `https://vega.github.io/schema/vega-lite/v5.json`. Setting the `$schema` property allows automatic validation and autocomplete in editors that support JSON schema.\",\n                    \"format\": \"uri\",\n                    \"type\": \"string\"\n                },\n                \"autosize\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/AutosizeType\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AutoSizeParams\"\n                        }\n                    ],\n                    \"description\": \"How the visualization size should be determined. If a string, should be one of `\\\"pad\\\"`, `\\\"fit\\\"` or `\\\"none\\\"`. Object values can additionally specify parameters for content sizing and automatic resizing.\\n\\n__Default value__: `pad`\"\n                },\n                \"background\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"CSS color property to use as the background of the entire view.\\n\\n__Default value:__ `\\\"white\\\"`\"\n                },\n                \"bounds\": {\n                    \"description\": \"The bounds calculation method to use for determining the extent of a sub-plot. One of `full` (the default) or `flush`.\\n\\n- If set to `full`, the entire calculated bounds (including axes, title, and legend) will be used.\\n- If set to `flush`, only the specified width and height values for the sub-view will be used. The `flush` setting can be useful when attempting to place sub-plots without axes or legends into a uniform grid structure.\\n\\n__Default value:__ `\\\"full\\\"`\",\n                    \"enum\": [\n                        \"full\",\n                        \"flush\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"center\": {\n                    \"description\": \"Boolean flag indicating if subviews should be centered relative to their respective rows or columns.\\n\\n__Default value:__ `false`\",\n                    \"type\": \"boolean\"\n                },\n                \"config\": {\n                    \"$ref\": \"#/definitions/Config\",\n                    \"description\": \"Vega-Lite configuration object. This property can only be defined at the top-level of a specification.\"\n                },\n                \"data\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Data\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                },\n                \"datasets\": {\n                    \"$ref\": \"#/definitions/Datasets\",\n                    \"description\": \"A global data store for named datasets. This is a mapping from names to inline datasets. This can be an array of objects or primitive values or a string. Arrays of primitive values are ingested as objects with a `data` property.\"\n                },\n                \"description\": {\n                    \"description\": \"Description of this mark for commenting purpose.\",\n                    \"type\": \"string\"\n                },\n                \"name\": {\n                    \"description\": \"Name of the visualization for later reference.\",\n                    \"type\": \"string\"\n                },\n                \"padding\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Padding\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The default visualization padding, in pixels, from the edge of the visualization canvas to the data rectangle. If a number, specifies padding for all sides. If an object, the value should have the format `{\\\"left\\\": 5, \\\"top\\\": 5, \\\"right\\\": 5, \\\"bottom\\\": 5}` to specify padding for each side of the visualization.\\n\\n__Default value__: `5`\"\n                },\n                \"params\": {\n                    \"description\": \"Dynamic variables or selections that parameterize a visualization.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/TopLevelParameter\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/Resolve\",\n                    \"description\": \"Scale, axis, and legend resolutions for view composition specifications.\"\n                },\n                \"spacing\": {\n                    \"description\": \"The spacing in pixels between sub-views of the concat operator.\\n\\n__Default value__: `10`\",\n                    \"type\": \"number\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TitleParams\"\n                        }\n                    ],\n                    \"description\": \"Title for the plot.\"\n                },\n                \"transform\": {\n                    \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Transform\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"usermeta\": {\n                    \"$ref\": \"#/definitions/Dict\",\n                    \"description\": \"Optional metadata that will be passed to Vega. This object is completely ignored by Vega and Vega-Lite and can be used for custom metadata.\"\n                },\n                \"vconcat\": {\n                    \"description\": \"A list of views to be concatenated and put into a column.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/NonNormalizedSpec\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"vconcat\"\n            ],\n            \"type\": \"object\"\n        },\n        \"TopLevelLayerSpec\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"$schema\": {\n                    \"description\": \"URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you have a reason to change this, use `https://vega.github.io/schema/vega-lite/v5.json`. Setting the `$schema` property allows automatic validation and autocomplete in editors that support JSON schema.\",\n                    \"format\": \"uri\",\n                    \"type\": \"string\"\n                },\n                \"autosize\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/AutosizeType\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AutoSizeParams\"\n                        }\n                    ],\n                    \"description\": \"How the visualization size should be determined. If a string, should be one of `\\\"pad\\\"`, `\\\"fit\\\"` or `\\\"none\\\"`. Object values can additionally specify parameters for content sizing and automatic resizing.\\n\\n__Default value__: `pad`\"\n                },\n                \"background\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"CSS color property to use as the background of the entire view.\\n\\n__Default value:__ `\\\"white\\\"`\"\n                },\n                \"config\": {\n                    \"$ref\": \"#/definitions/Config\",\n                    \"description\": \"Vega-Lite configuration object. This property can only be defined at the top-level of a specification.\"\n                },\n                \"data\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Data\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                },\n                \"datasets\": {\n                    \"$ref\": \"#/definitions/Datasets\",\n                    \"description\": \"A global data store for named datasets. This is a mapping from names to inline datasets. This can be an array of objects or primitive values or a string. Arrays of primitive values are ingested as objects with a `data` property.\"\n                },\n                \"description\": {\n                    \"description\": \"Description of this mark for commenting purpose.\",\n                    \"type\": \"string\"\n                },\n                \"encoding\": {\n                    \"$ref\": \"#/definitions/SharedEncoding\",\n                    \"description\": \"A shared key-value mapping between encoding channels and definition of fields in the underlying layers.\"\n                },\n                \"height\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"container\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Step\"\n                        }\n                    ],\n                    \"description\": \"The height of a visualization.\\n\\n- For a plot with a continuous y-field, height should be a number.\\n- For a plot with either a discrete y-field or no y-field, height can be either a number indicating a fixed height or an object in the form of `{step: number}` defining the height per discrete step. (No y-field is equivalent to having one discrete step.)\\n- To enable responsive sizing on height, it should be set to `\\\"container\\\"`.\\n\\n__Default value:__ Based on `config.view.continuousHeight` for a plot with a continuous y-field and `config.view.discreteHeight` otherwise.\\n\\n__Note:__ For plots with [`row` and `column` channels](https://vega.github.io/vega-lite/docs/encoding.html#facet), this represents the height of a single view and the `\\\"container\\\"` option cannot be used.\\n\\n__See also:__ [`height`](https://vega.github.io/vega-lite/docs/size.html) documentation.\"\n                },\n                \"layer\": {\n                    \"description\": \"Layer or single view specifications to be layered.\\n\\n__Note__: Specifications inside `layer` cannot use `row` and `column` channels as layering facet specifications is not allowed. Instead, use the [facet operator](https://vega.github.io/vega-lite/docs/facet.html) and place a layer inside a facet.\",\n                    \"items\": {\n                        \"anyOf\": [\n                            {\n                                \"$ref\": \"#/definitions/LayerSpec\"\n                            },\n                            {\n                                \"$ref\": \"#/definitions/UnitSpec\"\n                            }\n                        ]\n                    },\n                    \"type\": \"array\"\n                },\n                \"name\": {\n                    \"description\": \"Name of the visualization for later reference.\",\n                    \"type\": \"string\"\n                },\n                \"padding\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Padding\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The default visualization padding, in pixels, from the edge of the visualization canvas to the data rectangle. If a number, specifies padding for all sides. If an object, the value should have the format `{\\\"left\\\": 5, \\\"top\\\": 5, \\\"right\\\": 5, \\\"bottom\\\": 5}` to specify padding for each side of the visualization.\\n\\n__Default value__: `5`\"\n                },\n                \"params\": {\n                    \"description\": \"Dynamic variables or selections that parameterize a visualization.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/TopLevelParameter\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"projection\": {\n                    \"$ref\": \"#/definitions/Projection\",\n                    \"description\": \"An object defining properties of the geographic projection shared by underlying layers.\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/Resolve\",\n                    \"description\": \"Scale, axis, and legend resolutions for view composition specifications.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TitleParams\"\n                        }\n                    ],\n                    \"description\": \"Title for the plot.\"\n                },\n                \"transform\": {\n                    \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Transform\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"usermeta\": {\n                    \"$ref\": \"#/definitions/Dict\",\n                    \"description\": \"Optional metadata that will be passed to Vega. This object is completely ignored by Vega and Vega-Lite and can be used for custom metadata.\"\n                },\n                \"view\": {\n                    \"$ref\": \"#/definitions/ViewBackground\",\n                    \"description\": \"An object defining the view background's fill and stroke.\\n\\n__Default value:__ none (transparent)\"\n                },\n                \"width\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"container\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Step\"\n                        }\n                    ],\n                    \"description\": \"The width of a visualization.\\n\\n- For a plot with a continuous x-field, width should be a number.\\n- For a plot with either a discrete x-field or no x-field, width can be either a number indicating a fixed width or an object in the form of `{step: number}` defining the width per discrete step. (No x-field is equivalent to having one discrete step.)\\n- To enable responsive sizing on width, it should be set to `\\\"container\\\"`.\\n\\n__Default value:__ Based on `config.view.continuousWidth` for a plot with a continuous x-field and `config.view.discreteWidth` otherwise.\\n\\n__Note:__ For plots with [`row` and `column` channels](https://vega.github.io/vega-lite/docs/encoding.html#facet), this represents the width of a single view and the `\\\"container\\\"` option cannot be used.\\n\\n__See also:__ [`width`](https://vega.github.io/vega-lite/docs/size.html) documentation.\"\n                }\n            },\n            \"required\": [\n                \"layer\"\n            ],\n            \"type\": \"object\"\n        },\n        \"TopLevelRepeatSpec\": {\n            \"anyOf\": [\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"$schema\": {\n                            \"description\": \"URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you have a reason to change this, use `https://vega.github.io/schema/vega-lite/v5.json`. Setting the `$schema` property allows automatic validation and autocomplete in editors that support JSON schema.\",\n                            \"format\": \"uri\",\n                            \"type\": \"string\"\n                        },\n                        \"align\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/LayoutAlign\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RowCol<LayoutAlign>\"\n                                }\n                            ],\n                            \"description\": \"The alignment to apply to grid rows and columns. The supported string values are `\\\"all\\\"`, `\\\"each\\\"`, and `\\\"none\\\"`.\\n\\n- For `\\\"none\\\"`, a flow layout will be used, in which adjacent subviews are simply placed one after the other.\\n- For `\\\"each\\\"`, subviews will be aligned into a clean grid structure, but each row or column may be of variable size.\\n- For `\\\"all\\\"`, subviews will be aligned and each row or column will be sized identically based on the maximum observed size. String values for this property will be applied to both grid rows and columns.\\n\\nAlternatively, an object value of the form `{\\\"row\\\": string, \\\"column\\\": string}` can be used to supply different alignments for rows and columns.\\n\\n__Default value:__ `\\\"all\\\"`.\"\n                        },\n                        \"autosize\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/AutosizeType\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/AutoSizeParams\"\n                                }\n                            ],\n                            \"description\": \"How the visualization size should be determined. If a string, should be one of `\\\"pad\\\"`, `\\\"fit\\\"` or `\\\"none\\\"`. Object values can additionally specify parameters for content sizing and automatic resizing.\\n\\n__Default value__: `pad`\"\n                        },\n                        \"background\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"CSS color property to use as the background of the entire view.\\n\\n__Default value:__ `\\\"white\\\"`\"\n                        },\n                        \"bounds\": {\n                            \"description\": \"The bounds calculation method to use for determining the extent of a sub-plot. One of `full` (the default) or `flush`.\\n\\n- If set to `full`, the entire calculated bounds (including axes, title, and legend) will be used.\\n- If set to `flush`, only the specified width and height values for the sub-view will be used. The `flush` setting can be useful when attempting to place sub-plots without axes or legends into a uniform grid structure.\\n\\n__Default value:__ `\\\"full\\\"`\",\n                            \"enum\": [\n                                \"full\",\n                                \"flush\"\n                            ],\n                            \"type\": \"string\"\n                        },\n                        \"center\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RowCol<boolean>\"\n                                }\n                            ],\n                            \"description\": \"Boolean flag indicating if subviews should be centered relative to their respective rows or columns.\\n\\nAn object value of the form `{\\\"row\\\": boolean, \\\"column\\\": boolean}` can be used to supply different centering values for rows and columns.\\n\\n__Default value:__ `false`\"\n                        },\n                        \"columns\": {\n                            \"description\": \"The number of columns to include in the view composition layout.\\n\\n__Default value__: `undefined` -- An infinite number of columns (a single row) will be assumed. This is equivalent to `hconcat` (for `concat`) and to using the `column` channel (for `facet` and `repeat`).\\n\\n__Note__:\\n\\n1) This property is only for:\\n- the general (wrappable) `concat` operator (not `hconcat`/`vconcat`)\\n- the `facet` and `repeat` operator with one field/repetition definition (without row/column nesting)\\n\\n2) Setting the `columns` to `1` is equivalent to `vconcat` (for `concat`) and to using the `row` channel (for `facet` and `repeat`).\",\n                            \"type\": \"number\"\n                        },\n                        \"config\": {\n                            \"$ref\": \"#/definitions/Config\",\n                            \"description\": \"Vega-Lite configuration object. This property can only be defined at the top-level of a specification.\"\n                        },\n                        \"data\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Data\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                        },\n                        \"datasets\": {\n                            \"$ref\": \"#/definitions/Datasets\",\n                            \"description\": \"A global data store for named datasets. This is a mapping from names to inline datasets. This can be an array of objects or primitive values or a string. Arrays of primitive values are ingested as objects with a `data` property.\"\n                        },\n                        \"description\": {\n                            \"description\": \"Description of this mark for commenting purpose.\",\n                            \"type\": \"string\"\n                        },\n                        \"name\": {\n                            \"description\": \"Name of the visualization for later reference.\",\n                            \"type\": \"string\"\n                        },\n                        \"padding\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Padding\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"The default visualization padding, in pixels, from the edge of the visualization canvas to the data rectangle. If a number, specifies padding for all sides. If an object, the value should have the format `{\\\"left\\\": 5, \\\"top\\\": 5, \\\"right\\\": 5, \\\"bottom\\\": 5}` to specify padding for each side of the visualization.\\n\\n__Default value__: `5`\"\n                        },\n                        \"params\": {\n                            \"description\": \"Dynamic variables or selections that parameterize a visualization.\",\n                            \"items\": {\n                                \"$ref\": \"#/definitions/TopLevelParameter\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        \"repeat\": {\n                            \"anyOf\": [\n                                {\n                                    \"items\": {\n                                        \"type\": \"string\"\n                                    },\n                                    \"type\": \"array\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RepeatMapping\"\n                                }\n                            ],\n                            \"description\": \"Definition for fields to be repeated. One of: 1) An array of fields to be repeated. If `\\\"repeat\\\"` is an array, the field can be referred to as `{\\\"repeat\\\": \\\"repeat\\\"}`. The repeated views are laid out in a wrapped row. You can set the number of columns to control the wrapping. 2) An object that maps `\\\"row\\\"` and/or `\\\"column\\\"` to the listed fields to be repeated along the particular orientations. The objects `{\\\"repeat\\\": \\\"row\\\"}` and `{\\\"repeat\\\": \\\"column\\\"}` can be used to refer to the repeated field respectively.\"\n                        },\n                        \"resolve\": {\n                            \"$ref\": \"#/definitions/Resolve\",\n                            \"description\": \"Scale, axis, and legend resolutions for view composition specifications.\"\n                        },\n                        \"spacing\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RowCol<number>\"\n                                }\n                            ],\n                            \"description\": \"The spacing in pixels between sub-views of the composition operator. An object of the form `{\\\"row\\\": number, \\\"column\\\": number}` can be used to set different spacing values for rows and columns.\\n\\n__Default value__: Depends on `\\\"spacing\\\"` property of [the view composition configuration](https://vega.github.io/vega-lite/docs/config.html#view-config) (`20` by default)\"\n                        },\n                        \"spec\": {\n                            \"$ref\": \"#/definitions/NonNormalizedSpec\",\n                            \"description\": \"A specification of the view that gets repeated.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TitleParams\"\n                                }\n                            ],\n                            \"description\": \"Title for the plot.\"\n                        },\n                        \"transform\": {\n                            \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                            \"items\": {\n                                \"$ref\": \"#/definitions/Transform\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        \"usermeta\": {\n                            \"$ref\": \"#/definitions/Dict\",\n                            \"description\": \"Optional metadata that will be passed to Vega. This object is completely ignored by Vega and Vega-Lite and can be used for custom metadata.\"\n                        }\n                    },\n                    \"required\": [\n                        \"repeat\",\n                        \"spec\"\n                    ],\n                    \"type\": \"object\"\n                },\n                {\n                    \"additionalProperties\": false,\n                    \"properties\": {\n                        \"$schema\": {\n                            \"description\": \"URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you have a reason to change this, use `https://vega.github.io/schema/vega-lite/v5.json`. Setting the `$schema` property allows automatic validation and autocomplete in editors that support JSON schema.\",\n                            \"format\": \"uri\",\n                            \"type\": \"string\"\n                        },\n                        \"align\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/LayoutAlign\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RowCol<LayoutAlign>\"\n                                }\n                            ],\n                            \"description\": \"The alignment to apply to grid rows and columns. The supported string values are `\\\"all\\\"`, `\\\"each\\\"`, and `\\\"none\\\"`.\\n\\n- For `\\\"none\\\"`, a flow layout will be used, in which adjacent subviews are simply placed one after the other.\\n- For `\\\"each\\\"`, subviews will be aligned into a clean grid structure, but each row or column may be of variable size.\\n- For `\\\"all\\\"`, subviews will be aligned and each row or column will be sized identically based on the maximum observed size. String values for this property will be applied to both grid rows and columns.\\n\\nAlternatively, an object value of the form `{\\\"row\\\": string, \\\"column\\\": string}` can be used to supply different alignments for rows and columns.\\n\\n__Default value:__ `\\\"all\\\"`.\"\n                        },\n                        \"autosize\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/AutosizeType\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/AutoSizeParams\"\n                                }\n                            ],\n                            \"description\": \"How the visualization size should be determined. If a string, should be one of `\\\"pad\\\"`, `\\\"fit\\\"` or `\\\"none\\\"`. Object values can additionally specify parameters for content sizing and automatic resizing.\\n\\n__Default value__: `pad`\"\n                        },\n                        \"background\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Color\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"CSS color property to use as the background of the entire view.\\n\\n__Default value:__ `\\\"white\\\"`\"\n                        },\n                        \"bounds\": {\n                            \"description\": \"The bounds calculation method to use for determining the extent of a sub-plot. One of `full` (the default) or `flush`.\\n\\n- If set to `full`, the entire calculated bounds (including axes, title, and legend) will be used.\\n- If set to `flush`, only the specified width and height values for the sub-view will be used. The `flush` setting can be useful when attempting to place sub-plots without axes or legends into a uniform grid structure.\\n\\n__Default value:__ `\\\"full\\\"`\",\n                            \"enum\": [\n                                \"full\",\n                                \"flush\"\n                            ],\n                            \"type\": \"string\"\n                        },\n                        \"center\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"boolean\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RowCol<boolean>\"\n                                }\n                            ],\n                            \"description\": \"Boolean flag indicating if subviews should be centered relative to their respective rows or columns.\\n\\nAn object value of the form `{\\\"row\\\": boolean, \\\"column\\\": boolean}` can be used to supply different centering values for rows and columns.\\n\\n__Default value:__ `false`\"\n                        },\n                        \"columns\": {\n                            \"description\": \"The number of columns to include in the view composition layout.\\n\\n__Default value__: `undefined` -- An infinite number of columns (a single row) will be assumed. This is equivalent to `hconcat` (for `concat`) and to using the `column` channel (for `facet` and `repeat`).\\n\\n__Note__:\\n\\n1) This property is only for:\\n- the general (wrappable) `concat` operator (not `hconcat`/`vconcat`)\\n- the `facet` and `repeat` operator with one field/repetition definition (without row/column nesting)\\n\\n2) Setting the `columns` to `1` is equivalent to `vconcat` (for `concat`) and to using the `row` channel (for `facet` and `repeat`).\",\n                            \"type\": \"number\"\n                        },\n                        \"config\": {\n                            \"$ref\": \"#/definitions/Config\",\n                            \"description\": \"Vega-Lite configuration object. This property can only be defined at the top-level of a specification.\"\n                        },\n                        \"data\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Data\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                        },\n                        \"datasets\": {\n                            \"$ref\": \"#/definitions/Datasets\",\n                            \"description\": \"A global data store for named datasets. This is a mapping from names to inline datasets. This can be an array of objects or primitive values or a string. Arrays of primitive values are ingested as objects with a `data` property.\"\n                        },\n                        \"description\": {\n                            \"description\": \"Description of this mark for commenting purpose.\",\n                            \"type\": \"string\"\n                        },\n                        \"name\": {\n                            \"description\": \"Name of the visualization for later reference.\",\n                            \"type\": \"string\"\n                        },\n                        \"padding\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Padding\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/ExprRef\"\n                                }\n                            ],\n                            \"description\": \"The default visualization padding, in pixels, from the edge of the visualization canvas to the data rectangle. If a number, specifies padding for all sides. If an object, the value should have the format `{\\\"left\\\": 5, \\\"top\\\": 5, \\\"right\\\": 5, \\\"bottom\\\": 5}` to specify padding for each side of the visualization.\\n\\n__Default value__: `5`\"\n                        },\n                        \"params\": {\n                            \"description\": \"Dynamic variables or selections that parameterize a visualization.\",\n                            \"items\": {\n                                \"$ref\": \"#/definitions/TopLevelParameter\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        \"repeat\": {\n                            \"$ref\": \"#/definitions/LayerRepeatMapping\",\n                            \"description\": \"Definition for fields to be repeated. One of: 1) An array of fields to be repeated. If `\\\"repeat\\\"` is an array, the field can be referred to as `{\\\"repeat\\\": \\\"repeat\\\"}`. The repeated views are laid out in a wrapped row. You can set the number of columns to control the wrapping. 2) An object that maps `\\\"row\\\"` and/or `\\\"column\\\"` to the listed fields to be repeated along the particular orientations. The objects `{\\\"repeat\\\": \\\"row\\\"}` and `{\\\"repeat\\\": \\\"column\\\"}` can be used to refer to the repeated field respectively.\"\n                        },\n                        \"resolve\": {\n                            \"$ref\": \"#/definitions/Resolve\",\n                            \"description\": \"Scale, axis, and legend resolutions for view composition specifications.\"\n                        },\n                        \"spacing\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"number\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/RowCol<number>\"\n                                }\n                            ],\n                            \"description\": \"The spacing in pixels between sub-views of the composition operator. An object of the form `{\\\"row\\\": number, \\\"column\\\": number}` can be used to set different spacing values for rows and columns.\\n\\n__Default value__: Depends on `\\\"spacing\\\"` property of [the view composition configuration](https://vega.github.io/vega-lite/docs/config.html#view-config) (`20` by default)\"\n                        },\n                        \"spec\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/LayerSpec\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/UnitSpecWithFrame\"\n                                }\n                            ],\n                            \"description\": \"A specification of the view that gets repeated.\"\n                        },\n                        \"title\": {\n                            \"anyOf\": [\n                                {\n                                    \"$ref\": \"#/definitions/Text\"\n                                },\n                                {\n                                    \"$ref\": \"#/definitions/TitleParams\"\n                                }\n                            ],\n                            \"description\": \"Title for the plot.\"\n                        },\n                        \"transform\": {\n                            \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                            \"items\": {\n                                \"$ref\": \"#/definitions/Transform\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        \"usermeta\": {\n                            \"$ref\": \"#/definitions/Dict\",\n                            \"description\": \"Optional metadata that will be passed to Vega. This object is completely ignored by Vega and Vega-Lite and can be used for custom metadata.\"\n                        }\n                    },\n                    \"required\": [\n                        \"repeat\",\n                        \"spec\"\n                    ],\n                    \"type\": \"object\"\n                }\n            ]\n        },\n        \"TopLevelFacetSpec\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"$schema\": {\n                    \"description\": \"URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you have a reason to change this, use `https://vega.github.io/schema/vega-lite/v5.json`. Setting the `$schema` property allows automatic validation and autocomplete in editors that support JSON schema.\",\n                    \"format\": \"uri\",\n                    \"type\": \"string\"\n                },\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LayoutAlign\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<LayoutAlign>\"\n                        }\n                    ],\n                    \"description\": \"The alignment to apply to grid rows and columns. The supported string values are `\\\"all\\\"`, `\\\"each\\\"`, and `\\\"none\\\"`.\\n\\n- For `\\\"none\\\"`, a flow layout will be used, in which adjacent subviews are simply placed one after the other.\\n- For `\\\"each\\\"`, subviews will be aligned into a clean grid structure, but each row or column may be of variable size.\\n- For `\\\"all\\\"`, subviews will be aligned and each row or column will be sized identically based on the maximum observed size. String values for this property will be applied to both grid rows and columns.\\n\\nAlternatively, an object value of the form `{\\\"row\\\": string, \\\"column\\\": string}` can be used to supply different alignments for rows and columns.\\n\\n__Default value:__ `\\\"all\\\"`.\"\n                },\n                \"autosize\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/AutosizeType\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AutoSizeParams\"\n                        }\n                    ],\n                    \"description\": \"How the visualization size should be determined. If a string, should be one of `\\\"pad\\\"`, `\\\"fit\\\"` or `\\\"none\\\"`. Object values can additionally specify parameters for content sizing and automatic resizing.\\n\\n__Default value__: `pad`\"\n                },\n                \"background\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"CSS color property to use as the background of the entire view.\\n\\n__Default value:__ `\\\"white\\\"`\"\n                },\n                \"bounds\": {\n                    \"description\": \"The bounds calculation method to use for determining the extent of a sub-plot. One of `full` (the default) or `flush`.\\n\\n- If set to `full`, the entire calculated bounds (including axes, title, and legend) will be used.\\n- If set to `flush`, only the specified width and height values for the sub-view will be used. The `flush` setting can be useful when attempting to place sub-plots without axes or legends into a uniform grid structure.\\n\\n__Default value:__ `\\\"full\\\"`\",\n                    \"enum\": [\n                        \"full\",\n                        \"flush\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"center\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<boolean>\"\n                        }\n                    ],\n                    \"description\": \"Boolean flag indicating if subviews should be centered relative to their respective rows or columns.\\n\\nAn object value of the form `{\\\"row\\\": boolean, \\\"column\\\": boolean}` can be used to supply different centering values for rows and columns.\\n\\n__Default value:__ `false`\"\n                },\n                \"columns\": {\n                    \"description\": \"The number of columns to include in the view composition layout.\\n\\n__Default value__: `undefined` -- An infinite number of columns (a single row) will be assumed. This is equivalent to `hconcat` (for `concat`) and to using the `column` channel (for `facet` and `repeat`).\\n\\n__Note__:\\n\\n1) This property is only for:\\n- the general (wrappable) `concat` operator (not `hconcat`/`vconcat`)\\n- the `facet` and `repeat` operator with one field/repetition definition (without row/column nesting)\\n\\n2) Setting the `columns` to `1` is equivalent to `vconcat` (for `concat`) and to using the `row` channel (for `facet` and `repeat`).\",\n                    \"type\": \"number\"\n                },\n                \"config\": {\n                    \"$ref\": \"#/definitions/Config\",\n                    \"description\": \"Vega-Lite configuration object. This property can only be defined at the top-level of a specification.\"\n                },\n                \"data\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Data\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                },\n                \"datasets\": {\n                    \"$ref\": \"#/definitions/Datasets\",\n                    \"description\": \"A global data store for named datasets. This is a mapping from names to inline datasets. This can be an array of objects or primitive values or a string. Arrays of primitive values are ingested as objects with a `data` property.\"\n                },\n                \"description\": {\n                    \"description\": \"Description of this mark for commenting purpose.\",\n                    \"type\": \"string\"\n                },\n                \"facet\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/FacetFieldDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/FacetMapping\"\n                        }\n                    ],\n                    \"description\": \"Definition for how to facet the data. One of: 1) [a field definition for faceting the plot by one field](https://vega.github.io/vega-lite/docs/facet.html#field-def) 2) [An object that maps `row` and `column` channels to their field definitions](https://vega.github.io/vega-lite/docs/facet.html#mapping)\"\n                },\n                \"name\": {\n                    \"description\": \"Name of the visualization for later reference.\",\n                    \"type\": \"string\"\n                },\n                \"padding\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Padding\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The default visualization padding, in pixels, from the edge of the visualization canvas to the data rectangle. If a number, specifies padding for all sides. If an object, the value should have the format `{\\\"left\\\": 5, \\\"top\\\": 5, \\\"right\\\": 5, \\\"bottom\\\": 5}` to specify padding for each side of the visualization.\\n\\n__Default value__: `5`\"\n                },\n                \"params\": {\n                    \"description\": \"Dynamic variables or selections that parameterize a visualization.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/TopLevelParameter\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/Resolve\",\n                    \"description\": \"Scale, axis, and legend resolutions for view composition specifications.\"\n                },\n                \"spacing\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<number>\"\n                        }\n                    ],\n                    \"description\": \"The spacing in pixels between sub-views of the composition operator. An object of the form `{\\\"row\\\": number, \\\"column\\\": number}` can be used to set different spacing values for rows and columns.\\n\\n__Default value__: Depends on `\\\"spacing\\\"` property of [the view composition configuration](https://vega.github.io/vega-lite/docs/config.html#view-config) (`20` by default)\"\n                },\n                \"spec\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LayerSpec\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/UnitSpecWithFrame\"\n                        }\n                    ],\n                    \"description\": \"A specification of the view that gets faceted.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TitleParams\"\n                        }\n                    ],\n                    \"description\": \"Title for the plot.\"\n                },\n                \"transform\": {\n                    \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Transform\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"usermeta\": {\n                    \"$ref\": \"#/definitions/Dict\",\n                    \"description\": \"Optional metadata that will be passed to Vega. This object is completely ignored by Vega and Vega-Lite and can be used for custom metadata.\"\n                }\n            },\n            \"required\": [\n                \"data\",\n                \"facet\",\n                \"spec\"\n            ],\n            \"type\": \"object\"\n        },\n        \"TopLevelParameter\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/VariableParameter\"\n                },\n                {\n                    \"$ref\": \"#/definitions/TopLevelSelectionParameter\"\n                }\n            ]\n        },\n        \"TopLevelSelectionParameter\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"bind\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Binding\"\n                        },\n                        {\n                            \"additionalProperties\": {\n                                \"$ref\": \"#/definitions/Binding\"\n                            },\n                            \"type\": \"object\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/LegendBinding\"\n                        },\n                        {\n                            \"const\": \"scales\",\n                            \"type\": \"string\"\n                        }\n                    ],\n                    \"description\": \"When set, a selection is populated by input elements (also known as dynamic query widgets) or by interacting with the corresponding legend. Direct manipulation interaction is disabled by default; to re-enable it, set the selection's [`on`](https://vega.github.io/vega-lite/docs/selection.html#common-selection-properties) property.\\n\\nLegend bindings are restricted to selections that only specify a single field or encoding.\\n\\nQuery widget binding takes the form of Vega's [input element binding definition](https://vega.github.io/vega/docs/signals/#bind) or can be a mapping between projected field/encodings and binding definitions.\\n\\n__See also:__ [`bind`](https://vega.github.io/vega-lite/docs/bind.html) documentation.\"\n                },\n                \"name\": {\n                    \"$ref\": \"#/definitions/ParameterName\",\n                    \"description\": \"Required. A unique name for the selection parameter. Selection names should be valid JavaScript identifiers: they should contain only alphanumeric characters (or \\\"$\\\", or \\\"_\\\") and may not start with a digit. Reserved keywords that may not be used as parameter names are \\\"datum\\\", \\\"event\\\", \\\"item\\\", and \\\"parent\\\".\"\n                },\n                \"select\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SelectionType\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/PointSelectionConfig\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/IntervalSelectionConfig\"\n                        }\n                    ],\n                    \"description\": \"Determines the default event processing and data query for the selection. Vega-Lite currently supports two selection types:\\n\\n- `\\\"point\\\"` -- to select multiple discrete data values; the first value is selected on `click` and additional values toggled on shift-click.\\n- `\\\"interval\\\"` -- to select a continuous range of data values on `drag`.\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/SelectionInit\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/SelectionInitMapping\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/SelectionInitIntervalMapping\"\n                        }\n                    ],\n                    \"description\": \"Initialize the selection with a mapping between [projected channels or field names](https://vega.github.io/vega-lite/docs/selection.html#project) and initial values.\\n\\n__See also:__ [`init`](https://vega.github.io/vega-lite/docs/value.html) documentation.\"\n                },\n                \"views\": {\n                    \"description\": \"By default, top-level selections are applied to every view in the visualization. If this property is specified, selections will only be applied to views with the given names.\",\n                    \"items\": {\n                        \"type\": \"string\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"name\",\n                \"select\"\n            ],\n            \"type\": \"object\"\n        },\n        \"TopLevelSpec\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/TopLevelUnitSpec\"\n                },\n                {\n                    \"$ref\": \"#/definitions/TopLevelFacetSpec\"\n                },\n                {\n                    \"$ref\": \"#/definitions/TopLevelLayerSpec\"\n                },\n                {\n                    \"$ref\": \"#/definitions/TopLevelRepeatSpec\"\n                },\n                {\n                    \"$ref\": \"#/definitions/TopLevelConcatSpec\"\n                },\n                {\n                    \"$ref\": \"#/definitions/TopLevelVConcatSpec\"\n                },\n                {\n                    \"$ref\": \"#/definitions/TopLevelHConcatSpec\"\n                }\n            ],\n            \"description\": \"A Vega-Lite top-level specification. This is the root class for all Vega-Lite specifications. (The json schema is generated from this type.)\"\n        },\n        \"TopLevelUnitSpec\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"$schema\": {\n                    \"description\": \"URL to [JSON schema](http://json-schema.org/) for a Vega-Lite specification. Unless you have a reason to change this, use `https://vega.github.io/schema/vega-lite/v5.json`. Setting the `$schema` property allows automatic validation and autocomplete in editors that support JSON schema.\",\n                    \"format\": \"uri\",\n                    \"type\": \"string\"\n                },\n                \"align\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/LayoutAlign\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<LayoutAlign>\"\n                        }\n                    ],\n                    \"description\": \"The alignment to apply to grid rows and columns. The supported string values are `\\\"all\\\"`, `\\\"each\\\"`, and `\\\"none\\\"`.\\n\\n- For `\\\"none\\\"`, a flow layout will be used, in which adjacent subviews are simply placed one after the other.\\n- For `\\\"each\\\"`, subviews will be aligned into a clean grid structure, but each row or column may be of variable size.\\n- For `\\\"all\\\"`, subviews will be aligned and each row or column will be sized identically based on the maximum observed size. String values for this property will be applied to both grid rows and columns.\\n\\nAlternatively, an object value of the form `{\\\"row\\\": string, \\\"column\\\": string}` can be used to supply different alignments for rows and columns.\\n\\n__Default value:__ `\\\"all\\\"`.\"\n                },\n                \"autosize\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/AutosizeType\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/AutoSizeParams\"\n                        }\n                    ],\n                    \"description\": \"How the visualization size should be determined. If a string, should be one of `\\\"pad\\\"`, `\\\"fit\\\"` or `\\\"none\\\"`. Object values can additionally specify parameters for content sizing and automatic resizing.\\n\\n__Default value__: `pad`\"\n                },\n                \"background\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"CSS color property to use as the background of the entire view.\\n\\n__Default value:__ `\\\"white\\\"`\"\n                },\n                \"bounds\": {\n                    \"description\": \"The bounds calculation method to use for determining the extent of a sub-plot. One of `full` (the default) or `flush`.\\n\\n- If set to `full`, the entire calculated bounds (including axes, title, and legend) will be used.\\n- If set to `flush`, only the specified width and height values for the sub-view will be used. The `flush` setting can be useful when attempting to place sub-plots without axes or legends into a uniform grid structure.\\n\\n__Default value:__ `\\\"full\\\"`\",\n                    \"enum\": [\n                        \"full\",\n                        \"flush\"\n                    ],\n                    \"type\": \"string\"\n                },\n                \"center\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<boolean>\"\n                        }\n                    ],\n                    \"description\": \"Boolean flag indicating if subviews should be centered relative to their respective rows or columns.\\n\\nAn object value of the form `{\\\"row\\\": boolean, \\\"column\\\": boolean}` can be used to supply different centering values for rows and columns.\\n\\n__Default value:__ `false`\"\n                },\n                \"config\": {\n                    \"$ref\": \"#/definitions/Config\",\n                    \"description\": \"Vega-Lite configuration object. This property can only be defined at the top-level of a specification.\"\n                },\n                \"data\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Data\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                },\n                \"datasets\": {\n                    \"$ref\": \"#/definitions/Datasets\",\n                    \"description\": \"A global data store for named datasets. This is a mapping from names to inline datasets. This can be an array of objects or primitive values or a string. Arrays of primitive values are ingested as objects with a `data` property.\"\n                },\n                \"description\": {\n                    \"description\": \"Description of this mark for commenting purpose.\",\n                    \"type\": \"string\"\n                },\n                \"encoding\": {\n                    \"$ref\": \"#/definitions/FacetedEncoding\",\n                    \"description\": \"A key-value mapping between encoding channels and definition of fields.\"\n                },\n                \"height\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"container\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Step\"\n                        }\n                    ],\n                    \"description\": \"The height of a visualization.\\n\\n- For a plot with a continuous y-field, height should be a number.\\n- For a plot with either a discrete y-field or no y-field, height can be either a number indicating a fixed height or an object in the form of `{step: number}` defining the height per discrete step. (No y-field is equivalent to having one discrete step.)\\n- To enable responsive sizing on height, it should be set to `\\\"container\\\"`.\\n\\n__Default value:__ Based on `config.view.continuousHeight` for a plot with a continuous y-field and `config.view.discreteHeight` otherwise.\\n\\n__Note:__ For plots with [`row` and `column` channels](https://vega.github.io/vega-lite/docs/encoding.html#facet), this represents the height of a single view and the `\\\"container\\\"` option cannot be used.\\n\\n__See also:__ [`height`](https://vega.github.io/vega-lite/docs/size.html) documentation.\"\n                },\n                \"mark\": {\n                    \"$ref\": \"#/definitions/AnyMark\",\n                    \"description\": \"A string describing the mark type (one of `\\\"bar\\\"`, `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"tick\\\"`, `\\\"line\\\"`, `\\\"area\\\"`, `\\\"point\\\"`, `\\\"rule\\\"`, `\\\"geoshape\\\"`, and `\\\"text\\\"`) or a [mark definition object](https://vega.github.io/vega-lite/docs/mark.html#mark-def).\"\n                },\n                \"name\": {\n                    \"description\": \"Name of the visualization for later reference.\",\n                    \"type\": \"string\"\n                },\n                \"padding\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Padding\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The default visualization padding, in pixels, from the edge of the visualization canvas to the data rectangle. If a number, specifies padding for all sides. If an object, the value should have the format `{\\\"left\\\": 5, \\\"top\\\": 5, \\\"right\\\": 5, \\\"bottom\\\": 5}` to specify padding for each side of the visualization.\\n\\n__Default value__: `5`\"\n                },\n                \"params\": {\n                    \"description\": \"An array of parameters that may either be simple variables, or more complex selections that map user input to data queries.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/TopLevelParameter\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"projection\": {\n                    \"$ref\": \"#/definitions/Projection\",\n                    \"description\": \"An object defining properties of geographic projection, which will be applied to `shape` path for `\\\"geoshape\\\"` marks and to `latitude` and `\\\"longitude\\\"` channels for other marks.\"\n                },\n                \"resolve\": {\n                    \"$ref\": \"#/definitions/Resolve\",\n                    \"description\": \"Scale, axis, and legend resolutions for view composition specifications.\"\n                },\n                \"spacing\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/RowCol<number>\"\n                        }\n                    ],\n                    \"description\": \"The spacing in pixels between sub-views of the composition operator. An object of the form `{\\\"row\\\": number, \\\"column\\\": number}` can be used to set different spacing values for rows and columns.\\n\\n__Default value__: Depends on `\\\"spacing\\\"` property of [the view composition configuration](https://vega.github.io/vega-lite/docs/config.html#view-config) (`20` by default)\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TitleParams\"\n                        }\n                    ],\n                    \"description\": \"Title for the plot.\"\n                },\n                \"transform\": {\n                    \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Transform\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"usermeta\": {\n                    \"$ref\": \"#/definitions/Dict\",\n                    \"description\": \"Optional metadata that will be passed to Vega. This object is completely ignored by Vega and Vega-Lite and can be used for custom metadata.\"\n                },\n                \"view\": {\n                    \"$ref\": \"#/definitions/ViewBackground\",\n                    \"description\": \"An object defining the view background's fill and stroke.\\n\\n__Default value:__ none (transparent)\"\n                },\n                \"width\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"container\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Step\"\n                        }\n                    ],\n                    \"description\": \"The width of a visualization.\\n\\n- For a plot with a continuous x-field, width should be a number.\\n- For a plot with either a discrete x-field or no x-field, width can be either a number indicating a fixed width or an object in the form of `{step: number}` defining the width per discrete step. (No x-field is equivalent to having one discrete step.)\\n- To enable responsive sizing on width, it should be set to `\\\"container\\\"`.\\n\\n__Default value:__ Based on `config.view.continuousWidth` for a plot with a continuous x-field and `config.view.discreteWidth` otherwise.\\n\\n__Note:__ For plots with [`row` and `column` channels](https://vega.github.io/vega-lite/docs/encoding.html#facet), this represents the width of a single view and the `\\\"container\\\"` option cannot be used.\\n\\n__See also:__ [`width`](https://vega.github.io/vega-lite/docs/size.html) documentation.\"\n                }\n            },\n            \"required\": [\n                \"data\",\n                \"mark\"\n            ],\n            \"type\": \"object\"\n        },\n        \"TopoDataFormat\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"feature\": {\n                    \"description\": \"The name of the TopoJSON object set to convert to a GeoJSON feature collection. For example, in a map of the world, there may be an object set named `\\\"countries\\\"`. Using the feature property, we can extract this set and generate a GeoJSON feature object for each country.\",\n                    \"type\": \"string\"\n                },\n                \"mesh\": {\n                    \"description\": \"The name of the TopoJSON object set to convert to mesh. Similar to the `feature` option, `mesh` extracts a named TopoJSON object set.  Unlike the `feature` option, the corresponding geo data is returned as a single, unified mesh instance, not as individual GeoJSON features. Extracting a mesh is useful for more efficiently drawing borders or other geographic elements that you do not need to associate with specific regions such as individual countries, states or counties.\",\n                    \"type\": \"string\"\n                },\n                \"parse\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Parse\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"If set to `null`, disable type inference based on the spec and only use type inference based on the data. Alternatively, a parsing directive object can be provided for explicit data types. Each property of the object corresponds to a field name, and the value to the desired data type (one of `\\\"number\\\"`, `\\\"boolean\\\"`, `\\\"date\\\"`, or null (do not parse the field)). For example, `\\\"parse\\\": {\\\"modified_on\\\": \\\"date\\\"}` parses the `modified_on` field in each input record a Date value.\\n\\nFor `\\\"date\\\"`, we parse data based using JavaScript's [`Date.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse). For Specific date formats can be provided (e.g., `{foo: \\\"date:'%m%d%Y'\\\"}`), using the [d3-time-format syntax](https://github.com/d3/d3-time-format#locale_format). UTC date format parsing is supported similarly (e.g., `{foo: \\\"utc:'%m%d%Y'\\\"}`). See more about [UTC time](https://vega.github.io/vega-lite/docs/timeunit.html#utc)\"\n                },\n                \"type\": {\n                    \"const\": \"topojson\",\n                    \"description\": \"Type of input data: `\\\"json\\\"`, `\\\"csv\\\"`, `\\\"tsv\\\"`, `\\\"dsv\\\"`.\\n\\n__Default value:__  The default format type is determined by the extension of the file URL. If no extension is detected, `\\\"json\\\"` will be used by default.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"Transform\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/AggregateTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/BinTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/CalculateTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/DensityTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ExtentTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/FilterTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/FlattenTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/FoldTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/ImputeTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/JoinAggregateTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/LoessTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/LookupTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/QuantileTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/RegressionTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/TimeUnitTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/SampleTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/StackTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/WindowTransform\"\n                },\n                {\n                    \"$ref\": \"#/definitions/PivotTransform\"\n                }\n            ]\n        },\n        \"Type\": {\n            \"description\": \"Data type based on level of measurement\",\n            \"enum\": [\n                \"quantitative\",\n                \"ordinal\",\n                \"temporal\",\n                \"nominal\",\n                \"geojson\"\n            ],\n            \"type\": \"string\"\n        },\n        \"TypeForShape\": {\n            \"enum\": [\n                \"nominal\",\n                \"ordinal\",\n                \"geojson\"\n            ],\n            \"type\": \"string\"\n        },\n        \"TypedFieldDef\": {\n            \"additionalProperties\": false,\n            \"description\": \"Definition object for a data field, its type and transformation of an encoding channel.\",\n            \"properties\": {\n                \"aggregate\": {\n                    \"$ref\": \"#/definitions/Aggregate\",\n                    \"description\": \"Aggregation function for the field (e.g., `\\\"mean\\\"`, `\\\"sum\\\"`, `\\\"median\\\"`, `\\\"min\\\"`, `\\\"max\\\"`, `\\\"count\\\"`).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html) documentation.\"\n                },\n                \"bandPosition\": {\n                    \"description\": \"Relative position on a band of a stacked, binned, time unit, or band scale. For example, the marks will be positioned at the beginning of the band if set to `0`, and at the middle of the band if set to `0.5`.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0,\n                    \"type\": \"number\"\n                },\n                \"bin\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"boolean\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinParams\"\n                        },\n                        {\n                            \"const\": \"binned\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A flag for binning a `quantitative` field, [an object defining binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters), or indicating that the data for `x` or `y` channel are binned before they are imported into Vega-Lite (`\\\"binned\\\"`).\\n\\n- If `true`, default [binning parameters](https://vega.github.io/vega-lite/docs/bin.html#bin-parameters) will be applied.\\n\\n- If `\\\"binned\\\"`, this indicates that the data for the `x` (or `y`) channel are already binned. You can map the bin-start field to `x` (or `y`) and the bin-end field to `x2` (or `y2`). The scale and axis will be formatted similar to binning in Vega-Lite.  To adjust the axis ticks based on the bin step, you can also set the axis's [`tickMinStep`](https://vega.github.io/vega-lite/docs/axis.html#ticks) property.\\n\\n__Default value:__ `false`\\n\\n__See also:__ [`bin`](https://vega.github.io/vega-lite/docs/bin.html) documentation.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/Field\",\n                    \"description\": \"__Required.__ A string defining the name of the field from which to pull a data value or an object defining iterated values from the [`repeat`](https://vega.github.io/vega-lite/docs/repeat.html) operator.\\n\\n__See also:__ [`field`](https://vega.github.io/vega-lite/docs/field.html) documentation.\\n\\n__Notes:__ 1)  Dots (`.`) and brackets (`[` and `]`) can be used to access nested objects (e.g., `\\\"field\\\": \\\"foo.bar\\\"` and `\\\"field\\\": \\\"foo['bar']\\\"`). If field names contain dots or brackets but are not nested, you can use `\\\\\\\\` to escape dots and brackets (e.g., `\\\"a\\\\\\\\.b\\\"` and `\\\"a\\\\\\\\[0\\\\\\\\]\\\"`). See more details about escaping in the [field documentation](https://vega.github.io/vega-lite/docs/field.html). 2) `field` is not required if `aggregate` is `count`.\"\n                },\n                \"timeUnit\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/TimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/BinnedTimeUnit\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TimeUnitParams\"\n                        }\n                    ],\n                    \"description\": \"Time unit (e.g., `year`, `yearmonth`, `month`, `hours`) for a temporal field. or [a temporal field that gets casted as ordinal](https://vega.github.io/vega-lite/docs/type.html#cast).\\n\\n__Default value:__ `undefined` (None)\\n\\n__See also:__ [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html) documentation.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"A title for the field. If `null`, the title will be removed.\\n\\n__Default value:__  derived from the field's name and transformation function (`aggregate`, `bin` and `timeUnit`). If the field has an aggregate function, the function is displayed as part of the title (e.g., `\\\"Sum of Profit\\\"`). If the field is binned or has a time unit applied, the applied function is shown in parentheses (e.g., `\\\"Profit (binned)\\\"`, `\\\"Transaction Date (year-month)\\\"`). Otherwise, the title is simply the field name.\\n\\n__Notes__:\\n\\n1) You can customize the default field title format by providing the [`fieldTitle`](https://vega.github.io/vega-lite/docs/config.html#top-level-config) property in the [config](https://vega.github.io/vega-lite/docs/config.html) or [`fieldTitle` function via the `compile` function's options](https://vega.github.io/vega-lite/usage/compile.html#field-title).\\n\\n2) If both field definition's `title` and axis, header, or legend `title` are defined, axis/header/legend title will be used.\"\n                },\n                \"type\": {\n                    \"$ref\": \"#/definitions/StandardType\",\n                    \"description\": \"The type of measurement (`\\\"quantitative\\\"`, `\\\"temporal\\\"`, `\\\"ordinal\\\"`, or `\\\"nominal\\\"`) for the encoded field or constant value (`datum`). It can also be a `\\\"geojson\\\"` type for encoding ['geoshape'](https://vega.github.io/vega-lite/docs/geoshape.html).\\n\\nVega-Lite automatically infers data types in many cases as discussed below. However, type is required for a field if: (1) the field is not nominal and the field encoding has no specified `aggregate` (except `argmin` and `argmax`), `bin`, scale type, custom `sort` order, nor `timeUnit` or (2) if you wish to use an ordinal scale for a field with `bin` or `timeUnit`.\\n\\n__Default value:__\\n\\n1) For a data `field`, `\\\"nominal\\\"` is the default data type unless the field encoding has `aggregate`, `channel`, `bin`, scale type, `sort`, or `timeUnit` that satisfies the following criteria:\\n- `\\\"quantitative\\\"` is the default type if (1) the encoded field contains `bin` or `aggregate` except `\\\"argmin\\\"` and `\\\"argmax\\\"`, (2) the encoding channel is `latitude` or `longitude` channel or (3) if the specified scale type is [a quantitative scale](https://vega.github.io/vega-lite/docs/scale.html#type).\\n- `\\\"temporal\\\"` is the default type if (1) the encoded field contains `timeUnit` or (2) the specified scale type is a time or utc scale\\n- `\\\"ordinal\\\"` is the default type if (1) the encoded field contains a [custom `sort` order](https://vega.github.io/vega-lite/docs/sort.html#specifying-custom-sort-order), (2) the specified scale type is an ordinal/point/band scale, or (3) the encoding channel is `order`.\\n\\n2) For a constant value in data domain (`datum`):\\n- `\\\"quantitative\\\"` if the datum is a number\\n- `\\\"nominal\\\"` if the datum is a string\\n- `\\\"temporal\\\"` if the datum is [a date time object](https://vega.github.io/vega-lite/docs/datetime.html)\\n\\n__Note:__\\n- Data `type` describes the semantics of the data rather than the primitive data types (number, string, etc.). The same primitive data type can have different types of measurement. For example, numeric data can represent quantitative, ordinal, or nominal data.\\n- Data values for a temporal field can be either a date-time string (e.g., `\\\"2015-03-07 12:32:17\\\"`, `\\\"17:01\\\"`, `\\\"2015-03-16\\\"`. `\\\"2015\\\"`) or a timestamp number (e.g., `1552199579097`).\\n- When using with [`bin`](https://vega.github.io/vega-lite/docs/bin.html), the `type` property can be either `\\\"quantitative\\\"` (for using a linear bin scale) or [`\\\"ordinal\\\"` (for using an ordinal bin scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`timeUnit`](https://vega.github.io/vega-lite/docs/timeunit.html), the `type` property can be either `\\\"temporal\\\"` (default, for using a temporal scale) or [`\\\"ordinal\\\"` (for using an ordinal scale)](https://vega.github.io/vega-lite/docs/type.html#cast-bin).\\n- When using with [`aggregate`](https://vega.github.io/vega-lite/docs/aggregate.html), the `type` property refers to the post-aggregation data type. For example, we can calculate count `distinct` of a categorical field `\\\"cat\\\"` using `{\\\"aggregate\\\": \\\"distinct\\\", \\\"field\\\": \\\"cat\\\"}`. The `\\\"type\\\"` of the aggregate output is `\\\"quantitative\\\"`.\\n- Secondary channels (e.g., `x2`, `y2`, `xError`, `yError`) do not have `type` as they must have exactly the same type as their primary channels (e.g., `x`, `y`).\\n\\n__See also:__ [`type`](https://vega.github.io/vega-lite/docs/type.html) documentation.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"URI\": {\n            \"format\": \"uri-reference\",\n            \"type\": \"string\"\n        },\n        \"UnitSpec\": {\n            \"$ref\": \"#/definitions/GenericUnitSpec<Encoding,AnyMark>\",\n            \"description\": \"A unit specification, which can contain either [primitive marks or composite marks](https://vega.github.io/vega-lite/docs/mark.html#types).\"\n        },\n        \"UnitSpecWithFrame\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"data\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Data\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        }\n                    ],\n                    \"description\": \"An object describing the data source. Set to `null` to ignore the parent's data source. If no data is set, it is derived from the parent.\"\n                },\n                \"description\": {\n                    \"description\": \"Description of this mark for commenting purpose.\",\n                    \"type\": \"string\"\n                },\n                \"encoding\": {\n                    \"$ref\": \"#/definitions/Encoding\",\n                    \"description\": \"A key-value mapping between encoding channels and definition of fields.\"\n                },\n                \"height\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"container\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Step\"\n                        }\n                    ],\n                    \"description\": \"The height of a visualization.\\n\\n- For a plot with a continuous y-field, height should be a number.\\n- For a plot with either a discrete y-field or no y-field, height can be either a number indicating a fixed height or an object in the form of `{step: number}` defining the height per discrete step. (No y-field is equivalent to having one discrete step.)\\n- To enable responsive sizing on height, it should be set to `\\\"container\\\"`.\\n\\n__Default value:__ Based on `config.view.continuousHeight` for a plot with a continuous y-field and `config.view.discreteHeight` otherwise.\\n\\n__Note:__ For plots with [`row` and `column` channels](https://vega.github.io/vega-lite/docs/encoding.html#facet), this represents the height of a single view and the `\\\"container\\\"` option cannot be used.\\n\\n__See also:__ [`height`](https://vega.github.io/vega-lite/docs/size.html) documentation.\"\n                },\n                \"mark\": {\n                    \"$ref\": \"#/definitions/AnyMark\",\n                    \"description\": \"A string describing the mark type (one of `\\\"bar\\\"`, `\\\"circle\\\"`, `\\\"square\\\"`, `\\\"tick\\\"`, `\\\"line\\\"`, `\\\"area\\\"`, `\\\"point\\\"`, `\\\"rule\\\"`, `\\\"geoshape\\\"`, and `\\\"text\\\"`) or a [mark definition object](https://vega.github.io/vega-lite/docs/mark.html#mark-def).\"\n                },\n                \"name\": {\n                    \"description\": \"Name of the visualization for later reference.\",\n                    \"type\": \"string\"\n                },\n                \"params\": {\n                    \"description\": \"An array of parameters that may either be simple variables, or more complex selections that map user input to data queries.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/SelectionParameter\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"projection\": {\n                    \"$ref\": \"#/definitions/Projection\",\n                    \"description\": \"An object defining properties of geographic projection, which will be applied to `shape` path for `\\\"geoshape\\\"` marks and to `latitude` and `\\\"longitude\\\"` channels for other marks.\"\n                },\n                \"title\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/TitleParams\"\n                        }\n                    ],\n                    \"description\": \"Title for the plot.\"\n                },\n                \"transform\": {\n                    \"description\": \"An array of data transformations such as filter and new field calculation.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/Transform\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"view\": {\n                    \"$ref\": \"#/definitions/ViewBackground\",\n                    \"description\": \"An object defining the view background's fill and stroke.\\n\\n__Default value:__ none (transparent)\"\n                },\n                \"width\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"container\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/Step\"\n                        }\n                    ],\n                    \"description\": \"The width of a visualization.\\n\\n- For a plot with a continuous x-field, width should be a number.\\n- For a plot with either a discrete x-field or no x-field, width can be either a number indicating a fixed width or an object in the form of `{step: number}` defining the width per discrete step. (No x-field is equivalent to having one discrete step.)\\n- To enable responsive sizing on width, it should be set to `\\\"container\\\"`.\\n\\n__Default value:__ Based on `config.view.continuousWidth` for a plot with a continuous x-field and `config.view.discreteWidth` otherwise.\\n\\n__Note:__ For plots with [`row` and `column` channels](https://vega.github.io/vega-lite/docs/encoding.html#facet), this represents the width of a single view and the `\\\"container\\\"` option cannot be used.\\n\\n__See also:__ [`width`](https://vega.github.io/vega-lite/docs/size.html) documentation.\"\n                }\n            },\n            \"required\": [\n                \"mark\"\n            ],\n            \"type\": \"object\"\n        },\n        \"UrlData\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"format\": {\n                    \"$ref\": \"#/definitions/DataFormat\",\n                    \"description\": \"An object that specifies the format for parsing the data.\"\n                },\n                \"name\": {\n                    \"description\": \"Provide a placeholder name and bind data at runtime.\",\n                    \"type\": \"string\"\n                },\n                \"url\": {\n                    \"description\": \"An URL from which to load the data set. Use the `format.type` property to ensure the loaded data is correctly parsed.\",\n                    \"type\": \"string\"\n                }\n            },\n            \"required\": [\n                \"url\"\n            ],\n            \"type\": \"object\"\n        },\n        \"UtcMultiTimeUnit\": {\n            \"enum\": [\n                \"utcyearquarter\",\n                \"utcyearquartermonth\",\n                \"utcyearmonth\",\n                \"utcyearmonthdate\",\n                \"utcyearmonthdatehours\",\n                \"utcyearmonthdatehoursminutes\",\n                \"utcyearmonthdatehoursminutesseconds\",\n                \"utcyearweek\",\n                \"utcyearweekday\",\n                \"utcyearweekdayhours\",\n                \"utcyearweekdayhoursminutes\",\n                \"utcyearweekdayhoursminutesseconds\",\n                \"utcyeardayofyear\",\n                \"utcquartermonth\",\n                \"utcmonthdate\",\n                \"utcmonthdatehours\",\n                \"utcmonthdatehoursminutes\",\n                \"utcmonthdatehoursminutesseconds\",\n                \"utcweekday\",\n                \"utcweekdayhours\",\n                \"utcweekdayhoursminutes\",\n                \"utcweekdayhoursminutesseconds\",\n                \"utcdayhours\",\n                \"utcdayhoursminutes\",\n                \"utcdayhoursminutesseconds\",\n                \"utchoursminutes\",\n                \"utchoursminutesseconds\",\n                \"utcminutesseconds\",\n                \"utcsecondsmilliseconds\"\n            ],\n            \"type\": \"string\"\n        },\n        \"UtcSingleTimeUnit\": {\n            \"enum\": [\n                \"utcyear\",\n                \"utcquarter\",\n                \"utcmonth\",\n                \"utcweek\",\n                \"utcday\",\n                \"utcdayofyear\",\n                \"utcdate\",\n                \"utchours\",\n                \"utcminutes\",\n                \"utcseconds\",\n                \"utcmilliseconds\"\n            ],\n            \"type\": \"string\"\n        },\n        \"ValueDef<(number|\\\"width\\\"|\\\"height\\\"|ExprRef)>\": {\n            \"additionalProperties\": false,\n            \"description\": \"Definition object for a constant value (primitive value or gradient definition) of an encoding channel.\",\n            \"properties\": {\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"const\": \"width\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"const\": \"height\",\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"required\": [\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ValueDef<number>\": {\n            \"additionalProperties\": false,\n            \"description\": \"Definition object for a constant value (primitive value or gradient definition) of an encoding channel.\",\n            \"properties\": {\n                \"value\": {\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\",\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"value\"\n            ],\n            \"type\": \"object\"\n        },\n        \"ValueDefWithCondition<MarkPropFieldOrDatumDef,(Gradient|string|null)>\": {\n            \"additionalProperties\": false,\n            \"minProperties\": 1,\n            \"properties\": {\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<(Gradient|string|null|ExprRef)>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Gradient\"\n                        },\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ValueDefWithCondition<MarkPropFieldOrDatumDef,(string|null)>\": {\n            \"additionalProperties\": false,\n            \"minProperties\": 1,\n            \"properties\": {\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ValueDefWithCondition<MarkPropFieldOrDatumDef,number>\": {\n            \"additionalProperties\": false,\n            \"minProperties\": 1,\n            \"properties\": {\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<(number|ExprRef)>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ValueDefWithCondition<MarkPropFieldOrDatumDef,number[]>\": {\n            \"additionalProperties\": false,\n            \"minProperties\": 1,\n            \"properties\": {\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<(number[]|ExprRef)>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<(number[]|ExprRef)>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ValueDefWithCondition<MarkPropFieldOrDatumDef<TypeForShape>,(string|null)>\": {\n            \"additionalProperties\": false,\n            \"minProperties\": 1,\n            \"properties\": {\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalMarkPropFieldOrDatumDef<TypeForShape>\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<(string|null|ExprRef)>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ValueDefWithCondition<StringFieldDef,Text>\": {\n            \"additionalProperties\": false,\n            \"minProperties\": 1,\n            \"properties\": {\n                \"condition\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/ConditionalStringFieldDef\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ConditionalValueDef<(Text|ExprRef)>\"\n                        },\n                        {\n                            \"items\": {\n                                \"$ref\": \"#/definitions/ConditionalValueDef<(Text|ExprRef)>\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"A field definition or one or more value definition(s) with a parameter predicate.\"\n                },\n                \"value\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Text\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"A constant value in visual domain (e.g., `\\\"red\\\"` / `\\\"#0099ff\\\"` / [gradient definition](https://vega.github.io/vega-lite/docs/types.html#gradient) for color, values between `0` to `1` for opacity).\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"VariableParameter\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"bind\": {\n                    \"$ref\": \"#/definitions/Binding\",\n                    \"description\": \"Binds the parameter to an external input element such as a slider, selection list or radio button group.\"\n                },\n                \"expr\": {\n                    \"$ref\": \"#/definitions/Expr\",\n                    \"description\": \"An expression for the value of the parameter. This expression may include other parameters, in which case the parameter will automatically update in response to upstream parameter changes.\"\n                },\n                \"name\": {\n                    \"$ref\": \"#/definitions/ParameterName\",\n                    \"description\": \"A unique name for the variable parameter. Parameter names should be valid JavaScript identifiers: they should contain only alphanumeric characters (or \\\"$\\\", or \\\"_\\\") and may not start with a digit. Reserved keywords that may not be used as parameter names are \\\"datum\\\", \\\"event\\\", \\\"item\\\", and \\\"parent\\\".\"\n                },\n                \"react\": {\n                    \"description\": \"A boolean flag (default `true`) indicating if the update expression should be automatically re-evaluated when any upstream signal dependencies update. If `false`, the update expression will not register any dependencies on other signals, even for initialization.\\n\\n __Default value:__ `true`\",\n                    \"type\": \"boolean\"\n                },\n                \"value\": {\n                    \"description\": \"The [initial value](http://vega.github.io/vega-lite/docs/value.html) of the parameter.\\n\\n__Default value:__ `undefined`\"\n                }\n            },\n            \"required\": [\n                \"name\"\n            ],\n            \"type\": \"object\"\n        },\n        \"Vector10<string>\": {\n            \"items\": {\n                \"type\": \"string\"\n            },\n            \"maxItems\": 10,\n            \"minItems\": 10,\n            \"type\": \"array\"\n        },\n        \"Vector12<string>\": {\n            \"items\": {\n                \"type\": \"string\"\n            },\n            \"maxItems\": 12,\n            \"minItems\": 12,\n            \"type\": \"array\"\n        },\n        \"Vector2<DateTime>\": {\n            \"items\": {\n                \"$ref\": \"#/definitions/DateTime\"\n            },\n            \"maxItems\": 2,\n            \"minItems\": 2,\n            \"type\": \"array\"\n        },\n        \"Vector2<Vector2<number>>\": {\n            \"items\": {\n                \"$ref\": \"#/definitions/Vector2<number>\"\n            },\n            \"maxItems\": 2,\n            \"minItems\": 2,\n            \"type\": \"array\"\n        },\n        \"Vector2<boolean>\": {\n            \"items\": {\n                \"type\": \"boolean\"\n            },\n            \"maxItems\": 2,\n            \"minItems\": 2,\n            \"type\": \"array\"\n        },\n        \"Vector2<number>\": {\n            \"items\": {\n                \"type\": \"number\"\n            },\n            \"maxItems\": 2,\n            \"minItems\": 2,\n            \"type\": \"array\"\n        },\n        \"Vector2<string>\": {\n            \"items\": {\n                \"type\": \"string\"\n            },\n            \"maxItems\": 2,\n            \"minItems\": 2,\n            \"type\": \"array\"\n        },\n        \"Vector3<number>\": {\n            \"items\": {\n                \"type\": \"number\"\n            },\n            \"maxItems\": 3,\n            \"minItems\": 3,\n            \"type\": \"array\"\n        },\n        \"Vector7<string>\": {\n            \"items\": {\n                \"type\": \"string\"\n            },\n            \"maxItems\": 7,\n            \"minItems\": 7,\n            \"type\": \"array\"\n        },\n        \"ViewBackground\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"cornerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles or arcs' corners.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cursor\": {\n                    \"$ref\": \"#/definitions/Cursor\",\n                    \"description\": \"The mouse cursor used over the view. Any valid [CSS cursor type](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used.\"\n                },\n                \"fill\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The fill color.\\n\\n__Default value:__ `undefined`\"\n                },\n                \"fillOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The fill opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"opacity\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The overall opacity (value between [0,1]).\\n\\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or `square` marks or layered `bar` charts and `1` otherwise.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"stroke\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The stroke color.\\n\\n__Default value:__ `\\\"#ddd\\\"`\"\n                },\n                \"strokeCap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeCap\",\n                            \"description\": \"The stroke cap for line ending style. One of `\\\"butt\\\"`, `\\\"round\\\"`, or `\\\"square\\\"`.\\n\\n__Default value:__ `\\\"butt\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating stroke, space lengths for creating dashed or dotted lines.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset (in pixels) into which to begin drawing with the stroke dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeJoin\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeJoin\",\n                            \"description\": \"The stroke line join method. One of `\\\"miter\\\"`, `\\\"round\\\"` or `\\\"bevel\\\"`.\\n\\n__Default value:__ `\\\"miter\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeMiterLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The miter limit at which to bevel a line join.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke width, in pixels.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"style\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"string\"\n                        },\n                        {\n                            \"items\": {\n                                \"type\": \"string\"\n                            },\n                            \"type\": \"array\"\n                        }\n                    ],\n                    \"description\": \"A string or array of strings indicating the name of custom styles to apply to the view background. A style is a named collection of mark property defaults defined within the [style configuration](https://vega.github.io/vega-lite/docs/mark.html#style-config). If style is an array, later styles will override earlier styles.\\n\\n__Default value:__ `\\\"cell\\\"` __Note:__ Any specified view background properties will augment the default style.\"\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"ViewConfig\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"clip\": {\n                    \"description\": \"Whether the view should be clipped.\",\n                    \"type\": \"boolean\"\n                },\n                \"continuousHeight\": {\n                    \"description\": \"The default height when the plot has a continuous y-field for x or latitude, or has arc marks.\\n\\n__Default value:__ `200`\",\n                    \"type\": \"number\"\n                },\n                \"continuousWidth\": {\n                    \"description\": \"The default width when the plot has a continuous field for x or longitude, or has arc marks.\\n\\n__Default value:__ `200`\",\n                    \"type\": \"number\"\n                },\n                \"cornerRadius\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The radius in pixels of rounded rectangles or arcs' corners.\\n\\n__Default value:__ `0`\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"cursor\": {\n                    \"$ref\": \"#/definitions/Cursor\",\n                    \"description\": \"The mouse cursor used over the view. Any valid [CSS cursor type](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#Values) can be used.\"\n                },\n                \"discreteHeight\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"additionalProperties\": false,\n                            \"properties\": {\n                                \"step\": {\n                                    \"type\": \"number\"\n                                }\n                            },\n                            \"required\": [\n                                \"step\"\n                            ],\n                            \"type\": \"object\"\n                        }\n                    ],\n                    \"description\": \"The default height when the plot has non arc marks and either a discrete y-field or no y-field. The height can be either a number indicating a fixed height or an object in the form of `{step: number}` defining the height per discrete step.\\n\\n__Default value:__ a step size based on `config.view.step`.\"\n                },\n                \"discreteWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"additionalProperties\": false,\n                            \"properties\": {\n                                \"step\": {\n                                    \"type\": \"number\"\n                                }\n                            },\n                            \"required\": [\n                                \"step\"\n                            ],\n                            \"type\": \"object\"\n                        }\n                    ],\n                    \"description\": \"The default width when the plot has non-arc marks and either a discrete x-field or no x-field. The width can be either a number indicating a fixed width or an object in the form of `{step: number}` defining the width per discrete step.\\n\\n__Default value:__ a step size based on `config.view.step`.\"\n                },\n                \"fill\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The fill color.\\n\\n__Default value:__ `undefined`\"\n                },\n                \"fillOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The fill opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"opacity\": {\n                    \"anyOf\": [\n                        {\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The overall opacity (value between [0,1]).\\n\\n__Default value:__ `0.7` for non-aggregate plots with `point`, `tick`, `circle`, or `square` marks or layered `bar` charts and `1` otherwise.\",\n                    \"maximum\": 1,\n                    \"minimum\": 0\n                },\n                \"step\": {\n                    \"description\": \"Default step size for x-/y- discrete fields.\",\n                    \"type\": \"number\"\n                },\n                \"stroke\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/Color\"\n                        },\n                        {\n                            \"type\": \"null\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ],\n                    \"description\": \"The stroke color.\\n\\n__Default value:__ `\\\"#ddd\\\"`\"\n                },\n                \"strokeCap\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeCap\",\n                            \"description\": \"The stroke cap for line ending style. One of `\\\"butt\\\"`, `\\\"round\\\"`, or `\\\"square\\\"`.\\n\\n__Default value:__ `\\\"butt\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDash\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"An array of alternating stroke, space lengths for creating dashed or dotted lines.\",\n                            \"items\": {\n                                \"type\": \"number\"\n                            },\n                            \"type\": \"array\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeDashOffset\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The offset (in pixels) into which to begin drawing with the stroke dash array.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeJoin\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/StrokeJoin\",\n                            \"description\": \"The stroke line join method. One of `\\\"miter\\\"`, `\\\"round\\\"` or `\\\"bevel\\\"`.\\n\\n__Default value:__ `\\\"miter\\\"`\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeMiterLimit\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The miter limit at which to bevel a line join.\",\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeOpacity\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke opacity (value between [0,1]).\\n\\n__Default value:__ `1`\",\n                            \"maximum\": 1,\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                },\n                \"strokeWidth\": {\n                    \"anyOf\": [\n                        {\n                            \"description\": \"The stroke width, in pixels.\",\n                            \"minimum\": 0,\n                            \"type\": \"number\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/ExprRef\"\n                        }\n                    ]\n                }\n            },\n            \"type\": \"object\"\n        },\n        \"WindowEventType\": {\n            \"anyOf\": [\n                {\n                    \"$ref\": \"#/definitions/EventType\"\n                },\n                {\n                    \"type\": \"string\"\n                }\n            ]\n        },\n        \"WindowFieldDef\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"as\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The output name for the window operation.\"\n                },\n                \"field\": {\n                    \"$ref\": \"#/definitions/FieldName\",\n                    \"description\": \"The data field for which to compute the aggregate or window function. This can be omitted for window functions that do not operate over a field such as `\\\"count\\\"`, `\\\"rank\\\"`, `\\\"dense_rank\\\"`.\"\n                },\n                \"op\": {\n                    \"anyOf\": [\n                        {\n                            \"$ref\": \"#/definitions/AggregateOp\"\n                        },\n                        {\n                            \"$ref\": \"#/definitions/WindowOnlyOp\"\n                        }\n                    ],\n                    \"description\": \"The window or aggregation operation to apply within a window (e.g., `\\\"rank\\\"`, `\\\"lead\\\"`, `\\\"sum\\\"`, `\\\"average\\\"` or `\\\"count\\\"`). See the list of all supported operations [here](https://vega.github.io/vega-lite/docs/window.html#ops).\"\n                },\n                \"param\": {\n                    \"description\": \"Parameter values for the window functions. Parameter values can be omitted for operations that do not accept a parameter.\\n\\nSee the list of all supported operations and their parameters [here](https://vega.github.io/vega-lite/docs/transforms/window.html).\",\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [\n                \"op\",\n                \"as\"\n            ],\n            \"type\": \"object\"\n        },\n        \"WindowOnlyOp\": {\n            \"enum\": [\n                \"row_number\",\n                \"rank\",\n                \"dense_rank\",\n                \"percent_rank\",\n                \"cume_dist\",\n                \"ntile\",\n                \"lag\",\n                \"lead\",\n                \"first_value\",\n                \"last_value\",\n                \"nth_value\"\n            ],\n            \"type\": \"string\"\n        },\n        \"WindowTransform\": {\n            \"additionalProperties\": false,\n            \"properties\": {\n                \"frame\": {\n                    \"description\": \"A frame specification as a two-element array indicating how the sliding window should proceed. The array entries should either be a number indicating the offset from the current data object, or null to indicate unbounded rows preceding or following the current data object. The default value is `[null, 0]`, indicating that the sliding window includes the current object and all preceding objects. The value `[-5, 5]` indicates that the window should include five objects preceding and five objects following the current object. Finally, `[null, null]` indicates that the window frame should always include all data objects. If you this frame and want to assign the same value to add objects, you can use the simpler [join aggregate transform](https://vega.github.io/vega-lite/docs/joinaggregate.html). The only operators affected are the aggregation operations and the `first_value`, `last_value`, and `nth_value` window operations. The other window operations are not affected by this.\\n\\n__Default value:__:  `[null, 0]` (includes the current object and all preceding objects)\",\n                    \"items\": {\n                        \"type\": [\n                            \"null\",\n                            \"number\"\n                        ]\n                    },\n                    \"type\": \"array\"\n                },\n                \"groupby\": {\n                    \"description\": \"The data fields for partitioning the data objects into separate windows. If unspecified, all data points will be in a single window.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/FieldName\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"ignorePeers\": {\n                    \"description\": \"Indicates if the sliding window frame should ignore peer values (data that are considered identical by the sort criteria). The default is false, causing the window frame to expand to include all peer values. If set to true, the window frame will be defined by offset values only. This setting only affects those operations that depend on the window frame, namely aggregation operations and the first_value, last_value, and nth_value window operations.\\n\\n__Default value:__ `false`\",\n                    \"type\": \"boolean\"\n                },\n                \"sort\": {\n                    \"description\": \"A sort field definition for sorting data objects within a window. If two data objects are considered equal by the comparator, they are considered \\\"peer\\\" values of equal rank. If sort is not specified, the order is undefined: data objects are processed in the order they are observed and none are considered peers (the ignorePeers parameter is ignored and treated as if set to `true`).\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/SortField\"\n                    },\n                    \"type\": \"array\"\n                },\n                \"window\": {\n                    \"description\": \"The definition of the fields in the window, and what calculations to use.\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/WindowFieldDef\"\n                    },\n                    \"type\": \"array\"\n                }\n            },\n            \"required\": [\n                \"window\"\n            ],\n            \"type\": \"object\"\n        }\n    }\n}"
  },
  {
    "path": "wren-ai-service/src/pipelines/indexing/__init__.py",
    "content": "import asyncio\nimport json\nimport logging\nimport re\nfrom typing import Any, Dict, List, Optional\n\nimport orjson\nfrom haystack import Document, component\nfrom haystack.components.writers import DocumentWriter\nfrom haystack.document_stores.types import DocumentStore, DuplicatePolicy\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n@component\nclass DocumentCleaner:\n    \"\"\"\n    This component is used to clear all the documents in the specified document store(s).\n\n    \"\"\"\n\n    def __init__(self, stores: List[DocumentStore]) -> None:\n        self._stores = stores\n\n    @component.output_types()\n    async def run(self, project_id: Optional[str] = None) -> None:\n        async def _clear_documents(\n            store: DocumentStore, project_id: Optional[str] = None\n        ) -> None:\n            store_name = (\n                store.to_dict().get(\"init_parameters\", {}).get(\"index\", \"unknown\")\n            )\n            logger.info(f\"Project ID: {project_id}, Cleaning documents in {store_name}\")\n            filters = (\n                {\n                    \"operator\": \"AND\",\n                    \"conditions\": [\n                        {\"field\": \"project_id\", \"operator\": \"==\", \"value\": project_id},\n                    ],\n                }\n                if project_id\n                else None\n            )\n            await store.delete_documents(filters)\n\n        await asyncio.gather(\n            *[_clear_documents(store, project_id) for store in self._stores]\n        )\n\n\n@component\nclass MDLValidator:\n    \"\"\"\n    Validate the MDL to check if it is a valid JSON and contains the required keys.\n    \"\"\"\n\n    @component.output_types(mdl=Dict[str, Any])\n    def run(self, mdl: str) -> str:\n        try:\n            mdl_json = orjson.loads(mdl)\n            logger.info(f\"MDL JSON: {mdl_json}\")\n        except json.JSONDecodeError as e:\n            raise ValueError(f\"Invalid JSON: {e}\")\n        if \"models\" not in mdl_json:\n            mdl_json[\"models\"] = []\n        if \"views\" not in mdl_json:\n            mdl_json[\"views\"] = []\n        if \"relationships\" not in mdl_json:\n            mdl_json[\"relationships\"] = []\n        if \"metrics\" not in mdl_json:\n            mdl_json[\"metrics\"] = []\n\n        return {\"mdl\": mdl_json}\n\n\n@component\nclass AsyncDocumentWriter(DocumentWriter):\n    @component.output_types(documents_written=int)\n    async def run(\n        self, documents: List[Document], policy: Optional[DuplicatePolicy] = None\n    ):\n        if policy is None:\n            policy = self.policy\n\n        documents_written = await self.document_store.write_documents(\n            documents=documents, policy=policy\n        )\n        return {\"documents_written\": documents_written}\n\n\ndef clean_display_name(display_name: str) -> str:\n    if not display_name:\n        return display_name\n\n    # Define invalid character sets based on comments and test expectations\n    # Numbers are only invalid at prefix, not in middle or suffix\n    prefix_invalid = set(\n        [\n            \"-\",\n            \"&\",\n            \"%\",\n            \"=\",\n            \"+\",\n            \"'\",\n            '\"',\n            \"<\",\n            \">\",\n            \"#\",\n            \"|\",\n            \"!\",\n            \"(\",\n            \")\",\n            \"*\",\n            \",\",\n            \"/\",\n            \";\",\n            \"[\",\n            \"\\\\\",\n            \"]\",\n            \"^\",\n            \"{\",\n            \"}\",\n            \"~\",\n            \"0\",\n            \"1\",\n            \"2\",\n            \"3\",\n            \"4\",\n            \"5\",\n            \"6\",\n            \"7\",\n            \"8\",\n            \"9\",\n            \"\\x00\",\n            \".\",\n        ]\n    )\n    middle_invalid = set(\n        [\n            \"-\",\n            \"&\",\n            \"%\",\n            \"=\",\n            \"+\",\n            \"'\",\n            '\"',\n            \"<\",\n            \">\",\n            \"#\",\n            \"|\",\n            \"!\",\n            \"(\",\n            \")\",\n            \"/\",\n            \"?\",\n            \"[\",\n            \"\\\\\",\n            \"]\",\n            \"^\",\n            \"`\",\n            \"{\",\n            \"}\",\n            \"~\",\n            \".\",\n            \"*\",\n            \"@\",\n            \"$\",\n        ]\n    )\n    suffix_invalid = set(\n        [\n            \"-\",\n            \"&\",\n            \"%\",\n            \"=\",\n            \"+\",\n            \":\",\n            \"'\",\n            '\"',\n            \"<\",\n            \">\",\n            \"#\",\n            \"|\",\n            \"!\",\n            \"(\",\n            \")\",\n            \",\",\n            \".\",\n            \"/\",\n            \"@\",\n            \"[\",\n            \"\\\\\",\n            \"]\",\n            \"^\",\n            \"{\",\n            \"}\",\n            \"~\",\n        ]\n    )\n\n    result = list(display_name)\n    prefix_prepended = False\n\n    # Handle prefix invalid characters\n    if len(result) > 0 and result[0] in prefix_invalid:\n        # For numbers, prepend underscore; for other chars, replace with underscore\n        if result[0].isdigit():\n            result.insert(0, \"_\")\n            prefix_prepended = True\n        else:\n            result[0] = \"_\"\n\n    # Handle middle invalid characters (account for prepended prefix)\n    start_idx = 2 if prefix_prepended else 1\n    end_idx = len(result) - 1\n    for i in range(start_idx, end_idx):\n        if result[i] in middle_invalid:\n            result[i] = \"_\"\n\n    # Handle suffix invalid characters\n    if len(result) > 1 and result[-1] in suffix_invalid:\n        result[-1] = \"_\"\n\n    # Handle single character case\n    original_len = len(display_name)\n    if original_len == 1:\n        char = display_name[0]\n        # For single character, always replace with underscore (don't prepend)\n        if char in prefix_invalid or char in suffix_invalid:\n            result = [\"_\"]\n\n    cleaned = \"\".join(result)\n\n    # Collapse multiple consecutive underscores\n    cleaned = re.sub(r\"_+\", \"_\", cleaned)\n\n    return cleaned\n\n\n# Put the pipelines imports here to avoid circular imports and make them accessible directly to the rest of packages\nfrom .db_schema import DBSchema  # noqa: E402\nfrom .historical_question import HistoricalQuestion  # noqa: E402\nfrom .instructions import Instructions  # noqa: E402\nfrom .project_meta import ProjectMeta  # noqa: E402\nfrom .sql_pairs import SqlPairs  # noqa: E402\nfrom .table_description import TableDescription  # noqa: E402\n\n__all__ = [\n    \"DBSchema\",\n    \"TableDescription\",\n    \"HistoricalQuestion\",\n    \"SqlPairs\",\n    \"Instructions\",\n    \"ProjectMeta\",\n]\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/indexing/db_schema.py",
    "content": "import asyncio\nimport logging\nimport sys\nimport uuid\nfrom typing import Any, Dict, List, Optional\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom hamilton.function_modifiers import extract_fields\nfrom haystack import Document, component\nfrom haystack.components.writers import DocumentWriter\nfrom haystack.document_stores.types import DuplicatePolicy\nfrom langfuse.decorators import observe\nfrom tqdm import tqdm\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import DocumentStoreProvider, EmbedderProvider\nfrom src.pipelines.indexing import (\n    AsyncDocumentWriter,\n    DocumentCleaner,\n    MDLValidator,\n    clean_display_name,\n)\nfrom src.pipelines.indexing.utils import helper\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n@component\nclass DDLChunker:\n    @component.output_types(documents=List[Document])\n    async def run(\n        self,\n        mdl: Dict[str, Any],\n        column_batch_size: int,\n        project_id: Optional[str] = None,\n    ):\n        def _additional_meta() -> Dict[str, Any]:\n            return {\"project_id\": project_id} if project_id else {}\n\n        chunks = [\n            {\n                \"id\": str(uuid.uuid4()),\n                \"meta\": {\n                    \"type\": \"TABLE_SCHEMA\",\n                    \"name\": chunk[\"name\"],\n                    **_additional_meta(),\n                },\n                \"content\": chunk[\"payload\"],\n            }\n            for chunk in await self._get_ddl_commands(\n                **mdl, column_batch_size=column_batch_size\n            )\n        ]\n\n        return {\n            \"documents\": [\n                Document(**chunk)\n                for chunk in tqdm(\n                    chunks,\n                    desc=f\"Project ID: {project_id}, Chunking DDL commands into documents\",\n                )\n            ]\n        }\n\n    async def _model_preprocessor(\n        self, models: List[Dict[str, Any]], **kwargs\n    ) -> List[Dict[str, Any]]:\n        def _column_preprocessor(\n            column: Dict[str, Any], addition: Dict[str, Any]\n        ) -> Dict[str, Any]:\n            addition = {\n                key: helper(column, **addition)\n                for key, helper in helper.COLUMN_PREPROCESSORS.items()\n                if helper.condition(column, **addition)\n            }\n\n            return {\n                \"name\": column.get(\"name\", \"\"),\n                \"type\": column.get(\"type\", \"\"),\n                **addition,\n            }\n\n        async def _preprocessor(model: Dict[str, Any], **kwargs) -> Dict[str, Any]:\n            addition = {\n                key: await helper(model, **kwargs)\n                for key, helper in helper.MODEL_PREPROCESSORS.items()\n                if helper.condition(model, **kwargs)\n            }\n\n            columns = [\n                _column_preprocessor(column, addition)\n                for column in model.get(\"columns\", [])\n                if column.get(\"isHidden\") is not True\n            ]\n            return {\n                \"name\": model.get(\"name\", \"\"),\n                \"properties\": model.get(\"properties\", {}),\n                \"columns\": columns,\n                \"primaryKey\": model.get(\"primaryKey\", \"\"),\n            }\n\n        tasks = [_preprocessor(model, **kwargs) for model in models]\n\n        return await asyncio.gather(*tasks)\n\n    async def _get_ddl_commands(\n        self,\n        models: List[Dict[str, Any]],\n        relationships: List[Dict[str, Any]],\n        views: List[Dict[str, Any]],\n        metrics: List[Dict[str, Any]],\n        column_batch_size: int = 50,\n        **kwargs,\n    ) -> List[dict]:\n        return (\n            self._convert_models_and_relationships(\n                await self._model_preprocessor(models, **kwargs),\n                relationships,\n                column_batch_size,\n            )\n            + self._convert_views(views)\n            + self._convert_metrics(metrics)\n        )\n\n    def _convert_models_and_relationships(\n        self,\n        models: List[Dict[str, Any]],\n        relationships: List[Dict[str, Any]],\n        column_batch_size: int,\n    ) -> List[Dict[str, str]]:\n        def _model_command(model: Dict[str, Any]) -> dict:\n            properties = model.get(\"properties\", {})\n\n            model_properties = {\n                \"alias\": clean_display_name(properties.get(\"displayName\", \"\")),\n                \"description\": properties.get(\"description\", \"\"),\n            }\n            comment = f\"\\n/* {str(model_properties)} */\\n\"\n\n            table_name = model[\"name\"]\n            payload = {\n                \"type\": \"TABLE\",\n                \"comment\": comment,\n                \"name\": table_name,\n            }\n            return {\"name\": table_name, \"payload\": str(payload)}\n\n        def _column_command(column: Dict[str, Any], model: Dict[str, Any]) -> dict:\n            if column.get(\"relationship\"):\n                return None\n\n            comments = [\n                helper(column, model=model)\n                for helper in helper.COLUMN_COMMENT_HELPERS.values()\n                if helper.condition(column)\n            ]\n\n            return {\n                \"type\": \"COLUMN\",\n                \"comment\": \"\".join(comments),\n                \"name\": column[\"name\"],\n                \"data_type\": column[\"type\"],\n                \"is_primary_key\": column[\"name\"] == model[\"primaryKey\"],\n            }\n\n        def _relationship_command(\n            relationship: Dict[str, Any],\n            table_name: str,\n            primary_keys_map: Dict[str, str],\n        ) -> dict:\n            condition = relationship.get(\"condition\", \"\")\n            join_type = relationship.get(\"joinType\", \"\")\n            models = relationship.get(\"models\", [])\n\n            if len(models) != 2:\n                return None\n\n            if table_name not in models:\n                return None\n\n            if join_type not in [\"MANY_TO_ONE\", \"ONE_TO_MANY\", \"ONE_TO_ONE\"]:\n                return None\n\n            # Get related table and foreign key column\n            is_source = table_name == models[0]\n            related_table = models[1] if is_source else models[0]\n            condition_parts = condition.split(\" = \")\n            fk_column = condition_parts[0 if is_source else 1].split(\".\")[1]\n\n            # Build foreign key constraint\n            fk_constraint = f\"FOREIGN KEY ({fk_column}) REFERENCES {related_table}({primary_keys_map[related_table]})\"\n\n            return {\n                \"type\": \"FOREIGN_KEY\",\n                \"comment\": f'-- {{\"condition\": {condition}, \"joinType\": {join_type}}}\\n  ',\n                \"constraint\": fk_constraint,\n                \"tables\": models,\n            }\n\n        def _column_batch(\n            model: Dict[str, Any], primary_keys_map: Dict[str, str]\n        ) -> List[dict]:\n            commands = [\n                _column_command(column, model) for column in model[\"columns\"]\n            ] + [\n                _relationship_command(relationship, model[\"name\"], primary_keys_map)\n                for relationship in relationships\n            ]\n\n            filtered = [command for command in commands if command is not None]\n\n            return [\n                {\n                    \"name\": model[\"name\"],\n                    \"payload\": str(\n                        {\n                            \"type\": \"TABLE_COLUMNS\",\n                            \"columns\": filtered[i : i + column_batch_size],\n                        }\n                    ),\n                }\n                for i in range(0, len(filtered), column_batch_size)\n            ]\n\n        # A map to store model primary keys for foreign key relationships\n        primary_keys_map = {model[\"name\"]: model[\"primaryKey\"] for model in models}\n\n        return [\n            command\n            for model in models\n            for command in _column_batch(model, primary_keys_map)\n            + [_model_command(model)]\n        ]\n\n    def _convert_views(self, views: List[Dict[str, Any]]) -> List[Dict[str, str]]:\n        def _payload(view: Dict[str, Any]) -> dict:\n            return {\n                \"type\": \"VIEW\",\n                \"comment\": f\"/* {view['properties']} */\\n\"\n                if \"properties\" in view\n                else \"\",\n                \"name\": view[\"name\"],\n                \"statement\": view[\"statement\"],\n            }\n\n        return [\n            {\"name\": view[\"name\"], \"payload\": str(_payload(view))} for view in views\n        ]\n\n    def _convert_metrics(self, metrics: List[Dict[str, Any]]) -> List[Dict[str, str]]:\n        def _create_column(name: str, data_type: str, comment: str) -> dict:\n            return {\n                \"type\": \"COLUMN\",\n                \"comment\": comment,\n                \"name\": name,\n                \"data_type\": data_type,\n            }\n\n        def _dimensions(metric: Dict[str, Any]) -> List[dict]:\n            return [\n                _create_column(\n                    name=dim.get(\"name\", \"\"),\n                    data_type=dim.get(\"type\", \"\"),\n                    comment=\"-- This column is a dimension\\n  \",\n                )\n                for dim in metric.get(\"dimension\", [])\n            ]\n\n        def _measures(metric: Dict[str, Any]) -> List[dict]:\n            return [\n                _create_column(\n                    name=measure.get(\"name\", \"\"),\n                    data_type=measure.get(\"type\", \"\"),\n                    comment=f\"-- This column is a measure\\n  -- expression: {measure['expression']}\\n  \",\n                )\n                for measure in metric.get(\"measure\", [])\n            ]\n\n        def _payload(metric: Dict[str, Any]) -> dict:\n            return {\n                \"type\": \"METRIC\",\n                \"comment\": f\"\\n/* This table is a metric */\\n/* Metric Base Object: {metric['baseObject']} */\\n\",\n                \"name\": metric[\"name\"],\n                \"columns\": _dimensions(metric) + _measures(metric),\n            }\n\n        return [\n            {\"name\": metric[\"name\"], \"payload\": str(_payload(metric))}\n            for metric in metrics\n        ]\n\n\n## Start of Pipeline\n@observe(capture_input=False, capture_output=False)\n@extract_fields(dict(mdl=Dict[str, Any]))\ndef validate_mdl(mdl_str: str, validator: MDLValidator) -> Dict[str, Any]:\n    res = validator.run(mdl=mdl_str)\n    return dict(mdl=res[\"mdl\"])\n\n\n@observe(capture_input=False)\nasync def chunk(\n    mdl: Dict[str, Any],\n    chunker: DDLChunker,\n    column_batch_size: int,\n    project_id: Optional[str] = None,\n) -> Dict[str, Any]:\n    return await chunker.run(\n        mdl=mdl,\n        column_batch_size=column_batch_size,\n        project_id=project_id,\n    )\n\n\n@observe(capture_input=False, capture_output=False)\nasync def embedding(chunk: Dict[str, Any], embedder: Any) -> Dict[str, Any]:\n    return await embedder.run(documents=chunk[\"documents\"])\n\n\n@observe(capture_input=False, capture_output=False)\nasync def clean(\n    embedding: Dict[str, Any],\n    cleaner: DocumentCleaner,\n    project_id: Optional[str] = None,\n) -> Dict[str, Any]:\n    await cleaner.run(project_id=project_id)\n    return embedding\n\n\n@observe(capture_input=False)\nasync def write(clean: Dict[str, Any], writer: DocumentWriter) -> None:\n    return await writer.run(documents=clean[\"documents\"])\n\n\n## End of Pipeline\n\n\nclass DBSchema(BasicPipeline):\n    def __init__(\n        self,\n        embedder_provider: EmbedderProvider,\n        document_store_provider: DocumentStoreProvider,\n        column_batch_size: int = 50,\n        **kwargs,\n    ) -> None:\n        dbschema_store = document_store_provider.get_store()\n\n        self._components = {\n            \"cleaner\": DocumentCleaner([dbschema_store]),\n            \"validator\": MDLValidator(),\n            \"embedder\": embedder_provider.get_document_embedder(),\n            \"chunker\": DDLChunker(),\n            \"writer\": AsyncDocumentWriter(\n                document_store=dbschema_store,\n                policy=DuplicatePolicy.OVERWRITE,\n            ),\n        }\n        self._configs = {\n            \"column_batch_size\": column_batch_size,\n        }\n        self._final = \"write\"\n\n        helper.load_helpers()\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"DB Schema Indexing\")\n    async def run(\n        self, mdl_str: str, project_id: Optional[str] = None\n    ) -> Dict[str, Any]:\n        logger.info(\n            f\"Project ID: {project_id}, DB Schema Indexing pipeline is running...\"\n        )\n        return await self._pipe.execute(\n            [self._final],\n            inputs={\n                \"mdl_str\": mdl_str,\n                \"project_id\": project_id,\n                **self._components,\n                **self._configs,\n            },\n        )\n\n    @observe(name=\"Clean Documents for DB Schema\")\n    async def clean(self, project_id: Optional[str] = None) -> None:\n        await clean(\n            embedding={\"documents\": []},\n            cleaner=self._components[\"cleaner\"],\n            project_id=project_id,\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/indexing/historical_question.py",
    "content": "import logging\nimport sys\nimport uuid\nfrom typing import Any, Dict, List, Optional\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom hamilton.function_modifiers import extract_fields\nfrom haystack import Document, component\nfrom haystack.components.writers import DocumentWriter\nfrom haystack.document_stores.types import DuplicatePolicy\nfrom langfuse.decorators import observe\nfrom tqdm import tqdm\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import DocumentStoreProvider, EmbedderProvider\nfrom src.pipelines.indexing import AsyncDocumentWriter, DocumentCleaner, MDLValidator\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n@component\nclass ViewChunker:\n    \"\"\"\n    A component that processes views from an MDL (Model Definition Language) file and converts them into Document objects.\n\n    The component takes views in the following MDL format:\n    {\n        \"views\": [\n            {\n                \"statement\": \"SELECT * FROM employees\",\n                \"properties\": {\n                    \"historical_queries\": [], # List of previous related queries\n                    \"question\": \"What is the average salary of employees?\", # Current query\n                    \"summary\": \"The average salary of employees is $50,000.\", # Summary for the query\n                    \"viewId\": \"1234567890\" # Unique identifier\n                }\n            }\n        ]\n    }\n\n    And converts each view into a Document with:\n    - content: Concatenated string of historical queries and current question\n    - meta: Dictionary containing:\n        {\n            \"summary\": \"Generated description/answer\",\n            \"statement\": \"SQL statement\",\n            \"viewId\": \"Unique view identifier\",\n            \"project_id\": \"Optional project identifier\"\n        }\n\n    The Documents are then stored in the document store for later retrieval.\n    \"\"\"\n\n    @component.output_types(documents=List[Document])\n    def run(self, mdl: Dict[str, Any], project_id: Optional[str] = None) -> None:\n        def _get_content(view: Dict[str, Any]) -> str:\n            properties = view.get(\"properties\", {})\n            historical_queries = properties.get(\"historical_queries\", [])\n            question = properties.get(\"question\", \"\")\n\n            return \" \".join(historical_queries + [question])\n\n        def _get_meta(view: Dict[str, Any]) -> Dict[str, Any]:\n            properties = view.get(\"properties\", {})\n            return {\n                \"summary\": properties.get(\"summary\", \"\"),\n                \"statement\": view.get(\"statement\", \"\"),\n                \"viewId\": properties.get(\"viewId\", \"\"),\n            }\n\n        def _additional_meta() -> Dict[str, Any]:\n            return {\"project_id\": project_id} if project_id else {}\n\n        chunks = [\n            {\n                \"id\": str(uuid.uuid4()),\n                \"content\": _get_content(view),\n                \"meta\": {**_get_meta(view), **_additional_meta()},\n            }\n            for view in mdl[\"views\"]\n        ]\n\n        return {\n            \"documents\": [\n                Document(**chunk)\n                for chunk in tqdm(\n                    chunks,\n                    desc=f\"Project ID: {project_id}, Chunking views into documents\",\n                )\n            ]\n        }\n\n\n## Start of Pipeline\n@observe(capture_input=False, capture_output=False)\n@extract_fields(dict(mdl=Dict[str, Any]))\ndef validate_mdl(mdl_str: str, validator: MDLValidator) -> Dict[str, Any]:\n    res = validator.run(mdl=mdl_str)\n    return dict(mdl=res[\"mdl\"])\n\n\n@observe(capture_input=False)\ndef chunk(\n    mdl: Dict[str, Any],\n    chunker: ViewChunker,\n    project_id: Optional[str] = None,\n) -> Dict[str, Any]:\n    return chunker.run(mdl=mdl, project_id=project_id)\n\n\n@observe(capture_input=False, capture_output=False)\nasync def embedding(chunk: Dict[str, Any], embedder: Any) -> Dict[str, Any]:\n    return await embedder.run(documents=chunk[\"documents\"])\n\n\n@observe(capture_input=False, capture_output=False)\nasync def clean(\n    embedding: Dict[str, Any],\n    cleaner: DocumentCleaner,\n    project_id: Optional[str] = None,\n) -> Dict[str, Any]:\n    await cleaner.run(project_id=project_id)\n    return embedding\n\n\n@observe(capture_input=False)\nasync def write(clean: Dict[str, Any], writer: DocumentWriter) -> None:\n    return await writer.run(documents=clean[\"documents\"])\n\n\n## End of Pipeline\n\n\nclass HistoricalQuestion(BasicPipeline):\n    def __init__(\n        self,\n        embedder_provider: EmbedderProvider,\n        document_store_provider: DocumentStoreProvider,\n        **kwargs,\n    ) -> None:\n        # keep the store name as it is for now, might change in the future\n        store = document_store_provider.get_store(dataset_name=\"view_questions\")\n\n        self._components = {\n            \"cleaner\": DocumentCleaner([store]),\n            \"validator\": MDLValidator(),\n            \"embedder\": embedder_provider.get_document_embedder(),\n            \"chunker\": ViewChunker(),\n            \"writer\": AsyncDocumentWriter(\n                document_store=store,\n                policy=DuplicatePolicy.OVERWRITE,\n            ),\n        }\n        self._configs = {}\n        self._final = \"write\"\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"Historical Question Indexing\")\n    async def run(\n        self, mdl_str: str, project_id: Optional[str] = None\n    ) -> Dict[str, Any]:\n        logger.info(\n            f\"Project ID: {project_id}, Historical Question Indexing pipeline is running...\"\n        )\n        return await self._pipe.execute(\n            [self._final],\n            inputs={\n                \"mdl_str\": mdl_str,\n                \"project_id\": project_id,\n                **self._components,\n                **self._configs,\n            },\n        )\n\n    @observe(name=\"Clean Documents for Historical Question\")\n    async def clean(self, project_id: Optional[str] = None) -> None:\n        await clean(\n            embedding={\"documents\": []},\n            cleaner=self._components[\"cleaner\"],\n            project_id=project_id,\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/indexing/instructions.py",
    "content": "import logging\nimport sys\nimport uuid\nfrom typing import Any, Dict, List, Literal, Optional\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack import Document, component\nfrom haystack.document_stores.types import DocumentStore, DuplicatePolicy\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import DocumentStoreProvider, EmbedderProvider\nfrom src.pipelines.indexing import AsyncDocumentWriter\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nclass Instruction(BaseModel):\n    id: str\n    instruction: str = \"\"\n    question: str = \"\"\n    # This is used to identify the default instruction needed to be retrieved for the project\n    is_default: bool = False\n    scope: Literal[\"sql\", \"answer\", \"chart\"] = \"sql\"\n\n\n@component\nclass InstructionsConverter:\n    @component.output_types(documents=List[Document])\n    def run(self, instructions: list[Instruction], project_id: str = \"\"):\n        logger.info(f\"Project ID: {project_id} Converting instructions to documents...\")\n\n        addition = {\"project_id\": project_id} if project_id else {}\n\n        return {\n            \"documents\": [\n                Document(\n                    id=str(uuid.uuid4()),\n                    meta={\n                        \"instruction_id\": instruction.id,\n                        \"instruction\": instruction.instruction,\n                        \"is_default\": instruction.is_default,\n                        \"scope\": instruction.scope,\n                        **addition,\n                    },\n                    content=\"this is a global instruction, so no question is provided\"\n                    if instruction.is_default\n                    else instruction.question,\n                )\n                for instruction in instructions\n            ]\n        }\n\n\n@component\nclass InstructionsCleaner:\n    def __init__(self, instructions_store: DocumentStore) -> None:\n        self.store = instructions_store\n\n    @component.output_types()\n    async def run(\n        self, instruction_ids: List[str], project_id: Optional[str] = None\n    ) -> None:\n        filter = {\n            \"operator\": \"AND\",\n            \"conditions\": [\n                {\"field\": \"instruction_id\", \"operator\": \"in\", \"value\": instruction_ids},\n            ],\n        }\n\n        if project_id:\n            filter[\"conditions\"].append(\n                {\"field\": \"project_id\", \"operator\": \"==\", \"value\": project_id}\n            )\n\n        return await self.store.delete_documents(filter)\n\n\n## Start of Pipeline\n\n\n@observe(capture_input=False)\ndef to_documents(\n    instructions: List[Instruction],\n    document_converter: InstructionsConverter,\n    project_id: str = \"\",\n) -> Dict[str, Any]:\n    return document_converter.run(instructions=instructions, project_id=project_id)\n\n\n@observe(capture_input=False, capture_output=False)\nasync def embedding(\n    to_documents: Dict[str, Any],\n    embedder: Any,\n) -> Dict[str, Any]:\n    return await embedder.run(documents=to_documents[\"documents\"])\n\n\n@observe(capture_input=False, capture_output=False)\nasync def clean(\n    cleaner: InstructionsCleaner,\n    instructions: List[Instruction],\n    embedding: Dict[str, Any] = {},\n    project_id: str = \"\",\n    delete_all: bool = False,\n) -> Dict[str, Any]:\n    instruction_ids = [instruction.id for instruction in instructions]\n    if instruction_ids or delete_all:\n        await cleaner.run(instruction_ids=instruction_ids, project_id=project_id)\n\n    return embedding\n\n\n@observe(capture_input=False)\nasync def write(\n    clean: Dict[str, Any],\n    writer: AsyncDocumentWriter,\n) -> None:\n    return await writer.run(documents=clean[\"documents\"])\n\n\n## End of Pipeline\n\n\nclass Instructions(BasicPipeline):\n    def __init__(\n        self,\n        embedder_provider: EmbedderProvider,\n        document_store_provider: DocumentStoreProvider,\n        **kwargs,\n    ) -> None:\n        store = document_store_provider.get_store(dataset_name=\"instructions\")\n\n        self._components = {\n            \"cleaner\": InstructionsCleaner(store),\n            \"embedder\": embedder_provider.get_document_embedder(),\n            \"document_converter\": InstructionsConverter(),\n            \"writer\": AsyncDocumentWriter(\n                document_store=store,\n                policy=DuplicatePolicy.OVERWRITE,\n            ),\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"Instructions Indexing\")\n    async def run(\n        self,\n        instructions: list[Instruction],\n        project_id: str = \"\",\n    ) -> Dict[str, Any]:\n        logger.info(\n            f\"Project ID: {project_id} Instructions Indexing pipeline is running...\"\n        )\n\n        input = {\n            \"project_id\": project_id,\n            \"instructions\": instructions,\n            **self._components,\n        }\n\n        return await self._pipe.execute([\"write\"], inputs=input)\n\n    @observe(name=\"Clean Documents for Instructions\")\n    async def clean(\n        self,\n        instructions: Optional[List[Instruction]] = None,\n        project_id: Optional[str] = None,\n        delete_all: bool = False,\n    ) -> None:\n        await clean(\n            instructions=instructions or [],\n            cleaner=self._components[\"cleaner\"],\n            project_id=project_id,\n            delete_all=delete_all,\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/indexing/project_meta.py",
    "content": "import logging\nimport sys\nimport uuid\nfrom typing import Any, Optional\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom hamilton.function_modifiers import extract_fields\nfrom haystack import Document\nfrom haystack.components.writers import DocumentWriter\nfrom haystack.document_stores.types import DuplicatePolicy\nfrom langfuse.decorators import observe\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import DocumentStoreProvider\nfrom src.pipelines.indexing import AsyncDocumentWriter, DocumentCleaner, MDLValidator\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n## Start of Pipeline\n@observe(capture_input=False, capture_output=False)\n@extract_fields(dict(mdl=dict[str, Any]))\ndef validate_mdl(mdl_str: str, validator: MDLValidator) -> dict[str, Any]:\n    res = validator.run(mdl=mdl_str)\n    return dict(mdl=res[\"mdl\"])\n\n\n@observe(capture_input=False)\ndef chunk(\n    mdl: dict[str, Any],\n    project_id: Optional[str] = None,\n) -> dict[str, Any]:\n    addition = {\"project_id\": project_id} if project_id else {}\n    data_source = mdl.get(\"dataSource\", \"local_file\").lower()\n\n    if data_source == \"duckdb\":\n        # fix duckdb to local_file due to wren-ibis implementation at the moment\n        data_source = \"local_file\"\n\n    document = Document(\n        id=str(uuid.uuid4()),\n        meta={\"data_source\": data_source, **addition},\n    )\n    return {\"documents\": [document]}\n\n\n@observe(capture_input=False, capture_output=False)\nasync def clean(\n    chunk: dict[str, Any],\n    cleaner: DocumentCleaner,\n    project_id: Optional[str] = None,\n) -> dict[str, Any]:\n    await cleaner.run(project_id=project_id)\n    return chunk\n\n\n@observe(capture_input=False)\nasync def write(clean: dict[str, Any], writer: DocumentWriter) -> None:\n    return await writer.run(documents=clean[\"documents\"])\n\n\n## End of Pipeline\n\n\nclass ProjectMeta(BasicPipeline):\n    def __init__(\n        self,\n        document_store_provider: DocumentStoreProvider,\n        **kwargs,\n    ) -> None:\n        store = document_store_provider.get_store(dataset_name=\"project_meta\")\n\n        self._components = {\n            \"validator\": MDLValidator(),\n            \"cleaner\": DocumentCleaner([store]),\n            \"writer\": AsyncDocumentWriter(\n                document_store=store,\n                policy=DuplicatePolicy.OVERWRITE,\n            ),\n        }\n        self._final = \"write\"\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"Project Meta Indexing\")\n    async def run(\n        self, mdl_str: str, project_id: Optional[str] = None\n    ) -> dict[str, Any]:\n        logger.info(\n            f\"Project ID: {project_id}, Project Meta Indexing pipeline is running...\"\n        )\n        return await self._pipe.execute(\n            [self._final],\n            inputs={\n                \"mdl_str\": mdl_str,\n                \"project_id\": project_id,\n                **self._components,\n            },\n        )\n\n    @observe(name=\"Clean Documents for Project Meta\")\n    async def clean(self, project_id: Optional[str] = None) -> None:\n        await self._components[\"cleaner\"].run(project_id=project_id)\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/indexing/sql_pairs.py",
    "content": "import logging\nimport os\nimport sys\nimport uuid\nfrom typing import Any, Dict, List, Optional, Set\n\nimport orjson\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack import Document, component\nfrom haystack.document_stores.types import DocumentStore, DuplicatePolicy\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import DocumentStoreProvider, EmbedderProvider\nfrom src.pipelines.indexing import AsyncDocumentWriter\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nclass SqlPair(BaseModel):\n    id: str\n    sql: str = \"\"\n    question: str = \"\"\n\n\n@component\nclass SqlPairsConverter:\n    @component.output_types(documents=List[Document])\n    def run(self, sql_pairs: List[SqlPair], project_id: str = \"\"):\n        logger.info(f\"Project ID: {project_id} Converting SQL pairs to documents...\")\n\n        addition = {\"project_id\": project_id} if project_id else {}\n\n        return {\n            \"documents\": [\n                Document(\n                    id=str(uuid.uuid4()),\n                    meta={\n                        \"sql_pair_id\": sql_pair.id,\n                        \"sql\": sql_pair.sql,\n                        **addition,\n                    },\n                    content=sql_pair.question,\n                )\n                for sql_pair in sql_pairs\n            ]\n        }\n\n\n@component\nclass SqlPairsCleaner:\n    def __init__(self, sql_pairs_store: DocumentStore) -> None:\n        self.store = sql_pairs_store\n\n    @component.output_types()\n    async def run(\n        self, sql_pair_ids: List[str], project_id: Optional[str] = None\n    ) -> None:\n        filter = {\n            \"operator\": \"AND\",\n            \"conditions\": [\n                {\"field\": \"sql_pair_id\", \"operator\": \"in\", \"value\": sql_pair_ids},\n            ],\n        }\n\n        if project_id:\n            filter[\"conditions\"].append(\n                {\"field\": \"project_id\", \"operator\": \"==\", \"value\": project_id}\n            )\n\n        return await self.store.delete_documents(filter)\n\n\n## Start of Pipeline\n@observe(capture_input=False)\ndef boilerplates(\n    mdl_str: str,\n) -> Set[str]:\n    mdl = orjson.loads(mdl_str)\n\n    return {\n        boilerplate.lower()\n        for model in mdl.get(\"models\", [])\n        if (boilerplate := model.get(\"properties\", {}).get(\"boilerplate\"))\n    }\n\n\n@observe(capture_input=False)\ndef sql_pairs(\n    boilerplates: Set[str],\n    external_pairs: Dict[str, Any],\n) -> List[SqlPair]:\n    return [\n        SqlPair(\n            id=pair.get(\"id\"),\n            question=pair.get(\"question\"),\n            sql=pair.get(\"sql\"),\n        )\n        for boilerplate in boilerplates\n        if boilerplate in external_pairs\n        for pair in external_pairs[boilerplate]\n    ]\n\n\n@observe(capture_input=False)\ndef to_documents(\n    sql_pairs: List[SqlPair],\n    document_converter: SqlPairsConverter,\n    project_id: str = \"\",\n) -> Dict[str, Any]:\n    return document_converter.run(sql_pairs=sql_pairs, project_id=project_id)\n\n\n@observe(capture_input=False, capture_output=False)\nasync def embedding(\n    to_documents: Dict[str, Any],\n    embedder: Any,\n) -> Dict[str, Any]:\n    return await embedder.run(documents=to_documents[\"documents\"])\n\n\n@observe(capture_input=False, capture_output=False)\nasync def clean(\n    cleaner: SqlPairsCleaner,\n    sql_pairs: List[SqlPair],\n    embedding: Dict[str, Any] = {},\n    project_id: str = \"\",\n    delete_all: bool = False,\n) -> Dict[str, Any]:\n    sql_pair_ids = [sql_pair.id for sql_pair in sql_pairs]\n    if sql_pair_ids or delete_all:\n        await cleaner.run(sql_pair_ids=sql_pair_ids, project_id=project_id)\n\n    return embedding\n\n\n@observe(capture_input=False)\nasync def write(\n    clean: Dict[str, Any],\n    writer: AsyncDocumentWriter,\n) -> None:\n    return await writer.run(documents=clean[\"documents\"])\n\n\n## End of Pipeline\n\n\ndef _load_sql_pairs(sql_pairs_path: str) -> Dict[str, Any]:\n    if not sql_pairs_path:\n        return {}\n\n    if not os.path.exists(sql_pairs_path):\n        logger.warning(f\"SQL pairs file not found: {sql_pairs_path}\")\n        return {}\n\n    try:\n        with open(sql_pairs_path, \"r\") as file:\n            return orjson.loads(file.read())\n    except Exception as e:\n        logger.error(f\"Error loading SQL pairs file: {e}\")\n        return {}\n\n\nclass SqlPairs(BasicPipeline):\n    def __init__(\n        self,\n        embedder_provider: EmbedderProvider,\n        document_store_provider: DocumentStoreProvider,\n        sql_pairs_path: str = \"sql_pairs.json\",\n        **kwargs,\n    ) -> None:\n        store = document_store_provider.get_store(dataset_name=\"sql_pairs\")\n\n        self._components = {\n            \"cleaner\": SqlPairsCleaner(store),\n            \"embedder\": embedder_provider.get_document_embedder(),\n            \"document_converter\": SqlPairsConverter(),\n            \"writer\": AsyncDocumentWriter(\n                document_store=store,\n                policy=DuplicatePolicy.OVERWRITE,\n            ),\n        }\n\n        self._external_pairs = _load_sql_pairs(sql_pairs_path)\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"SQL Pairs Indexing\")\n    async def run(\n        self,\n        mdl_str: str,\n        project_id: str = \"\",\n        external_pairs: Optional[Dict[str, Any]] = None,\n    ) -> Dict[str, Any]:\n        logger.info(\n            f\"Project ID: {project_id} SQL Pairs Indexing pipeline is running...\"\n        )\n\n        input = {\n            \"mdl_str\": mdl_str,\n            \"project_id\": project_id,\n            \"external_pairs\": {\n                **self._external_pairs,\n                **(external_pairs or {}),\n            },\n            **self._components,\n        }\n\n        return await self._pipe.execute([\"write\"], inputs=input)\n\n    @observe(name=\"Clean Documents for SQL Pairs\")\n    async def clean(\n        self,\n        sql_pairs: List[SqlPair] = [],\n        project_id: Optional[str] = None,\n        delete_all: bool = False,\n    ) -> None:\n        await clean(\n            sql_pairs=sql_pairs,\n            cleaner=self._components[\"cleaner\"],\n            project_id=project_id,\n            delete_all=delete_all,\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/indexing/table_description.py",
    "content": "import logging\nimport sys\nimport uuid\nfrom typing import Any, Dict, List, Optional\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom hamilton.function_modifiers import extract_fields\nfrom haystack import Document, component\nfrom haystack.components.writers import DocumentWriter\nfrom haystack.document_stores.types import DuplicatePolicy\nfrom langfuse.decorators import observe\nfrom tqdm import tqdm\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import DocumentStoreProvider, EmbedderProvider\nfrom src.pipelines.indexing import AsyncDocumentWriter, DocumentCleaner, MDLValidator\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n@component\nclass TableDescriptionChunker:\n    @component.output_types(documents=List[Document])\n    def run(self, mdl: Dict[str, Any], project_id: Optional[str] = None):\n        def _additional_meta() -> Dict[str, Any]:\n            return {\"project_id\": project_id} if project_id else {}\n\n        chunks = [\n            {\n                \"id\": str(uuid.uuid4()),\n                \"meta\": {\n                    \"type\": \"TABLE_DESCRIPTION\",\n                    \"name\": chunk[\"name\"],\n                    **_additional_meta(),\n                },\n                \"content\": str(chunk),\n            }\n            for chunk in self._get_table_descriptions(mdl)\n        ]\n\n        return {\n            \"documents\": [\n                Document(**chunk)\n                for chunk in tqdm(\n                    chunks,\n                    desc=f\"Project ID: {project_id}, Chunking table descriptions into documents\",\n                )\n            ]\n        }\n\n    def _get_table_descriptions(self, mdl: Dict[str, Any]) -> List[str]:\n        def _structure_data(mdl_type: str, payload: Dict[str, Any]) -> Dict[str, Any]:\n            return {\n                \"mdl_type\": mdl_type,\n                \"name\": payload.get(\"name\"),\n                \"columns\": [column[\"name\"] for column in payload.get(\"columns\", [])],\n                \"properties\": payload.get(\"properties\", {}),\n            }\n\n        resources = (\n            [_structure_data(\"MODEL\", model) for model in mdl[\"models\"]]\n            + [_structure_data(\"METRIC\", metric) for metric in mdl[\"metrics\"]]\n            + [_structure_data(\"VIEW\", view) for view in mdl[\"views\"]]\n        )\n\n        return [\n            {\n                \"name\": resource[\"name\"],\n                \"description\": resource[\"properties\"].get(\"description\", \"\"),\n                \"columns\": \", \".join(resource[\"columns\"]),\n            }\n            for resource in resources\n            if resource[\"name\"] is not None\n        ]\n\n\n## Start of Pipeline\n@observe(capture_input=False, capture_output=False)\n@extract_fields(dict(mdl=Dict[str, Any]))\ndef validate_mdl(mdl_str: str, validator: MDLValidator) -> Dict[str, Any]:\n    res = validator.run(mdl=mdl_str)\n    return dict(mdl=res[\"mdl\"])\n\n\n@observe(capture_input=False)\ndef chunk(\n    mdl: Dict[str, Any],\n    chunker: TableDescriptionChunker,\n    project_id: Optional[str] = None,\n) -> Dict[str, Any]:\n    return chunker.run(mdl=mdl, project_id=project_id)\n\n\n@observe(capture_input=False, capture_output=False)\nasync def embedding(chunk: Dict[str, Any], embedder: Any) -> Dict[str, Any]:\n    return await embedder.run(documents=chunk[\"documents\"])\n\n\n@observe(capture_input=False, capture_output=False)\nasync def clean(\n    embedding: Dict[str, Any],\n    cleaner: DocumentCleaner,\n    project_id: Optional[str] = None,\n) -> Dict[str, Any]:\n    await cleaner.run(project_id=project_id)\n    return embedding\n\n\n@observe(capture_input=False)\nasync def write(clean: Dict[str, Any], writer: DocumentWriter) -> None:\n    return await writer.run(documents=clean[\"documents\"])\n\n\n## End of Pipeline\n\n\nclass TableDescription(BasicPipeline):\n    def __init__(\n        self,\n        embedder_provider: EmbedderProvider,\n        document_store_provider: DocumentStoreProvider,\n        **kwargs,\n    ) -> None:\n        table_description_store = document_store_provider.get_store(\n            dataset_name=\"table_descriptions\"\n        )\n\n        self._components = {\n            \"cleaner\": DocumentCleaner([table_description_store]),\n            \"validator\": MDLValidator(),\n            \"embedder\": embedder_provider.get_document_embedder(),\n            \"chunker\": TableDescriptionChunker(),\n            \"writer\": AsyncDocumentWriter(\n                document_store=table_description_store,\n                policy=DuplicatePolicy.OVERWRITE,\n            ),\n        }\n        self._configs = {}\n        self._final = \"write\"\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"Table Description Indexing\")\n    async def run(\n        self, mdl_str: str, project_id: Optional[str] = None\n    ) -> Dict[str, Any]:\n        logger.info(\n            f\"Project ID: {project_id}, Table Description Indexing pipeline is running...\"\n        )\n        return await self._pipe.execute(\n            [self._final],\n            inputs={\n                \"mdl_str\": mdl_str,\n                \"project_id\": project_id,\n                **self._components,\n                **self._configs,\n            },\n        )\n\n    @observe(name=\"Clean Documents for Table Description\")\n    async def clean(self, project_id: Optional[str] = None) -> None:\n        await clean(\n            embedding={\"documents\": []},\n            cleaner=self._components[\"cleaner\"],\n            project_id=project_id,\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/indexing/utils/helper.py",
    "content": "import importlib\nimport logging\nimport pkgutil\nimport re\nimport sys\nfrom typing import Any, Callable, Dict\n\nimport orjson\n\nfrom src.pipelines.indexing import clean_display_name\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nclass Helper:\n    def __init__(\n        self,\n        condition: Callable[[Dict[str, Any]], bool],\n        helper: Callable[[Dict[str, Any]], Any],\n    ):\n        self.condiction = condition\n        self.helper = helper\n\n    def condition(self, column: Dict[str, Any], **kwargs) -> bool:\n        return self.condiction(column, **kwargs)\n\n    def __call__(self, column: Dict[str, Any], **kwargs) -> Any:\n        return self.helper(column, **kwargs)\n\n\ndef _properties_comment(column: Dict[str, Any], **_) -> str:\n    props = column[\"properties\"]\n    column_properties = {\n        \"alias\": clean_display_name(props.get(\"displayName\", \"\")),\n        \"description\": props.get(\"description\", \"\"),\n    }\n\n    # Add any nested columns if they exist\n    nested = {k: v for k, v in props.items() if k.startswith(\"nested\")}\n    if nested:\n        column_properties[\"nested_columns\"] = nested\n\n    if (json_type := props.get(\"json_type\", \"\")) and json_type in [\n        \"JSON\",\n        \"JSON_ARRAY\",\n    ]:\n        json_fields = {\n            k: v for k, v in column[\"properties\"].items() if re.match(r\".*json.*\", k)\n        }\n        if json_fields:\n            column_properties[\"json_type\"] = json_type\n            column_properties[\"json_fields\"] = json_fields\n\n    return f\"-- {orjson.dumps(column_properties).decode('utf-8')}\\n  \"\n\n\nCOLUMN_PREPROCESSORS = {\n    \"properties\": Helper(\n        condition=lambda column, **_: \"properties\" in column,\n        helper=lambda column, **_: column.get(\"properties\"),\n    ),\n    \"relationship\": Helper(\n        condition=lambda column, **_: \"relationship\" in column,\n        helper=lambda column, **_: column.get(\"relationship\"),\n    ),\n    \"expression\": Helper(\n        condition=lambda column, **_: \"expression\" in column,\n        helper=lambda column, **_: column.get(\"expression\"),\n    ),\n    \"isCalculated\": Helper(\n        condition=lambda column, **_: column.get(\"isCalculated\", False),\n        helper=lambda column, **_: column.get(\"isCalculated\"),\n    ),\n}\n\nCOLUMN_COMMENT_HELPERS = {\n    \"properties\": Helper(\n        condition=lambda column, **_: \"properties\" in column,\n        helper=_properties_comment,\n    ),\n    \"isCalculated\": Helper(\n        condition=lambda column, **_: column.get(\"isCalculated\", False),\n        helper=lambda column,\n        **_: f\"-- This column is a Calculated Field\\n  -- column expression: {column['expression']}\\n  \",\n    ),\n}\n\nMODEL_PREPROCESSORS = {}\n\n\ndef load_helpers(package_path: str = \"src.pipelines.indexing.utils\"):\n    \"\"\"\n    Dynamically loads preprocessors and comment helpers from modules within a specified package path.\n\n    This function walks through all modules in the given package path and looks for modules\n    that define MODEL_PREPROCESSORS, COLUMN_PREPROCESSORS and COLUMN_COMMENT_HELPERS dictionaries.\n    When found, these helpers are added to the corresponding global dictionaries.\n\n    The helpers are used to preprocess and format comments for database schema elements like\n    models and columns during the DB Schema indexing pipeline.\n\n    Args:\n        package_path (str): The Python package path to search for helper modules.\n                          Defaults to \"src.pipelines.indexing.utils\".\n\n    Returns:\n        None: The function updates the global MODEL_PREPROCESSORS, COLUMN_PREPROCESSORS\n              and COLUMN_COMMENT_HELPERS dictionaries in place.\n\n    Example:\n        If a module in the package path contains:\n\n        MODEL_PREPROCESSORS = {\n            \"example\": Helper(\n                condition=lambda model: True,\n                helper=lambda model, **_: model.get(\"example\", \"\"),\n            )\n        }\n\n        COLUMN_PREPROCESSORS = {\n            \"example\": Helper(\n                condition=lambda column: True,\n                helper=lambda column, **_: column.get(\"example\", \"\"),\n            )\n        }\n\n        COLUMN_COMMENT_HELPERS = {\n            \"example\": Helper(\n                condition=lambda column: True,\n                helper=lambda column, **_: f\"-- {column.get('example')}\\n  \",\n            )\n        }\n\n        These will be added to their respective global dictionaries.\n    \"\"\"\n    package = importlib.import_module(package_path)\n\n    for _, name, _ in pkgutil.walk_packages(package.__path__, package.__name__ + \".\"):\n        if name in sys.modules:\n            continue\n\n        module = importlib.import_module(name)\n        logger.info(f\"Imported Helper from {name}\")\n        if hasattr(module, \"MODEL_PREPROCESSORS\"):\n            MODEL_PREPROCESSORS.update(module.MODEL_PREPROCESSORS)\n            logger.info(f\"Updated Helper for model preprocessors: {name}\")\n        if hasattr(module, \"COLUMN_PREPROCESSORS\"):\n            COLUMN_PREPROCESSORS.update(module.COLUMN_PREPROCESSORS)\n            logger.info(f\"Updated Helper for column preprocessors: {name}\")\n        if hasattr(module, \"COLUMN_COMMENT_HELPERS\"):\n            COLUMN_COMMENT_HELPERS.update(module.COLUMN_COMMENT_HELPERS)\n            logger.info(f\"Updated Helper for column comment helpers: {name}\")\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/retrieval/__init__.py",
    "content": "from .db_schema_retrieval import DbSchemaRetrieval\nfrom .historical_question_retrieval import HistoricalQuestionRetrieval\nfrom .instructions import Instructions\nfrom .preprocess_sql_data import PreprocessSqlData\nfrom .sql_executor import SQLExecutor\nfrom .sql_functions import SqlFunctions\nfrom .sql_knowledge import SqlKnowledges\nfrom .sql_pairs_retrieval import SqlPairsRetrieval\n\n__all__ = [\n    \"HistoricalQuestionRetrieval\",\n    \"PreprocessSqlData\",\n    \"DbSchemaRetrieval\",\n    \"SQLExecutor\",\n    \"SqlPairsRetrieval\",\n    \"Instructions\",\n    \"SqlFunctions\",\n    \"SqlKnowledges\",\n]\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/retrieval/db_schema_retrieval.py",
    "content": "import ast\nimport logging\nimport sys\nfrom typing import Any, Optional\n\nimport orjson\nimport tiktoken\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack import Document\nfrom haystack.components.builders.prompt_builder import PromptBuilder\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import DocumentStoreProvider, EmbedderProvider, LLMProvider\nfrom src.pipelines.common import (\n    build_table_ddl,\n    clean_up_new_lines,\n    get_engine_supported_data_type,\n)\nfrom src.utils import trace_cost\nfrom src.web.v1.services.ask import AskHistory\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\ntable_columns_selection_system_prompt = \"\"\"\n### TASK ###\nYou are a highly skilled data analyst. Your goal is to examine the provided database schema, interpret the posed question, and identify the specific columns from the relevant tables required to construct an accurate SQL query.\n\nThe database schema includes tables, columns, primary keys, foreign keys, relationships, and any relevant constraints.\n\n### INSTRUCTIONS ###\n1. Carefully analyze the schema and identify the essential tables and columns needed to answer the question.\n2. For each table, provide a clear and concise reasoning for why specific columns are selected.\n3. List each reason as part of a step-by-step chain of thought, justifying the inclusion of each column.\n4. If a \".\" is included in columns, put the name before the first dot into chosen columns.\n5. The number of columns chosen must match the number of reasoning.\n6. Final chosen columns must be only column names, don't prefix it with table names.\n7. If the chosen column is a child column of a STRUCT type column, choose the parent column instead of the child column.\n\n### FINAL ANSWER FORMAT ###\nPlease provide your response as a JSON object, structured as follows:\n\n{\n    \"results\": [\n        {\n            \"table_selection_reason\": \"Reason for selecting tablename1\",\n            \"table_contents\": {\n              \"chain_of_thought_reasoning\": [\n                  \"Reason 1 for selecting column1\",\n                  \"Reason 2 for selecting column2\",\n                  ...\n              ],\n              \"columns\": [\"column1\", \"column2\", ...]\n            },\n            \"table_name\":\"tablename1\",\n        },\n        {\n            \"table_selection_reason\": \"Reason for selecting tablename2\",\n            \"table_contents\":\n            {\n              \"chain_of_thought_reasoning\": [\n                  \"Reason 1 for selecting column1\",\n                  \"Reason 2 for selecting column2\",\n                  ...\n              ],\n              \"columns\": [\"column1\", \"column2\", ...]\n            },\n            \"table_name\":\"tablename2\"\n        },\n        ...\n    ]\n}\n\n### ADDITIONAL NOTES ###\n- Each table key must list only the columns relevant to answering the question.\n- Provide a reasoning list (`chain_of_thought_reasoning`) for each table, explaining why each column is necessary.\n- Provide the reason of selecting the table in (`table_selection_reason`) for each table.\n- Be logical, concise, and ensure the output strictly follows the required JSON format.\n- Use table name used in the \"Create Table\" statement, don't use \"alias\".\n- Match Column names with the definition in the \"Create Table\" statement.\n- Match Table names with the definition in the \"Create Table\" statement.\n\nGood luck!\n\n\"\"\"\n\ntable_columns_selection_user_prompt_template = \"\"\"\n### Database Schema ###\n\n{% for db_schema in db_schemas %}\n    {{ db_schema }}\n{% endfor %}\n\n### INPUT ###\n{{ question }}\n\"\"\"\n\n\ndef _build_metric_ddl(content: dict) -> str:\n    columns_ddl = [\n        f\"{column['comment']}{column['name']} {get_engine_supported_data_type(column['data_type'])}\"\n        for column in content[\"columns\"]\n        if column[\"data_type\"].lower()\n        != \"unknown\"  # quick fix: filtering out UNKNOWN column type\n    ]\n\n    return (\n        f\"{content['comment']}CREATE TABLE {content['name']} (\\n  \"\n        + \",\\n  \".join(columns_ddl)\n        + \"\\n);\"\n    )\n\n\ndef _build_view_ddl(content: dict) -> str:\n    return (\n        f\"{content['comment']}CREATE VIEW {content['name']}\\nAS {content['statement']}\"\n    )\n\n\n## Start of Pipeline\n@observe(capture_input=False, capture_output=False)\nasync def embedding(query: str, embedder: Any, histories: list[AskHistory]) -> dict:\n    if query:\n        if histories:\n            previous_query_summaries = [history.question for history in histories]\n        else:\n            previous_query_summaries = []\n\n        query = \"\\n\".join(previous_query_summaries) + \"\\n\" + query\n\n        return await embedder.run(query)\n    else:\n        return {}\n\n\n@observe(capture_input=False)\nasync def table_retrieval(\n    embedding: dict, project_id: str, tables: list[str], table_retriever: Any\n) -> dict:\n    filters = {\n        \"operator\": \"AND\",\n        \"conditions\": [\n            {\"field\": \"type\", \"operator\": \"==\", \"value\": \"TABLE_DESCRIPTION\"},\n        ],\n    }\n\n    if project_id:\n        filters[\"conditions\"].append(\n            {\"field\": \"project_id\", \"operator\": \"==\", \"value\": project_id}\n        )\n\n    if embedding:\n        return await table_retriever.run(\n            query_embedding=embedding.get(\"embedding\"),\n            filters=filters,\n        )\n    else:\n        filters[\"conditions\"].append(\n            {\"field\": \"name\", \"operator\": \"in\", \"value\": tables}\n        )\n\n        return await table_retriever.run(\n            query_embedding=[],\n            filters=filters,\n        )\n\n\n@observe(capture_input=False)\nasync def dbschema_retrieval(\n    table_retrieval: dict, project_id: str, dbschema_retriever: Any\n) -> list[Document]:\n    tables = table_retrieval.get(\"documents\", [])\n    table_names = []\n    for table in tables:\n        content = ast.literal_eval(table.content)\n        table_names.append(content[\"name\"])\n\n    table_name_conditions = [\n        {\"field\": \"name\", \"operator\": \"==\", \"value\": table_name}\n        for table_name in table_names\n    ]\n\n    if table_name_conditions:\n        filters = {\n            \"operator\": \"AND\",\n            \"conditions\": [\n                {\"field\": \"type\", \"operator\": \"==\", \"value\": \"TABLE_SCHEMA\"},\n                {\"operator\": \"OR\", \"conditions\": table_name_conditions},\n            ],\n        }\n\n        if project_id:\n            filters[\"conditions\"].append(\n                {\"field\": \"project_id\", \"operator\": \"==\", \"value\": project_id}\n            )\n\n        results = await dbschema_retriever.run(query_embedding=[], filters=filters)\n        return results[\"documents\"]\n\n    return []\n\n\n@observe()\ndef construct_db_schemas(dbschema_retrieval: list[Document]) -> list[dict]:\n    db_schemas = {}\n    for document in dbschema_retrieval:\n        content = ast.literal_eval(document.content)\n        if content[\"type\"] == \"TABLE\":\n            if document.meta[\"name\"] not in db_schemas:\n                db_schemas[document.meta[\"name\"]] = content\n            else:\n                db_schemas[document.meta[\"name\"]] = {\n                    **content,\n                    \"columns\": db_schemas[document.meta[\"name\"]].get(\"columns\", []),\n                }\n        elif content[\"type\"] == \"TABLE_COLUMNS\":\n            if document.meta[\"name\"] not in db_schemas:\n                db_schemas[document.meta[\"name\"]] = {\"columns\": content[\"columns\"]}\n            else:\n                if \"columns\" not in db_schemas[document.meta[\"name\"]]:\n                    db_schemas[document.meta[\"name\"]][\"columns\"] = content[\"columns\"]\n                else:\n                    db_schemas[document.meta[\"name\"]][\"columns\"] += content[\"columns\"]\n\n    # remove incomplete schemas\n    db_schemas = {k: v for k, v in db_schemas.items() if \"type\" in v and \"columns\" in v}\n\n    return list(db_schemas.values())\n\n\n@observe(capture_input=False)\ndef check_using_db_schemas_without_pruning(\n    construct_db_schemas: list[dict],\n    dbschema_retrieval: list[Document],\n    encoding: tiktoken.Encoding,\n    enable_column_pruning: bool,\n    context_window_size: int,\n) -> dict:\n    retrieval_results = []\n    has_calculated_field = False\n    has_metric = False\n    has_json_field = False\n\n    for table_schema in construct_db_schemas:\n        if table_schema[\"type\"] == \"TABLE\":\n            ddl, _has_calculated_field, _has_json_field = build_table_ddl(table_schema)\n            retrieval_results.append(\n                {\n                    \"table_name\": table_schema[\"name\"],\n                    \"table_ddl\": ddl,\n                }\n            )\n            if _has_calculated_field:\n                has_calculated_field = True\n            if _has_json_field:\n                has_json_field = True\n\n    for document in dbschema_retrieval:\n        content = ast.literal_eval(document.content)\n\n        if content[\"type\"] == \"METRIC\":\n            retrieval_results.append(\n                {\n                    \"table_name\": content[\"name\"],\n                    \"table_ddl\": _build_metric_ddl(content),\n                }\n            )\n            has_metric = True\n        elif content[\"type\"] == \"VIEW\":\n            retrieval_results.append(\n                {\n                    \"table_name\": content[\"name\"],\n                    \"table_ddl\": _build_view_ddl(content),\n                }\n            )\n\n    table_ddls = [\n        retrieval_result[\"table_ddl\"] for retrieval_result in retrieval_results\n    ]\n    _token_count = len(encoding.encode(\" \".join(table_ddls)))\n    if _token_count > context_window_size or enable_column_pruning:\n        return {\n            \"db_schemas\": [],\n            \"tokens\": _token_count,\n            \"has_calculated_field\": has_calculated_field,\n            \"has_metric\": has_metric,\n            \"has_json_field\": has_json_field,\n        }\n\n    return {\n        \"db_schemas\": retrieval_results,\n        \"tokens\": _token_count,\n        \"has_calculated_field\": has_calculated_field,\n        \"has_metric\": has_metric,\n        \"has_json_field\": has_json_field,\n    }\n\n\n@observe(capture_input=False)\ndef prompt(\n    query: str,\n    construct_db_schemas: list[dict],\n    prompt_builder: PromptBuilder,\n    check_using_db_schemas_without_pruning: dict,\n    histories: list[AskHistory],\n) -> dict:\n    if not check_using_db_schemas_without_pruning[\"db_schemas\"]:\n        db_schemas = [\n            build_table_ddl(construct_db_schema)[0]\n            for construct_db_schema in construct_db_schemas\n        ]\n\n        previous_query_summaries = (\n            [history.question for history in histories] if histories else []\n        )\n\n        query = \"\\n\".join(previous_query_summaries) + \"\\n\" + query\n\n        _prompt = prompt_builder.run(question=query, db_schemas=db_schemas)\n        return {\"prompt\": clean_up_new_lines(_prompt.get(\"prompt\"))}\n    else:\n        return {}\n\n\n@observe(as_type=\"generation\", capture_input=False)\n@trace_cost\nasync def filter_columns_in_tables(\n    prompt: dict, table_columns_selection_generator: Any, generator_name: str\n) -> dict:\n    if prompt:\n        return await table_columns_selection_generator(\n            prompt=prompt.get(\"prompt\")\n        ), generator_name\n    else:\n        return {}, generator_name\n\n\n@observe()\ndef construct_retrieval_results(\n    check_using_db_schemas_without_pruning: dict,\n    filter_columns_in_tables: dict,\n    construct_db_schemas: list[dict],\n    dbschema_retrieval: list[Document],\n) -> dict[str, Any]:\n    if filter_columns_in_tables:\n        columns_and_tables_needed = orjson.loads(\n            filter_columns_in_tables[\"replies\"][0]\n        )[\"results\"]\n\n        # we need to change the below code to match the new schema of structured output\n        # the objective of this loop is to change the structure of JSON to match the needed format\n        reformated_json = {}\n        for table in columns_and_tables_needed:\n            reformated_json[table[\"table_name\"]] = table[\"table_contents\"]\n        columns_and_tables_needed = reformated_json\n        tables = set(columns_and_tables_needed.keys())\n        retrieval_results = []\n        has_calculated_field = False\n        has_metric = False\n        has_json_field = False\n\n        for table_schema in construct_db_schemas:\n            if table_schema[\"type\"] == \"TABLE\" and table_schema[\"name\"] in tables:\n                ddl, _has_calculated_field, _has_json_field = build_table_ddl(\n                    table_schema,\n                    columns=set(\n                        columns_and_tables_needed[table_schema[\"name\"]][\"columns\"]\n                    ),\n                    tables=tables,\n                )\n                if _has_calculated_field:\n                    has_calculated_field = True\n                if _has_json_field:\n                    has_json_field = True\n\n                retrieval_results.append(\n                    {\n                        \"table_name\": table_schema[\"name\"],\n                        \"table_ddl\": ddl,\n                    }\n                )\n\n        for document in dbschema_retrieval:\n            if document.meta[\"name\"] in columns_and_tables_needed:\n                content = ast.literal_eval(document.content)\n\n                if content[\"type\"] == \"METRIC\":\n                    retrieval_results.append(\n                        {\n                            \"table_name\": content[\"name\"],\n                            \"table_ddl\": _build_metric_ddl(content),\n                        }\n                    )\n                    has_metric = True\n                elif content[\"type\"] == \"VIEW\":\n                    retrieval_results.append(\n                        {\n                            \"table_name\": content[\"name\"],\n                            \"table_ddl\": _build_view_ddl(content),\n                        }\n                    )\n\n        return {\n            \"retrieval_results\": retrieval_results,\n            \"has_calculated_field\": has_calculated_field,\n            \"has_metric\": has_metric,\n            \"has_json_field\": has_json_field,\n        }\n    else:\n        retrieval_results = check_using_db_schemas_without_pruning[\"db_schemas\"]\n\n        return {\n            \"retrieval_results\": retrieval_results,\n            \"has_calculated_field\": check_using_db_schemas_without_pruning[\n                \"has_calculated_field\"\n            ],\n            \"has_metric\": check_using_db_schemas_without_pruning[\"has_metric\"],\n            \"has_json_field\": check_using_db_schemas_without_pruning[\"has_json_field\"],\n        }\n\n\n## End of Pipeline\nclass MatchingTableContents(BaseModel):\n    chain_of_thought_reasoning: list[str]\n    columns: list[str]\n\n\nclass MatchingTable(BaseModel):\n    table_name: str\n    table_contents: MatchingTableContents\n    table_selection_reason: str\n\n\nclass RetrievalResults(BaseModel):\n    results: list[MatchingTable]\n\n\nRETRIEVAL_MODEL_KWARGS = {\n    \"response_format\": {\n        \"type\": \"json_schema\",\n        \"json_schema\": {\n            \"name\": \"retrieval_schema\",\n            \"schema\": RetrievalResults.model_json_schema(),\n        },\n    }\n}\n\n\nclass DbSchemaRetrieval(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        embedder_provider: EmbedderProvider,\n        document_store_provider: DocumentStoreProvider,\n        table_retrieval_size: int = 10,\n        table_column_retrieval_size: int = 100,\n        **kwargs,\n    ):\n        self._components = {\n            \"embedder\": embedder_provider.get_text_embedder(),\n            \"table_retriever\": document_store_provider.get_retriever(\n                document_store_provider.get_store(dataset_name=\"table_descriptions\"),\n                top_k=table_retrieval_size,\n            ),\n            \"dbschema_retriever\": document_store_provider.get_retriever(\n                document_store_provider.get_store(),\n                top_k=table_column_retrieval_size,\n            ),\n            \"table_columns_selection_generator\": llm_provider.get_generator(\n                system_prompt=table_columns_selection_system_prompt,\n                generation_kwargs=RETRIEVAL_MODEL_KWARGS,\n            ),\n            \"generator_name\": llm_provider.get_model(),\n            \"prompt_builder\": PromptBuilder(\n                template=table_columns_selection_user_prompt_template\n            ),\n        }\n\n        # for the first time, we need to load the encodings\n        _model = llm_provider.get_model()\n        if \"gpt-4o\" in _model or \"gpt-4o-mini\" in _model:\n            _encoding = tiktoken.get_encoding(\"o200k_base\")\n        else:\n            _encoding = tiktoken.get_encoding(\"cl100k_base\")\n\n        self._configs = {\n            \"encoding\": _encoding,\n            \"context_window_size\": llm_provider.get_context_window_size(),\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"Ask Retrieval\")\n    async def run(\n        self,\n        query: str = \"\",\n        tables: Optional[list[str]] = None,\n        project_id: Optional[str] = None,\n        histories: Optional[list[AskHistory]] = None,\n        enable_column_pruning: bool = False,\n    ):\n        logger.info(\"Ask Retrieval pipeline is running...\")\n        return await self._pipe.execute(\n            [\"construct_retrieval_results\"],\n            inputs={\n                \"query\": query,\n                \"tables\": tables,\n                \"project_id\": project_id or \"\",\n                \"histories\": histories or [],\n                \"enable_column_pruning\": enable_column_pruning,\n                **self._components,\n                **self._configs,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/retrieval/historical_question_retrieval.py",
    "content": "import logging\nimport sys\nfrom typing import Any, Dict, List, Optional\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack import Document, component\nfrom haystack_integrations.document_stores.qdrant import QdrantDocumentStore\nfrom langfuse.decorators import observe\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import DocumentStoreProvider, EmbedderProvider\nfrom src.pipelines.common import ScoreFilter\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n@component\nclass OutputFormatter:\n    @component.output_types(\n        documents=List[Optional[Dict]],\n    )\n    def run(self, documents: List[Document]):\n        list = [\n            {\n                \"question\": doc.content,\n                \"summary\": doc.meta.get(\"summary\", \"\"),\n                \"statement\": doc.meta.get(\"statement\") or doc.meta.get(\"sql\"),\n                \"viewId\": doc.meta.get(\"viewId\", \"\"),\n            }\n            for doc in documents\n        ]\n\n        return {\"documents\": list}\n\n\n## Start of Pipeline\n@observe(capture_input=False)\nasync def count_documents(\n    view_questions_store: QdrantDocumentStore,\n    project_id: Optional[str] = None,\n) -> int:\n    filters = (\n        {\n            \"operator\": \"AND\",\n            \"conditions\": [\n                {\"field\": \"project_id\", \"operator\": \"==\", \"value\": project_id},\n            ],\n        }\n        if project_id\n        else None\n    )\n\n    return await view_questions_store.count_documents(filters=filters)\n\n\n@observe(capture_input=False, capture_output=False)\nasync def embedding(count_documents: int, query: str, embedder: Any) -> dict:\n    if count_documents:\n        return await embedder.run(query)\n\n    return {}\n\n\n@observe(capture_input=False)\nasync def retrieval(\n    embedding: dict,\n    project_id: str,\n    view_questions_retriever: Any,\n) -> dict:\n    if embedding:\n        filters = (\n            {\n                \"operator\": \"AND\",\n                \"conditions\": [\n                    {\"field\": \"project_id\", \"operator\": \"==\", \"value\": project_id},\n                ],\n            }\n            if project_id\n            else None\n        )\n\n        view_question_res = await view_questions_retriever.run(\n            query_embedding=embedding.get(\"embedding\"),\n            filters=filters,\n        )\n        return dict(documents=view_question_res.get(\"documents\"))\n\n    return {}\n\n\n@observe(capture_input=False)\ndef filtered_documents(\n    retrieval: dict,\n    score_filter: ScoreFilter,\n    historical_question_retrieval_similarity_threshold: float,\n) -> dict:\n    if retrieval:\n        return score_filter.run(\n            documents=retrieval.get(\"documents\"),\n            score=historical_question_retrieval_similarity_threshold,\n        )\n\n    return {}\n\n\n@observe(capture_input=False)\ndef formatted_output(\n    filtered_documents: dict, output_formatter: OutputFormatter\n) -> dict:\n    if filtered_documents:\n        return output_formatter.run(documents=filtered_documents.get(\"documents\"))\n\n    return {\"documents\": []}\n\n\n## End of Pipeline\n\n\nclass HistoricalQuestionRetrieval(BasicPipeline):\n    def __init__(\n        self,\n        embedder_provider: EmbedderProvider,\n        document_store_provider: DocumentStoreProvider,\n        historical_question_retrieval_similarity_threshold: float = 0.9,\n        **kwargs,\n    ) -> None:\n        view_questions_store = document_store_provider.get_store(\n            dataset_name=\"view_questions\"\n        )\n        self._components = {\n            \"view_questions_store\": view_questions_store,\n            \"embedder\": embedder_provider.get_text_embedder(),\n            \"view_questions_retriever\": document_store_provider.get_retriever(\n                document_store=view_questions_store,\n            ),\n            \"score_filter\": ScoreFilter(),\n            # TODO: add a llm filter to filter out low scoring document, in case ScoreFilter is not accurate enough\n            \"output_formatter\": OutputFormatter(),\n        }\n\n        self._configs = {\n            \"historical_question_retrieval_similarity_threshold\": historical_question_retrieval_similarity_threshold,\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"Historical Question\")\n    async def run(self, query: str, project_id: Optional[str] = None):\n        logger.info(\"HistoricalQuestion Retrieval pipeline is running...\")\n        return await self._pipe.execute(\n            [\"formatted_output\"],\n            inputs={\n                \"query\": query,\n                \"project_id\": project_id or \"\",\n                **self._components,\n                **self._configs,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/retrieval/instructions.py",
    "content": "import logging\nimport sys\nfrom typing import Any, Dict, List, Optional\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack import Document, component\nfrom haystack_integrations.document_stores.qdrant import QdrantDocumentStore\nfrom langfuse.decorators import observe\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import DocumentStoreProvider, EmbedderProvider\nfrom src.pipelines.common import ScoreFilter\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n@component\nclass OutputFormatter:\n    @component.output_types(\n        documents=List[Optional[Dict]],\n    )\n    def run(self, documents: List[Document]):\n        list = []\n\n        for doc in documents:\n            formatted = {\n                \"instruction\": doc.meta.get(\"instruction\", \"\"),\n                \"question\": doc.content,\n                \"instruction_id\": doc.meta.get(\"instruction_id\", \"\"),\n            }\n            list.append(formatted)\n\n        return {\"documents\": list}\n\n\n@component\nclass ScopeFilter:\n    @component.output_types(\n        documents=List[Document],\n    )\n    def run(\n        self,\n        documents: List[Document],\n        scope: str = \"sql\",\n    ):\n        return {\n            \"documents\": list(\n                filter(\n                    lambda document: document.meta.get(\"scope\", \"sql\") == scope,\n                    documents,\n                ),\n            )\n        }\n\n\n## Start of Pipeline\n@observe(capture_input=False)\nasync def count_documents(\n    store: QdrantDocumentStore, project_id: Optional[str] = None\n) -> int:\n    filters = (\n        {\n            \"operator\": \"AND\",\n            \"conditions\": [\n                {\"field\": \"project_id\", \"operator\": \"==\", \"value\": project_id},\n            ],\n        }\n        if project_id\n        else None\n    )\n    document_count = await store.count_documents(filters=filters)\n    return document_count\n\n\n@observe(capture_input=False, capture_output=False)\nasync def embedding(count_documents: int, query: str, embedder: Any) -> dict:\n    if count_documents:\n        return await embedder.run(query)\n\n    return {}\n\n\n@observe(capture_input=False)\nasync def retrieval(embedding: dict, project_id: str, retriever: Any) -> dict:\n    if not embedding:\n        return {}\n\n    filters = {\n        \"operator\": \"AND\",\n        \"conditions\": [\n            {\"field\": \"is_default\", \"operator\": \"==\", \"value\": False},\n        ],\n    }\n\n    if project_id:\n        filters[\"conditions\"].append(\n            {\"field\": \"project_id\", \"operator\": \"==\", \"value\": project_id}\n        )\n\n    res = await retriever.run(\n        query_embedding=embedding.get(\"embedding\"),\n        filters=filters,\n    )\n    return dict(documents=res.get(\"documents\"))\n\n\n@observe(capture_input=False)\ndef filtered_documents(\n    retrieval: dict,\n    scope: str,\n    scope_filter: ScopeFilter,\n    score_filter: ScoreFilter,\n    similarity_threshold: float,\n    top_k: int,\n) -> dict:\n    if not retrieval:\n        return {}\n\n    res = scope_filter.run(\n        documents=retrieval.get(\"documents\"),\n        scope=scope,\n    )\n\n    return score_filter.run(\n        documents=res.get(\"documents\"),\n        score=similarity_threshold,\n        max_size=top_k,\n    )\n\n\n@observe(capture_input=False)\nasync def default_instructions(\n    count_documents: int,\n    retriever: Any,\n    project_id: str,\n    scope_filter: ScopeFilter,\n    scope: str,\n) -> list[Document]:\n    if not count_documents:\n        return []\n\n    filters = {\n        \"operator\": \"AND\",\n        \"conditions\": [\n            {\"field\": \"is_default\", \"operator\": \"==\", \"value\": True},\n        ],\n    }\n\n    if project_id:\n        filters[\"conditions\"].append(\n            {\"field\": \"project_id\", \"operator\": \"==\", \"value\": project_id}\n        )\n\n    _res = await retriever.run(\n        query_embedding=None,\n        filters=filters,\n    )\n\n    res = scope_filter.run(\n        documents=_res.get(\"documents\"),\n        scope=scope,\n    )\n\n    return dict(documents=res.get(\"documents\"))\n\n\n@observe(capture_input=False)\ndef formatted_output(\n    default_instructions: list[Document],\n    filtered_documents: dict,\n    output_formatter: OutputFormatter,\n) -> dict:\n    if not filtered_documents and not default_instructions:\n        return {\"documents\": []}\n\n    merged = default_instructions.get(\"documents\") + filtered_documents.get(\"documents\")\n    documents = output_formatter.run(documents=merged)\n    return documents\n\n\n## End of Pipeline\n\n\nclass Instructions(BasicPipeline):\n    def __init__(\n        self,\n        embedder_provider: EmbedderProvider,\n        document_store_provider: DocumentStoreProvider,\n        similarity_threshold: float = 0.7,\n        top_k: int = 10,\n        **kwargs,\n    ) -> None:\n        store = document_store_provider.get_store(dataset_name=\"instructions\")\n        self._components = {\n            \"store\": store,\n            \"embedder\": embedder_provider.get_text_embedder(),\n            \"retriever\": document_store_provider.get_retriever(\n                document_store=store,\n            ),\n            \"scope_filter\": ScopeFilter(),\n            \"score_filter\": ScoreFilter(),\n            \"output_formatter\": OutputFormatter(),\n        }\n        self._configs = {\n            \"similarity_threshold\": similarity_threshold,\n            \"top_k\": top_k,\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"Instructions Retrieval\")\n    async def run(\n        self, query: str, project_id: Optional[str] = None, scope: str = \"sql\"\n    ):\n        logger.info(\"Instructions Retrieval pipeline is running...\")\n        return await self._pipe.execute(\n            [\"formatted_output\"],\n            inputs={\n                \"query\": query,\n                \"project_id\": project_id or \"\",\n                \"scope\": scope,\n                **self._components,\n                **self._configs,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/retrieval/preprocess_sql_data.py",
    "content": "import logging\nimport sys\nfrom typing import Dict\n\nimport tiktoken\nfrom hamilton import base\nfrom hamilton.driver import Driver\nfrom langfuse.decorators import observe\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import LLMProvider\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n## Start of Pipeline\n@observe(capture_input=False, capture_output=False)\ndef preprocess(\n    sql_data: Dict,\n    encoding: tiktoken.Encoding,\n    context_window_size: int,\n) -> Dict:\n    def reduce_data_size(data: list, reduction_step: int = 50) -> list:\n        \"\"\"Reduce the size of data by removing elements from the end.\n\n        Args:\n            data: The input list to reduce\n            reduction_step: Number of elements to remove (must be positive)\n\n        Returns:\n            list: A list with reduced size\n\n        Raises:\n            ValueError: If reduction_step is not positive\n        \"\"\"\n        if reduction_step <= 0:\n            raise ValueError(\"reduction_step must be positive\")\n\n        elements_to_keep = max(0, len(data) - reduction_step)\n        returned_data = data[:elements_to_keep]\n\n        logger.info(\n            f\"Reducing data size by {reduction_step} rows. \"\n            f\"Original size: {len(data)}, New size: {len(returned_data)}\"\n        )\n\n        return returned_data\n\n    _token_count = len(encoding.encode(str(sql_data)))\n    num_rows_used_in_llm = len(sql_data.get(\"data\", []))\n    iteration = 0\n\n    while _token_count > context_window_size:\n        if iteration > 1000:\n            \"\"\"\n            Avoid infinite loop\n            If the token count is still too high after 1000 iterations, break\n            \"\"\"\n            break\n\n        iteration += 1\n\n        data = sql_data.get(\"data\", [])\n        sql_data[\"data\"] = reduce_data_size(data)\n        num_rows_used_in_llm = len(sql_data.get(\"data\", []))\n        _token_count = len(encoding.encode(str(sql_data)))\n        logger.info(f\"Token count: {_token_count}\")\n\n    return {\n        \"sql_data\": sql_data,\n        \"num_rows_used_in_llm\": num_rows_used_in_llm,\n        \"tokens\": _token_count,\n    }\n\n\n## End of Pipeline\n\n\nclass PreprocessSqlData(BasicPipeline):\n    def __init__(\n        self,\n        llm_provider: LLMProvider,\n        **kwargs,\n    ):\n        _model = llm_provider.get_model()\n        if _model == \"gpt-4o-mini\" or _model == \"gpt-4o\":\n            _encoding = tiktoken.get_encoding(\"o200k_base\")\n        else:\n            _encoding = tiktoken.get_encoding(\"cl100k_base\")\n\n        self._configs = {\n            \"encoding\": _encoding,\n            \"context_window_size\": llm_provider.get_context_window_size(),\n        }\n\n        super().__init__(Driver({}, sys.modules[__name__], adapter=base.DictResult()))\n\n    @observe(name=\"Preprocess SQL Data\")\n    def run(\n        self,\n        sql_data: Dict,\n    ):\n        logger.info(\"Preprocess SQL Data pipeline is running...\")\n        return self._pipe.execute(\n            [\"preprocess\"],\n            inputs={\n                \"sql_data\": sql_data,\n                **self._configs,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/retrieval/sql_executor.py",
    "content": "import logging\nimport sys\nfrom typing import Any, Dict, Optional\n\nimport aiohttp\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack import component\nfrom langfuse.decorators import observe\n\nfrom src.core.engine import Engine\nfrom src.core.pipeline import BasicPipeline\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n@component\nclass DataFetcher:\n    def __init__(self, engine: Engine):\n        self._engine = engine\n\n    @component.output_types(\n        results=Optional[Dict[str, Any]],\n    )\n    async def run(\n        self,\n        sql: str,\n        project_id: str | None = None,\n        limit: int = 500,\n    ):\n        async with aiohttp.ClientSession() as session:\n            _, data, addition = await self._engine.execute_sql(\n                sql,\n                session,\n                project_id=project_id,\n                dry_run=False,\n                limit=limit,\n            )\n\n            if addition.get(\"error_message\"):\n                return {\"results\": data, \"error_message\": addition.get(\"error_message\")}\n            return {\"results\": data}\n\n\n## Start of Pipeline\n@observe(capture_input=False)\nasync def execute_sql(\n    sql: str,\n    data_fetcher: DataFetcher,\n    project_id: str | None = None,\n    limit: int = 500,\n) -> dict:\n    return await data_fetcher.run(\n        sql=sql,\n        project_id=project_id,\n        limit=limit,\n    )\n\n\n## End of Pipeline\n\n\nclass SQLExecutor(BasicPipeline):\n    def __init__(\n        self,\n        engine: Engine,\n        **kwargs,\n    ):\n        self._components = {\n            \"data_fetcher\": DataFetcher(engine=engine),\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"SQL Execution\")\n    async def run(\n        self, sql: str, project_id: str | None = None, limit: int = 500\n    ) -> dict:\n        logger.info(\"SQL Execution pipeline is running...\")\n        return await self._pipe.execute(\n            [\"execute_sql\"],\n            inputs={\n                \"sql\": sql,\n                \"project_id\": project_id,\n                \"limit\": limit,\n                **self._components,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/retrieval/sql_functions.py",
    "content": "import logging\nimport sys\nfrom typing import List, Optional\n\nimport aiohttp\nfrom cachetools import TTLCache\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom langfuse.decorators import observe\n\nfrom src.core.engine import Engine\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import DocumentStoreProvider\nfrom src.pipelines.common import retrieve_metadata\nfrom src.providers.engine.wren import WrenIbis\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nclass SqlFunction:\n    _expr: str = None\n\n    def __init__(self, definition: dict):\n        def _extract() -> tuple[str, list, str]:\n            return (\n                definition.get(\"name\", \"\").upper(),\n                definition.get(\"function_type\", \"\"),\n                definition.get(\"description\", \"\"),\n            )\n\n        name, function_type, description = _extract()\n\n        self._expr = f\"type: {function_type}, name: {name}, description: {description}\"\n\n    @classmethod\n    def empty(cls, definition: dict):\n        return (\n            not definition.get(\"name\", \"\")\n            or not definition.get(\"function_type\", \"\")\n            or not definition.get(\"description\", \"\")\n        )\n\n    def __str__(self):\n        return self._expr\n\n    def __repr__(self):\n        return self._expr\n\n\n## Start of Pipeline\n@observe(capture_input=False)\nasync def get_functions(\n    engine: WrenIbis,\n    data_source: str,\n) -> List[SqlFunction]:\n    async with aiohttp.ClientSession() as session:\n        func_list = await engine.get_func_list(\n            session=session,\n            data_source=data_source,\n        )\n\n        return [\n            SqlFunction(definition=func)\n            for func in func_list\n            if not SqlFunction.empty(func)\n        ]\n\n\n@observe(capture_input=False)\ndef cache(\n    data_source: str,\n    get_functions: List[SqlFunction],\n    ttl_cache: TTLCache,\n) -> List[SqlFunction]:\n    ttl_cache[data_source] = get_functions\n    return get_functions\n\n\n## End of Pipeline\n\n\nclass SqlFunctions(BasicPipeline):\n    def __init__(\n        self,\n        engine: Engine,\n        document_store_provider: DocumentStoreProvider,\n        ttl: int = 60 * 60 * 24,\n        **kwargs,\n    ) -> None:\n        self._retriever = document_store_provider.get_retriever(\n            document_store_provider.get_store(\"project_meta\")\n        )\n        self._cache = TTLCache(maxsize=100, ttl=ttl)\n        self._components = {\n            \"engine\": engine,\n            \"ttl_cache\": self._cache,\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"SQL Functions Retrieval\")\n    async def run(\n        self,\n        project_id: Optional[str] = None,\n    ) -> List[SqlFunction]:\n        logger.info(\n            f\"Project ID: {project_id} SQL Functions Retrieval pipeline is running...\"\n        )\n\n        metadata = await retrieve_metadata(project_id or \"\", self._retriever)\n        _data_source = metadata.get(\"data_source\", \"local_file\")\n\n        if _data_source in self._cache:\n            logger.info(f\"Hit cache of SQL Functions for {_data_source}\")\n            return self._cache[_data_source]\n\n        input = {\n            \"data_source\": _data_source,\n            \"project_id\": project_id,\n            **self._components,\n        }\n        result = await self._pipe.execute([\"cache\"], inputs=input)\n        return result[\"cache\"]\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/retrieval/sql_knowledge.py",
    "content": "import logging\nimport sys\nfrom typing import Dict, Optional\n\nimport aiohttp\nfrom cachetools import TTLCache\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom langfuse.decorators import observe\n\nfrom src.core.engine import Engine\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import DocumentStoreProvider\nfrom src.pipelines.common import retrieve_metadata\nfrom src.providers.engine.wren import WrenIbis\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nclass SqlKnowledge:\n    def __init__(self, sql_knowledge: dict):\n        self._data: Dict = sql_knowledge\n\n    @classmethod\n    def empty(cls, sql_knowledge: dict):\n        return (\n            not sql_knowledge\n            or not sql_knowledge.get(\"text_to_sql_rule\")\n            or not sql_knowledge.get(\"instructions\")\n        )\n\n    @property\n    def text_to_sql_rule(self) -> str:\n        return self._data.get(\"text_to_sql_rule\", \"\")\n\n    @property\n    def instructions(self) -> dict:\n        return self._data.get(\"instructions\", {})\n\n    @property\n    def calculated_field_instructions(self) -> str:\n        return self.instructions.get(\"calculated_field_instructions\", \"\")\n\n    @property\n    def metric_instructions(self) -> str:\n        return self.instructions.get(\"metric_instructions\", \"\")\n\n    @property\n    def json_field_instructions(self) -> str:\n        return self.instructions.get(\"json_field_instructions\", \"\")\n\n    def __str__(self):\n        return f\"text_to_sql_rule: {self.text_to_sql_rule}, instructions: {self.instructions}\"\n\n    def __repr__(self):\n        return self.__str__()\n\n\n## Start of Pipeline\n@observe(capture_input=False)\nasync def get_knowledge(\n    engine: WrenIbis,\n    data_source: str,\n) -> Optional[SqlKnowledge]:\n    async with aiohttp.ClientSession() as session:\n        knowledge_dict = await engine.get_sql_knowledge(\n            session=session,\n            data_source=data_source,\n        )\n\n        if not knowledge_dict or SqlKnowledge.empty(knowledge_dict):\n            return None\n\n        return SqlKnowledge(sql_knowledge=knowledge_dict)\n\n\n@observe(capture_input=False)\ndef cache(\n    data_source: str,\n    get_knowledge: Optional[SqlKnowledge],\n    ttl_cache: TTLCache,\n) -> Optional[SqlKnowledge]:\n    if get_knowledge:\n        ttl_cache[data_source] = get_knowledge\n\n    return get_knowledge\n\n\n## End of Pipeline\n\n\nclass SqlKnowledges(BasicPipeline):\n    def __init__(\n        self,\n        engine: Engine,\n        document_store_provider: DocumentStoreProvider,\n        ttl: int = 60 * 60 * 24,\n        **kwargs,\n    ) -> None:\n        self._retriever = document_store_provider.get_retriever(\n            document_store_provider.get_store(\"project_meta\")\n        )\n        self._cache = TTLCache(maxsize=100, ttl=ttl)\n        self._components = {\n            \"engine\": engine,\n            \"ttl_cache\": self._cache,\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"SQL Knowledge Retrieval\")\n    async def run(\n        self,\n        project_id: Optional[str] = None,\n    ) -> Optional[SqlKnowledge]:\n        logger.info(\n            f\"Project ID: {project_id} SQL Knowledge Retrieval pipeline is running...\"\n        )\n\n        metadata = await retrieve_metadata(project_id or \"\", self._retriever)\n        _data_source = metadata.get(\"data_source\", \"local_file\")\n\n        if _data_source in self._cache:\n            logger.info(f\"Hit cache of SQL Knowledge for {_data_source}\")\n            return self._cache[_data_source]\n\n        input = {\n            \"data_source\": _data_source,\n            \"project_id\": project_id,\n            **self._components,\n        }\n        result = await self._pipe.execute([\"cache\"], inputs=input)\n        return result[\"cache\"]\n"
  },
  {
    "path": "wren-ai-service/src/pipelines/retrieval/sql_pairs_retrieval.py",
    "content": "import logging\nimport sys\nfrom typing import Any, Dict, List, Optional\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDriver\nfrom haystack import Document, component\nfrom haystack_integrations.document_stores.qdrant import QdrantDocumentStore\nfrom langfuse.decorators import observe\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.core.provider import DocumentStoreProvider, EmbedderProvider\nfrom src.pipelines.common import ScoreFilter\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n@component\nclass OutputFormatter:\n    @component.output_types(\n        documents=List[Optional[Dict]],\n    )\n    def run(self, documents: List[Document]):\n        list = []\n\n        for doc in documents:\n            formatted = {\n                \"question\": doc.content,\n                \"sql\": doc.meta.get(\"sql\"),\n            }\n            list.append(formatted)\n\n        return {\"documents\": list}\n\n\n## Start of Pipeline\n@observe(capture_input=False)\nasync def count_documents(\n    store: QdrantDocumentStore, project_id: Optional[str] = None\n) -> int:\n    filters = (\n        {\n            \"operator\": \"AND\",\n            \"conditions\": [\n                {\"field\": \"project_id\", \"operator\": \"==\", \"value\": project_id},\n            ],\n        }\n        if project_id\n        else None\n    )\n    document_count = await store.count_documents(filters=filters)\n    return document_count\n\n\n@observe(capture_input=False, capture_output=False)\nasync def embedding(count_documents: int, query: str, embedder: Any) -> dict:\n    if count_documents:\n        return await embedder.run(query)\n\n    return {}\n\n\n@observe(capture_input=False)\nasync def retrieval(embedding: dict, project_id: str, retriever: Any) -> dict:\n    if embedding:\n        filters = (\n            {\n                \"operator\": \"AND\",\n                \"conditions\": [\n                    {\"field\": \"project_id\", \"operator\": \"==\", \"value\": project_id},\n                ],\n            }\n            if project_id\n            else None\n        )\n\n        res = await retriever.run(\n            query_embedding=embedding.get(\"embedding\"),\n            filters=filters,\n        )\n        return dict(documents=res.get(\"documents\"))\n\n    return {}\n\n\n@observe(capture_input=False)\ndef filtered_documents(\n    retrieval: dict,\n    score_filter: ScoreFilter,\n    sql_pairs_similarity_threshold: float,\n    sql_pairs_retrieval_max_size: int,\n) -> dict:\n    if retrieval:\n        return score_filter.run(\n            documents=retrieval.get(\"documents\"),\n            score=sql_pairs_similarity_threshold,\n            max_size=sql_pairs_retrieval_max_size,\n        )\n\n    return {}\n\n\n@observe(capture_input=False)\ndef formatted_output(\n    filtered_documents: dict, output_formatter: OutputFormatter\n) -> dict:\n    if filtered_documents:\n        return output_formatter.run(documents=filtered_documents.get(\"documents\"))\n\n    return {\"documents\": []}\n\n\n## End of Pipeline\n\n\nclass SqlPairsRetrieval(BasicPipeline):\n    def __init__(\n        self,\n        embedder_provider: EmbedderProvider,\n        document_store_provider: DocumentStoreProvider,\n        sql_pairs_similarity_threshold: float = 0.7,\n        sql_pairs_retrieval_max_size: int = 10,\n        **kwargs,\n    ) -> None:\n        store = document_store_provider.get_store(dataset_name=\"sql_pairs\")\n        self._components = {\n            \"store\": store,\n            \"embedder\": embedder_provider.get_text_embedder(),\n            \"retriever\": document_store_provider.get_retriever(\n                document_store=store,\n            ),\n            \"score_filter\": ScoreFilter(),\n            # TODO: add a llm filter to filter out low scoring document, in case ScoreFilter is not accurate enough\n            \"output_formatter\": OutputFormatter(),\n        }\n        self._configs = {\n            \"sql_pairs_similarity_threshold\": sql_pairs_similarity_threshold,\n            \"sql_pairs_retrieval_max_size\": sql_pairs_retrieval_max_size,\n        }\n\n        super().__init__(\n            AsyncDriver({}, sys.modules[__name__], result_builder=base.DictResult())\n        )\n\n    @observe(name=\"SqlPairs Retrieval\")\n    async def run(self, query: str, project_id: Optional[str] = None):\n        logger.info(\"SqlPairs Retrieval pipeline is running...\")\n        return await self._pipe.execute(\n            [\"formatted_output\"],\n            inputs={\n                \"query\": query,\n                \"project_id\": project_id or \"\",\n                **self._components,\n                **self._configs,\n            },\n        )\n"
  },
  {
    "path": "wren-ai-service/src/providers/__init__.py",
    "content": "import logging\nfrom dataclasses import dataclass\n\nfrom src.core.engine import Engine\nfrom src.core.pipeline import PipelineComponent\nfrom src.core.provider import DocumentStoreProvider, EmbedderProvider, LLMProvider\nfrom src.providers import loader\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\ndef provider_factory(\n    config: dict = {},\n) -> LLMProvider | EmbedderProvider | DocumentStoreProvider | Engine:\n    return loader.get_provider(config.get(\"provider\"))(**config)\n\n\ndef llm_processor(entry: dict) -> dict:\n    \"\"\"\n    Process the LLM configuration entry.\n\n    This function takes a dictionary containing LLM configuration and processes it\n    into a standardized format. The input dictionary is expected to have the following structure:\n\n    {\n        \"type\": \"llm\",\n        \"provider\": \"openai_llm\",\n        \"models\": [\n            {\n                \"model\": \"gpt-4o-mini\",\n                \"kwargs\": {\n                    \"temperature\": 0,\n                    \"n\": 1,\n                    \"max_tokens\": 4096,\n                    \"response_format\": {\"type\": \"json_object\"}\n                },\n                \"context_window_size\": 100000\n            }\n        ],\n        \"api_base\": \"https://api.openai.com/v1\"\n    }\n\n    The function processes this input and returns a dictionary with the following structure:\n\n    {\n        \"openai_llm.gpt-4o-mini\": {\n            \"provider\": \"openai_llm\",\n            \"model\": \"gpt-4o-mini\",\n            \"kwargs\": {\n                \"temperature\": 0,\n                \"n\": 1,\n                \"max_tokens\": 4096,\n                \"response_format\": {\"type\": \"json_object\"}\n            },\n            \"context_window_size\": 100000,\n            \"api_base\": \"https://api.openai.com/v1\"\n        }\n    }\n\n    Args:\n        entry (dict): The input LLM configuration dictionary.\n\n    Returns:\n        dict: A processed dictionary with standardized LLM configuration.\n\n    Note:\n        The function does not handle the `api_key` field. It is to be handled by the provider itself.\n    \"\"\"\n\n    def build_fallback_params(all_models: dict) -> dict:\n        result = {}\n        for model_name, model in all_models.items():\n            result[model_name] = {\n                \"model_name\": model_name,\n                \"litellm_params\": {\n                    \"model\": model[\"model\"],\n                    **({\"api_base\": model[\"api_base\"]} if \"api_base\" in model else {}),\n                    **(\n                        {\"api_version\": model[\"api_version\"]}\n                        if \"api_version\" in model\n                        else {}\n                    ),\n                    \"timeout\": model.get(\"timeout\", 120.0),\n                    **model.get(\"kwargs\", {}),\n                },\n            }\n        return result\n\n    others = {k: v for k, v in entry.items() if k not in [\"type\", \"provider\", \"models\"]}\n    returned = {}\n    all_models = {m[\"model\"]: m for m in entry.get(\"models\", [])}\n    fallback_model_params = build_fallback_params(all_models)\n\n    for model in entry.get(\"models\", []):\n        model_name = f\"{entry.get('provider')}.{model.get('alias', model.get('model'))}\"\n        model_additional_params = {\n            k: v\n            for k, v in model.items()\n            if k not in [\"model\", \"kwargs\", \"alias\", \"context_window_size\"]\n        }\n\n        fallback_model_names = [model[\"model\"]] + model.get(\"fallbacks\", [])\n        fallback_model_list = [\n            fallback_model_params[m]\n            for m in fallback_model_names\n            if m in fallback_model_params\n        ]\n\n        returned[model_name] = {\n            \"provider\": entry[\"provider\"],\n            \"model\": model[\"model\"],\n            \"kwargs\": model[\"kwargs\"],\n            \"context_window_size\": model.get(\"context_window_size\", 100000),\n            \"fallback_model_list\": fallback_model_list,\n            **model_additional_params,\n            **others,\n        }\n    return returned\n\n\ndef embedder_processor(entry: dict) -> dict:\n    \"\"\"\n    Process the embedder configuration entry.\n\n    This function takes a dictionary containing embedder configuration and processes it\n    into a standardized format. The input dictionary is expected to have the following structure:\n\n    {\n        \"type\": \"embedder\",\n        \"provider\": \"openai_embedder\",\n        \"models\": [\n            {\n                \"model\": \"text-embedding-ada-002\",\n                \"dimension\": 1536\n            }\n        ]\n    }\n\n    The function processes this input and returns a dictionary with the following structure:\n\n    {\n        \"openai_embedder.text-embedding-ada-002\": {\n            \"provider\": \"openai_embedder\",\n            \"model\": \"text-embedding-ada-002\",\n            \"dimension\": 1536\n        }\n    }\n\n    Args:\n        entry (dict): The input embedder configuration dictionary.\n\n    Returns:\n        dict: A processed dictionary with standardized embedder configuration.\n\n    Note:\n        The function does not handle the `api_key` field. It is to be handled by the provider itself.\n    \"\"\"\n    others = {k: v for k, v in entry.items() if k not in [\"type\", \"provider\", \"models\"]}\n    returned = {}\n    for model in entry[\"models\"]:\n        identifier = f\"{entry['provider']}.{model.get('alias', model.get('model'))}\"\n        model_additional_params = {\n            k: v for k, v in model.items() if k not in [\"model\", \"kwargs\", \"alias\"]\n        }\n        returned[identifier] = {\n            \"provider\": entry[\"provider\"],\n            \"model\": model[\"model\"],\n            **model_additional_params,\n            **others,\n        }\n\n    return returned\n\n\ndef document_store_processor(entry: dict) -> dict:\n    \"\"\"\n    Process the document store configuration entry.\n\n    This function takes a dictionary containing document store configuration and processes it\n    into a standardized format. The input dictionary is expected to have the following structure:\n\n    {\n        \"type\": \"document_store\",\n        \"provider\": \"qdrant\",\n        \"location\": \"http://localhost:6333\",\n        \"embedding_model_dim\": 3072,\n        \"timeout\": 120,\n        \"recreate_index\": False,\n    }\n\n    The function processes this input and returns a dictionary with the following structure:\n\n    {\n        \"qdrant\": {\n            \"provider\": \"qdrant\",\n            \"location\": \"http://localhost:6333\",\n            \"embedding_model_dim\": 3072,\n            \"timeout\": 120,\n            \"recreate_index\": False,\n        }\n    }\n\n    Args:\n        entry (dict): The input document store configuration dictionary.\n\n    Returns:\n        dict: A processed dictionary with standardized document store configuration.\n\n    Note:\n        The function does not handle the `api_key` field. It is to be handled by the provider itself.\n    \"\"\"\n    return {entry[\"provider\"]: {k: v for k, v in entry.items() if k not in [\"type\"]}}\n\n\ndef engine_processor(entry: dict) -> dict:\n    \"\"\"\n    Process the engine configuration entry.\n\n    This function takes a dictionary containing engine configuration and processes it\n    into a standardized format. The input dictionary is expected to have the following structure:\n\n    {\n        \"type\": \"engine\",\n        \"provider\": \"wren_ui\",\n        \"kwargs\": {\n            \"host\": \"localhost\",\n            \"port\": 8000\n        }\n    }\n\n    The function processes this input and returns a dictionary with the following structure:\n\n    {\n        \"wren_ui\": {\n            \"provider\": \"wren_ui\",\n            \"kwargs\": {\n                \"host\": \"localhost\",\n                \"port\": 8000\n            }\n        }\n    }\n\n    Args:\n        entry (dict): The input engine configuration dictionary.\n\n    Returns:\n        dict: A processed dictionary with standardized engine configuration.\n    \"\"\"\n    return {entry[\"provider\"]: {k: v for k, v in entry.items() if k not in [\"type\"]}}\n\n\ndef pipeline_processor(entry: dict) -> dict:\n    \"\"\"\n    Process the pipeline configuration entry.\n\n    This function takes a dictionary containing pipeline configuration and processes it\n    into a standardized format. The input dictionary is expected to have the following structure:\n\n    {\n        \"type\": \"pipeline\",\n        \"pipes\": [\n            {\n                \"name\": \"indexing\",\n                \"llm\": \"openai_llm.gpt-4o-mini\",\n                \"embedder\": \"openai_embedder.text-embedding-3-large\",\n                \"document_store\": \"qdrant\",\n                \"engine\": \"wren_ui\"\n            }\n        ]\n    }\n\n    The function processes this input and returns a dictionary with the following structure:\n\n    {\n        \"indexing\": {\n            \"llm\": \"openai_llm.gpt-4o-mini\",\n            \"embedder\": \"openai_embedder.text-embedding-3-large\",\n            \"document_store\": \"qdrant\",\n            \"engine\": \"wren_ui\",\n        }\n    }\n\n    Args:\n        entry (dict): The input pipeline configuration dictionary.\n\n    Returns:\n        dict: A processed dictionary with standardized pipeline configuration.\n    \"\"\"\n    return {\n        pipe[\"name\"]: {\n            \"llm\": pipe.get(\"llm\"),\n            \"embedder\": pipe.get(\"embedder\"),\n            \"document_store\": pipe.get(\"document_store\"),\n            \"engine\": pipe.get(\"engine\"),\n        }\n        for pipe in entry[\"pipes\"]\n    }\n\n\n@dataclass\nclass Configuration:\n    providers: dict\n    pipelines: dict\n\n\ndef transform(config: list[dict]) -> Configuration:\n    _TYPE_TO_PROCESSOR = {\n        \"llm\": llm_processor,\n        \"embedder\": embedder_processor,\n        \"document_store\": document_store_processor,\n        \"engine\": engine_processor,\n        \"pipeline\": pipeline_processor,\n    }\n\n    returned = {\n        \"embedder\": {},\n        \"llm\": {},\n        \"document_store\": {},\n        \"engine\": {},\n        \"pipeline\": {},\n    }\n\n    for entry in config:\n        type = entry[\"type\"]\n        processor = _TYPE_TO_PROCESSOR.get(type)\n        if not processor:\n            logger.error(f\"Unknown type: {type}\")\n            raise ValueError(f\"Unknown type: {type}\")\n\n        converted = processor(entry)\n        returned[type].update(converted)\n\n    return Configuration(\n        providers={k: v for k, v in returned.items() if k != \"pipeline\"},\n        pipelines=returned[\"pipeline\"],\n    )\n\n\ndef generate_components(configs: list[dict]) -> dict[str, PipelineComponent]:\n    \"\"\"\n    Generate pipeline components from configuration.\n\n    This function takes a list of configuration dictionaries and generates pipeline components\n    based on the provided configurations. The configurations are processed into a standardized\n    format and then instantiated into actual provider objects.\n\n    Args:\n        configs (list[dict]): A list of configuration dictionaries.\n\n    Returns:\n        dict: A dictionary of pipeline components.\n\n    Note:\n        instantiated_providers example:\n        {\n            \"embedder\": {\n                \"openai_embedder.text-embedding-3-large\": <EmbedderProvider>\n            },\n            \"llm\": {\n                \"openai_llm.gpt-4o-mini\": <LLMProvider>\n            },\n            ...\n        }\n\n    \"\"\"\n    loader.import_mods()\n\n    config = transform(configs)\n\n    instantiated_providers = {\n        type: {\n            identifier: provider_factory(config)\n            for identifier, config in configs.items()\n        }\n        for type, configs in config.providers.items()\n    }\n\n    def get(type: str, components: dict, instantiated_providers: dict):\n        identifier = components.get(type)\n        return instantiated_providers[type].get(identifier)\n\n    def componentize(components: dict, instantiated_providers: dict):\n        return PipelineComponent(\n            embedder_provider=get(\"embedder\", components, instantiated_providers),\n            llm_provider=get(\"llm\", components, instantiated_providers),\n            document_store_provider=get(\n                \"document_store\", components, instantiated_providers\n            ),\n            engine=get(\"engine\", components, instantiated_providers),\n        )\n\n    return {\n        pipe_name: componentize(components, instantiated_providers)\n        for pipe_name, components in config.pipelines.items()\n    }\n"
  },
  {
    "path": "wren-ai-service/src/providers/document_store/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/src/providers/document_store/qdrant.py",
    "content": "import logging\nimport os\nfrom typing import Any, Dict, List, Optional\n\nimport numpy as np\nimport qdrant_client\nfrom haystack import Document, component\nfrom haystack.document_stores.types import DuplicatePolicy\nfrom haystack.utils import Secret\nfrom haystack_integrations.components.retrievers.qdrant import QdrantEmbeddingRetriever\nfrom haystack_integrations.document_stores.qdrant import (\n    QdrantDocumentStore,\n    document_store,\n)\nfrom haystack_integrations.document_stores.qdrant.converters import (\n    DENSE_VECTORS_NAME,\n    SPARSE_VECTORS_NAME,\n    convert_id,\n    convert_qdrant_point_to_haystack_document,\n)\nfrom haystack_integrations.document_stores.qdrant.filters import (\n    convert_filters_to_qdrant,\n)\nfrom qdrant_client.http import models as rest\nfrom tqdm import tqdm\n\nfrom src.core.provider import DocumentStoreProvider\nfrom src.providers.loader import provider\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\ndef convert_haystack_documents_to_qdrant_points(\n    documents: List[Document],\n    *,\n    use_sparse_embeddings: bool,\n) -> List[rest.PointStruct]:\n    points = []\n    for document in documents:\n        payload = document.to_dict(flatten=True)\n        if use_sparse_embeddings:\n            vector = {}\n\n            dense_vector = payload.pop(\"embedding\", None)\n            if dense_vector is not None:\n                vector[DENSE_VECTORS_NAME] = dense_vector\n\n            sparse_vector = payload.pop(\"sparse_embedding\", None)\n            if sparse_vector is not None:\n                sparse_vector_instance = rest.SparseVector(**sparse_vector)\n                vector[SPARSE_VECTORS_NAME] = sparse_vector_instance\n\n        else:\n            vector = payload.pop(\"embedding\") or {}\n        _id = convert_id(payload.get(\"id\"))\n\n        point = rest.PointStruct(\n            payload=payload,\n            vector=vector,\n            id=_id,\n        )\n        points.append(point)\n    return points\n\n\nclass AsyncQdrantDocumentStore(QdrantDocumentStore):\n    def __init__(\n        self,\n        location: Optional[str] = None,\n        url: Optional[str] = None,\n        port: int = 6333,\n        grpc_port: int = 6334,\n        prefer_grpc: bool = False,\n        https: Optional[bool] = None,\n        api_key: Optional[Secret] = None,\n        prefix: Optional[str] = None,\n        timeout: Optional[int] = None,\n        host: Optional[str] = None,\n        path: Optional[str] = None,\n        force_disable_check_same_thread: bool = False,\n        index: str = \"Document\",\n        embedding_dim: int = 768,\n        on_disk: bool = False,\n        use_sparse_embeddings: bool = False,\n        sparse_idf: bool = False,\n        similarity: str = \"cosine\",\n        return_embedding: bool = False,\n        progress_bar: bool = True,\n        recreate_index: bool = False,\n        shard_number: Optional[int] = None,\n        replication_factor: Optional[int] = None,\n        write_consistency_factor: Optional[int] = None,\n        on_disk_payload: Optional[bool] = None,\n        hnsw_config: Optional[dict] = None,\n        optimizers_config: Optional[dict] = None,\n        wal_config: Optional[dict] = None,\n        quantization_config: Optional[dict] = None,\n        init_from: Optional[dict] = None,\n        wait_result_from_api: bool = True,\n        metadata: Optional[dict] = None,\n        write_batch_size: int = 100,\n        scroll_size: int = 10_000,\n        payload_fields_to_index: Optional[List[dict]] = None,\n    ):\n        super(AsyncQdrantDocumentStore, self).__init__(\n            location=location,\n            url=url,\n            port=port,\n            grpc_port=grpc_port,\n            prefer_grpc=prefer_grpc,\n            https=https,\n            api_key=api_key,\n            prefix=prefix,\n            timeout=timeout,\n            host=host,\n            path=path,\n            force_disable_check_same_thread=force_disable_check_same_thread,\n            index=index,\n            embedding_dim=embedding_dim,\n            on_disk=on_disk,\n            use_sparse_embeddings=use_sparse_embeddings,\n            sparse_idf=sparse_idf,\n            similarity=similarity,\n            return_embedding=return_embedding,\n            progress_bar=progress_bar,\n            recreate_index=recreate_index,\n            shard_number=shard_number,\n            replication_factor=replication_factor,\n            write_consistency_factor=write_consistency_factor,\n            on_disk_payload=on_disk_payload,\n            hnsw_config=hnsw_config,\n            optimizers_config=optimizers_config,\n            wal_config=wal_config,\n            quantization_config=quantization_config,\n            init_from=init_from,\n            wait_result_from_api=wait_result_from_api,\n            metadata=metadata,\n            write_batch_size=write_batch_size,\n            scroll_size=scroll_size,\n            payload_fields_to_index=payload_fields_to_index,\n        )\n\n        self.async_client = qdrant_client.AsyncQdrantClient(\n            location=location,\n            url=url,\n            port=port,\n            grpc_port=grpc_port,\n            prefer_grpc=prefer_grpc,\n            https=https,\n            api_key=api_key.resolve_value() if api_key else None,\n            prefix=prefix,\n            timeout=timeout,\n            host=host,\n            path=path,\n            force_disable_check_same_thread=force_disable_check_same_thread,\n            metadata=metadata or {},\n        )\n\n        # to improve the indexing performance\n        # see https://qdrant.tech/documentation/guides/multiple-partitions/?q=mul#calibrate-performance\n        self.client.create_payload_index(\n            collection_name=index, field_name=\"project_id\", field_schema=\"keyword\"\n        )\n\n    async def _query_by_embedding(\n        self,\n        query_embedding: List[float],\n        filters: Optional[Dict[str, Any]] = None,\n        top_k: int = 10,\n        scale_score: bool = True,\n        return_embedding: bool = False,\n    ) -> List[Document]:\n        qdrant_filters = convert_filters_to_qdrant(filters)\n\n        points = await self.async_client.search(\n            collection_name=self.index,\n            query_vector=rest.NamedVector(\n                name=DENSE_VECTORS_NAME if self.use_sparse_embeddings else \"\",\n                vector=query_embedding,\n            ),\n            search_params=(\n                rest.SearchParams(\n                    quantization=rest.QuantizationSearchParams(\n                        rescore=True,\n                        oversampling=3.0,\n                    ),\n                )\n                if len(query_embedding)\n                >= 1024  # reference: https://qdrant.tech/articles/binary-quantization/#when-should-you-not-use-bq\n                else None\n            ),\n            query_filter=qdrant_filters,\n            limit=top_k,\n            with_vectors=return_embedding,\n        )\n        results = [\n            convert_qdrant_point_to_haystack_document(\n                point, use_sparse_embeddings=self.use_sparse_embeddings\n            )\n            for point in points\n        ]\n        if scale_score:\n            for document in results:\n                score = document.score\n                if self.similarity == \"cosine\":\n                    score = (score + 1) / 2\n                else:\n                    score = float(1 / (1 + np.exp(-score / 100)))\n                document.score = score\n        return results\n\n    async def _query_by_filters(\n        self,\n        filters: Optional[Dict[str, Any]] = None,\n        top_k: Optional[int] = None,\n    ) -> List[Document]:\n        qdrant_filters = convert_filters_to_qdrant(filters)\n        points_list = []\n        offset = None\n        while True:\n            points = await self.async_client.scroll(\n                collection_name=self.index,\n                offset=offset,\n                scroll_filter=qdrant_filters,\n                limit=top_k,\n            )\n            points_list.extend(points[0])\n            if points[1] is None:\n                break\n            offset = points[1]\n\n        if points_list:\n            return [\n                convert_qdrant_point_to_haystack_document(\n                    point, use_sparse_embeddings=self.use_sparse_embeddings\n                )\n                for point in points_list\n            ]\n        else:\n            return []\n\n    async def delete_documents(self, filters: Optional[Dict[str, Any]] = None):\n        if not filters:\n            qdrant_filters = rest.Filter()\n        else:\n            qdrant_filters = convert_filters_to_qdrant(filters)\n\n        try:\n            await self.async_client.delete(\n                collection_name=self.index,\n                points_selector=qdrant_filters,\n                wait=self.wait_result_from_api,\n            )\n        except KeyError:\n            logger.warning(\n                \"Called QdrantDocumentStore.delete_documents() on a non-existing ID\",\n            )\n\n    async def count_documents(self, filters: Optional[Dict[str, Any]] = None) -> int:\n        if not filters:\n            qdrant_filters = rest.Filter()\n        else:\n            qdrant_filters = convert_filters_to_qdrant(filters)\n\n        return (\n            await self.async_client.count(\n                collection_name=self.index, count_filter=qdrant_filters\n            )\n        ).count\n\n    async def write_documents(\n        self, documents: List[Document], policy: DuplicatePolicy = DuplicatePolicy.FAIL\n    ):\n        for doc in documents:\n            if not isinstance(doc, Document):\n                msg = f\"DocumentStore.write_documents() expects a list of Documents but got an element of {type(doc)}.\"\n                raise ValueError(msg)\n\n        self._set_up_collection(\n            self.index,\n            self.embedding_dim,\n            False,\n            self.similarity,\n            self.use_sparse_embeddings,\n            self.sparse_idf,\n            self.on_disk,\n            self.payload_fields_to_index,\n        )\n\n        if len(documents) == 0:\n            logger.warning(\n                \"Calling QdrantDocumentStore.write_documents() with empty list\"\n            )\n            return\n\n        document_objects = self._handle_duplicate_documents(\n            documents=documents,\n            policy=policy,\n        )\n\n        batched_documents = document_store.get_batches_from_generator(\n            document_objects, self.write_batch_size\n        )\n        with tqdm(\n            total=len(document_objects), disable=not self.progress_bar\n        ) as progress_bar:\n            for document_batch in batched_documents:\n                batch = convert_haystack_documents_to_qdrant_points(\n                    document_batch,\n                    use_sparse_embeddings=self.use_sparse_embeddings,\n                )\n\n                await self.async_client.upsert(\n                    collection_name=self.index,\n                    points=batch,\n                    wait=self.wait_result_from_api,\n                )\n\n                progress_bar.update(self.write_batch_size)\n        return len(document_objects)\n\n\nclass AsyncQdrantEmbeddingRetriever(QdrantEmbeddingRetriever):\n    def __init__(\n        self,\n        document_store: AsyncQdrantDocumentStore,\n        filters: Optional[Dict[str, Any]] = None,\n        top_k: int = 10,\n        scale_score: bool = True,\n        return_embedding: bool = False,\n    ):\n        super(AsyncQdrantEmbeddingRetriever, self).__init__(\n            document_store=document_store,\n            filters=filters,\n            top_k=top_k,\n            scale_score=scale_score,\n            return_embedding=return_embedding,\n        )\n        self._document_store = document_store\n\n    @component.output_types(documents=List[Document])\n    async def run(\n        self,\n        query_embedding: List[float],\n        filters: Optional[Dict[str, Any]] = None,\n        top_k: Optional[int] = None,\n        scale_score: Optional[bool] = None,\n        return_embedding: Optional[bool] = None,\n    ):\n        if query_embedding:\n            docs = await self._document_store._query_by_embedding(\n                query_embedding=query_embedding,\n                filters=filters or self._filters,\n                top_k=top_k or self._top_k,\n                scale_score=scale_score or self._scale_score,\n                return_embedding=return_embedding or self._return_embedding,\n            )\n        else:\n            docs = await self._document_store._query_by_filters(\n                filters=filters,\n                top_k=top_k,\n            )\n\n        return {\"documents\": docs}\n\n\n@provider(\"qdrant\")\nclass QdrantProvider(DocumentStoreProvider):\n    def __init__(\n        self,\n        location: str = os.getenv(\"QDRANT_HOST\", \"qdrant\"),\n        api_key: Optional[str] = os.getenv(\"QDRANT_API_KEY\", None),\n        timeout: Optional[int] = (\n            int(os.getenv(\"QDRANT_TIMEOUT\")) if os.getenv(\"QDRANT_TIMEOUT\") else 120\n        ),\n        embedding_model_dim: int = (\n            int(os.getenv(\"EMBEDDING_MODEL_DIMENSION\"))\n            if os.getenv(\"EMBEDDING_MODEL_DIMENSION\")\n            else 0\n        ),\n        recreate_index: bool = (\n            bool(os.getenv(\"SHOULD_FORCE_DEPLOY\"))\n            if os.getenv(\"SHOULD_FORCE_DEPLOY\")\n            else False\n        ),\n        **_,\n    ):\n        self._location = location\n        self._api_key = Secret.from_token(api_key) if api_key else None\n        self._timeout = timeout\n        self._embedding_model_dim = embedding_model_dim\n        self._reset_document_store(recreate_index)\n\n    def _reset_document_store(self, recreate_index: bool):\n        self.get_store(recreate_index=recreate_index)\n        self.get_store(dataset_name=\"table_descriptions\", recreate_index=recreate_index)\n        self.get_store(dataset_name=\"view_questions\", recreate_index=recreate_index)\n        self.get_store(dataset_name=\"sql_pairs\", recreate_index=recreate_index)\n        self.get_store(dataset_name=\"instructions\", recreate_index=recreate_index)\n        self.get_store(dataset_name=\"project_meta\", recreate_index=recreate_index)\n\n    def get_store(\n        self,\n        dataset_name: Optional[str] = None,\n        recreate_index: bool = False,\n    ):\n        return AsyncQdrantDocumentStore(\n            location=self._location,\n            api_key=self._api_key,\n            embedding_dim=self._embedding_model_dim,\n            index=dataset_name or \"Document\",\n            recreate_index=recreate_index,\n            on_disk=True,\n            timeout=self._timeout,\n            quantization_config=(\n                rest.BinaryQuantization(\n                    binary=rest.BinaryQuantizationConfig(\n                        always_ram=True,\n                    )\n                )\n                if self._embedding_model_dim >= 1024\n                else None\n            ),\n            # to improve the indexing performance, we disable building global index for the whole collection\n            # see https://qdrant.tech/documentation/guides/multiple-partitions/?q=mul#calibrate-performance\n            hnsw_config=rest.HnswConfigDiff(\n                payload_m=16,\n                m=0,\n            ),\n        )\n\n    def get_retriever(\n        self,\n        document_store: AsyncQdrantDocumentStore,\n        top_k: int = 10,\n    ):\n        return AsyncQdrantEmbeddingRetriever(\n            document_store=document_store,\n            top_k=top_k,\n        )\n"
  },
  {
    "path": "wren-ai-service/src/providers/embedder/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/src/providers/embedder/litellm.py",
    "content": "import asyncio\nimport logging\nimport os\nfrom typing import Any, Dict, List, Optional, Tuple\n\nimport backoff\nimport openai\nfrom haystack import Document, component\nfrom litellm import aembedding\n\nfrom src.core.provider import EmbedderProvider\nfrom src.providers.loader import provider\nfrom src.utils import remove_trailing_slash\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\ndef _prepare_texts_to_embed(documents: List[Document]) -> List[str]:\n    \"\"\"\n    Prepare the texts to embed by concatenating the Document text with the metadata fields to embed.\n    \"\"\"\n    texts_to_embed = []\n    for doc in documents:\n        text_to_embed = \"\\n\".join([doc.content or \"\"])\n\n        # copied from OpenAI embedding_utils (https://github.com/openai/openai-python/blob/main/openai/embeddings_utils.py)\n        # replace newlines, which can negatively affect performance.\n        text_to_embed = text_to_embed.replace(\"\\n\", \" \")\n        texts_to_embed.append(text_to_embed)\n    return texts_to_embed\n\n\n@component\nclass AsyncTextEmbedder:\n    def __init__(\n        self,\n        model: str,\n        api_key: Optional[str] = None,\n        api_base_url: Optional[str] = None,\n        timeout: Optional[float] = None,\n        **kwargs,\n    ):\n        self._api_key = api_key\n        self._model = model\n        self._api_base_url = api_base_url\n        self._timeout = timeout\n        self._kwargs = kwargs\n\n    @component.output_types(embedding=List[float], meta=Dict[str, Any])\n    @backoff.on_exception(backoff.expo, openai.APIError, max_time=60.0, max_tries=3)\n    async def run(self, text: str):\n        if not isinstance(text, str):\n            raise TypeError(\n                \"AsyncTextEmbedder expects a string as an input.\"\n                \"In case you want to embed a list of Documents, please use the AsyncDocumentEmbedder.\"\n            )\n\n        # copied from OpenAI embedding_utils (https://github.com/openai/openai-python/blob/main/openai/embeddings_utils.py)\n        # replace newlines, which can negatively affect performance.\n        text_to_embed = text.replace(\"\\n\", \" \")\n\n        response = await aembedding(\n            model=self._model,\n            input=[text_to_embed],\n            api_key=self._api_key,\n            api_base=self._api_base_url,\n            timeout=self._timeout,\n            **self._kwargs,\n        )\n\n        meta = {\n            \"model\": response.model,\n            \"usage\": dict(response.usage) if hasattr(response, \"usage\") else {},\n        }\n\n        return {\"embedding\": response.data[0][\"embedding\"], \"meta\": meta}\n\n\n@component\nclass AsyncDocumentEmbedder:\n    def __init__(\n        self,\n        model: str,\n        batch_size: int = 32,\n        api_key: Optional[str] = None,\n        api_base_url: Optional[str] = None,\n        timeout: Optional[float] = None,\n        **kwargs,\n    ):\n        self._api_key = api_key\n        self._model = model\n        self._batch_size = batch_size\n        self._api_base_url = api_base_url\n        self._timeout = timeout\n        self._kwargs = kwargs\n\n    async def _embed_batch(\n        self, texts_to_embed: List[str], batch_size: int\n    ) -> Tuple[List[List[float]], Dict[str, Any]]:\n        async def embed_single_batch(batch: List[str]) -> Any:\n            return await aembedding(\n                model=self._model,\n                input=batch,\n                api_key=self._api_key,\n                api_base=self._api_base_url,\n                timeout=self._timeout,\n                **self._kwargs,\n            )\n\n        batches = [\n            texts_to_embed[i : i + batch_size]\n            for i in range(0, len(texts_to_embed), batch_size)\n        ]\n\n        responses = await asyncio.gather(\n            *[embed_single_batch(batch) for batch in batches]\n        )\n\n        all_embeddings = []\n        meta: Dict[str, Any] = {}\n\n        for response in responses:\n            embeddings = [el[\"embedding\"] for el in response.data]\n            all_embeddings.extend(embeddings)\n\n            if \"model\" not in meta:\n                meta[\"model\"] = response.model\n            if \"usage\" not in meta:\n                meta[\"usage\"] = (\n                    dict(response.usage) if hasattr(response, \"usage\") else {}\n                )\n            else:\n                if hasattr(response, \"usage\"):\n                    meta[\"usage\"][\"prompt_tokens\"] += response.usage.prompt_tokens\n                    meta[\"usage\"][\"total_tokens\"] += response.usage.total_tokens\n\n        return all_embeddings, meta\n\n    @component.output_types(documents=List[Document], meta=Dict[str, Any])\n    @backoff.on_exception(backoff.expo, openai.APIError, max_time=60.0, max_tries=3)\n    async def run(self, documents: List[Document]):\n        if (\n            not isinstance(documents, list)\n            or documents\n            and not isinstance(documents[0], Document)\n        ):\n            raise TypeError(\n                \"AsyncDocumentEmbedder expects a list of Documents as input.\"\n                \"In case you want to embed a string, please use the AsyncTextEmbedder.\"\n            )\n\n        texts_to_embed = _prepare_texts_to_embed(documents=documents)\n\n        embeddings, meta = await self._embed_batch(\n            texts_to_embed=texts_to_embed,\n            batch_size=self._batch_size,\n        )\n\n        for doc, emb in zip(documents, embeddings):\n            doc.embedding = emb\n\n        return {\"documents\": documents, \"meta\": meta}\n\n\n@provider(\"litellm_embedder\")\nclass LitellmEmbedderProvider(EmbedderProvider):\n    def __init__(\n        self,\n        model: str,\n        api_key_name: Optional[\n            str\n        ] = None,  # e.g. EMBEDDER_OPENAI_API_KEY, EMBEDDER_ANTHROPIC_API_KEY, etc.\n        api_base: Optional[str] = None,\n        timeout: float = 120.0,\n        **kwargs,\n    ):\n        self._api_key = os.getenv(api_key_name) if api_key_name else None\n        self._api_base = remove_trailing_slash(api_base) if api_base else None\n        self._embedding_model = model\n        self._timeout = timeout\n        if \"provider\" in kwargs:\n            del kwargs[\"provider\"]\n        self._kwargs = kwargs\n\n    def get_text_embedder(self):\n        return AsyncTextEmbedder(\n            api_key=self._api_key,\n            api_base_url=self._api_base,\n            model=self._embedding_model,\n            timeout=self._timeout,\n            **self._kwargs,\n        )\n\n    def get_document_embedder(self):\n        return AsyncDocumentEmbedder(\n            api_key=self._api_key,\n            api_base_url=self._api_base,\n            model=self._embedding_model,\n            timeout=self._timeout,\n            **self._kwargs,\n        )\n"
  },
  {
    "path": "wren-ai-service/src/providers/engine/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/src/providers/engine/wren.py",
    "content": "import asyncio\nimport base64\nimport logging\nimport os\nfrom typing import Any, Dict, Optional, Tuple\n\nimport aiohttp\nimport orjson\n\nfrom src.config import settings\nfrom src.core.engine import Engine, remove_limit_statement\nfrom src.providers.loader import provider\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n@provider(\"wren_ui\")\nclass WrenUI(Engine):\n    def __init__(\n        self,\n        endpoint: str = os.getenv(\"WREN_UI_ENDPOINT\"),\n        **_,\n    ):\n        self._endpoint = endpoint\n\n    async def execute_sql(\n        self,\n        sql: str,\n        session: aiohttp.ClientSession,\n        project_id: str | None = None,\n        dry_run: bool = True,\n        timeout: float = settings.engine_timeout,\n        limit: int = 500,\n        **kwargs,\n    ) -> Tuple[bool, Optional[Dict[str, Any]], Optional[Dict[str, Any]]]:\n        data = {\n            \"sql\": remove_limit_statement(sql),\n            \"projectId\": project_id,\n        }\n        if dry_run:\n            data[\"dryRun\"] = True\n            data[\"limit\"] = 1\n        else:\n            data[\"limit\"] = limit\n\n        try:\n            async with session.post(\n                f\"{self._endpoint}/api/graphql\",\n                json={\n                    \"query\": \"mutation PreviewSql($data: PreviewSQLDataInput) { previewSql(data: $data) }\",\n                    \"variables\": {\"data\": data},\n                },\n                timeout=aiohttp.ClientTimeout(total=timeout),\n            ) as response:\n                res_json = await response.json()\n                if res_data := res_json.get(\"data\"):\n                    res = res_data.get(\"previewSql\", {}) if res_data else {}\n                    if dry_run:\n                        return (\n                            True,\n                            res,\n                            {\n                                \"correlation_id\": res_json.get(\"correlationId\", \"\"),\n                            },\n                        )\n\n                    data = res.get(\"data\", []) if res else []\n                    if len(data) > 0:\n                        return (\n                            True,\n                            res,\n                            {\n                                \"correlation_id\": res_json.get(\"correlationId\", \"\"),\n                            },\n                        )\n\n                    return (\n                        False,\n                        res,\n                        {\n                            \"correlation_id\": res_json.get(\"correlationId\", \"\"),\n                        },\n                    )\n\n                error_message = res_json.get(\"errors\", [{}])[0].get(\n                    \"message\", \"Unknown error\"\n                )\n                logger.error(f\"Error executing SQL: {error_message}\")\n                dialect_sql = (\n                    (\n                        (\n                            (res_json.get(\"errors\", [{}])[0] or {}).get(\n                                \"extensions\", {}\n                            )\n                            or {}\n                        ).get(\"other\", {})\n                        or {}\n                    ).get(\"metadata\", {})\n                    or {}\n                ).get(\"dialectSql\", \"\") or \"\"\n                planned_sql = (\n                    (\n                        (\n                            (res_json.get(\"errors\", [{}])[0] or {}).get(\n                                \"extensions\", {}\n                            )\n                            or {}\n                        ).get(\"other\", {})\n                        or {}\n                    ).get(\"metadata\", {})\n                    or {}\n                ).get(\"plannedSql\", \"\") or \"\"\n\n                return (\n                    False,\n                    {},\n                    {\n                        \"error_message\": error_message,\n                        \"error_sql\": dialect_sql or planned_sql or sql,\n                        \"correlation_id\": (\n                            (\n                                (\n                                    (res_json.get(\"errors\", [{}])[0] or {}).get(\n                                        \"extensions\", {}\n                                    )\n                                    or {}\n                                ).get(\"other\", {})\n                                or {}\n                            ).get(\"correlationId\")\n                            or \"\"\n                        ),\n                    },\n                )\n        except asyncio.TimeoutError:\n            return (\n                False,\n                {},\n                {\"error_message\": f\"Request timed out: {timeout} seconds\"},\n            )\n\n\n@provider(\"wren_ibis\")\nclass WrenIbis(Engine):\n    def __init__(\n        self,\n        endpoint: str = os.getenv(\"WREN_IBIS_ENDPOINT\"),\n        source: str = os.getenv(\"WREN_IBIS_SOURCE\"),\n        manifest: str = os.getenv(\"WREN_IBIS_MANIFEST\"),\n        connection_info: str = os.getenv(\"WREN_IBIS_CONNECTION_INFO\"),\n        **_,\n    ):\n        self._endpoint = endpoint\n        self._source = source\n        self._manifest = manifest\n        self._connection_info = (\n            orjson.loads(base64.b64decode(connection_info)) if connection_info else {}\n        )\n\n    async def execute_sql(\n        self,\n        sql: str,\n        session: aiohttp.ClientSession,\n        dry_run: bool = True,\n        timeout: float = settings.engine_timeout,\n        limit: int = 500,\n        **kwargs,\n    ) -> Tuple[bool, Optional[Dict[str, Any]]]:\n        api_endpoint = f\"{self._endpoint}/v3/connector/{self._source}/query\"\n        if dry_run:\n            api_endpoint += \"?dryRun=true&limit=1\"\n        else:\n            api_endpoint += f\"?limit={limit}\"\n\n        try:\n            async with session.post(\n                api_endpoint,\n                json={\n                    \"sql\": remove_limit_statement(sql),\n                    \"manifestStr\": self._manifest,\n                    \"connectionInfo\": self._connection_info,\n                },\n                timeout=aiohttp.ClientTimeout(total=timeout),\n            ) as response:\n                if dry_run:\n                    res = await response.text()\n                else:\n                    res = await response.json()\n\n                if response.status == 200 or response.status == 204:\n                    return (\n                        True,\n                        res,\n                        {\n                            \"correlation_id\": \"\",\n                        },\n                    )\n\n                return (\n                    False,\n                    None,\n                    {\n                        \"error_message\": res,\n                        \"correlation_id\": \"\",\n                    },\n                )\n        except asyncio.TimeoutError:\n            return False, None, f\"Request timed out: {timeout} seconds\"\n\n    async def dry_plan(\n        self,\n        session: aiohttp.ClientSession,\n        sql: str,\n        data_source: str,\n        timeout: float = settings.engine_timeout,\n        allow_fallback: bool = True,\n        **kwargs,\n    ) -> Tuple[bool, str]:\n        api_endpoint = f\"{self._endpoint}/v3/connector/{data_source}/dry-plan\"\n        try:\n            async with session.post(\n                api_endpoint,\n                headers={\n                    \"x-wren-fallback_disable\": \"false\" if allow_fallback else \"true\",\n                },\n                json={\n                    \"sql\": sql,\n                    \"manifestStr\": self._manifest,\n                },\n                timeout=aiohttp.ClientTimeout(total=timeout),\n            ) as response:\n                res = await response.text()\n\n                if response.status != 200:\n                    raise Exception(f\"Request failed with message: {res}\")\n\n                return True, \"\"\n        except asyncio.TimeoutError:\n            logger.error(f\"Request timed out: {timeout} seconds\")\n            return False, f\"Request timed out: {timeout} seconds\"\n        except Exception as e:\n            logger.exception(f\"Unexpected error during dry_plan: {str(e)}\")\n            return False, f\"Unexpected error during dry_plan: {str(e)}\"\n\n    async def get_func_list(\n        self,\n        session: aiohttp.ClientSession,\n        data_source: str,\n        timeout: float = settings.engine_timeout,\n    ) -> list[str]:\n        api_endpoint = f\"{self._endpoint}/v3/connector/{data_source}/functions\"\n        try:\n            async with session.get(api_endpoint, timeout=timeout) as response:\n                res = await response.json()\n\n                if response.status != 200:\n                    raise Exception(f\"Request failed with message: {res}\")\n\n                return res\n        except asyncio.TimeoutError:\n            logger.error(f\"Request timed out: {timeout} seconds\")\n            return []\n        except Exception as e:\n            logger.exception(f\"Unexpected error during get_func_list: {str(e)}\")\n            return []\n\n    async def get_sql_knowledge(\n        self,\n        session: aiohttp.ClientSession,\n        data_source: str,\n        timeout: float = settings.engine_timeout,\n    ) -> Optional[Dict[str, Any]]:\n        api_endpoint = f\"{self._endpoint}/v3/connector/{data_source}/knowledge\"\n        try:\n            async with session.get(api_endpoint, timeout=timeout) as response:\n                res = await response.json()\n\n                if response.status != 200:\n                    raise Exception(f\"Request failed with message: {res}\")\n\n                return res\n        except asyncio.TimeoutError:\n            logger.error(f\"Request timed out: {timeout} seconds\")\n            return None\n        except Exception as e:\n            logger.exception(f\"Unexpected error during get_sql_knowledge: {str(e)}\")\n            return None\n\n\n@provider(\"wren_engine\")\nclass WrenEngine(Engine):\n    def __init__(\n        self,\n        endpoint: str = os.getenv(\"WREN_ENGINE_ENDPOINT\"),\n        manifest: str = os.getenv(\"WREN_ENGINE_MANIFEST\"),\n        **_,\n    ):\n        self._endpoint = endpoint\n        self._manifest = manifest\n\n    async def execute_sql(\n        self,\n        sql: str,\n        session: aiohttp.ClientSession,\n        dry_run: bool = True,\n        timeout: float = settings.engine_timeout,\n        limit: int = 500,\n        **kwargs,\n    ) -> Tuple[bool, Optional[Dict[str, Any]], Optional[str]]:\n        api_endpoint = (\n            f\"{self._endpoint}/v1/mdl/dry-run\"\n            if dry_run\n            else f\"{self._endpoint}/v1/mdl/preview\"\n        )\n\n        try:\n            async with session.get(\n                api_endpoint,\n                json={\n                    \"manifest\": orjson.loads(base64.b64decode(self._manifest))\n                    if self._manifest\n                    else {},\n                    \"sql\": remove_limit_statement(sql),\n                    \"limit\": 1 if dry_run else limit,\n                },\n                timeout=aiohttp.ClientTimeout(total=timeout),\n            ) as response:\n                if dry_run:\n                    res = await response.text()\n                else:\n                    res = await response.json()\n\n                if response.status == 200:\n                    return (\n                        True,\n                        res,\n                        {\n                            \"correlation_id\": \"\",\n                        },\n                    )\n\n                return (\n                    False,\n                    None,\n                    {\n                        \"error_message\": res,\n                        \"correlation_id\": \"\",\n                    },\n                )\n        except asyncio.TimeoutError:\n            return False, None, f\"Request timed out: {timeout} seconds\"\n"
  },
  {
    "path": "wren-ai-service/src/providers/llm/__init__.py",
    "content": "import logging\nfrom dataclasses import asdict, dataclass, field\nfrom enum import Enum\nfrom typing import Any, Dict, List, Optional\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nclass ChatRole(str, Enum):\n    \"\"\"Enumeration representing the roles within a chat.\"\"\"\n\n    ASSISTANT = \"assistant\"\n    USER = \"user\"\n    SYSTEM = \"system\"\n    FUNCTION = \"function\"\n\n\n@dataclass\nclass ChatMessage:\n    \"\"\"\n    Represents a message in a LLM chat conversation.\n\n    :param content: The text content of the message.\n    :param role: The role of the entity sending the message.\n    :param name: The name of the function being called (only applicable for role FUNCTION).\n    :param meta: Additional metadata associated with the message.\n    \"\"\"\n\n    content: str\n    role: ChatRole\n    name: Optional[str] = None\n    image_url: Optional[str] = None\n    meta: Dict[str, Any] = field(default_factory=dict, hash=False)\n\n    def is_from(self, role: ChatRole) -> bool:\n        \"\"\"\n        Check if the message is from a specific role.\n\n        :param role: The role to check against.\n        :returns: True if the message is from the specified role, False otherwise.\n        \"\"\"\n        return self.role == role\n\n    @classmethod\n    def from_assistant(\n        cls, content: str, meta: Optional[Dict[str, Any]] = None\n    ) -> \"ChatMessage\":\n        \"\"\"\n        Create a message from the assistant.\n\n        :param content: The text content of the message.\n        :param meta: Additional metadata associated with the message.\n        :returns: A new ChatMessage instance.\n        \"\"\"\n        return cls(\n            content, ChatRole.ASSISTANT, name=None, image_url=None, meta=meta or {}\n        )\n\n    @classmethod\n    def from_user(cls, content: str, image_url: Optional[str] = None) -> \"ChatMessage\":\n        \"\"\"\n        Create a message from the user.\n\n        :param content: The text content of the message.\n        :returns: A new ChatMessage instance.\n        \"\"\"\n        return cls(content, ChatRole.USER, name=None, image_url=image_url)\n\n    @classmethod\n    def from_system(cls, content: str) -> \"ChatMessage\":\n        \"\"\"\n        Create a message from the system.\n\n        :param content: The text content of the message.\n        :returns: A new ChatMessage instance.\n        \"\"\"\n        return cls(content, ChatRole.SYSTEM, name=None, image_url=None)\n\n    @classmethod\n    def from_function(cls, content: str, name: str) -> \"ChatMessage\":\n        \"\"\"\n        Create a message from a function call.\n\n        :param content: The text content of the message.\n        :param name: The name of the function being called.\n        :returns: A new ChatMessage instance.\n        \"\"\"\n        return cls(content, ChatRole.FUNCTION, name=name, image_url=None, meta=None)\n\n    def to_dict(self) -> Dict[str, Any]:\n        \"\"\"\n        Converts ChatMessage into a dictionary.\n\n        :returns:\n            Serialized version of the object.\n        \"\"\"\n        data = asdict(self)\n        data[\"role\"] = self.role.value\n\n        return data\n\n    @classmethod\n    def from_dict(cls, data: Dict[str, Any]) -> \"ChatMessage\":\n        \"\"\"\n        Creates a new ChatMessage object from a dictionary.\n\n        :param data:\n            The dictionary to build the ChatMessage object.\n        :returns:\n            The created object.\n        \"\"\"\n        data[\"role\"] = ChatRole(data[\"role\"])\n\n        return cls(**data)\n\n\n@dataclass\nclass StreamingChunk:\n    \"\"\"\n    The StreamingChunk class encapsulates a segment of streamed content along with associated metadata.\n\n    This structure facilitates the handling and processing of streamed data in a systematic manner.\n\n    :param content: The content of the message chunk as a string.\n    :param meta: A dictionary containing metadata related to the message chunk.\n    \"\"\"\n\n    content: str\n    meta: Dict[str, Any] = field(default_factory=dict, hash=False)\n\n\ndef build_message(completion: Any, choice: Any) -> ChatMessage:\n    \"\"\"\n    Converts the response from the OpenAI API to a ChatMessage.\n\n    :param completion:\n        The completion returned by the OpenAI API.\n    :param choice:\n        The choice returned by the OpenAI API.\n    :returns:\n        The ChatMessage.\n    \"\"\"\n    # function or tools calls are not going to happen in non-chat generation\n    # as users can not send ChatMessage with function or tools calls\n    chat_message = ChatMessage.from_assistant(choice.message.content or \"\")\n    chat_message.meta.update(\n        {\n            \"model\": completion.model,\n            \"index\": choice.index,\n            \"finish_reason\": choice.finish_reason,\n            \"usage\": dict(completion.usage) if hasattr(completion, \"usage\") else {},\n        }\n    )\n    return chat_message\n\n\ndef check_finish_reason(message: ChatMessage) -> None:\n    \"\"\"\n    Check the `finish_reason` returned with the OpenAI completions.\n\n    If the `finish_reason` is `length`, log a warning to the user.\n\n    :param message:\n        The message returned by the LLM.\n    \"\"\"\n    if message.meta[\"finish_reason\"] == \"length\":\n        logger.warning(\n            \"The completion for index %s has been truncated before reaching a natural stopping point. \"\n            \"Finish reason: %s. Increase the max_tokens parameter to allow for longer completions.\",\n            message.meta[\"index\"],\n            message.meta[\"finish_reason\"],\n        )\n    if message.meta[\"finish_reason\"] == \"content_filter\":\n        logger.warning(\n            \"The completion for index %s has been truncated due to the content filter. \"\n            \"Finish reason: %s.\",\n            message.meta[\"index\"],\n            message.meta[\"finish_reason\"],\n        )\n\n\ndef connect_chunks(chunk: Any, chunks: List[StreamingChunk]) -> ChatMessage:\n    \"\"\"\n    Connects the streaming chunks into a single ChatMessage.\n    \"\"\"\n    complete_response = ChatMessage.from_assistant(\n        \"\".join([chunk.content for chunk in chunks])\n    )\n    complete_response.meta.update(\n        {\n            \"model\": chunk.model,\n            \"index\": 0,\n            \"finish_reason\": chunk.choices[0].finish_reason,\n            \"usage\": dict(chunk.usage) if hasattr(chunk, \"usage\") else {},\n        }\n    )\n    return complete_response\n\n\ndef build_chunk(chunk: Any) -> StreamingChunk:\n    \"\"\"\n    Converts the response from the OpenAI API to a StreamingChunk.\n\n    :param chunk:\n        The chunk returned by the OpenAI API.\n    :returns:\n        The StreamingChunk.\n    \"\"\"\n    # function or tools calls are not going to happen in non-chat generation\n    # as users can not send ChatMessage with function or tools calls\n    choice = chunk.choices[0]\n    content = choice.delta.content or \"\"\n    chunk_message = StreamingChunk(content)\n    chunk_message.meta.update(\n        {\n            \"model\": chunk.model,\n            \"index\": choice.index,\n            \"finish_reason\": choice.finish_reason,\n        }\n    )\n    return chunk_message\n\n\ndef convert_message_to_openai_format(message: ChatMessage) -> Dict[str, str]:\n    \"\"\"\n    Convert a message to the format expected by OpenAI's Chat API.\n\n    See the [API reference](https://platform.openai.com/docs/api-reference/chat/create) for details.\n\n    :returns: A dictionary with the following key:\n        - `role`\n        - `content`\n        - `name` (optional)\n    \"\"\"\n    openai_msg = {\"role\": message.role.value}\n\n    if message.content and hasattr(message, \"image_url\") and message.image_url:\n        openai_msg[\"content\"] = [\n            {\"type\": \"text\", \"text\": message.content},\n            {\"type\": \"image_url\", \"image_url\": {\"url\": message.image_url}},\n        ]\n    elif message.content:\n        openai_msg[\"content\"] = message.content\n    elif hasattr(message, \"image_url\") and message.image_url:\n        openai_msg[\"content\"] = [\n            {\"type\": \"image_url\", \"image_url\": {\"url\": message.image_url}}\n        ]\n\n    if hasattr(message, \"name\") and message.name:\n        openai_msg[\"name\"] = message.name\n\n    return openai_msg\n"
  },
  {
    "path": "wren-ai-service/src/providers/llm/litellm.py",
    "content": "import os\nfrom typing import Any, Callable, Dict, List, Optional\n\nimport backoff\nimport openai\nfrom litellm import Router, acompletion\n\nfrom src.core.provider import LLMProvider\nfrom src.providers.llm import (\n    ChatMessage,\n    StreamingChunk,\n    build_chunk,\n    build_message,\n    check_finish_reason,\n    connect_chunks,\n    convert_message_to_openai_format,\n)\nfrom src.providers.loader import provider\nfrom src.utils import extract_braces_content, remove_trailing_slash\n\n\n@provider(\"litellm_llm\")\nclass LitellmLLMProvider(LLMProvider):\n    def __init__(\n        self,\n        model: str,\n        api_key_name: Optional[\n            str\n        ] = None,  # e.g. OPENAI_API_KEY, LLM_ANTHROPIC_API_KEY, etc.\n        api_base: Optional[str] = None,\n        api_version: Optional[str] = None,\n        kwargs: Optional[Dict[str, Any]] = None,\n        timeout: float = 120.0,\n        context_window_size: int = 100000,\n        fallback_model_list: Optional[List[Dict[str, Any]]] = None,\n        fallback_testing: bool = False,\n        **_,\n    ):\n        self._model = model\n        # TODO: remove _api_key, _api_base, _api_version in the future, as it is not used in litellm\n        self._api_key = os.getenv(api_key_name) if api_key_name else None\n        self._api_base = remove_trailing_slash(api_base) if api_base else None\n        self._api_version = api_version\n        self._model_kwargs = kwargs or {}\n        self._timeout = timeout\n        self._context_window_size = context_window_size\n        # build a dynamic list of all fallback model names (beyond the first)\n        self._has_fallbacks = (\n            fallback_model_list is not None and len(fallback_model_list) > 1\n        )\n        fallbacks = (\n            [{self._model: [m[\"model_name\"] for m in fallback_model_list[1:]]}]\n            if self._has_fallbacks\n            else []\n        )\n        self._router = Router(\n            model_list=fallback_model_list or [],\n            fallbacks=fallbacks,\n        )\n        self._enable_fallback_testing = fallback_testing and self._has_fallbacks\n\n    def get_generator(\n        self,\n        system_prompt: Optional[str] = None,\n        generation_kwargs: Optional[Dict[str, Any]] = None,\n        streaming_callback: Optional[Callable[[StreamingChunk], None]] = None,\n    ):\n        combined_generation_kwargs = {\n            **(generation_kwargs or {}),\n            **(self._model_kwargs or {}),\n        }\n\n        @backoff.on_exception(backoff.expo, openai.APIError, max_time=60.0, max_tries=3)\n        async def _run(\n            prompt: str,\n            image_url: Optional[str] = None,\n            current_system_prompt: Optional[str] = None,\n            history_messages: Optional[List[ChatMessage]] = None,\n            generation_kwargs: Optional[Dict[str, Any]] = None,\n            query_id: Optional[str] = None,\n        ):\n            message = ChatMessage.from_user(prompt, image_url)\n            _system_prompt = system_prompt\n            if current_system_prompt:\n                _system_prompt = current_system_prompt\n\n            if _system_prompt:\n                messages = [ChatMessage.from_system(_system_prompt)]\n                if history_messages:\n                    messages.extend(history_messages)\n                messages.append(message)\n            else:\n                if history_messages:\n                    messages = history_messages + [message]\n                else:\n                    messages = [message]\n\n            openai_formatted_messages = [\n                convert_message_to_openai_format(message) for message in messages\n            ]\n\n            generation_kwargs = {\n                **combined_generation_kwargs,\n                **(generation_kwargs or {}),\n            }\n\n            allowed_openai_params = generation_kwargs.get(\n                \"allowed_openai_params\", []\n            ) + ([\"reasoning_effort\"] if self._model.startswith(\"gpt-5\") else [])\n\n            if self._has_fallbacks:\n                completion = await self._router.acompletion(\n                    model=self._model,\n                    messages=openai_formatted_messages,\n                    stream=streaming_callback is not None,\n                    allowed_openai_params=allowed_openai_params,\n                    mock_testing_fallbacks=self._enable_fallback_testing,\n                    **generation_kwargs,\n                )\n            else:\n                completion = await acompletion(\n                    model=self._model,\n                    api_key=self._api_key,\n                    api_base=self._api_base,\n                    api_version=self._api_version,\n                    timeout=self._timeout,\n                    messages=openai_formatted_messages,\n                    stream=streaming_callback is not None,\n                    allowed_openai_params=allowed_openai_params,\n                    **generation_kwargs,\n                )\n\n            completions: List[ChatMessage] = []\n            if streaming_callback is not None:\n                num_responses = generation_kwargs.pop(\"n\", 1)\n                if num_responses > 1:\n                    raise ValueError(\n                        \"Cannot stream multiple responses, please set n=1.\"\n                    )\n                chunks: List[StreamingChunk] = []\n\n                async for chunk in completion:\n                    if chunk.choices and streaming_callback:\n                        chunk_delta: StreamingChunk = build_chunk(chunk)\n                        chunks.append(chunk_delta)\n                        streaming_callback(\n                            chunk_delta, query_id\n                        )  # invoke callback with the chunk_delta\n                completions = [connect_chunks(chunk, chunks)]\n            else:\n                completions = [\n                    build_message(completion, choice) for choice in completion.choices\n                ]\n\n            # before returning, do post-processing of the completions\n            for response in completions:\n                check_finish_reason(response)\n\n            return {\n                \"replies\": [\n                    extract_braces_content(message.content) for message in completions\n                ],\n                \"meta\": [message.meta for message in completions],\n            }\n\n        return _run\n"
  },
  {
    "path": "wren-ai-service/src/providers/loader.py",
    "content": "import importlib\nimport logging\nimport pkgutil\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nPROVIDERS_PATH = \"src.providers\"\nPROVIDERS = {}\n\n\ndef import_mods(package_name=PROVIDERS_PATH):\n    \"\"\"\n    This function is designed to import all submodules within a given package,\n    including those in nested packages.\n\n    The function works by first importing the initial package using its name.\n    It then iterates through the package directory and imports each submodule it encounters.\n    This includes submodules in any nested packages.\n\n    This is particularly useful in scenarios where you want to ensure that all submodules are loaded\n    and ready for use, without having to manually import each one individually.\n\n    Parameters:\n        package_name (str): The name of the initial package to import submodules from.\n        Defaults to the value of PROVIDERS_PATH.\n\n    Returns:\n        None: This function doesn't return anything; it simply imports the submodules.\n\n    Raises:\n        ModuleNotFoundError: If a submodule cannot be found.\n    \"\"\"\n    package = importlib.import_module(package_name)\n\n    # Iterate through all the submodules in the package\n    for _, name, _ in pkgutil.walk_packages(package.__path__, package.__name__ + \".\"):\n        # Import each submodule\n        importlib.import_module(name)\n\n\ndef provider(name: str):\n    \"\"\"\n    This decorator is designed to register a provider class and add it to the PROVIDERS dictionary.\n\n    The decorator works by taking a name as an argument, which is used as a key in the PROVIDERS dictionary.\n    The value associated with this key is the provider class that the decorator is applied to.\n\n    This is particularly useful in scenarios where you want to maintain a registry of provider classes,\n    and you want to be able to access these classes using a unique name.\n\n    Parameters:\n        name (str): The name of the provider. This is used as a key in the PROVIDERS dictionary.\n\n    Returns:\n        function: The decorator function that registers the provider class.\n\n    Raises:\n        KeyError: If a provider with the same name is already registered in the PROVIDERS dictionary.\n    \"\"\"\n\n    def wrapper(cls):\n        PROVIDERS[name] = cls\n        return cls\n\n    return wrapper\n\n\ndef get_provider(name: str):\n    \"\"\"\n    This function is designed to return a provider class by its name.\n\n    The function works by taking a name as an argument, which is used to look up\n    the corresponding provider class in a dictionary of registered providers.\n\n    This is particularly useful in scenarios where you have a registry of provider classes\n    and you want to be able to retrieve a specific provider class using its unique name.\n\n    Parameters:\n        name (str): The name of the provider. This is used as a key to look up\n        the provider class in the dictionary of registered providers.\n\n    Returns:\n        type: The provider class corresponding to the given name.\n\n    Raises:\n        KeyError: If a provider with the given name is not found in the dictionary of registered providers.\n    \"\"\"\n    return PROVIDERS[name]\n"
  },
  {
    "path": "wren-ai-service/src/utils.py",
    "content": "import functools\nimport logging\nimport os\nimport re\nfrom pathlib import Path\n\nimport requests\nfrom dotenv import load_dotenv\nfrom langfuse.decorators import langfuse_context\n\nfrom src.config import Settings\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nclass CustomFormatter(logging.Formatter):\n    def __init__(self, is_dev: bool):\n        super().__init__()\n\n        try:\n            if not is_dev:\n                # Imports the Cloud Logging client library\n                import google.cloud.logging\n\n                # Instantiates a client\n                client = google.cloud.logging.Client()\n\n                # Retrieves a Cloud Logging handler based on the environment\n                # you're running in and integrates the handler with the\n                # Python logging module. By default this captures all logs\n                # at INFO level and higher\n                client.setup_logging()\n        except Exception:\n            pass\n\n    def format(self, record):\n        _LOGGING_FORMAT = \"{levelname:<.1}{asctime}.{msecs:03.0f} {process} {name}:{lineno}] {message}\"\n        _DATE_FMT = \"%m%d %H:%M:%S\"\n\n        formatter = logging.Formatter(\n            fmt=_LOGGING_FORMAT,\n            datefmt=_DATE_FMT,\n            style=\"{\",\n        )\n        return formatter.format(record)\n\n\ndef setup_custom_logger(name, level_str: str, is_dev: bool):\n    level_str = level_str.upper()\n\n    if level_str not in logging._nameToLevel:\n        raise ValueError(f\"Invalid logging level: {level_str}\")\n\n    level = logging._nameToLevel[level_str]\n\n    handler = logging.StreamHandler()\n    handler.setFormatter(CustomFormatter(is_dev))\n\n    logger = logging.getLogger(name)\n    logger.setLevel(level)\n    logger.addHandler(handler)\n    return logger\n\n\ndef load_env_vars() -> str:\n    # DEPRECATED: This method is deprecated and will be removed in the future\n    if Path(\".env.dev\").exists():\n        load_dotenv(\".env.dev\", override=True)\n        return \"dev\"\n\n    return \"prod\"\n\n\ndef remove_trailing_slash(endpoint: str) -> str:\n    return endpoint.rstrip(\"/\") if endpoint.endswith(\"/\") else endpoint\n\n\ndef init_langfuse(settings: Settings):\n    langfuse_context.configure(\n        enabled=settings.langfuse_enable,\n        host=settings.langfuse_host,\n        public_key=os.getenv(\"LANGFUSE_PUBLIC_KEY\"),\n        secret_key=os.getenv(\"LANGFUSE_SECRET_KEY\"),\n    )\n\n    logger.info(f\"LANGFUSE_ENABLE: {settings.langfuse_enable}\")\n    logger.info(f\"LANGFUSE_HOST: {settings.langfuse_host}\")\n\n\ndef trace_metadata(func):\n    \"\"\"\n    This decorator is used to add metadata to the current Langfuse trace.\n    It should be applied after creating a trace. Here’s an example of how to use it:\n\n    ```python\n    @observe(name=\"Mock\")\n    @trace_metadata\n    async def mock():\n        return \"Mock\"\n    ```\n\n    Args:\n        func (Callable): the function to decorate\n\n    Returns:\n        Callable: the decorated function\n    \"\"\"\n\n    def extract(*args) -> dict:\n        request = args[1]  # fix the position of the request object\n        metadata = {}\n\n        if hasattr(request, \"project_id\"):\n            metadata[\"project_id\"] = request.project_id\n        if hasattr(request, \"thread_id\"):\n            metadata[\"thread_id\"] = request.thread_id\n        if hasattr(request, \"mdl_hash\"):\n            metadata[\"mdl_hash\"] = request.mdl_hash\n        if hasattr(request, \"user_id\"):\n            metadata[\"user_id\"] = request.user_id\n        if hasattr(request, \"query\"):\n            metadata[\"query\"] = request.query\n\n        return metadata\n\n    @functools.wraps(func)\n    async def wrapper(*args, **kwargs):\n        trace_id = langfuse_context.get_current_trace_id()\n\n        results = await func(*args, **kwargs, trace_id=trace_id)\n\n        addition = {}\n        if isinstance(results, dict):\n            additional_metadata = results.get(\"metadata\", {})\n            addition.update(additional_metadata)\n\n        metadata = extract(*args)\n        service_metadata = kwargs.get(\n            \"service_metadata\",\n            {\n                \"pipes_metadata\": {},\n                \"service_version\": \"\",\n            },\n        )\n        langfuse_metadata = {\n            **service_metadata.get(\"pipes_metadata\"),\n            **addition,\n            \"mdl_hash\": metadata.get(\"mdl_hash\"),\n            \"project_id\": metadata.get(\"project_id\"),\n            \"query\": metadata.get(\"query\"),\n        }\n        langfuse_context.update_current_trace(\n            user_id=metadata.get(\"user_id\"),\n            session_id=metadata.get(\"thread_id\"),\n            release=service_metadata.get(\"service_version\"),\n            metadata=langfuse_metadata,\n        )\n\n        return results\n\n    return wrapper\n\n\ndef trace_cost(func):\n    @functools.wraps(func)\n    async def wrapper(*args, **kwargs):\n        result, generator_name = await func(*args, **kwargs)\n\n        if isinstance(result, dict):\n            if meta := result.get(\"meta\", []):\n                model = meta[0].get(\"model\")\n                langfuse_context.update_current_observation(\n                    model=model,\n                    usage_details=meta[0].get(\"usage\", {}),\n                )\n                langfuse_context.update_current_trace(\n                    metadata={\"fallback_is_triggered\": model != generator_name}\n                )\n\n        return result\n\n    return wrapper\n\n\ndef fetch_wren_ai_docs(doc_endpoint: str, is_oss: bool) -> list[dict]:\n    doc_endpoint = remove_trailing_slash(doc_endpoint)\n    api_endpoint = (\n        f\"{doc_endpoint}/oss/llms.md\" if is_oss else f\"{doc_endpoint}/cloud/llms.md\"\n    )\n\n    try:\n        response = requests.get(api_endpoint, timeout=10)\n        response.raise_for_status()  # Raise exception for 4XX/5XX responses\n        docs = response.text.split(\"\\n---\\n\")\n    except requests.RequestException as e:\n        logger.error(f\"Failed to fetch Wren AI docs: {str(e)}\")\n        return []  # Return empty list on error\n\n    doc_endpoint_base = f\"{doc_endpoint}/oss\" if is_oss else f\"{doc_endpoint}/cloud\"\n    results = []\n    for doc in docs:\n        if doc:\n            path, content = doc.split(\"\\n\")\n            results.append(\n                {\n                    \"path\": f'{doc_endpoint_base}/{path.replace(\".md\", \"\")}',\n                    \"content\": content,\n                }\n            )\n\n    return results\n\n\ndef extract_braces_content(resp: str) -> str:\n    \"\"\"\n    Extracts JSON content enclosed in a markdown code block that starts with ```json.\n    Returns the JSON string including braces, or the original string if no match is found.\n    \"\"\"\n    match = re.search(r\"```json\\s*(\\{.*?\\})\\s*```\", resp, re.DOTALL)\n    return match.group(1) if match else resp\n"
  },
  {
    "path": "wren-ai-service/src/web/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/src/web/development.py",
    "content": "import inspect\nimport logging\nfrom typing import Any, Dict, get_type_hints\n\nfrom fastapi import APIRouter, HTTPException\n\nlogger = logging.getLogger(\"wren-ai-service\")\nrouter = APIRouter()\n\n\ndef _extract_run_method_params(pipeline_instance) -> Dict[str, str]:\n    \"\"\"Extract parameter information from a pipeline's run method\"\"\"\n    run_method = getattr(pipeline_instance, \"run\", None)\n    if not run_method:\n        return {}\n\n    try:\n        # Get the method signature\n        sig = inspect.signature(run_method)\n\n        # Get type hints\n        type_hints = get_type_hints(run_method)\n\n        params = {}\n        for param_name, param in sig.parameters.items():\n            if param_name == \"self\":\n                continue\n\n            # Get the type annotation as string\n            param_type = type_hints.get(param_name)\n            if param_type:\n                # Handle complex types by getting their string representation\n                type_str = str(param_type).replace(\"typing.\", \"\")\n            else:\n                # Fallback to parameter annotation\n                if param.annotation != inspect.Parameter.empty:\n                    type_str = str(param.annotation).replace(\"typing.\", \"\")\n                else:\n                    type_str = \"Any\"\n\n            params[param_name] = type_str\n\n        return params\n    except Exception as e:\n        logger.warning(f\"Failed to extract parameters from pipeline run method: {e}\")\n        return {}\n\n\n@router.get(\"/pipelines\")\nasync def get_pipelines() -> dict:\n    from src.__main__ import app\n\n    service_container = app.state.service_container\n    pipeline_params = {}\n\n    # Extract pipelines from all services\n    for _, service in service_container.__dict__.items():\n        if hasattr(service, \"_pipelines\"):\n            for pipeline_name, pipeline_instance in service._pipelines.items():\n                pipeline_params[pipeline_name] = _extract_run_method_params(\n                    pipeline_instance\n                )\n\n    return pipeline_params\n\n\n@router.post(\"/pipelines/{pipeline_name}\")\nasync def run_pipeline(pipeline_name: str, request_body: Dict[str, Any]) -> dict:\n    from src.__main__ import app\n\n    service_container = app.state.service_container\n    pipe_components = {}\n\n    for _, service in service_container.__dict__.items():\n        if hasattr(service, \"_pipelines\"):\n            for _pipeline_name, pipeline_instance in service._pipelines.items():\n                pipe_components[_pipeline_name] = pipeline_instance\n\n    if pipeline_name not in pipe_components:\n        logger.error(f\"Pipeline {pipeline_name} not found\")\n        raise HTTPException(\n            status_code=404, detail=f\"Pipeline '{pipeline_name}' not found\"\n        )\n\n    try:\n        pipeline = pipe_components[pipeline_name]\n        result = await pipeline.run(**request_body)\n        return result\n    except Exception as e:\n        logger.error(f\"Error running pipeline {pipeline_name}: {e}\")\n        raise HTTPException(\n            status_code=500, detail=f\"Error running pipeline '{pipeline_name}': {e}\"\n        )\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/src/web/v1/routers/__init__.py",
    "content": "from fastapi import APIRouter\n\nfrom src.web.v1.routers import (\n    ask,\n    ask_feedbacks,\n    chart,\n    chart_adjustment,\n    instructions,\n    question_recommendation,\n    relationship_recommendation,\n    semantics_description,\n    semantics_preparation,\n    sql_answers,\n    sql_corrections,\n    sql_pairs,\n    sql_question,\n)\n\nrouter = APIRouter()\nrouter.include_router(ask.router)\nrouter.include_router(ask_feedbacks.router)\nrouter.include_router(question_recommendation.router)\nrouter.include_router(relationship_recommendation.router)\nrouter.include_router(semantics_description.router)\nrouter.include_router(semantics_preparation.router)\nrouter.include_router(sql_answers.router)\nrouter.include_router(chart.router)\nrouter.include_router(chart_adjustment.router)\nrouter.include_router(sql_pairs.router)\nrouter.include_router(sql_question.router)\nrouter.include_router(instructions.router)\nrouter.include_router(sql_corrections.router)\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/routers/ask.py",
    "content": "import uuid\nfrom dataclasses import asdict\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends\nfrom fastapi.responses import StreamingResponse\n\nfrom src.globals import (\n    ServiceContainer,\n    ServiceMetadata,\n    get_service_container,\n    get_service_metadata,\n)\nfrom src.web.v1.services.ask import (\n    AskRequest,\n    AskResponse,\n    AskResultRequest,\n    AskResultResponse,\n    StopAskRequest,\n    StopAskResponse,\n)\n\nrouter = APIRouter()\n\n\n@router.post(\"/asks\")\nasync def ask(\n    ask_request: AskRequest,\n    background_tasks: BackgroundTasks,\n    service_container: ServiceContainer = Depends(get_service_container),\n    service_metadata: ServiceMetadata = Depends(get_service_metadata),\n) -> AskResponse:\n    query_id = str(uuid.uuid4())\n    ask_request.query_id = query_id\n    service_container.ask_service._ask_results[query_id] = AskResultResponse(\n        status=\"understanding\",\n    )\n\n    background_tasks.add_task(\n        service_container.ask_service.ask,\n        ask_request,\n        service_metadata=asdict(service_metadata),\n    )\n    return AskResponse(query_id=query_id)\n\n\n@router.patch(\"/asks/{query_id}\")\nasync def stop_ask(\n    query_id: str,\n    stop_ask_request: StopAskRequest,\n    background_tasks: BackgroundTasks,\n    service_container: ServiceContainer = Depends(get_service_container),\n) -> StopAskResponse:\n    stop_ask_request.query_id = query_id\n    background_tasks.add_task(\n        service_container.ask_service.stop_ask,\n        stop_ask_request,\n    )\n    return StopAskResponse(query_id=query_id)\n\n\n@router.get(\"/asks/{query_id}/result\")\nasync def get_ask_result(\n    query_id: str,\n    service_container: ServiceContainer = Depends(get_service_container),\n) -> AskResultResponse:\n    return service_container.ask_service.get_ask_result(\n        AskResultRequest(query_id=query_id)\n    )\n\n\n@router.get(\"/asks/{query_id}/streaming-result\")\nasync def get_ask_streaming_result(\n    query_id: str,\n    service_container: ServiceContainer = Depends(get_service_container),\n) -> StreamingResponse:\n    return StreamingResponse(\n        service_container.ask_service.get_ask_streaming_result(query_id),\n        media_type=\"text/event-stream\",\n    )\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/routers/ask_feedbacks.py",
    "content": "import uuid\nfrom dataclasses import asdict\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends\n\nfrom src.globals import (\n    ServiceContainer,\n    ServiceMetadata,\n    get_service_container,\n    get_service_metadata,\n)\nfrom src.web.v1.services.ask_feedback import (\n    AskFeedbackRequest,\n    AskFeedbackResponse,\n    AskFeedbackResultRequest,\n    AskFeedbackResultResponse,\n    StopAskFeedbackRequest,\n    StopAskFeedbackResponse,\n)\n\nrouter = APIRouter()\n\n\n@router.post(\"/ask-feedbacks\")\nasync def ask_feedback(\n    ask_feedback_request: AskFeedbackRequest,\n    background_tasks: BackgroundTasks,\n    service_container: ServiceContainer = Depends(get_service_container),\n    service_metadata: ServiceMetadata = Depends(get_service_metadata),\n) -> AskFeedbackResponse:\n    query_id = str(uuid.uuid4())\n    ask_feedback_request.query_id = query_id\n    service_container.ask_feedback_service._ask_feedback_results[\n        query_id\n    ] = AskFeedbackResultResponse(\n        status=\"searching\",\n    )\n\n    background_tasks.add_task(\n        service_container.ask_feedback_service.ask_feedback,\n        ask_feedback_request,\n        service_metadata=asdict(service_metadata),\n    )\n    return AskFeedbackResponse(query_id=query_id)\n\n\n@router.patch(\"/ask-feedbacks/{query_id}\")\nasync def stop_ask_feedback(\n    query_id: str,\n    stop_ask_feedback_request: StopAskFeedbackRequest,\n    background_tasks: BackgroundTasks,\n    service_container: ServiceContainer = Depends(get_service_container),\n) -> StopAskFeedbackResponse:\n    stop_ask_feedback_request.query_id = query_id\n    background_tasks.add_task(\n        service_container.ask_feedback_service.stop_ask_feedback,\n        stop_ask_feedback_request,\n    )\n    return StopAskFeedbackResponse(query_id=query_id)\n\n\n@router.get(\"/ask-feedbacks/{query_id}\")\nasync def get_ask_feedback_result(\n    query_id: str,\n    service_container: ServiceContainer = Depends(get_service_container),\n) -> AskFeedbackResultResponse:\n    return service_container.ask_feedback_service.get_ask_feedback_result(\n        AskFeedbackResultRequest(query_id=query_id)\n    )\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/routers/chart.py",
    "content": "import uuid\nfrom dataclasses import asdict\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends\n\nfrom src.globals import (\n    ServiceContainer,\n    ServiceMetadata,\n    get_service_container,\n    get_service_metadata,\n)\nfrom src.web.v1.services.chart import (\n    ChartRequest,\n    ChartResponse,\n    ChartResultRequest,\n    ChartResultResponse,\n    StopChartRequest,\n    StopChartResponse,\n)\n\nrouter = APIRouter()\n\n\n@router.post(\"/charts\")\nasync def chart(\n    chart_request: ChartRequest,\n    background_tasks: BackgroundTasks,\n    service_container: ServiceContainer = Depends(get_service_container),\n    service_metadata: ServiceMetadata = Depends(get_service_metadata),\n) -> ChartResponse:\n    query_id = str(uuid.uuid4())\n    chart_request.query_id = query_id\n    service_container.chart_service._chart_results[query_id] = ChartResultResponse(\n        status=\"fetching\",\n    )\n\n    background_tasks.add_task(\n        service_container.chart_service.chart,\n        chart_request,\n        service_metadata=asdict(service_metadata),\n    )\n    return ChartResponse(query_id=query_id)\n\n\n@router.patch(\"/charts/{query_id}\")\nasync def stop_chart(\n    query_id: str,\n    stop_chart_request: StopChartRequest,\n    background_tasks: BackgroundTasks,\n    service_container: ServiceContainer = Depends(get_service_container),\n) -> StopChartResponse:\n    stop_chart_request.query_id = query_id\n    background_tasks.add_task(\n        service_container.ask_service.stop_ask,\n        stop_chart_request,\n    )\n    return StopChartResponse(query_id=query_id)\n\n\n@router.get(\"/charts/{query_id}\")\nasync def get_chart_result(\n    query_id: str,\n    service_container: ServiceContainer = Depends(get_service_container),\n) -> ChartResultResponse:\n    return service_container.chart_service.get_chart_result(\n        ChartResultRequest(query_id=query_id)\n    )\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/routers/chart_adjustment.py",
    "content": "import uuid\nfrom dataclasses import asdict\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends\n\nfrom src.globals import (\n    ServiceContainer,\n    ServiceMetadata,\n    get_service_container,\n    get_service_metadata,\n)\nfrom src.web.v1.services.chart_adjustment import (\n    ChartAdjustmentRequest,\n    ChartAdjustmentResponse,\n    ChartAdjustmentResultRequest,\n    ChartAdjustmentResultResponse,\n    StopChartAdjustmentRequest,\n    StopChartAdjustmentResponse,\n)\n\nrouter = APIRouter()\n\n\n@router.post(\"/chart-adjustments\")\nasync def chart_adjustment(\n    chart_adjustment_request: ChartAdjustmentRequest,\n    background_tasks: BackgroundTasks,\n    service_container: ServiceContainer = Depends(get_service_container),\n    service_metadata: ServiceMetadata = Depends(get_service_metadata),\n) -> ChartAdjustmentResponse:\n    query_id = str(uuid.uuid4())\n    chart_adjustment_request.query_id = query_id\n    service_container.chart_adjustment_service._chart_adjustment_results[\n        query_id\n    ] = ChartAdjustmentResultResponse(\n        status=\"fetching\",\n    )\n\n    background_tasks.add_task(\n        service_container.chart_adjustment_service.chart_adjustment,\n        chart_adjustment_request,\n        service_metadata=asdict(service_metadata),\n    )\n    return ChartAdjustmentResponse(query_id=query_id)\n\n\n@router.patch(\"/chart-adjustments/{query_id}\")\nasync def stop_chart_adjustment(\n    query_id: str,\n    stop_chart_adjustment_request: StopChartAdjustmentRequest,\n    background_tasks: BackgroundTasks,\n    service_container: ServiceContainer = Depends(get_service_container),\n) -> StopChartAdjustmentResponse:\n    stop_chart_adjustment_request.query_id = query_id\n    background_tasks.add_task(\n        service_container.chart_adjustment_service.stop_chart_adjustment,\n        stop_chart_adjustment_request,\n    )\n    return StopChartAdjustmentResponse(query_id=query_id)\n\n\n@router.get(\"/chart-adjustments/{query_id}\")\nasync def get_chart_adjustment_result(\n    query_id: str,\n    service_container: ServiceContainer = Depends(get_service_container),\n) -> ChartAdjustmentResultResponse:\n    return service_container.chart_adjustment_service.get_chart_adjustment_result(\n        ChartAdjustmentResultRequest(query_id=query_id)\n    )\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/routers/instructions.py",
    "content": "import uuid\nfrom dataclasses import asdict\nfrom typing import List, Literal, Optional\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends, Response\nfrom pydantic import BaseModel\n\nfrom src.globals import (\n    ServiceContainer,\n    ServiceMetadata,\n    get_service_container,\n    get_service_metadata,\n)\nfrom src.web.v1.services import BaseRequest, InstructionsService\n\nrouter = APIRouter()\n\n\nclass PostRequest(BaseRequest):\n    instructions: List[InstructionsService.Instruction]\n\n\nclass PostResponse(BaseModel):\n    event_id: str\n\n\n@router.post(\"/instructions\")\nasync def index(\n    request: PostRequest,\n    background_tasks: BackgroundTasks,\n    service_container: ServiceContainer = Depends(get_service_container),\n    service_metadata: ServiceMetadata = Depends(get_service_metadata),\n) -> PostResponse:\n    event_id = str(uuid.uuid4())\n    service = service_container.instructions_service\n    service[event_id] = InstructionsService.Event(event_id=event_id)\n\n    index_request = InstructionsService.IndexRequest(\n        event_id=event_id, **request.model_dump()\n    )\n\n    background_tasks.add_task(\n        service.index,\n        index_request,\n        service_metadata=asdict(service_metadata),\n    )\n    return PostResponse(event_id=event_id)\n\n\nclass DeleteRequest(BaseRequest):\n    instruction_ids: List[str]\n\n\n@router.delete(\"/instructions\")\nasync def delete(\n    request: DeleteRequest,\n    response: Response,\n    service_container: ServiceContainer = Depends(get_service_container),\n    service_metadata: ServiceMetadata = Depends(get_service_metadata),\n) -> None | InstructionsService.Error:\n    event_id = str(uuid.uuid4())\n    service = service_container.instructions_service\n    service[event_id] = InstructionsService.Event(event_id=event_id, status=\"deleting\")\n\n    delete_request = InstructionsService.DeleteRequest(\n        event_id=event_id,\n        **request.model_dump(),\n    )\n\n    await service.delete(delete_request, service_metadata=asdict(service_metadata))\n\n    event: InstructionsService.Event = service[event_id]\n\n    if event.status == \"failed\":\n        response.status_code = 500\n        return event.error\n\n\nclass GetResponse(BaseModel):\n    event_id: str\n    status: Literal[\"indexing\", \"deleting\", \"finished\", \"failed\"]\n    error: Optional[dict]\n    trace_id: Optional[str]\n\n\n@router.get(\"/instructions/{event_id}\")\nasync def get(\n    event_id: str,\n    container: ServiceContainer = Depends(get_service_container),\n) -> GetResponse:\n    event: InstructionsService.Event = container.instructions_service[event_id]\n    return GetResponse(**event.model_dump())\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/routers/question_recommendation.py",
    "content": "import uuid\nfrom dataclasses import asdict\nfrom typing import Literal, Optional\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends\nfrom pydantic import BaseModel\n\nfrom src.globals import (\n    ServiceContainer,\n    ServiceMetadata,\n    get_service_container,\n    get_service_metadata,\n)\nfrom src.web.v1.services import BaseRequest, QuestionRecommendation\n\nrouter = APIRouter()\n\n\nclass PostRequest(BaseRequest):\n    mdl: str\n    previous_questions: list[str] = []\n    max_questions: int = 5\n    max_categories: int = 3\n    regenerate: bool = False\n    allow_data_preview: bool = True\n\n\nclass PostResponse(BaseModel):\n    id: str\n\n\n@router.post(\n    \"/question-recommendations\",\n    response_model=PostResponse,\n)\nasync def recommend(\n    request: PostRequest,\n    background_tasks: BackgroundTasks,\n    service_container: ServiceContainer = Depends(get_service_container),\n    service_metadata: ServiceMetadata = Depends(get_service_metadata),\n) -> PostResponse:\n    event_id = str(uuid.uuid4())\n    service = service_container.question_recommendation\n    service[event_id] = QuestionRecommendation.Event(event_id=event_id)\n\n    _request = QuestionRecommendation.Request(event_id=event_id, **request.model_dump())\n\n    background_tasks.add_task(\n        service.recommend,\n        _request,\n        service_metadata=asdict(service_metadata),\n    )\n\n    return PostResponse(id=event_id)\n\n\nclass GetResponse(BaseModel):\n    id: str\n    status: Literal[\"generating\", \"finished\", \"failed\"]\n    response: Optional[dict]\n    error: Optional[dict]\n    trace_id: Optional[str] = None\n\n\n@router.get(\n    \"/question-recommendations/{event_id}\",\n    response_model=GetResponse,\n)\nasync def get(\n    event_id: str,\n    service_container: ServiceContainer = Depends(get_service_container),\n) -> GetResponse:\n    event: QuestionRecommendation.Event = service_container.question_recommendation[\n        event_id\n    ]\n\n    def _formatter(response: dict) -> dict:\n        questions = [\n            question\n            for _, questions in response[\"questions\"].items()\n            for question in questions\n        ]\n        return {\"questions\": questions}\n\n    return GetResponse(\n        id=event.event_id,\n        status=event.status,\n        response=_formatter(event.response),\n        error=event.error and event.error.model_dump(),\n        trace_id=event.trace_id,\n    )\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/routers/relationship_recommendation.py",
    "content": "import uuid\nfrom dataclasses import asdict\nfrom typing import Literal, Optional\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends\nfrom pydantic import BaseModel\n\nfrom src.globals import (\n    ServiceContainer,\n    ServiceMetadata,\n    get_service_container,\n    get_service_metadata,\n)\nfrom src.web.v1.services import BaseRequest, RelationshipRecommendation\n\nrouter = APIRouter()\n\n\nclass PostRequest(BaseRequest):\n    mdl: str\n\n\nclass PostResponse(BaseModel):\n    id: str\n\n\n@router.post(\n    \"/relationship-recommendations\",\n    response_model=PostResponse,\n)\nasync def recommend(\n    request: PostRequest,\n    background_tasks: BackgroundTasks,\n    service_container: ServiceContainer = Depends(get_service_container),\n    service_metadata: ServiceMetadata = Depends(get_service_metadata),\n) -> PostResponse:\n    id = str(uuid.uuid4())\n    service = service_container.relationship_recommendation\n\n    service[id] = RelationshipRecommendation.Resource(id=id)\n    input = RelationshipRecommendation.Input(\n        id=id,\n        mdl=request.mdl,\n        project_id=request.project_id,\n        configuration=request.configurations,\n    )\n\n    background_tasks.add_task(\n        service.recommend, input, service_metadata=asdict(service_metadata)\n    )\n\n    return PostResponse(id=id)\n\n\nclass GetResponse(BaseModel):\n    id: str\n    status: Literal[\"generating\", \"finished\", \"failed\"]\n    response: Optional[dict]\n    error: Optional[dict]\n    trace_id: Optional[str] = None\n\n\n@router.get(\n    \"/relationship-recommendations/{id}\",\n    response_model=GetResponse,\n)\nasync def get(\n    id: str,\n    service_container: ServiceContainer = Depends(get_service_container),\n) -> GetResponse:\n    resource = service_container.relationship_recommendation[id]\n\n    return GetResponse(\n        id=resource.id,\n        status=resource.status,\n        response=resource.response,\n        error=resource.error and resource.error.model_dump(),\n        trace_id=resource.trace_id,\n    )\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/routers/semantics_description.py",
    "content": "import uuid\nfrom dataclasses import asdict\nfrom typing import Literal, Optional\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends\nfrom pydantic import BaseModel\n\nfrom src.globals import (\n    ServiceContainer,\n    ServiceMetadata,\n    get_service_container,\n    get_service_metadata,\n)\nfrom src.web.v1.services import BaseRequest, SemanticsDescription\n\nrouter = APIRouter()\n\n\nclass PostRequest(BaseRequest):\n    selected_models: list[str]\n    user_prompt: str\n    mdl: str\n\n\nclass PostResponse(BaseModel):\n    id: str\n\n\n@router.post(\n    \"/semantics-descriptions\",\n    response_model=PostResponse,\n)\nasync def generate(\n    request: PostRequest,\n    background_tasks: BackgroundTasks,\n    service_container: ServiceContainer = Depends(get_service_container),\n    service_metadata: ServiceMetadata = Depends(get_service_metadata),\n) -> PostResponse:\n    id = str(uuid.uuid4())\n    service = service_container.semantics_description\n    service[id] = SemanticsDescription.Resource(id=id)\n\n    generate_request = SemanticsDescription.GenerateRequest(\n        id=id, **request.model_dump()\n    )\n\n    background_tasks.add_task(\n        service.generate,\n        generate_request,\n        service_metadata=asdict(service_metadata),\n    )\n    return PostResponse(id=id)\n\n\nclass GetResponse(BaseModel):\n    id: str\n    status: Literal[\"generating\", \"finished\", \"failed\"]\n    response: Optional[list[dict]]\n    error: Optional[dict]\n    trace_id: Optional[str] = None\n\n\n@router.get(\n    \"/semantics-descriptions/{id}\",\n    response_model=GetResponse,\n)\nasync def get(\n    id: str,\n    service_container: ServiceContainer = Depends(get_service_container),\n) -> GetResponse:\n    resource = service_container.semantics_description[id]\n\n    def _formatter(response: Optional[dict]) -> Optional[list[dict]]:\n        if response is None:\n            return None\n\n        return [\n            {\n                \"name\": model_name,\n                \"columns\": [\n                    {\n                        \"name\": column[\"name\"],\n                        \"description\": column[\"properties\"].get(\"description\", \"\"),\n                    }\n                    for column in model_data[\"columns\"]\n                ],\n                \"description\": model_data[\"properties\"].get(\"description\", \"\"),\n            }\n            for model_name, model_data in response.items()\n        ]\n\n    return GetResponse(\n        id=resource.id,\n        status=resource.status,\n        response=resource.response and _formatter(resource.response),\n        error=resource.error and resource.error.model_dump(),\n        trace_id=resource.trace_id,\n    )\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/routers/semantics_preparation.py",
    "content": "from dataclasses import asdict\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends, HTTPException\n\nfrom src.globals import (\n    ServiceContainer,\n    ServiceMetadata,\n    get_service_container,\n    get_service_metadata,\n)\nfrom src.web.v1.services.semantics_preparation import (\n    SemanticsPreparationRequest,\n    SemanticsPreparationResponse,\n    SemanticsPreparationStatusRequest,\n    SemanticsPreparationStatusResponse,\n)\n\nrouter = APIRouter()\n\n\n@router.post(\"/semantics-preparations\")\nasync def prepare_semantics(\n    prepare_semantics_request: SemanticsPreparationRequest,\n    background_tasks: BackgroundTasks,\n    service_container: ServiceContainer = Depends(get_service_container),\n    service_metadata: ServiceMetadata = Depends(get_service_metadata),\n) -> SemanticsPreparationResponse:\n    service_container.semantics_preparation_service._prepare_semantics_statuses[\n        prepare_semantics_request.mdl_hash\n    ] = SemanticsPreparationStatusResponse(\n        status=\"indexing\",\n    )\n\n    background_tasks.add_task(\n        service_container.semantics_preparation_service.prepare_semantics,\n        prepare_semantics_request,\n        service_metadata=asdict(service_metadata),\n    )\n    return SemanticsPreparationResponse(mdl_hash=prepare_semantics_request.mdl_hash)\n\n\n@router.get(\"/semantics-preparations/{mdl_hash}/status\")\nasync def get_prepare_semantics_status(\n    mdl_hash: str,\n    service_container: ServiceContainer = Depends(get_service_container),\n) -> SemanticsPreparationStatusResponse:\n    return service_container.semantics_preparation_service.get_prepare_semantics_status(\n        SemanticsPreparationStatusRequest(mdl_hash=mdl_hash)\n    )\n\n\n@router.delete(\"/semantics\")\nasync def delete_semantics(\n    project_id: str,\n    service_container: ServiceContainer = Depends(get_service_container),\n) -> None:\n    if not project_id:\n        raise HTTPException(status_code=400, detail=\"Project ID is required\")\n    await service_container.semantics_preparation_service.delete_semantics(project_id)\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/routers/sql_answers.py",
    "content": "import uuid\nfrom dataclasses import asdict\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends\nfrom fastapi.responses import StreamingResponse\n\nfrom src.globals import (\n    ServiceContainer,\n    ServiceMetadata,\n    get_service_container,\n    get_service_metadata,\n)\nfrom src.web.v1.services.sql_answer import (\n    SqlAnswerRequest,\n    SqlAnswerResponse,\n    SqlAnswerResultRequest,\n    SqlAnswerResultResponse,\n)\n\nrouter = APIRouter()\n\n\n@router.post(\"/sql-answers\")\nasync def sql_answer(\n    sql_answer_request: SqlAnswerRequest,\n    background_tasks: BackgroundTasks,\n    service_container: ServiceContainer = Depends(get_service_container),\n    service_metadata: ServiceMetadata = Depends(get_service_metadata),\n) -> SqlAnswerResponse:\n    query_id = str(uuid.uuid4())\n    sql_answer_request.query_id = query_id\n    service_container.sql_answer_service._sql_answer_results[\n        query_id\n    ] = SqlAnswerResultResponse(\n        status=\"preprocessing\",\n    )\n\n    background_tasks.add_task(\n        service_container.sql_answer_service.sql_answer,\n        sql_answer_request,\n        service_metadata=asdict(service_metadata),\n    )\n    return SqlAnswerResponse(query_id=query_id)\n\n\n@router.get(\"/sql-answers/{query_id}\")\nasync def get_sql_answer_result(\n    query_id: str,\n    service_container: ServiceContainer = Depends(get_service_container),\n) -> SqlAnswerResultResponse:\n    return service_container.sql_answer_service.get_sql_answer_result(\n        SqlAnswerResultRequest(query_id=query_id)\n    )\n\n\n@router.get(\"/sql-answers/{query_id}/streaming\")\nasync def get_sql_answer_streaming_result(\n    query_id: str,\n    service_container: ServiceContainer = Depends(get_service_container),\n) -> StreamingResponse:\n    return StreamingResponse(\n        service_container.sql_answer_service.get_sql_answer_streaming_result(query_id),\n        media_type=\"text/event-stream\",\n    )\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/routers/sql_corrections.py",
    "content": "import uuid\nfrom dataclasses import asdict\nfrom typing import List, Literal, Optional\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends\nfrom pydantic import BaseModel\n\nfrom src.globals import (\n    ServiceContainer,\n    ServiceMetadata,\n    get_service_container,\n    get_service_metadata,\n)\nfrom src.web.v1.services import BaseRequest, SqlCorrectionService\n\nrouter = APIRouter()\n\n\nclass PostRequest(BaseRequest):\n    sql: str\n    error: str\n    retrieved_tables: Optional[List[str]] = None\n    use_dry_plan: bool = False\n    allow_dry_plan_fallback: bool = True\n\n\nclass PostResponse(BaseModel):\n    event_id: str\n\n\n@router.post(\"/sql-corrections\")\nasync def correct(\n    request: PostRequest,\n    background_tasks: BackgroundTasks,\n    service_container: ServiceContainer = Depends(get_service_container),\n    service_metadata: ServiceMetadata = Depends(get_service_metadata),\n) -> PostResponse:\n    event_id = str(uuid.uuid4())\n    service = service_container.sql_correction_service\n    service[event_id] = SqlCorrectionService.Event(event_id=event_id)\n\n    _request = SqlCorrectionService.CorrectionRequest(\n        event_id=event_id, **request.model_dump()\n    )\n\n    background_tasks.add_task(\n        service.correct,\n        _request,\n        service_metadata=asdict(service_metadata),\n    )\n    return PostResponse(event_id=event_id)\n\n\nclass GetResponse(BaseModel):\n    event_id: str\n    status: Literal[\"correcting\", \"finished\", \"failed\"]\n    response: Optional[str] = None\n    error: Optional[dict] = None\n    trace_id: Optional[str] = None\n    invalid_sql: Optional[str] = None\n\n\n@router.get(\"/sql-corrections/{event_id}\")\nasync def get(\n    event_id: str,\n    container: ServiceContainer = Depends(get_service_container),\n) -> GetResponse:\n    event: SqlCorrectionService.Event = container.sql_correction_service[event_id]\n    return GetResponse(**event.model_dump())\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/routers/sql_pairs.py",
    "content": "import uuid\nfrom dataclasses import asdict\nfrom typing import List, Literal, Optional\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends, Response\nfrom pydantic import BaseModel\n\nfrom src.globals import (\n    ServiceContainer,\n    ServiceMetadata,\n    get_service_container,\n    get_service_metadata,\n)\nfrom src.pipelines.indexing.sql_pairs import SqlPair\nfrom src.web.v1.services import BaseRequest, SqlPairsService\n\nrouter = APIRouter()\n\n\nclass PostRequest(BaseRequest):\n    sql_pairs: List[SqlPair]\n\n\nclass PostResponse(BaseModel):\n    event_id: str\n\n\n@router.post(\"/sql-pairs\")\nasync def prepare(\n    request: PostRequest,\n    background_tasks: BackgroundTasks,\n    service_container: ServiceContainer = Depends(get_service_container),\n    service_metadata: ServiceMetadata = Depends(get_service_metadata),\n) -> PostResponse:\n    event_id = str(uuid.uuid4())\n    service = service_container.sql_pairs_service\n    service[event_id] = SqlPairsService.Event(id=event_id, status=\"indexing\")\n\n    index_request = SqlPairsService.IndexRequest(id=event_id, **request.model_dump())\n\n    background_tasks.add_task(\n        service.index,\n        index_request,\n        service_metadata=asdict(service_metadata),\n    )\n    return PostResponse(event_id=event_id)\n\n\nclass DeleteRequest(BaseRequest):\n    sql_pair_ids: List[str]\n\n\n@router.delete(\"/sql-pairs\")\nasync def delete(\n    request: DeleteRequest,\n    response: Response,\n    service_container: ServiceContainer = Depends(get_service_container),\n    service_metadata: ServiceMetadata = Depends(get_service_metadata),\n) -> None | SqlPairsService.Event.Error:\n    event_id = str(uuid.uuid4())\n    service = service_container.sql_pairs_service\n    service[event_id] = SqlPairsService.Event(id=event_id, status=\"deleting\")\n\n    delete_request = SqlPairsService.DeleteRequest(\n        id=event_id,\n        **request.model_dump(),\n    )\n\n    await service.delete(delete_request, service_metadata=asdict(service_metadata))\n\n    event: SqlPairsService.Event = service[event_id]\n\n    if event.status == \"failed\":\n        response.status_code = 500\n        return event.error\n\n\nclass GetResponse(BaseModel):\n    event_id: str\n    status: Literal[\"indexing\", \"deleting\", \"finished\", \"failed\"]\n    error: Optional[dict]\n    trace_id: Optional[str]\n\n\n@router.get(\"/sql-pairs/{event_id}\")\nasync def get(\n    event_id: str,\n    container: ServiceContainer = Depends(get_service_container),\n) -> GetResponse:\n    event: SqlPairsService.Event = container.sql_pairs_service[event_id]\n    return GetResponse(\n        event_id=event.id,\n        status=event.status,\n        error=event.error and event.error.model_dump(),\n        trace_id=event.trace_id,\n    )\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/routers/sql_question.py",
    "content": "import uuid\nfrom dataclasses import asdict\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends\n\nfrom src.globals import (\n    ServiceContainer,\n    ServiceMetadata,\n    get_service_container,\n    get_service_metadata,\n)\nfrom src.web.v1.services.sql_question import (\n    SqlQuestionRequest,\n    SqlQuestionResponse,\n    SqlQuestionResultRequest,\n    SqlQuestionResultResponse,\n)\n\nrouter = APIRouter()\n\n\n@router.post(\"/sql-questions\")\nasync def sql_question(\n    sql_question_request: SqlQuestionRequest,\n    background_tasks: BackgroundTasks,\n    service_container: ServiceContainer = Depends(get_service_container),\n    service_metadata: ServiceMetadata = Depends(get_service_metadata),\n) -> SqlQuestionResponse:\n    query_id = str(uuid.uuid4())\n    sql_question_request.query_id = query_id\n    service_container.sql_question_service._sql_question_results[\n        query_id\n    ] = SqlQuestionResultResponse(\n        status=\"generating\",\n    )\n\n    background_tasks.add_task(\n        service_container.sql_question_service.sql_question,\n        sql_question_request,\n        service_metadata=asdict(service_metadata),\n    )\n    return SqlQuestionResponse(query_id=query_id)\n\n\n@router.get(\"/sql-questions/{query_id}\")\nasync def get_sql_question_result(\n    query_id: str,\n    service_container: ServiceContainer = Depends(get_service_container),\n) -> SqlQuestionResultResponse:\n    return service_container.sql_question_service.get_sql_question_result(\n        SqlQuestionResultRequest(query_id=query_id)\n    )\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/services/__init__.py",
    "content": "from datetime import datetime\nfrom typing import Literal, Optional\n\nimport orjson\nimport pytz\nfrom pydantic import AliasChoices, BaseModel, Field\n\n\nclass MetadataTraceable:\n    def with_metadata(self) -> dict:\n        return {\n            \"resource\": self,\n            \"metadata\": {\n                **self._error_metadata(),\n            },\n        }\n\n    def _error_metadata(self):\n        return {\n            \"error_type\": self.error and self.error.code,\n            \"error_message\": self.error and self.error.message,\n            \"request_from\": self.request_from,\n        }\n\n\nclass Configuration(BaseModel):\n    class Timezone(BaseModel):\n        name: str = \"UTC\"\n        utc_offset: str = \"\"  # Deprecated, will be removed in the future\n\n    def show_current_time(self):\n        # Get the current time in the specified timezone\n        tz = pytz.timezone(\n            self.timezone.name\n        )  # Assuming timezone.name contains the timezone string\n        current_time = datetime.now(tz)\n\n        return f\"{current_time.strftime('%Y-%m-%d %A %H:%M:%S')}\"  # YYYY-MM-DD weekday_name HH:MM:SS, ex: 2024-10-23 Wednesday 12:00:00\n\n    language: str = \"English\"\n    timezone: Timezone = Timezone()\n\n\nclass SSEEvent(BaseModel):\n    class SSEEventMessage(BaseModel):\n        message: str\n\n        def to_dict(self):\n            return {\"message\": self.message}\n\n    data: SSEEventMessage\n\n    def serialize(self):\n        return f\"data: {orjson.dumps(self.data.to_dict()).decode()}\\n\\n\"\n\n\n# for POST, PATCH, UPDATE, DELETE requests\nclass BaseRequest(BaseModel):\n    _query_id: str | None = None\n    project_id: Optional[str] = None\n    thread_id: Optional[str] = None\n    configurations: Configuration = Field(\n        default_factory=Configuration,\n        alias=AliasChoices(\"configurations\", \"configuration\"),  # accept both keys\n    )\n    request_from: Literal[\"ui\", \"api\"] = \"ui\"\n\n    @property\n    def query_id(self) -> str:\n        return self._query_id\n\n    @query_id.setter\n    def query_id(self, query_id: str):\n        self._query_id = query_id\n\n\n# Put the services imports here to avoid circular imports and make them accessible directly to the rest of packages\nfrom .ask import AskService  # noqa: E402\nfrom .ask_feedback import AskFeedbackService  # noqa: E402\nfrom .chart import ChartService  # noqa: E402\nfrom .chart_adjustment import ChartAdjustmentService  # noqa: E402\nfrom .instructions import InstructionsService  # noqa: E402\nfrom .question_recommendation import QuestionRecommendation  # noqa: E402\nfrom .relationship_recommendation import RelationshipRecommendation  # noqa: E402\nfrom .semantics_description import SemanticsDescription  # noqa: E402\nfrom .semantics_preparation import SemanticsPreparationService  # noqa: E402\nfrom .sql_answer import SqlAnswerService  # noqa: E402\nfrom .sql_corrections import SqlCorrectionService  # noqa: E402\nfrom .sql_pairs import SqlPairsService  # noqa: E402\nfrom .sql_question import SqlQuestionService  # noqa: E402\n\n__all__ = [\n    \"AskService\",\n    \"AskFeedbackService\",\n    \"ChartService\",\n    \"ChartAdjustmentService\",\n    \"QuestionRecommendation\",\n    \"RelationshipRecommendation\",\n    \"SemanticsDescription\",\n    \"SemanticsPreparationService\",\n    \"SqlAnswerService\",\n    \"SqlCorrectionService\",\n    \"SqlPairsService\",\n    \"SqlQuestionService\",\n    \"InstructionsService\",\n]\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/services/ask.py",
    "content": "import asyncio\nimport logging\nfrom typing import Dict, List, Literal, Optional\n\nfrom cachetools import TTLCache\nfrom langfuse.decorators import observe\nfrom pydantic import AliasChoices, BaseModel, Field\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.utils import trace_metadata\nfrom src.web.v1.services import BaseRequest, SSEEvent\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nclass AskHistory(BaseModel):\n    sql: str\n    question: str\n\n\n# POST /v1/asks\nclass AskRequest(BaseRequest):\n    query: str\n    # don't recommend to use id as a field name, but it's used in the older version of API spec\n    # so we need to support as a choice, and will remove it in the future\n    mdl_hash: Optional[str] = Field(validation_alias=AliasChoices(\"mdl_hash\", \"id\"))\n    histories: Optional[list[AskHistory]] = Field(default_factory=list)\n    ignore_sql_generation_reasoning: bool = False\n    enable_column_pruning: bool = False\n    use_dry_plan: bool = False\n    allow_dry_plan_fallback: bool = True\n    custom_instruction: Optional[str] = None\n\n\nclass AskResponse(BaseModel):\n    query_id: str\n\n\n# PATCH /v1/asks/{query_id}\nclass StopAskRequest(BaseRequest):\n    status: Literal[\"stopped\"]\n\n\nclass StopAskResponse(BaseModel):\n    query_id: str\n\n\n# GET /v1/asks/{query_id}/result\nclass AskResult(BaseModel):\n    sql: str\n    type: Literal[\"llm\", \"view\"] = \"llm\"\n    viewId: Optional[str] = None\n\n\nclass AskError(BaseModel):\n    code: Literal[\"NO_RELEVANT_DATA\", \"NO_RELEVANT_SQL\", \"OTHERS\"]\n    message: str\n\n\nclass AskResultRequest(BaseModel):\n    query_id: str\n\n\nclass _AskResultResponse(BaseModel):\n    status: Literal[\n        \"understanding\",\n        \"searching\",\n        \"planning\",\n        \"generating\",\n        \"correcting\",\n        \"finished\",\n        \"failed\",\n        \"stopped\",\n    ]\n    rephrased_question: Optional[str] = None\n    intent_reasoning: Optional[str] = None\n    sql_generation_reasoning: Optional[str] = None\n    type: Optional[Literal[\"GENERAL\", \"TEXT_TO_SQL\"]] = None\n    retrieved_tables: Optional[List[str]] = None\n    response: Optional[List[AskResult]] = None\n    invalid_sql: Optional[str] = None\n    error: Optional[AskError] = None\n    trace_id: Optional[str] = None\n    is_followup: bool = False\n    general_type: Optional[\n        Literal[\"MISLEADING_QUERY\", \"DATA_ASSISTANCE\", \"USER_GUIDE\"]\n    ] = None\n\n\nclass AskResultResponse(_AskResultResponse):\n    is_followup: Optional[bool] = Field(False, exclude=True)\n    general_type: Optional[\n        Literal[\"MISLEADING_QUERY\", \"DATA_ASSISTANCE\", \"USER_GUIDE\"]\n    ] = Field(None, exclude=True)\n\n\nclass AskService:\n    def __init__(\n        self,\n        pipelines: Dict[str, BasicPipeline],\n        allow_intent_classification: bool = True,\n        allow_sql_generation_reasoning: bool = True,\n        allow_sql_functions_retrieval: bool = True,\n        allow_sql_diagnosis: bool = True,\n        allow_sql_knowledge_retrieval: bool = True,\n        enable_column_pruning: bool = False,\n        max_sql_correction_retries: int = 3,\n        max_histories: int = 5,\n        maxsize: int = 1_000_000,\n        ttl: int = 120,\n    ):\n        self._pipelines = pipelines\n        self._ask_results: Dict[str, AskResultResponse] = TTLCache(\n            maxsize=maxsize, ttl=ttl\n        )\n        self._allow_sql_generation_reasoning = allow_sql_generation_reasoning\n        self._allow_sql_functions_retrieval = allow_sql_functions_retrieval\n        self._allow_intent_classification = allow_intent_classification\n        self._allow_sql_diagnosis = allow_sql_diagnosis\n        self._allow_sql_knowledge_retrieval = allow_sql_knowledge_retrieval\n        self._enable_column_pruning = enable_column_pruning\n        self._max_histories = max_histories\n        self._max_sql_correction_retries = max_sql_correction_retries\n\n    def _is_stopped(self, query_id: str, container: dict):\n        if (\n            result := container.get(query_id)\n        ) is not None and result.status == \"stopped\":\n            return True\n\n        return False\n\n    @observe(name=\"Ask Question\")\n    @trace_metadata\n    async def ask(\n        self,\n        ask_request: AskRequest,\n        **kwargs,\n    ):\n        trace_id = kwargs.get(\"trace_id\")\n        results = {\n            \"ask_result\": {},\n            \"metadata\": {\n                \"type\": \"\",\n                \"error_type\": \"\",\n                \"error_message\": \"\",\n                \"request_from\": ask_request.request_from,\n            },\n        }\n\n        query_id = ask_request.query_id\n        histories = ask_request.histories[: self._max_histories][\n            ::-1\n        ]  # reverse the order of histories\n        rephrased_question = None\n        intent_reasoning = None\n        sql_generation_reasoning = None\n        sql_samples = []\n        instructions = []\n        api_results = []\n        table_names = []\n        error_message = None\n        invalid_sql = None\n        allow_sql_generation_reasoning = (\n            self._allow_sql_generation_reasoning\n            and not ask_request.ignore_sql_generation_reasoning\n        )\n        enable_column_pruning = (\n            self._enable_column_pruning or ask_request.enable_column_pruning\n        )\n        allow_sql_functions_retrieval = self._allow_sql_functions_retrieval\n        allow_sql_diagnosis = self._allow_sql_diagnosis\n        allow_sql_knowledge_retrieval = self._allow_sql_knowledge_retrieval\n        max_sql_correction_retries = self._max_sql_correction_retries\n        current_sql_correction_retries = 0\n        use_dry_plan = ask_request.use_dry_plan\n        allow_dry_plan_fallback = ask_request.allow_dry_plan_fallback\n        sql_knowledge = None\n\n        try:\n            user_query = ask_request.query\n\n            # ask status can be understanding, searching, generating, finished, failed, stopped\n            # we will need to handle business logic for each status\n            if not self._is_stopped(query_id, self._ask_results):\n                self._ask_results[query_id] = AskResultResponse(\n                    status=\"understanding\",\n                    trace_id=trace_id,\n                    is_followup=True if histories else False,\n                )\n\n                historical_question = await self._pipelines[\"historical_question\"].run(\n                    query=user_query,\n                    project_id=ask_request.project_id,\n                )\n\n                # we only return top 1 result\n                historical_question_result = historical_question.get(\n                    \"formatted_output\", {}\n                ).get(\"documents\", [])[:1]\n\n                if historical_question_result:\n                    api_results = [\n                        AskResult(\n                            **{\n                                \"sql\": result.get(\"statement\"),\n                                \"type\": \"view\" if result.get(\"viewId\") else \"llm\",\n                                \"viewId\": result.get(\"viewId\"),\n                            }\n                        )\n                        for result in historical_question_result\n                    ]\n                    sql_generation_reasoning = \"\"\n                else:\n                    # Run both pipeline operations concurrently\n                    sql_samples_task, instructions_task = await asyncio.gather(\n                        self._pipelines[\"sql_pairs_retrieval\"].run(\n                            query=user_query,\n                            project_id=ask_request.project_id,\n                        ),\n                        self._pipelines[\"instructions_retrieval\"].run(\n                            query=user_query,\n                            project_id=ask_request.project_id,\n                            scope=\"sql\",\n                        ),\n                    )\n\n                    # Extract results from completed tasks\n                    sql_samples = sql_samples_task[\"formatted_output\"].get(\n                        \"documents\", []\n                    )\n                    instructions = instructions_task[\"formatted_output\"].get(\n                        \"documents\", []\n                    )\n\n                    if self._allow_intent_classification:\n                        intent_classification_result = (\n                            await self._pipelines[\"intent_classification\"].run(\n                                query=user_query,\n                                histories=histories,\n                                sql_samples=sql_samples,\n                                instructions=instructions,\n                                project_id=ask_request.project_id,\n                                configuration=ask_request.configurations,\n                            )\n                        ).get(\"post_process\", {})\n                        intent = intent_classification_result.get(\"intent\")\n                        rephrased_question = intent_classification_result.get(\n                            \"rephrased_question\"\n                        )\n                        intent_reasoning = intent_classification_result.get(\"reasoning\")\n\n                        if rephrased_question:\n                            user_query = rephrased_question\n\n                        if intent == \"MISLEADING_QUERY\":\n                            asyncio.create_task(\n                                self._pipelines[\"misleading_assistance\"].run(\n                                    query=user_query,\n                                    histories=histories,\n                                    db_schemas=intent_classification_result.get(\n                                        \"db_schemas\"\n                                    ),\n                                    language=ask_request.configurations.language,\n                                    query_id=ask_request.query_id,\n                                    custom_instruction=ask_request.custom_instruction,\n                                )\n                            )\n\n                            self._ask_results[query_id] = AskResultResponse(\n                                status=\"finished\",\n                                type=\"GENERAL\",\n                                rephrased_question=rephrased_question,\n                                intent_reasoning=intent_reasoning,\n                                trace_id=trace_id,\n                                is_followup=True if histories else False,\n                                general_type=\"MISLEADING_QUERY\",\n                            )\n                            results[\"metadata\"][\"type\"] = \"MISLEADING_QUERY\"\n                            return results\n                        elif intent == \"GENERAL\":\n                            asyncio.create_task(\n                                self._pipelines[\"data_assistance\"].run(\n                                    query=user_query,\n                                    histories=histories,\n                                    db_schemas=intent_classification_result.get(\n                                        \"db_schemas\"\n                                    ),\n                                    language=ask_request.configurations.language,\n                                    query_id=ask_request.query_id,\n                                    custom_instruction=ask_request.custom_instruction,\n                                )\n                            )\n\n                            self._ask_results[query_id] = AskResultResponse(\n                                status=\"finished\",\n                                type=\"GENERAL\",\n                                rephrased_question=rephrased_question,\n                                intent_reasoning=intent_reasoning,\n                                trace_id=trace_id,\n                                is_followup=True if histories else False,\n                                general_type=\"DATA_ASSISTANCE\",\n                            )\n                            results[\"metadata\"][\"type\"] = \"GENERAL\"\n                            return results\n                        elif intent == \"USER_GUIDE\":\n                            asyncio.create_task(\n                                self._pipelines[\"user_guide_assistance\"].run(\n                                    query=user_query,\n                                    language=ask_request.configurations.language,\n                                    query_id=ask_request.query_id,\n                                    custom_instruction=ask_request.custom_instruction,\n                                )\n                            )\n\n                            self._ask_results[query_id] = AskResultResponse(\n                                status=\"finished\",\n                                type=\"GENERAL\",\n                                rephrased_question=rephrased_question,\n                                intent_reasoning=intent_reasoning,\n                                trace_id=trace_id,\n                                is_followup=True if histories else False,\n                                general_type=\"USER_GUIDE\",\n                            )\n                            results[\"metadata\"][\"type\"] = \"GENERAL\"\n                            return results\n                        else:\n                            self._ask_results[query_id] = AskResultResponse(\n                                status=\"understanding\",\n                                type=\"TEXT_TO_SQL\",\n                                rephrased_question=rephrased_question,\n                                intent_reasoning=intent_reasoning,\n                                trace_id=trace_id,\n                                is_followup=True if histories else False,\n                            )\n            if not self._is_stopped(query_id, self._ask_results) and not api_results:\n                self._ask_results[query_id] = AskResultResponse(\n                    status=\"searching\",\n                    type=\"TEXT_TO_SQL\",\n                    rephrased_question=rephrased_question,\n                    intent_reasoning=intent_reasoning,\n                    trace_id=trace_id,\n                    is_followup=True if histories else False,\n                )\n\n                retrieval_result = await self._pipelines[\"db_schema_retrieval\"].run(\n                    query=user_query,\n                    histories=histories,\n                    project_id=ask_request.project_id,\n                    enable_column_pruning=enable_column_pruning,\n                )\n                _retrieval_result = retrieval_result.get(\n                    \"construct_retrieval_results\", {}\n                )\n                documents = _retrieval_result.get(\"retrieval_results\", [])\n                table_names = [document.get(\"table_name\") for document in documents]\n                table_ddls = [document.get(\"table_ddl\") for document in documents]\n\n                if not documents:\n                    logger.exception(f\"ask pipeline - NO_RELEVANT_DATA: {user_query}\")\n                    if not self._is_stopped(query_id, self._ask_results):\n                        self._ask_results[query_id] = AskResultResponse(\n                            status=\"failed\",\n                            type=\"TEXT_TO_SQL\",\n                            error=AskError(\n                                code=\"NO_RELEVANT_DATA\",\n                                message=\"No relevant data\",\n                            ),\n                            rephrased_question=rephrased_question,\n                            intent_reasoning=intent_reasoning,\n                            trace_id=trace_id,\n                            is_followup=True if histories else False,\n                        )\n                    results[\"metadata\"][\"error_type\"] = \"NO_RELEVANT_DATA\"\n                    results[\"metadata\"][\"type\"] = \"TEXT_TO_SQL\"\n                    return results\n\n            if (\n                not self._is_stopped(query_id, self._ask_results)\n                and not api_results\n                and allow_sql_generation_reasoning\n            ):\n                self._ask_results[query_id] = AskResultResponse(\n                    status=\"planning\",\n                    type=\"TEXT_TO_SQL\",\n                    rephrased_question=rephrased_question,\n                    intent_reasoning=intent_reasoning,\n                    retrieved_tables=table_names,\n                    trace_id=trace_id,\n                    is_followup=True if histories else False,\n                )\n\n                if histories:\n                    sql_generation_reasoning = (\n                        await self._pipelines[\"followup_sql_generation_reasoning\"].run(\n                            query=user_query,\n                            contexts=table_ddls,\n                            histories=histories,\n                            sql_samples=sql_samples,\n                            instructions=instructions,\n                            configuration=ask_request.configurations,\n                            query_id=query_id,\n                        )\n                    ).get(\"post_process\", {})\n                else:\n                    sql_generation_reasoning = (\n                        await self._pipelines[\"sql_generation_reasoning\"].run(\n                            query=user_query,\n                            contexts=table_ddls,\n                            sql_samples=sql_samples,\n                            instructions=instructions,\n                            configuration=ask_request.configurations,\n                            query_id=query_id,\n                        )\n                    ).get(\"post_process\", {})\n\n                self._ask_results[query_id] = AskResultResponse(\n                    status=\"planning\",\n                    type=\"TEXT_TO_SQL\",\n                    rephrased_question=rephrased_question,\n                    intent_reasoning=intent_reasoning,\n                    retrieved_tables=table_names,\n                    sql_generation_reasoning=sql_generation_reasoning,\n                    trace_id=trace_id,\n                    is_followup=True if histories else False,\n                )\n\n            if not self._is_stopped(query_id, self._ask_results) and not api_results:\n                self._ask_results[query_id] = AskResultResponse(\n                    status=\"generating\",\n                    type=\"TEXT_TO_SQL\",\n                    rephrased_question=rephrased_question,\n                    intent_reasoning=intent_reasoning,\n                    retrieved_tables=table_names,\n                    sql_generation_reasoning=sql_generation_reasoning,\n                    trace_id=trace_id,\n                    is_followup=True if histories else False,\n                )\n\n                if allow_sql_functions_retrieval:\n                    sql_functions = await self._pipelines[\n                        \"sql_functions_retrieval\"\n                    ].run(\n                        project_id=ask_request.project_id,\n                    )\n                else:\n                    sql_functions = []\n\n                if allow_sql_knowledge_retrieval:\n                    sql_knowledge = await self._pipelines[\n                        \"sql_knowledge_retrieval\"\n                    ].run(\n                        project_id=ask_request.project_id,\n                    )\n\n                has_calculated_field = _retrieval_result.get(\n                    \"has_calculated_field\", False\n                )\n                has_metric = _retrieval_result.get(\"has_metric\", False)\n                has_json_field = _retrieval_result.get(\"has_json_field\", False)\n\n                if histories:\n                    text_to_sql_generation_results = await self._pipelines[\n                        \"followup_sql_generation\"\n                    ].run(\n                        query=user_query,\n                        contexts=table_ddls,\n                        sql_generation_reasoning=sql_generation_reasoning,\n                        histories=histories,\n                        project_id=ask_request.project_id,\n                        sql_samples=sql_samples,\n                        instructions=instructions,\n                        has_calculated_field=has_calculated_field,\n                        has_metric=has_metric,\n                        has_json_field=has_json_field,\n                        sql_functions=sql_functions,\n                        use_dry_plan=use_dry_plan,\n                        allow_dry_plan_fallback=allow_dry_plan_fallback,\n                        sql_knowledge=sql_knowledge,\n                    )\n                else:\n                    text_to_sql_generation_results = await self._pipelines[\n                        \"sql_generation\"\n                    ].run(\n                        query=user_query,\n                        contexts=table_ddls,\n                        sql_generation_reasoning=sql_generation_reasoning,\n                        project_id=ask_request.project_id,\n                        sql_samples=sql_samples,\n                        instructions=instructions,\n                        has_calculated_field=has_calculated_field,\n                        has_metric=has_metric,\n                        has_json_field=has_json_field,\n                        sql_functions=sql_functions,\n                        use_dry_plan=use_dry_plan,\n                        allow_dry_plan_fallback=allow_dry_plan_fallback,\n                        sql_knowledge=sql_knowledge,\n                    )\n\n                if sql_valid_result := text_to_sql_generation_results[\"post_process\"][\n                    \"valid_generation_result\"\n                ]:\n                    api_results = [\n                        AskResult(\n                            **{\n                                \"sql\": sql_valid_result.get(\"sql\"),\n                                \"type\": \"llm\",\n                            }\n                        )\n                    ]\n                elif failed_dry_run_result := text_to_sql_generation_results[\n                    \"post_process\"\n                ][\"invalid_generation_result\"]:\n                    while current_sql_correction_retries < max_sql_correction_retries:\n                        if failed_dry_run_result[\"type\"] == \"TIME_OUT\":\n                            break\n\n                        original_sql = failed_dry_run_result[\"original_sql\"]\n                        invalid_sql = failed_dry_run_result[\"sql\"]\n                        error_message = failed_dry_run_result[\"error\"]\n                        current_sql_correction_retries += 1\n\n                        self._ask_results[query_id] = AskResultResponse(\n                            status=\"correcting\",\n                            type=\"TEXT_TO_SQL\",\n                            rephrased_question=rephrased_question,\n                            intent_reasoning=intent_reasoning,\n                            retrieved_tables=table_names,\n                            sql_generation_reasoning=sql_generation_reasoning,\n                            trace_id=trace_id,\n                            is_followup=True if histories else False,\n                        )\n\n                        if allow_sql_diagnosis:\n                            sql_diagnosis_results = await self._pipelines[\n                                \"sql_diagnosis\"\n                            ].run(\n                                contexts=table_ddls,\n                                original_sql=original_sql,\n                                invalid_sql=invalid_sql,\n                                error_message=error_message,\n                                language=ask_request.configurations.language,\n                            )\n                            sql_diagnosis_reasoning = sql_diagnosis_results[\n                                \"post_process\"\n                            ].get(\"reasoning\")\n\n                        sql_correction_results = await self._pipelines[\n                            \"sql_correction\"\n                        ].run(\n                            contexts=table_ddls,\n                            instructions=instructions,\n                            invalid_generation_result={\n                                \"sql\": original_sql,\n                                \"error\": sql_diagnosis_reasoning\n                                if allow_sql_diagnosis\n                                else error_message,\n                            },\n                            project_id=ask_request.project_id,\n                            use_dry_plan=use_dry_plan,\n                            allow_dry_plan_fallback=allow_dry_plan_fallback,\n                            sql_functions=sql_functions,\n                            sql_knowledge=sql_knowledge,\n                        )\n\n                        if valid_generation_result := sql_correction_results[\n                            \"post_process\"\n                        ][\"valid_generation_result\"]:\n                            api_results = [\n                                AskResult(\n                                    **{\n                                        \"sql\": valid_generation_result.get(\"sql\"),\n                                        \"type\": \"llm\",\n                                    }\n                                )\n                            ]\n                            break\n\n                        failed_dry_run_result = sql_correction_results[\"post_process\"][\n                            \"invalid_generation_result\"\n                        ]\n\n            if api_results:\n                if not self._is_stopped(query_id, self._ask_results):\n                    self._ask_results[query_id] = AskResultResponse(\n                        status=\"finished\",\n                        type=\"TEXT_TO_SQL\",\n                        response=api_results,\n                        rephrased_question=rephrased_question,\n                        intent_reasoning=intent_reasoning,\n                        retrieved_tables=table_names,\n                        sql_generation_reasoning=sql_generation_reasoning,\n                        trace_id=trace_id,\n                        is_followup=True if histories else False,\n                    )\n                results[\"ask_result\"] = api_results\n                results[\"metadata\"][\"type\"] = \"TEXT_TO_SQL\"\n            else:\n                logger.exception(f\"ask pipeline - NO_RELEVANT_SQL: {user_query}\")\n                if not self._is_stopped(query_id, self._ask_results):\n                    self._ask_results[query_id] = AskResultResponse(\n                        status=\"failed\",\n                        type=\"TEXT_TO_SQL\",\n                        error=AskError(\n                            code=\"NO_RELEVANT_SQL\",\n                            message=error_message or \"No relevant SQL\",\n                        ),\n                        rephrased_question=rephrased_question,\n                        intent_reasoning=intent_reasoning,\n                        retrieved_tables=table_names,\n                        sql_generation_reasoning=sql_generation_reasoning,\n                        invalid_sql=invalid_sql,\n                        trace_id=trace_id,\n                        is_followup=True if histories else False,\n                    )\n                results[\"metadata\"][\"error_type\"] = \"NO_RELEVANT_SQL\"\n                results[\"metadata\"][\"error_message\"] = error_message\n                results[\"metadata\"][\"type\"] = \"TEXT_TO_SQL\"\n\n            return results\n        except Exception as e:\n            logger.exception(f\"ask pipeline - OTHERS: {e}\")\n\n            self._ask_results[query_id] = AskResultResponse(\n                status=\"failed\",\n                type=\"TEXT_TO_SQL\",\n                error=AskError(\n                    code=\"OTHERS\",\n                    message=str(e),\n                ),\n                trace_id=trace_id,\n                is_followup=True if histories else False,\n            )\n\n            results[\"metadata\"][\"error_type\"] = \"OTHERS\"\n            results[\"metadata\"][\"error_message\"] = str(e)\n            results[\"metadata\"][\"type\"] = \"TEXT_TO_SQL\"\n            return results\n\n    def stop_ask(\n        self,\n        stop_ask_request: StopAskRequest,\n    ):\n        self._ask_results[stop_ask_request.query_id] = AskResultResponse(\n            status=\"stopped\",\n        )\n\n    def get_ask_result(\n        self,\n        ask_result_request: AskResultRequest,\n    ) -> AskResultResponse:\n        if (result := self._ask_results.get(ask_result_request.query_id)) is None:\n            logger.exception(\n                f\"ask pipeline - OTHERS: {ask_result_request.query_id} is not found\"\n            )\n            return AskResultResponse(\n                status=\"failed\",\n                type=\"TEXT_TO_SQL\",\n                error=AskError(\n                    code=\"OTHERS\",\n                    message=f\"{ask_result_request.query_id} is not found\",\n                ),\n            )\n\n        return result\n\n    async def get_ask_streaming_result(\n        self,\n        query_id: str,\n    ):\n        if self._ask_results.get(query_id):\n            _pipeline_name = \"\"\n            if self._ask_results.get(query_id).type == \"GENERAL\":\n                if self._ask_results.get(query_id).general_type == \"USER_GUIDE\":\n                    _pipeline_name = \"user_guide_assistance\"\n                elif self._ask_results.get(query_id).general_type == \"DATA_ASSISTANCE\":\n                    _pipeline_name = \"data_assistance\"\n                elif self._ask_results.get(query_id).general_type == \"MISLEADING_QUERY\":\n                    _pipeline_name = \"misleading_assistance\"\n            elif self._ask_results.get(query_id).status == \"planning\":\n                if self._ask_results.get(query_id).is_followup:\n                    _pipeline_name = \"followup_sql_generation_reasoning\"\n                else:\n                    _pipeline_name = \"sql_generation_reasoning\"\n\n            if _pipeline_name:\n                async for chunk in self._pipelines[\n                    _pipeline_name\n                ].get_streaming_results(query_id):\n                    event = SSEEvent(\n                        data=SSEEvent.SSEEventMessage(message=chunk),\n                    )\n                    yield event.serialize()\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/services/ask_feedback.py",
    "content": "import asyncio\nimport logging\nfrom typing import Dict, List, Literal, Optional\n\nfrom cachetools import TTLCache\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.utils import trace_metadata\nfrom src.web.v1.services import BaseRequest\nfrom src.web.v1.services.ask import AskError, AskResult\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n# POST /v1/ask-feedbacks\nclass AskFeedbackRequest(BaseRequest):\n    question: str\n    tables: List[str]\n    sql_generation_reasoning: str\n    sql: str\n\n\nclass AskFeedbackResponse(BaseModel):\n    query_id: str\n\n\n# PATCH /v1/ask-feedbacks/{query_id}\nclass StopAskFeedbackRequest(BaseRequest):\n    status: Literal[\"stopped\"]\n\n\nclass StopAskFeedbackResponse(BaseModel):\n    query_id: str\n\n\n# GET /v1/ask-feedbacks/{query_id}\nclass AskFeedbackResultRequest(BaseModel):\n    query_id: str\n\n\nclass AskFeedbackResultResponse(BaseModel):\n    status: Literal[\n        \"searching\",\n        \"generating\",\n        \"correcting\",\n        \"finished\",\n        \"failed\",\n        \"stopped\",\n    ]\n    invalid_sql: Optional[str] = None\n    error: Optional[AskError] = None\n    response: Optional[List[AskResult]] = None\n    trace_id: Optional[str] = None\n\n\nclass AskFeedbackService:\n    def __init__(\n        self,\n        pipelines: Dict[str, BasicPipeline],\n        allow_sql_knowledge_retrieval: bool = True,\n        allow_sql_functions_retrieval: bool = True,\n        allow_sql_diagnosis: bool = True,\n        maxsize: int = 1_000_000,\n        ttl: int = 120,\n    ):\n        self._pipelines = pipelines\n        self._ask_feedback_results: Dict[str, AskFeedbackResultResponse] = TTLCache(\n            maxsize=maxsize, ttl=ttl\n        )\n        self._allow_sql_knowledge_retrieval = allow_sql_knowledge_retrieval\n        self._allow_sql_functions_retrieval = allow_sql_functions_retrieval\n        self._allow_sql_diagnosis = allow_sql_diagnosis\n\n    def _is_stopped(self, query_id: str, container: dict):\n        if (\n            result := container.get(query_id)\n        ) is not None and result.status == \"stopped\":\n            return True\n\n        return False\n\n    @observe(name=\"Ask Feedback\")\n    @trace_metadata\n    async def ask_feedback(\n        self,\n        ask_feedback_request: AskFeedbackRequest,\n        **kwargs,\n    ):\n        trace_id = kwargs.get(\"trace_id\")\n        results = {\n            \"ask_feedback_result\": {},\n            \"metadata\": {\n                \"error_type\": \"\",\n                \"error_message\": \"\",\n                \"request_from\": ask_feedback_request.request_from,\n            },\n        }\n\n        query_id = ask_feedback_request.query_id\n        allow_sql_functions_retrieval = self._allow_sql_functions_retrieval\n        allow_sql_diagnosis = self._allow_sql_diagnosis\n        api_results = []\n        error_message = None\n        invalid_sql = None\n        sql_knowledge = None\n        allow_sql_knowledge_retrieval = self._allow_sql_knowledge_retrieval\n\n        try:\n            if not self._is_stopped(query_id, self._ask_feedback_results):\n                self._ask_feedback_results[query_id] = AskFeedbackResultResponse(\n                    status=\"searching\",\n                    trace_id=trace_id,\n                )\n\n                (\n                    retrieval_task,\n                    sql_samples_task,\n                    instructions_task,\n                ) = await asyncio.gather(\n                    self._pipelines[\"db_schema_retrieval\"].run(\n                        tables=ask_feedback_request.tables,\n                        project_id=ask_feedback_request.project_id,\n                    ),\n                    self._pipelines[\"sql_pairs_retrieval\"].run(\n                        query=ask_feedback_request.question,\n                        project_id=ask_feedback_request.project_id,\n                    ),\n                    self._pipelines[\"instructions_retrieval\"].run(\n                        query=ask_feedback_request.question,\n                        project_id=ask_feedback_request.project_id,\n                        scope=\"sql\",\n                    ),\n                )\n\n                if allow_sql_functions_retrieval:\n                    sql_functions = await self._pipelines[\n                        \"sql_functions_retrieval\"\n                    ].run(\n                        project_id=ask_feedback_request.project_id,\n                    )\n                else:\n                    sql_functions = []\n\n                if allow_sql_knowledge_retrieval:\n                    sql_knowledge = await self._pipelines[\n                        \"sql_knowledge_retrieval\"\n                    ].run(\n                        project_id=ask_feedback_request.project_id,\n                    )\n\n                # Extract results from completed tasks\n                _retrieval_result = retrieval_task.get(\n                    \"construct_retrieval_results\", {}\n                )\n                has_calculated_field = _retrieval_result.get(\n                    \"has_calculated_field\", False\n                )\n                has_metric = _retrieval_result.get(\"has_metric\", False)\n                has_json_field = _retrieval_result.get(\"has_json_field\", False)\n                documents = _retrieval_result.get(\"retrieval_results\", [])\n                table_ddls = [document.get(\"table_ddl\") for document in documents]\n                sql_samples = sql_samples_task[\"formatted_output\"].get(\"documents\", [])\n                instructions = instructions_task[\"formatted_output\"].get(\n                    \"documents\", []\n                )\n\n            if not self._is_stopped(query_id, self._ask_feedback_results):\n                self._ask_feedback_results[query_id] = AskFeedbackResultResponse(\n                    status=\"generating\",\n                    trace_id=trace_id,\n                )\n\n                text_to_sql_generation_results = await self._pipelines[\n                    \"sql_regeneration\"\n                ].run(\n                    contexts=table_ddls,\n                    sql_generation_reasoning=ask_feedback_request.sql_generation_reasoning,\n                    sql=ask_feedback_request.sql,\n                    project_id=ask_feedback_request.project_id,\n                    sql_samples=sql_samples,\n                    instructions=instructions,\n                    has_calculated_field=has_calculated_field,\n                    has_metric=has_metric,\n                    has_json_field=has_json_field,\n                    sql_functions=sql_functions,\n                    sql_knowledge=sql_knowledge,\n                )\n\n                if sql_valid_result := text_to_sql_generation_results[\"post_process\"][\n                    \"valid_generation_result\"\n                ]:\n                    api_results = [\n                        AskResult(\n                            **{\n                                \"sql\": sql_valid_result.get(\"sql\"),\n                                \"type\": \"llm\",\n                            }\n                        )\n                    ]\n                elif failed_dry_run_result := text_to_sql_generation_results[\n                    \"post_process\"\n                ][\"invalid_generation_result\"]:\n                    if failed_dry_run_result[\"type\"] != \"TIME_OUT\":\n                        original_sql = failed_dry_run_result[\"original_sql\"]\n                        invalid_sql = failed_dry_run_result[\"sql\"]\n                        error_message = failed_dry_run_result[\"error\"]\n\n                        self._ask_feedback_results[\n                            query_id\n                        ] = AskFeedbackResultResponse(\n                            status=\"correcting\",\n                            trace_id=trace_id,\n                        )\n\n                        if allow_sql_diagnosis:\n                            sql_diagnosis_results = await self._pipelines[\n                                \"sql_diagnosis\"\n                            ].run(\n                                contexts=table_ddls,\n                                original_sql=original_sql,\n                                invalid_sql=invalid_sql,\n                                error_message=error_message,\n                            )\n                            sql_diagnosis_reasoning = sql_diagnosis_results[\n                                \"post_process\"\n                            ].get(\"reasoning\")\n\n                        sql_correction_results = await self._pipelines[\n                            \"sql_correction\"\n                        ].run(\n                            contexts=table_ddls,\n                            instructions=instructions,\n                            invalid_generation_result={\n                                \"sql\": original_sql,\n                                \"error\": sql_diagnosis_reasoning\n                                if allow_sql_diagnosis\n                                else error_message,\n                            },\n                            project_id=ask_feedback_request.project_id,\n                            sql_functions=sql_functions,\n                            sql_knowledge=sql_knowledge,\n                        )\n\n                        if valid_generation_result := sql_correction_results[\n                            \"post_process\"\n                        ][\"valid_generation_result\"]:\n                            api_results = [\n                                AskResult(\n                                    **{\n                                        \"sql\": valid_generation_result.get(\"sql\"),\n                                        \"type\": \"llm\",\n                                    }\n                                )\n                            ]\n                        elif failed_dry_run_result := sql_correction_results[\n                            \"post_process\"\n                        ][\"invalid_generation_result\"]:\n                            invalid_sql = failed_dry_run_result[\"sql\"]\n                            error_message = failed_dry_run_result[\"error\"]\n                    else:\n                        invalid_sql = failed_dry_run_result[\"sql\"]\n                        error_message = failed_dry_run_result[\"error\"]\n\n            if api_results:\n                if not self._is_stopped(query_id, self._ask_feedback_results):\n                    self._ask_feedback_results[query_id] = AskFeedbackResultResponse(\n                        status=\"finished\",\n                        response=api_results,\n                        trace_id=trace_id,\n                    )\n                results[\"ask_feedback_result\"] = api_results\n            else:\n                logger.exception(\"ask feedback pipeline - NO_RELEVANT_SQL\")\n                if not self._is_stopped(query_id, self._ask_feedback_results):\n                    self._ask_feedback_results[query_id] = AskFeedbackResultResponse(\n                        status=\"failed\",\n                        error=AskError(\n                            code=\"NO_RELEVANT_SQL\",\n                            message=error_message or \"No relevant SQL\",\n                        ),\n                        invalid_sql=invalid_sql,\n                        trace_id=trace_id,\n                    )\n                results[\"metadata\"][\"error_type\"] = \"NO_RELEVANT_SQL\"\n                results[\"metadata\"][\"error_message\"] = error_message\n\n            return results\n\n        except Exception as e:\n            logger.exception(f\"ask feedback pipeline - OTHERS: {e}\")\n\n            self._ask_feedback_results[query_id] = AskFeedbackResultResponse(\n                status=\"failed\",\n                error=AskError(\n                    code=\"OTHERS\",\n                    message=str(e),\n                ),\n                trace_id=trace_id,\n            )\n\n            results[\"metadata\"][\"error_type\"] = \"OTHERS\"\n            results[\"metadata\"][\"error_message\"] = str(e)\n            return results\n\n    def stop_ask_feedback(\n        self,\n        stop_ask_feedback_request: StopAskFeedbackRequest,\n    ):\n        self._ask_feedback_results[\n            stop_ask_feedback_request.query_id\n        ] = AskFeedbackResultResponse(\n            status=\"stopped\",\n        )\n\n    def get_ask_feedback_result(\n        self,\n        ask_feedback_result_request: AskFeedbackResultRequest,\n    ) -> AskFeedbackResultResponse:\n        if (\n            result := self._ask_feedback_results.get(\n                ask_feedback_result_request.query_id\n            )\n        ) is None:\n            logger.exception(\n                f\"ask feedback pipeline - OTHERS: {ask_feedback_result_request.query_id} is not found\"\n            )\n            return AskFeedbackResultResponse(\n                status=\"failed\",\n                error=AskError(\n                    code=\"OTHERS\",\n                    message=f\"{ask_feedback_result_request.query_id} is not found\",\n                ),\n            )\n\n        return result\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/services/chart.py",
    "content": "import logging\nfrom typing import Any, Dict, Literal, Optional\n\nfrom cachetools import TTLCache\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.utils import trace_metadata\nfrom src.web.v1.services import BaseRequest\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n# POST /v1/charts\nclass ChartRequest(BaseRequest):\n    query: str\n    sql: str\n    data: Optional[Dict[str, Any]] = None\n    remove_data_from_chart_schema: bool = True\n    custom_instruction: Optional[str] = None\n\n\nclass ChartResponse(BaseModel):\n    query_id: str\n\n\n# PATCH /v1/charts/{query_id}\nclass StopChartRequest(BaseRequest):\n    status: Literal[\"stopped\"]\n\n\nclass StopChartResponse(BaseModel):\n    query_id: str\n\n\n# GET /v1/charts/{query_id}/result\nclass ChartError(BaseModel):\n    code: Literal[\"NO_CHART\", \"OTHERS\"]\n    message: str\n\n\nclass ChartResultRequest(BaseModel):\n    query_id: str\n\n\nclass ChartResult(BaseModel):\n    reasoning: str\n    chart_type: Literal[\n        \"line\", \"bar\", \"pie\", \"grouped_bar\", \"stacked_bar\", \"area\", \"multi_line\", \"\"\n    ]  # empty string for no chart\n    chart_schema: dict\n\n\nclass ChartResultResponse(BaseModel):\n    status: Literal[\"fetching\", \"generating\", \"finished\", \"failed\", \"stopped\"]\n    response: Optional[ChartResult] = None\n    error: Optional[ChartError] = None\n    trace_id: Optional[str] = None\n\n\nclass ChartService:\n    def __init__(\n        self,\n        pipelines: Dict[str, BasicPipeline],\n        maxsize: int = 1_000_000,\n        ttl: int = 120,\n    ):\n        self._pipelines = pipelines\n        self._chart_results: Dict[str, ChartResultResponse] = TTLCache(\n            maxsize=maxsize, ttl=ttl\n        )\n\n    def _is_stopped(self, query_id: str):\n        if (\n            result := self._chart_results.get(query_id)\n        ) is not None and result.status == \"stopped\":\n            return True\n\n        return False\n\n    @observe(name=\"Generate Chart\")\n    @trace_metadata\n    async def chart(\n        self,\n        chart_request: ChartRequest,\n        **kwargs,\n    ):\n        trace_id = kwargs.get(\"trace_id\")\n        results = {\n            \"chart_result\": {},\n            \"metadata\": {\n                \"error_type\": \"\",\n                \"error_message\": \"\",\n                \"request_from\": chart_request.request_from,\n            },\n        }\n\n        try:\n            query_id = chart_request.query_id\n            execute_sql_error_message = None\n\n            if not chart_request.data:\n                self._chart_results[query_id] = ChartResultResponse(\n                    status=\"fetching\",\n                    trace_id=trace_id,\n                )\n\n                execute_sql_result = (\n                    await self._pipelines[\"sql_executor\"].run(\n                        sql=chart_request.sql,\n                        project_id=chart_request.project_id,\n                    )\n                )[\"execute_sql\"]\n\n                sql_data = execute_sql_result[\"results\"]\n                execute_sql_error_message = execute_sql_result.get(\n                    \"error_message\", None\n                )\n            else:\n                sql_data = chart_request.data\n                execute_sql_error_message = None\n\n            if execute_sql_error_message:\n                self._chart_results[query_id] = ChartResultResponse(\n                    status=\"failed\",\n                    error=ChartError(\n                        code=\"OTHERS\",\n                        message=execute_sql_error_message,\n                    ),\n                    trace_id=trace_id,\n                )\n                results[\"metadata\"][\"error_type\"] = \"OTHERS\"\n                results[\"metadata\"][\"error_message\"] = execute_sql_error_message\n                return results\n\n            self._chart_results[query_id] = ChartResultResponse(\n                status=\"generating\",\n                trace_id=trace_id,\n            )\n\n            chart_generation_result = await self._pipelines[\"chart_generation\"].run(\n                query=chart_request.query,\n                sql=chart_request.sql,\n                data=sql_data,\n                language=chart_request.configurations.language,\n                remove_data_from_chart_schema=chart_request.remove_data_from_chart_schema,\n                custom_instruction=chart_request.custom_instruction,\n            )\n            chart_result = chart_generation_result[\"post_process\"][\"results\"]\n\n            if not chart_result.get(\"chart_schema\", {}) and not chart_result.get(\n                \"reasoning\", \"\"\n            ):\n                self._chart_results[query_id] = ChartResultResponse(\n                    status=\"failed\",\n                    error=ChartError(\n                        code=\"NO_CHART\", message=\"chart generation failed\"\n                    ),\n                    trace_id=trace_id,\n                )\n                results[\"metadata\"][\"error_type\"] = \"NO_CHART\"\n                results[\"metadata\"][\"error_message\"] = \"chart generation failed\"\n            else:\n                self._chart_results[query_id] = ChartResultResponse(\n                    status=\"finished\",\n                    response=ChartResult(**chart_result),\n                    trace_id=trace_id,\n                )\n                results[\"chart_result\"] = chart_result\n\n            return results\n        except Exception as e:\n            logger.exception(f\"chart pipeline - OTHERS: {e}\")\n\n            self._chart_results[chart_request.query_id] = ChartResultResponse(\n                status=\"failed\",\n                error=ChartError(\n                    code=\"OTHERS\",\n                    message=str(e),\n                ),\n                trace_id=trace_id,\n            )\n\n            results[\"metadata\"][\"error_type\"] = \"OTHERS\"\n            results[\"metadata\"][\"error_message\"] = str(e)\n            return results\n\n    def stop_chart(\n        self,\n        stop_chart_request: StopChartRequest,\n    ):\n        self._chart_results[stop_chart_request.query_id] = ChartResultResponse(\n            status=\"stopped\",\n        )\n\n    def get_chart_result(\n        self,\n        chart_result_request: ChartResultRequest,\n    ) -> ChartResultResponse:\n        if (result := self._chart_results.get(chart_result_request.query_id)) is None:\n            logger.exception(\n                f\"chart pipeline - OTHERS: {chart_result_request.query_id} is not found\"\n            )\n            return ChartResultResponse(\n                status=\"failed\",\n                error=ChartError(\n                    code=\"OTHERS\",\n                    message=f\"{chart_result_request.query_id} is not found\",\n                ),\n            )\n\n        return result\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/services/chart_adjustment.py",
    "content": "import logging\nfrom typing import Dict, Literal, Optional\n\nfrom cachetools import TTLCache\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.utils import trace_metadata\nfrom src.web.v1.services import BaseRequest\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n# POST /v1/chart-adjustments\nclass ChartAdjustmentOption(BaseModel):\n    chart_type: Literal[\n        \"bar\", \"grouped_bar\", \"line\", \"pie\", \"stacked_bar\", \"area\", \"multi_line\"\n    ]\n    x_axis: Optional[str] = None\n    y_axis: Optional[str] = None\n    x_offset: Optional[str] = None\n    color: Optional[str] = None\n    theta: Optional[str] = None\n\n\nclass ChartAdjustmentRequest(BaseRequest):\n    query: str\n    sql: str\n    adjustment_option: ChartAdjustmentOption\n    chart_schema: dict\n\n\nclass ChartAdjustmentResponse(BaseModel):\n    query_id: str\n\n\n# PATCH /v1/chart-adjustments/{query_id}\nclass StopChartAdjustmentRequest(BaseRequest):\n    status: Literal[\"stopped\"]\n\n\nclass StopChartAdjustmentResponse(BaseModel):\n    query_id: str\n\n\n# GET /v1/chart-adjustments/{query_id}/result\nclass ChartAdjustmentError(BaseModel):\n    code: Literal[\"NO_CHART\", \"OTHERS\"]\n    message: str\n\n\nclass ChartAdjustmentResultRequest(BaseModel):\n    query_id: str\n\n\nclass ChartAdjustmentResult(BaseModel):\n    reasoning: str\n    chart_type: Literal[\n        \"line\", \"bar\", \"pie\", \"grouped_bar\", \"stacked_bar\", \"area\", \"multi_line\", \"\"\n    ]  # empty string for no chart\n    chart_schema: dict\n\n\nclass ChartAdjustmentResultResponse(BaseModel):\n    status: Literal[\n        \"understanding\", \"fetching\", \"generating\", \"finished\", \"failed\", \"stopped\"\n    ]\n    response: Optional[ChartAdjustmentResult] = None\n    error: Optional[ChartAdjustmentError] = None\n    trace_id: Optional[str] = None\n\n\nclass ChartAdjustmentService:\n    def __init__(\n        self,\n        pipelines: Dict[str, BasicPipeline],\n        maxsize: int = 1_000_000,\n        ttl: int = 120,\n    ):\n        self._pipelines = pipelines\n        self._chart_adjustment_results: Dict[\n            str, ChartAdjustmentResultResponse\n        ] = TTLCache(maxsize=maxsize, ttl=ttl)\n\n    def _is_stopped(self, query_id: str):\n        if (\n            result := self._chart_adjustment_results.get(query_id)\n        ) is not None and result.status == \"stopped\":\n            return True\n\n        return False\n\n    @observe(name=\"Adjust Chart\")\n    @trace_metadata\n    async def chart_adjustment(\n        self,\n        chart_adjustment_request: ChartAdjustmentRequest,\n        **kwargs,\n    ):\n        trace_id = kwargs.get(\"trace_id\")\n        results = {\n            \"chart_adjustment_result\": {},\n            \"metadata\": {\n                \"error_type\": \"\",\n                \"error_message\": \"\",\n                \"request_from\": chart_adjustment_request.request_from,\n            },\n        }\n\n        try:\n            query_id = chart_adjustment_request.query_id\n            execute_sql_error_message = None\n\n            self._chart_adjustment_results[query_id] = ChartAdjustmentResultResponse(\n                status=\"fetching\",\n                trace_id=trace_id,\n            )\n\n            execute_sql_result = (\n                await self._pipelines[\"sql_executor\"].run(\n                    sql=chart_adjustment_request.sql,\n                    project_id=chart_adjustment_request.project_id,\n                )\n            )[\"execute_sql\"]\n\n            sql_data = execute_sql_result[\"results\"]\n            execute_sql_error_message = execute_sql_result.get(\"error_message\", None)\n\n            if execute_sql_error_message:\n                self._chart_adjustment_results[\n                    query_id\n                ] = ChartAdjustmentResultResponse(\n                    status=\"failed\",\n                    error=ChartAdjustmentError(\n                        code=\"OTHERS\",\n                        message=execute_sql_error_message,\n                    ),\n                )\n                results[\"metadata\"][\"error_type\"] = \"OTHERS\"\n                results[\"metadata\"][\"error_message\"] = execute_sql_error_message\n                return results\n\n            self._chart_adjustment_results[query_id] = ChartAdjustmentResultResponse(\n                status=\"generating\",\n                trace_id=trace_id,\n            )\n\n            chart_adjustment_result = await self._pipelines[\"chart_adjustment\"].run(\n                query=chart_adjustment_request.query,\n                sql=chart_adjustment_request.sql,\n                adjustment_option=chart_adjustment_request.adjustment_option,\n                chart_schema=chart_adjustment_request.chart_schema,\n                data=sql_data,\n                language=chart_adjustment_request.configurations.language,\n            )\n            chart_result = chart_adjustment_result[\"post_process\"][\"results\"]\n\n            if not chart_result.get(\"chart_schema\", {}) and not chart_result.get(\n                \"reasoning\", \"\"\n            ):\n                self._chart_adjustment_results[\n                    query_id\n                ] = ChartAdjustmentResultResponse(\n                    status=\"failed\",\n                    error=ChartAdjustmentError(\n                        code=\"NO_CHART\", message=\"chart generation failed\"\n                    ),\n                    trace_id=trace_id,\n                )\n                results[\"metadata\"][\"error_type\"] = \"NO_CHART\"\n                results[\"metadata\"][\"error_message\"] = \"chart generation failed\"\n            else:\n                self._chart_adjustment_results[\n                    query_id\n                ] = ChartAdjustmentResultResponse(\n                    status=\"finished\",\n                    response=ChartAdjustmentResult(**chart_result),\n                    trace_id=trace_id,\n                )\n                results[\"chart_adjustment_result\"] = chart_result\n\n            return results\n        except Exception as e:\n            logger.exception(f\"chart adjustment pipeline - OTHERS: {e}\")\n\n            self._chart_adjustment_results[\n                chart_adjustment_request.query_id\n            ] = ChartAdjustmentResultResponse(\n                status=\"failed\",\n                error=ChartAdjustmentError(\n                    code=\"OTHERS\",\n                    message=str(e),\n                ),\n                trace_id=trace_id,\n            )\n\n            results[\"metadata\"][\"error_type\"] = \"OTHERS\"\n            results[\"metadata\"][\"error_message\"] = str(e)\n            return results\n\n    def stop_chart_adjustment(\n        self,\n        stop_chart_adjustment_request: StopChartAdjustmentRequest,\n    ):\n        self._chart_adjustment_results[\n            stop_chart_adjustment_request.query_id\n        ] = ChartAdjustmentResultResponse(\n            status=\"stopped\",\n        )\n\n    def get_chart_adjustment_result(\n        self,\n        chart_adjustment_result_request: ChartAdjustmentResultRequest,\n    ) -> ChartAdjustmentResultResponse:\n        if (\n            result := self._chart_adjustment_results.get(\n                chart_adjustment_result_request.query_id\n            )\n        ) is None:\n            logger.exception(\n                f\"chart adjustment pipeline - OTHERS: {chart_adjustment_result_request.query_id} is not found\"\n            )\n            return ChartAdjustmentResultResponse(\n                status=\"failed\",\n                error=ChartAdjustmentError(\n                    code=\"OTHERS\",\n                    message=f\"{chart_adjustment_result_request.query_id} is not found\",\n                ),\n            )\n\n        return result\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/services/instructions.py",
    "content": "import logging\nfrom typing import Dict, List, Literal, Optional\n\nfrom cachetools import TTLCache\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.pipelines.indexing.instructions import Instruction\nfrom src.utils import trace_metadata\nfrom src.web.v1.services import BaseRequest, MetadataTraceable\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nclass InstructionsService:\n    class Instruction(BaseModel):\n        id: str\n        instruction: str\n        questions: List[str]\n        # This is used to identify the default instruction needed to be retrieved for the project\n        is_default: bool = False\n        scope: Literal[\"sql\", \"answer\", \"chart\"] = \"sql\"\n\n    class Error(BaseModel):\n        code: Literal[\"OTHERS\"]\n        message: str\n\n    class Event(BaseModel, MetadataTraceable):\n        event_id: str\n        status: Literal[\"indexing\", \"deleting\", \"finished\", \"failed\"] = \"indexing\"\n        error: Optional[\"InstructionsService.Error\"] = None\n        trace_id: Optional[str] = None\n        request_from: Literal[\"ui\", \"api\"] = \"ui\"\n\n    def __init__(\n        self,\n        pipelines: Dict[str, BasicPipeline],\n        maxsize: int = 1_000_000,\n        ttl: int = 120,\n    ):\n        self._pipelines = pipelines\n        self._cache: Dict[str, self.Event] = TTLCache(maxsize=maxsize, ttl=ttl)\n\n    # todo: move it to utils for super class?\n    def _handle_exception(\n        self,\n        id: str,\n        error_message: str,\n        code: str = \"OTHERS\",\n        trace_id: Optional[str] = None,\n        request_from: Literal[\"ui\", \"api\"] = \"ui\",\n    ):\n        self._cache[id] = self.Event(\n            event_id=id,\n            status=\"failed\",\n            error=self.Error(code=code, message=error_message),\n            trace_id=trace_id,\n            request_from=request_from,\n        )\n        logger.error(error_message)\n\n    class IndexRequest(BaseRequest):\n        event_id: str\n        instructions: List[\"InstructionsService.Instruction\"]\n\n    @observe(name=\"Index Instructions\")\n    @trace_metadata\n    async def index(\n        self,\n        request: IndexRequest,\n        **kwargs,\n    ):\n        logger.info(\n            f\"Request {request.event_id}: Instructions Indexing process is running...\"\n        )\n        trace_id = kwargs.get(\"trace_id\")\n\n        try:\n            instructions = []\n            for instruction in request.instructions:\n                if instruction.is_default:\n                    instructions.append(\n                        Instruction(\n                            id=instruction.id,\n                            instruction=instruction.instruction,\n                            question=\"\",\n                            is_default=True,\n                            scope=instruction.scope,\n                        )\n                    )\n                else:\n                    for question in instruction.questions:\n                        instructions.append(\n                            Instruction(\n                                id=instruction.id,\n                                instruction=instruction.instruction,\n                                question=question,\n                                is_default=False,\n                                scope=instruction.scope,\n                            )\n                        )\n\n            await self._pipelines[\"instructions_indexing\"].run(\n                project_id=request.project_id,\n                instructions=instructions,\n            )\n\n            self._cache[request.event_id] = self.Event(\n                event_id=request.event_id,\n                status=\"finished\",\n                trace_id=trace_id,\n                request_from=request.request_from,\n            )\n\n        except Exception as e:\n            self._handle_exception(\n                request.event_id,\n                f\"An error occurred during instructions indexing: {str(e)}\",\n                trace_id=trace_id,\n                request_from=request.request_from,\n            )\n\n        return self._cache[request.event_id].with_metadata()\n\n    class DeleteRequest(BaseRequest):\n        event_id: str\n        instruction_ids: List[str]\n\n    @observe(name=\"Delete Instructions\")\n    @trace_metadata\n    async def delete(\n        self,\n        request: DeleteRequest,\n        **kwargs,\n    ):\n        logger.info(\n            f\"Request {request.event_id}: Instructions Deletion process is running...\"\n        )\n        trace_id = kwargs.get(\"trace_id\")\n\n        try:\n            instructions = [Instruction(id=id) for id in request.instruction_ids]\n            await self._pipelines[\"instructions_indexing\"].clean(\n                instructions=instructions, project_id=request.project_id\n            )\n\n            self._cache[request.event_id] = self.Event(\n                event_id=request.event_id,\n                status=\"finished\",\n                trace_id=trace_id,\n                request_from=request.request_from,\n            )\n        except Exception as e:\n            self._handle_exception(\n                request.event_id,\n                f\"Failed to delete instructions: {e}\",\n                trace_id=trace_id,\n                request_from=request.request_from,\n            )\n\n        return self._cache[request.event_id].with_metadata()\n\n    def __getitem__(self, event_id: str) -> Event:\n        response = self._cache.get(event_id)\n\n        if response is None:\n            message = f\"Instructions Event with ID '{event_id}' not found.\"\n            logger.exception(message)\n            return self.Event(\n                event_id=event_id,\n                status=\"failed\",\n                error=self.Error(code=\"OTHERS\", message=message),\n            )\n\n        return response\n\n    def __setitem__(self, event_id: str, value: Event):\n        self._cache[event_id] = value\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/services/question_recommendation.py",
    "content": "import asyncio\nimport logging\nfrom typing import Dict, Literal, Optional\n\nimport orjson\nfrom cachetools import TTLCache\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.utils import trace_metadata\nfrom src.web.v1.services import BaseRequest, MetadataTraceable\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nclass QuestionRecommendation:\n    class Error(BaseModel):\n        code: Literal[\"OTHERS\", \"MDL_PARSE_ERROR\", \"RESOURCE_NOT_FOUND\"]\n        message: str\n\n    class Event(BaseModel, MetadataTraceable):\n        event_id: str\n        status: Literal[\"generating\", \"finished\", \"failed\"] = \"generating\"\n        response: dict = {\"questions\": {}}\n        error: Optional[\"QuestionRecommendation.Error\"] = None\n        trace_id: Optional[str] = None\n        request_from: Literal[\"ui\", \"api\"] = \"ui\"\n\n    def __init__(\n        self,\n        pipelines: Dict[str, BasicPipeline],\n        allow_sql_functions_retrieval: bool = True,\n        maxsize: int = 1_000_000,\n        ttl: int = 120,\n        allow_sql_knowledge_retrieval: bool = True,\n    ):\n        self._pipelines = pipelines\n        self._cache: Dict[str, QuestionRecommendation.Event] = TTLCache(\n            maxsize=maxsize, ttl=ttl\n        )\n        self._allow_sql_functions_retrieval = allow_sql_functions_retrieval\n        self._allow_sql_knowledge_retrieval = allow_sql_knowledge_retrieval\n\n    def _handle_exception(\n        self,\n        event_id: str,\n        error_message: str,\n        code: str = \"OTHERS\",\n        trace_id: Optional[str] = None,\n        request_from: Literal[\"ui\", \"api\"] = \"ui\",\n    ):\n        self._cache[event_id] = self.Event(\n            event_id=event_id,\n            status=\"failed\",\n            error=self.Error(code=code, message=error_message),\n            trace_id=trace_id,\n            request_from=request_from,\n        )\n        logger.error(error_message)\n\n    @observe(name=\"Validate Question\")\n    async def _validate_question(\n        self,\n        candidate: dict,\n        request_id: str,\n        max_questions: int,\n        max_categories: int,\n        project_id: Optional[str] = None,\n        allow_data_preview: bool = True,\n    ):\n        async def _document_retrieval() -> tuple[list[str], bool, bool, bool]:\n            retrieval_result = await self._pipelines[\"db_schema_retrieval\"].run(\n                query=candidate[\"question\"],\n                project_id=project_id,\n            )\n            _retrieval_result = retrieval_result.get(\"construct_retrieval_results\", {})\n            documents = _retrieval_result.get(\"retrieval_results\", [])\n            table_ddls = [document.get(\"table_ddl\") for document in documents]\n            has_calculated_field = _retrieval_result.get(\"has_calculated_field\", False)\n            has_metric = _retrieval_result.get(\"has_metric\", False)\n            has_json_field = _retrieval_result.get(\"has_json_field\", False)\n            return table_ddls, has_calculated_field, has_metric, has_json_field\n\n        async def _sql_pairs_retrieval() -> list[dict]:\n            sql_pairs_result = await self._pipelines[\"sql_pairs_retrieval\"].run(\n                query=candidate[\"question\"],\n                project_id=project_id,\n            )\n            sql_samples = sql_pairs_result[\"formatted_output\"].get(\"documents\", [])\n            return sql_samples\n\n        async def _instructions_retrieval() -> list[dict]:\n            result = await self._pipelines[\"instructions_retrieval\"].run(\n                query=candidate[\"question\"],\n                project_id=project_id,\n                scope=\"sql\",\n            )\n            instructions = result[\"formatted_output\"].get(\"instructions\", [])\n            return instructions\n\n        try:\n            _document, sql_samples, instructions = await asyncio.gather(\n                _document_retrieval(),\n                _sql_pairs_retrieval(),\n                _instructions_retrieval(),\n            )\n            table_ddls, has_calculated_field, has_metric, has_json_field = _document\n\n            if self._allow_sql_functions_retrieval:\n                sql_functions = await self._pipelines[\"sql_functions_retrieval\"].run(\n                    project_id=project_id,\n                )\n            else:\n                sql_functions = []\n\n            if self._allow_sql_knowledge_retrieval:\n                sql_knowledge = await self._pipelines[\"sql_knowledge_retrieval\"].run(\n                    project_id=project_id,\n                )\n            else:\n                sql_knowledge = None\n\n            generated_sql = await self._pipelines[\"sql_generation\"].run(\n                query=candidate[\"question\"],\n                contexts=table_ddls,\n                project_id=project_id,\n                sql_samples=sql_samples,\n                instructions=instructions,\n                has_calculated_field=has_calculated_field,\n                has_metric=has_metric,\n                has_json_field=has_json_field,\n                sql_functions=sql_functions,\n                allow_data_preview=allow_data_preview,\n                sql_knowledge=sql_knowledge,\n            )\n\n            post_process = generated_sql[\"post_process\"]\n\n            if len(post_process[\"valid_generation_result\"]) == 0:\n                return post_process\n\n            valid_sql = post_process[\"valid_generation_result\"][\"sql\"]\n\n            # Partial update the resource\n            current = self._cache[request_id]\n            questions = current.response[\"questions\"]\n\n            if (\n                candidate[\"category\"] not in questions\n                and len(questions) >= max_categories\n            ):\n                # Skip to update the question dictionary if it is already full\n                return post_process\n\n            currnet_category = questions.setdefault(candidate[\"category\"], [])\n\n            if len(currnet_category) >= max_questions:\n                # Skip to update the questions for the category if it is already full\n                return post_process\n\n            currnet_category.append({**candidate, \"sql\": valid_sql})\n            return post_process\n\n        except Exception as e:\n            logger.error(f\"Request {request_id}: Error validating question: {str(e)}\")\n\n    class Request(BaseRequest):\n        event_id: str\n        mdl: str\n        previous_questions: list[str] = []\n        max_questions: int = 5\n        max_categories: int = 3\n        regenerate: bool = False\n        allow_data_preview: bool = True\n\n    async def _recommend(self, request: dict):\n        resp = await self._pipelines[\"question_recommendation\"].run(**request)\n        questions = resp.get(\"normalized\", {}).get(\"questions\", [])\n        validation_tasks = [\n            self._validate_question(\n                question,\n                request[\"event_id\"],\n                request[\"max_questions\"],\n                request[\"max_categories\"],\n                project_id=request[\"project_id\"],\n                allow_data_preview=request[\"allow_data_preview\"],\n            )\n            for question in questions\n        ]\n\n        await asyncio.gather(*validation_tasks, return_exceptions=True)\n\n    @observe(name=\"Generate Question Recommendation\")\n    @trace_metadata\n    async def recommend(self, input: Request, **kwargs) -> Event:\n        logger.info(\n            f\"Request {input.event_id}: Generate Question Recommendation pipeline is running...\"\n        )\n        trace_id = kwargs.get(\"trace_id\")\n\n        try:\n            mdl = orjson.loads(input.mdl)\n            retrieval_result = await self._pipelines[\"db_schema_retrieval\"].run(\n                tables=[model[\"name\"] for model in mdl[\"models\"]],\n                project_id=input.project_id,\n            )\n            _retrieval_result = retrieval_result.get(\"construct_retrieval_results\", {})\n            documents = _retrieval_result.get(\"retrieval_results\", [])\n            table_ddls = [document.get(\"table_ddl\") for document in documents]\n\n            request = {\n                \"contexts\": table_ddls,\n                \"previous_questions\": input.previous_questions,\n                \"language\": input.configurations.language,\n                \"max_questions\": input.max_questions,\n                \"max_categories\": input.max_categories,\n                \"project_id\": input.project_id,\n                \"event_id\": input.event_id,\n                \"allow_data_preview\": input.allow_data_preview,\n            }\n\n            await self._recommend(request)\n\n            resource = self._cache[input.event_id]\n            resource.trace_id = trace_id\n            response = resource.response\n\n            categories_count = {\n                category: input.max_questions - len(questions)\n                for category, questions in response[\"questions\"].items()\n                if len(questions) < input.max_questions\n            }\n            categories = list(categories_count.keys())\n            need_regenerate = len(categories) > 0 and input.regenerate\n\n            resource.status = \"generating\" if need_regenerate else \"finished\"\n\n            if resource.status == \"finished\":\n                return resource.with_metadata()\n\n            await self._recommend(\n                {\n                    **request,\n                    \"categories\": categories,\n                    \"max_categories\": len(categories),\n                },\n            )\n\n            self._cache[input.event_id].status = \"finished\"\n            self._cache[input.event_id].request_from = input.request_from\n\n        except orjson.JSONDecodeError as e:\n            self._handle_exception(\n                input.event_id,\n                f\"Failed to parse MDL: {str(e)}\",\n                code=\"MDL_PARSE_ERROR\",\n                trace_id=trace_id,\n                request_from=input.request_from,\n            )\n        except Exception as e:\n            self._handle_exception(\n                input.event_id,\n                f\"An error occurred during question recommendation generation: {str(e)}\",\n                trace_id=trace_id,\n                request_from=input.request_from,\n            )\n\n        return self._cache[input.event_id].with_metadata()\n\n    def __getitem__(self, id: str) -> Event:\n        response = self._cache.get(id)\n\n        if response is None:\n            message = f\"Question Recommendation Resource with ID '{id}' not found.\"\n            logger.exception(message)\n            return self.Event(\n                event_id=id,\n                status=\"failed\",\n                error=self.Error(code=\"RESOURCE_NOT_FOUND\", message=message),\n            )\n\n        return response\n\n    def __setitem__(self, id: str, value: Event):\n        self._cache[id] = value\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/services/relationship_recommendation.py",
    "content": "import logging\nfrom typing import Dict, Literal, Optional\n\nimport orjson\nfrom cachetools import TTLCache\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.utils import trace_metadata\nfrom src.web.v1.services import BaseRequest, MetadataTraceable\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nclass RelationshipRecommendation:\n    class Input(BaseRequest):\n        id: str\n        mdl: str\n\n    class Resource(BaseModel, MetadataTraceable):\n        class Error(BaseModel):\n            code: Literal[\"OTHERS\", \"MDL_PARSE_ERROR\", \"RESOURCE_NOT_FOUND\"]\n            message: str\n\n        id: str\n        status: Literal[\"generating\", \"finished\", \"failed\"] = \"generating\"\n        response: Optional[dict] = None\n        error: Optional[Error] = None\n        trace_id: Optional[str] = None\n        request_from: Literal[\"ui\", \"api\"] = \"ui\"\n\n    def __init__(\n        self,\n        pipelines: Dict[str, BasicPipeline],\n        maxsize: int = 1_000_000,\n        ttl: int = 120,\n    ):\n        self._pipelines = pipelines\n        self._cache: Dict[str, RelationshipRecommendation.Resource] = TTLCache(\n            maxsize=maxsize, ttl=ttl\n        )\n\n    def _handle_exception(\n        self,\n        input: Input,\n        error_message: str,\n        code: str = \"OTHERS\",\n        trace_id: Optional[str] = None,\n        request_from: Literal[\"ui\", \"api\"] = \"ui\",\n    ):\n        self._cache[input.id] = self.Resource(\n            id=input.id,\n            status=\"failed\",\n            error=self.Resource.Error(code=code, message=error_message),\n            trace_id=trace_id,\n            request_from=request_from,\n        )\n        logger.error(error_message)\n\n    @observe(name=\"Generate Relationship Recommendation\")\n    @trace_metadata\n    async def recommend(self, request: Input, **kwargs) -> Resource:\n        logger.info(\"Generate Relationship Recommendation pipeline is running...\")\n        trace_id = kwargs.get(\"trace_id\")\n\n        try:\n            mdl_dict = orjson.loads(request.mdl)\n\n            input = {\n                \"mdl\": mdl_dict,\n                \"language\": request.configurations.language,\n            }\n\n            resp = await self._pipelines[\"relationship_recommendation\"].run(**input)\n\n            self._cache[request.id] = self.Resource(\n                id=request.id,\n                status=\"finished\",\n                response=resp.get(\"validated\"),\n                trace_id=trace_id,\n                request_from=request.request_from,\n            )\n        except orjson.JSONDecodeError as e:\n            self._handle_exception(\n                request,\n                f\"Failed to parse MDL: {str(e)}\",\n                code=\"MDL_PARSE_ERROR\",\n                trace_id=trace_id,\n                request_from=request.request_from,\n            )\n        except Exception as e:\n            self._handle_exception(\n                request,\n                f\"An error occurred during relationship recommendation generation: {str(e)}\",\n                trace_id=trace_id,\n                request_from=request.request_from,\n            )\n\n        return self._cache[request.id].with_metadata()\n\n    def __getitem__(self, id: str) -> Resource:\n        response = self._cache.get(id)\n\n        if response is None:\n            message = f\"Relationship Recommendation Resource with ID '{id}' not found.\"\n            logger.exception(message)\n            return self.Resource(\n                id=id,\n                status=\"failed\",\n                error=self.Resource.Error(code=\"RESOURCE_NOT_FOUND\", message=message),\n            )\n\n        return response\n\n    def __setitem__(self, id: str, value: Resource):\n        self._cache[id] = value\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/services/semantics_description.py",
    "content": "import asyncio\nimport logging\nfrom typing import Dict, Literal, Optional\n\nimport orjson\nfrom cachetools import TTLCache\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.utils import trace_metadata\nfrom src.web.v1.services import BaseRequest, MetadataTraceable\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nclass SemanticsDescription:\n    class Resource(BaseModel, MetadataTraceable):\n        class Error(BaseModel):\n            code: Literal[\"OTHERS\", \"MDL_PARSE_ERROR\", \"RESOURCE_NOT_FOUND\"]\n            message: str\n\n        id: str\n        status: Literal[\"generating\", \"finished\", \"failed\"] = \"generating\"\n        response: Optional[dict] = None\n        error: Optional[Error] = None\n        trace_id: Optional[str] = None\n        request_from: Literal[\"ui\", \"api\"] = \"ui\"\n\n    def __init__(\n        self,\n        pipelines: Dict[str, BasicPipeline],\n        maxsize: int = 1_000_000,\n        ttl: int = 120,\n    ):\n        self._pipelines = pipelines\n        self._cache: Dict[str, self.Resource] = TTLCache(maxsize=maxsize, ttl=ttl)\n\n    def _handle_exception(\n        self,\n        id: str,\n        error_message: str,\n        code: str = \"OTHERS\",\n        trace_id: Optional[str] = None,\n        request_from: Literal[\"ui\", \"api\"] = \"ui\",\n    ):\n        self[id] = self.Resource(\n            id=id,\n            status=\"failed\",\n            error=self.Resource.Error(code=code, message=error_message),\n            trace_id=trace_id,\n            request_from=request_from,\n        )\n        logger.error(error_message)\n\n    class GenerateRequest(BaseRequest):\n        id: str\n        selected_models: list[str]\n        user_prompt: str\n        mdl: str\n\n    def _chunking(\n        self, mdl_dict: dict, request: GenerateRequest, chunk_size: int = 50\n    ) -> list[dict]:\n        template = {\n            \"user_prompt\": request.user_prompt,\n            \"language\": request.configurations.language,\n        }\n\n        chunks = [\n            {\n                **model,\n                \"columns\": model[\"columns\"][i : i + chunk_size],\n            }\n            for model in mdl_dict[\"models\"]\n            if model[\"name\"] in request.selected_models\n            for i in range(0, len(model[\"columns\"]), chunk_size)\n        ]\n\n        return [\n            {\n                **template,\n                \"mdl\": {\"models\": [chunk]},\n                \"selected_models\": [chunk[\"name\"]],\n            }\n            for chunk in chunks\n        ]\n\n    async def _generate_task(self, request_id: str, chunk: dict):\n        resp = await self._pipelines[\"semantics_description\"].run(**chunk)\n        output = resp.get(\"output\")\n\n        current = self[request_id]\n        current.response = current.response or {}\n\n        for key in output.keys():\n            if key not in current.response:\n                current.response[key] = output[key]\n                continue\n\n            current.response[key][\"columns\"].extend(output[key][\"columns\"])\n\n    @observe(name=\"Generate Semantics Description\")\n    @trace_metadata\n    async def generate(self, request: GenerateRequest, **kwargs) -> Resource:\n        logger.info(\"Generate Semantics Description pipeline is running...\")\n        trace_id = kwargs.get(\"trace_id\")\n\n        try:\n            mdl_dict = orjson.loads(request.mdl)\n\n            chunks = self._chunking(mdl_dict, request)\n            tasks = [self._generate_task(request.id, chunk) for chunk in chunks]\n\n            await asyncio.gather(*tasks)\n\n            self[request.id].status = \"finished\"\n            self[request.id].trace_id = trace_id\n            self[request.id].request_from = request.request_from\n        except orjson.JSONDecodeError as e:\n            self._handle_exception(\n                request.id,\n                f\"Failed to parse MDL: {str(e)}\",\n                code=\"MDL_PARSE_ERROR\",\n                trace_id=trace_id,\n                request_from=request.request_from,\n            )\n        except Exception as e:\n            self._handle_exception(\n                request.id,\n                f\"An error occurred during semantics description generation: {str(e)}\",\n                trace_id=trace_id,\n                request_from=request.request_from,\n            )\n\n        return self[request.id].with_metadata()\n\n    def __getitem__(self, id: str) -> Resource:\n        response = self._cache.get(id)\n\n        if response is None:\n            message = f\"Semantics Description Resource with ID '{id}' not found.\"\n            logger.exception(message)\n            return self.Resource(\n                id=id,\n                status=\"failed\",\n                error=self.Resource.Error(code=\"RESOURCE_NOT_FOUND\", message=message),\n            )\n\n        return response\n\n    def __setitem__(self, id: str, value: Resource):\n        self._cache[id] = value\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/services/semantics_preparation.py",
    "content": "import asyncio\nimport logging\nfrom typing import Dict, Literal, Optional\n\nfrom cachetools import TTLCache\nfrom langfuse.decorators import observe\nfrom pydantic import AliasChoices, BaseModel, Field\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.utils import trace_metadata\nfrom src.web.v1.services import BaseRequest\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n# POST /v1/semantics-preparations\nclass SemanticsPreparationRequest(BaseRequest):\n    mdl: str\n    # don't recommend to use id as a field name, but it's used in the API spec\n    # so we need to support as a choice, and will remove it in the future\n    mdl_hash: str = Field(validation_alias=AliasChoices(\"mdl_hash\", \"id\"))\n\n\nclass SemanticsPreparationResponse(BaseModel):\n    # don't recommend to use id as a field name, but it's used in the API spec\n    # so we need to support as a choice, and will remove it in the future\n    mdl_hash: str = Field(serialization_alias=\"id\")\n\n\n# GET /v1/semantics-preparations/{mdl_hash}/status\nclass SemanticsPreparationStatusRequest(BaseModel):\n    # don't recommend to use id as a field name, but it's used in the API spec\n    # so we need to support as a choice, and will remove it in the future\n    mdl_hash: str = Field(validation_alias=AliasChoices(\"mdl_hash\", \"id\"))\n\n\nclass SemanticsPreparationStatusResponse(BaseModel):\n    class SemanticsPreparationError(BaseModel):\n        code: Literal[\"OTHERS\"]\n        message: str\n\n    status: Literal[\"indexing\", \"finished\", \"failed\"]\n    error: Optional[SemanticsPreparationError] = None\n\n\nclass SemanticsPreparationService:\n    def __init__(\n        self,\n        pipelines: Dict[str, BasicPipeline],\n        maxsize: int = 1_000_000,\n        ttl: int = 120,\n    ):\n        self._pipelines = pipelines\n        self._prepare_semantics_statuses: Dict[\n            str, SemanticsPreparationStatusResponse\n        ] = TTLCache(maxsize=maxsize, ttl=ttl)\n\n    @observe(name=\"Prepare Semantics\")\n    @trace_metadata\n    async def prepare_semantics(\n        self,\n        prepare_semantics_request: SemanticsPreparationRequest,\n        **kwargs,\n    ):\n        results = {\n            \"metadata\": {\n                \"error_type\": \"\",\n                \"error_message\": \"\",\n                \"request_from\": prepare_semantics_request.request_from,\n            },\n        }\n\n        try:\n            logger.info(f\"MDL: {prepare_semantics_request.mdl}\")\n\n            input = {\n                \"mdl_str\": prepare_semantics_request.mdl,\n                \"project_id\": prepare_semantics_request.project_id,\n            }\n\n            tasks = [\n                self._pipelines[name].run(**input)\n                for name in [\n                    \"db_schema\",\n                    \"historical_question\",\n                    \"table_description\",\n                    \"sql_pairs\",\n                    \"project_meta\",\n                ]\n            ]\n\n            await asyncio.gather(*tasks)\n\n            self._prepare_semantics_statuses[\n                prepare_semantics_request.mdl_hash\n            ] = SemanticsPreparationStatusResponse(\n                status=\"finished\",\n            )\n        except Exception as e:\n            logger.exception(f\"Failed to prepare semantics: {e}\")\n\n            self._prepare_semantics_statuses[\n                prepare_semantics_request.mdl_hash\n            ] = SemanticsPreparationStatusResponse(\n                status=\"failed\",\n                error=SemanticsPreparationStatusResponse.SemanticsPreparationError(\n                    code=\"OTHERS\",\n                    message=f\"Failed to prepare semantics: {e}\",\n                ),\n            )\n\n            results[\"metadata\"][\"error_type\"] = \"INDEXING_FAILED\"\n            results[\"metadata\"][\"error_message\"] = str(e)\n\n        return results\n\n    def get_prepare_semantics_status(\n        self, prepare_semantics_status_request: SemanticsPreparationStatusRequest\n    ) -> SemanticsPreparationStatusResponse:\n        if (\n            result := self._prepare_semantics_statuses.get(\n                prepare_semantics_status_request.mdl_hash\n            )\n        ) is None:\n            logger.exception(\n                f\"id is not found for SemanticsPreparation: {prepare_semantics_status_request.mdl_hash}\"\n            )\n            return SemanticsPreparationStatusResponse(\n                status=\"failed\",\n                error=SemanticsPreparationStatusResponse.SemanticsPreparationError(\n                    code=\"OTHERS\",\n                    message=\"{prepare_semantics_status_request.id} is not found\",\n                ),\n            )\n\n        return result\n\n    @observe(name=\"Delete Semantics Documents\")\n    @trace_metadata\n    async def delete_semantics(self, project_id: str, **kwargs):\n        logger.info(f\"Project ID: {project_id}, Deleting semantics documents...\")\n\n        tasks = [\n            self._pipelines[name].clean(project_id=project_id)\n            for name in [\n                \"db_schema\",\n                \"historical_question\",\n                \"table_description\",\n                \"project_meta\",\n            ]\n        ] + [\n            self._pipelines[name].clean(\n                project_id=project_id,\n                delete_all=True,\n            )\n            for name in [\"sql_pairs\", \"instructions\"]\n        ]\n\n        await asyncio.gather(*tasks)\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/services/sql_answer.py",
    "content": "import asyncio\nimport logging\nfrom typing import Dict, Literal, Optional\n\nfrom cachetools import TTLCache\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.utils import trace_metadata\nfrom src.web.v1.services import BaseRequest, SSEEvent\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n# POST /v1/sql-answers\nclass SqlAnswerRequest(BaseRequest):\n    query: str\n    sql: str\n    sql_data: Dict\n    custom_instruction: Optional[str] = None\n\n\nclass SqlAnswerResponse(BaseModel):\n    query_id: str\n\n\n# GET /v1/sql-answers/{query_id}\nclass SqlAnswerResultRequest(BaseModel):\n    query_id: str\n\n\nclass SqlAnswerResultResponse(BaseModel):\n    class SqlAnswerError(BaseModel):\n        code: Literal[\"OTHERS\"]\n        message: str\n\n    status: Literal[\"preprocessing\", \"succeeded\", \"failed\"]\n    num_rows_used_in_llm: Optional[int] = None\n    error: Optional[SqlAnswerError] = None\n    trace_id: Optional[str] = None\n\n\nclass SqlAnswerService:\n    def __init__(\n        self,\n        pipelines: Dict[str, BasicPipeline],\n        maxsize: int = 1_000_000,\n        ttl: int = 120,\n    ):\n        self._pipelines = pipelines\n        self._sql_answer_results: Dict[str, SqlAnswerResultResponse] = TTLCache(\n            maxsize=maxsize, ttl=ttl\n        )\n\n    @observe(name=\"SQL Answer\")\n    @trace_metadata\n    async def sql_answer(\n        self,\n        sql_answer_request: SqlAnswerRequest,\n        **kwargs,\n    ):\n        trace_id = kwargs.get(\"trace_id\")\n        results = {\n            \"metadata\": {\n                \"error\": {\n                    \"type\": \"\",\n                    \"message\": \"\",\n                },\n                \"request_from\": sql_answer_request.request_from,\n            },\n        }\n\n        try:\n            query_id = sql_answer_request.query_id\n\n            self._sql_answer_results[query_id] = SqlAnswerResultResponse(\n                status=\"preprocessing\",\n                trace_id=trace_id,\n            )\n\n            preprocessed_sql_data = self._pipelines[\"preprocess_sql_data\"].run(\n                sql_data=sql_answer_request.sql_data,\n            )[\"preprocess\"]\n\n            if preprocessed_sql_data.get(\"num_rows_used_in_llm\") == 0:\n                results[\"metadata\"][\"error_type\"] = \"NO_DATA\"\n                results[\"metadata\"][\"error_message\"] = \"No data to answer\"\n\n            self._sql_answer_results[query_id] = SqlAnswerResultResponse(\n                status=\"succeeded\",\n                num_rows_used_in_llm=preprocessed_sql_data.get(\"num_rows_used_in_llm\"),\n                trace_id=trace_id,\n            )\n\n            asyncio.create_task(\n                self._pipelines[\"sql_answer\"].run(\n                    query=sql_answer_request.query,\n                    sql=sql_answer_request.sql,\n                    sql_data=preprocessed_sql_data.get(\"sql_data\", {}),\n                    language=sql_answer_request.configurations.language,\n                    current_time=sql_answer_request.configurations.show_current_time(),\n                    query_id=query_id,\n                    custom_instruction=sql_answer_request.custom_instruction,\n                )\n            )\n\n            return results\n        except Exception as e:\n            logger.exception(f\"sql answer pipeline - OTHERS: {e}\")\n\n            self._sql_answer_results[\n                sql_answer_request.query_id\n            ] = SqlAnswerResultResponse(\n                status=\"failed\",\n                error=SqlAnswerResultResponse.SqlAnswerError(\n                    code=\"OTHERS\",\n                    message=str(e),\n                ),\n                trace_id=trace_id,\n            )\n\n            results[\"metadata\"][\"error_type\"] = \"OTHERS\"\n            results[\"metadata\"][\"error_message\"] = str(e)\n            return results\n\n    def get_sql_answer_result(\n        self,\n        sql_answer_result_request: SqlAnswerResultRequest,\n    ) -> SqlAnswerResultResponse:\n        if (\n            result := self._sql_answer_results.get(sql_answer_result_request.query_id)\n        ) is None:\n            logger.exception(\n                f\"sql answer pipeline - OTHERS: {sql_answer_result_request.query_id} is not found\"\n            )\n            return SqlAnswerResultResponse(\n                status=\"failed\",\n                error=SqlAnswerResultResponse.SqlAnswerError(\n                    code=\"OTHERS\",\n                    message=f\"{sql_answer_result_request.query_id} is not found\",\n                ),\n            )\n\n        return result\n\n    async def get_sql_answer_streaming_result(\n        self,\n        query_id: str,\n    ):\n        if (\n            self._sql_answer_results.get(query_id)\n            and self._sql_answer_results.get(query_id).status == \"succeeded\"\n        ):\n            async for chunk in self._pipelines[\"sql_answer\"].get_streaming_results(\n                query_id\n            ):\n                event = SSEEvent(\n                    data=SSEEvent.SSEEventMessage(message=chunk),\n                )\n                yield event.serialize()\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/services/sql_corrections.py",
    "content": "import logging\nfrom typing import List, Literal, Optional\n\nfrom cachetools import TTLCache\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.utils import trace_metadata\nfrom src.web.v1.services import BaseRequest, MetadataTraceable\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nclass SqlCorrectionService:\n    class Error(BaseModel):\n        code: Literal[\"OTHERS\"]\n        message: str\n\n    class Event(BaseModel, MetadataTraceable):\n        event_id: str\n        status: Literal[\"correcting\", \"finished\", \"failed\"] = \"correcting\"\n        response: Optional[str] = None\n        error: Optional[\"SqlCorrectionService.Error\"] = None\n        invalid_sql: Optional[str] = None\n        trace_id: Optional[str] = None\n        request_from: Literal[\"ui\", \"api\"] = \"ui\"\n\n    def __init__(\n        self,\n        pipelines: dict[str, BasicPipeline],\n        maxsize: int = 1_000_000,\n        ttl: int = 120,\n        allow_sql_knowledge_retrieval: bool = True,\n    ):\n        self._pipelines = pipelines\n        self._cache: dict[str, self.Event] = TTLCache(maxsize=maxsize, ttl=ttl)\n        self._allow_sql_knowledge_retrieval = allow_sql_knowledge_retrieval\n\n    def _handle_exception(\n        self,\n        event_id: str,\n        error_message: str,\n        code: str = \"OTHERS\",\n        invalid_sql: Optional[str] = None,\n        trace_id: Optional[str] = None,\n        request_from: Literal[\"ui\", \"api\"] = \"ui\",\n    ):\n        self._cache[event_id] = self.Event(\n            event_id=event_id,\n            status=\"failed\",\n            error=self.Error(code=code, message=error_message),\n            trace_id=trace_id,\n            invalid_sql=invalid_sql,\n            request_from=request_from,\n        )\n        logger.error(error_message)\n\n    class CorrectionRequest(BaseRequest):\n        event_id: str\n        sql: str\n        error: str\n        retrieved_tables: Optional[List[str]] = None\n        use_dry_plan: bool = False\n        allow_dry_plan_fallback: bool = True\n\n    @observe(name=\"SQL Correction\")\n    @trace_metadata\n    async def correct(\n        self,\n        request: CorrectionRequest,\n        **kwargs,\n    ):\n        logger.info(f\"Request {request.event_id}: SQL Correction process is running...\")\n        trace_id = kwargs.get(\"trace_id\")\n        event_id = request.event_id\n        sql = request.sql\n        error = request.error\n        project_id = request.project_id\n        retrieved_tables = request.retrieved_tables\n        use_dry_plan = request.use_dry_plan\n        allow_dry_plan_fallback = request.allow_dry_plan_fallback\n        sql_knowledge = None\n\n        try:\n            _invalid = {\n                \"sql\": sql,\n                \"error\": error,\n            }\n\n            if not retrieved_tables:\n                retrieved_tables = (\n                    await self._pipelines[\"sql_tables_extraction\"].run(\n                        sql=sql,\n                    )\n                )[\"post_process\"]\n\n            if self._allow_sql_knowledge_retrieval:\n                sql_knowledge = await self._pipelines[\"sql_knowledge_retrieval\"].run(\n                    project_id=project_id,\n                )\n\n            documents = (\n                (\n                    await self._pipelines[\"db_schema_retrieval\"].run(\n                        project_id=project_id,\n                        tables=retrieved_tables,\n                    )\n                )\n                .get(\"construct_retrieval_results\", {})\n                .get(\"retrieval_results\", [])\n            )\n            table_ddls = [document.get(\"table_ddl\") for document in documents]\n\n            res = await self._pipelines[\"sql_correction\"].run(\n                contexts=table_ddls,\n                invalid_generation_result=_invalid,\n                project_id=project_id,\n                use_dry_plan=use_dry_plan,\n                allow_dry_plan_fallback=allow_dry_plan_fallback,\n                sql_knowledge=sql_knowledge,\n            )\n\n            post_process = res[\"post_process\"]\n            valid = post_process[\"valid_generation_result\"]\n            invalid = post_process[\"invalid_generation_result\"]\n\n            if not valid:\n                error_message = invalid[\"error\"]\n                self._handle_exception(\n                    event_id,\n                    f\"An error occurred during SQL correction: {error_message}\",\n                    trace_id=trace_id,\n                    invalid_sql=invalid[\"sql\"],\n                    request_from=request.request_from,\n                )\n            else:\n                corrected = valid[\"sql\"]\n                self._cache[event_id] = self.Event(\n                    event_id=event_id,\n                    status=\"finished\",\n                    trace_id=trace_id,\n                    response=corrected,\n                    request_from=request.request_from,\n                )\n\n        except Exception as e:\n            self._handle_exception(\n                event_id,\n                f\"An error occurred during SQL correction: {str(e)}\",\n                trace_id=trace_id,\n                request_from=request.request_from,\n            )\n\n        return self._cache[event_id].with_metadata()\n\n    def __getitem__(self, event_id: str) -> Event:\n        response = self._cache.get(event_id)\n\n        if response is None:\n            message = f\"SQL Correction Event with ID '{event_id}' not found.\"\n            logger.exception(message)\n            return self.Event(\n                event_id=event_id,\n                status=\"failed\",\n                error=self.Error(code=\"OTHERS\", message=message),\n            )\n\n        return response\n\n    def __setitem__(self, event_id: str, value: Event):\n        self._cache[event_id] = value\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/services/sql_pairs.py",
    "content": "import logging\nfrom typing import Dict, List, Literal, Optional\n\nfrom cachetools import TTLCache\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.pipelines.indexing.sql_pairs import SqlPair\nfrom src.utils import trace_metadata\nfrom src.web.v1.services import BaseRequest, MetadataTraceable\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nclass SqlPairsService:\n    class Event(BaseModel, MetadataTraceable):\n        class Error(BaseModel):\n            code: Literal[\"OTHERS\"]\n            message: str\n\n        id: str\n        status: Literal[\"indexing\", \"deleting\", \"finished\", \"failed\"] = \"indexing\"\n        error: Optional[Error] = None\n        trace_id: Optional[str] = None\n        request_from: Literal[\"ui\", \"api\"] = \"ui\"\n\n    def __init__(\n        self,\n        pipelines: Dict[str, BasicPipeline],\n        maxsize: int = 1_000_000,\n        ttl: int = 120,\n    ):\n        self._pipelines = pipelines\n        self._cache: Dict[str, self.Event] = TTLCache(maxsize=maxsize, ttl=ttl)\n\n    def _handle_exception(\n        self,\n        id: str,\n        error_message: str,\n        code: str = \"OTHERS\",\n        trace_id: Optional[str] = None,\n        request_from: Literal[\"ui\", \"api\"] = \"ui\",\n    ):\n        self._cache[id] = self.Event(\n            id=id,\n            status=\"failed\",\n            error=self.Event.Error(code=code, message=error_message),\n            trace_id=trace_id,\n            request_from=request_from,\n        )\n        logger.error(error_message)\n\n    class IndexRequest(BaseRequest):\n        id: str\n        sql_pairs: List[SqlPair]\n\n    @observe(name=\"Prepare SQL Pairs\")\n    @trace_metadata\n    async def index(\n        self,\n        request: IndexRequest,\n        **kwargs,\n    ):\n        logger.info(f\"Request {request.id}: SQL Pairs Indexing process is running...\")\n        trace_id = kwargs.get(\"trace_id\")\n\n        try:\n            input = {\n                \"mdl_str\": '{\"models\": [{\"properties\": {\"boilerplate\": \"sql_pairs\"}}]}',\n                \"project_id\": request.project_id,\n                \"external_pairs\": {\n                    \"sql_pairs\": [\n                        sql_pair.model_dump() for sql_pair in request.sql_pairs\n                    ],\n                },\n            }\n            await self._pipelines[\"sql_pairs\"].run(**input)\n\n            self._cache[request.id] = self.Event(\n                id=request.id,\n                status=\"finished\",\n                trace_id=trace_id,\n                request_from=request.request_from,\n            )\n\n        except Exception as e:\n            self._handle_exception(\n                request.id,\n                f\"An error occurred during SQL pairs indexing: {str(e)}\",\n                trace_id=trace_id,\n                request_from=request.request_from,\n            )\n\n        return self._cache[request.id].with_metadata()\n\n    class DeleteRequest(BaseRequest):\n        id: str\n        sql_pair_ids: List[str]\n\n    @observe(name=\"Delete SQL Pairs\")\n    @trace_metadata\n    async def delete(\n        self,\n        request: DeleteRequest,\n        **kwargs,\n    ):\n        logger.info(f\"Request {request.id}: SQL Pairs Deletion process is running...\")\n\n        try:\n            sql_pairs = [SqlPair(id=id) for id in request.sql_pair_ids]\n            await self._pipelines[\"sql_pairs\"].clean(\n                sql_pairs=sql_pairs, project_id=request.project_id\n            )\n\n            self._cache[request.id] = self.Event(\n                id=request.id,\n                status=\"finished\",\n                request_from=request.request_from,\n            )\n        except Exception as e:\n            self._handle_exception(\n                request.id,\n                f\"Failed to delete SQL pairs: {e}\",\n                request_from=request.request_from,\n            )\n\n        return self._cache[request.id].with_metadata()\n\n    def __getitem__(self, id: str) -> Event:\n        response = self._cache.get(id)\n\n        if response is None:\n            message = f\"SQL Pairs Event with ID '{id}' not found.\"\n            logger.exception(message)\n            return self.Event(\n                id=id,\n                status=\"failed\",\n                error=self.Event.Error(code=\"OTHERS\", message=message),\n            )\n\n        return response\n\n    def __setitem__(self, id: str, value: Event):\n        self._cache[id] = value\n"
  },
  {
    "path": "wren-ai-service/src/web/v1/services/sql_question.py",
    "content": "import asyncio\nimport logging\nfrom typing import Dict, Literal, Optional\n\nfrom cachetools import TTLCache\nfrom langfuse.decorators import observe\nfrom pydantic import BaseModel\n\nfrom src.core.pipeline import BasicPipeline\nfrom src.utils import trace_metadata\nfrom src.web.v1.services import BaseRequest\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\n# POST /v1/sql-questions\nclass SqlQuestionRequest(BaseRequest):\n    sqls: list[str]\n\n\nclass SqlQuestionResponse(BaseModel):\n    query_id: str\n\n\n# GET /v1/sql-questions/{query_id}\nclass SqlQuestionResultRequest(BaseModel):\n    query_id: str\n\n\nclass SqlQuestionResultResponse(BaseModel):\n    class SqlQuestionError(BaseModel):\n        code: Literal[\"OTHERS\"]\n        message: str\n\n    status: Literal[\"generating\", \"succeeded\", \"failed\"]\n    error: Optional[SqlQuestionError] = None\n    questions: Optional[list[str]] = None\n    trace_id: Optional[str] = None\n\n\nclass SqlQuestionService:\n    def __init__(\n        self,\n        pipelines: Dict[str, BasicPipeline],\n        maxsize: int = 1_000_000,\n        ttl: int = 120,\n    ):\n        self._pipelines = pipelines\n        self._sql_question_results: Dict[str, SqlQuestionResultResponse] = TTLCache(\n            maxsize=maxsize, ttl=ttl\n        )\n\n    @observe(name=\"SQL Question\")\n    @trace_metadata\n    async def sql_question(\n        self,\n        sql_question_request: SqlQuestionRequest,\n        **kwargs,\n    ):\n        trace_id = kwargs.get(\"trace_id\")\n        results = {\n            \"sql_question_result\": {},\n            \"metadata\": {\n                \"error_type\": \"\",\n                \"error_message\": \"\",\n            },\n            \"request_from\": sql_question_request.request_from,\n        }\n\n        try:\n            query_id = sql_question_request.query_id\n\n            self._sql_question_results[query_id] = SqlQuestionResultResponse(\n                status=\"generating\",\n                trace_id=trace_id,\n            )\n\n            tasks = [\n                self._pipelines[\"sql_question_generation\"].run(\n                    sql=sql,\n                    configuration=sql_question_request.configurations,\n                )\n                for sql in sql_question_request.sqls\n            ]\n            sql_questions_results = await asyncio.gather(*tasks)\n            sql_questions = [res[\"post_process\"] for res in sql_questions_results]\n\n            self._sql_question_results[query_id] = SqlQuestionResultResponse(\n                status=\"succeeded\",\n                questions=sql_questions,\n                trace_id=trace_id,\n            )\n\n            results[\"sql_question_result\"] = sql_questions\n            return results\n        except Exception as e:\n            logger.exception(f\"sql question pipeline - OTHERS: {e}\")\n\n            self._sql_question_results[\n                sql_question_request.query_id\n            ] = SqlQuestionResultResponse(\n                status=\"failed\",\n                error=SqlQuestionResultResponse.SqlQuestionError(\n                    code=\"OTHERS\",\n                    message=str(e),\n                ),\n                trace_id=trace_id,\n            )\n\n            results[\"metadata\"][\"error_type\"] = \"OTHERS\"\n            results[\"metadata\"][\"error_message\"] = str(e)\n            return results\n\n    def get_sql_question_result(\n        self,\n        sql_question_result_request: SqlQuestionResultRequest,\n    ) -> SqlQuestionResultResponse:\n        if (\n            result := self._sql_question_results.get(\n                sql_question_result_request.query_id\n            )\n        ) is None:\n            logger.exception(\n                f\"sql question pipeline - OTHERS: {sql_question_result_request.query_id} is not found\"\n            )\n            return SqlQuestionResultResponse(\n                status=\"failed\",\n                error=SqlQuestionResultResponse.SqlQuestionError(\n                    code=\"OTHERS\",\n                    message=f\"{sql_question_result_request.query_id} is not found\",\n                ),\n            )\n\n        return result\n"
  },
  {
    "path": "wren-ai-service/tests/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/tests/data/book_2_mdl.json",
    "content": "{\n  \"catalog\": \"wrenai\",\n  \"schema\": \"spider\",\n  \"models\": [\n    {\n      \"name\": \"book\",\n      \"properties\": {},\n      \"refSql\": \"select * from \\\"wrenai\\\".spider.\\\"book_2-book\\\"\",\n      \"columns\": [\n        {\n          \"name\": \"Book_ID\",\n          \"type\": \"INTEGER\",\n          \"notNull\": false,\n          \"isCalculated\": false,\n          \"expression\": \"Book_ID\",\n          \"properties\": {}\n        },\n        {\n          \"name\": \"Title\",\n          \"type\": \"VARCHAR\",\n          \"notNull\": false,\n          \"isCalculated\": false,\n          \"expression\": \"Title\",\n          \"properties\": {}\n        },\n        {\n          \"name\": \"Issues\",\n          \"type\": \"REAL\",\n          \"notNull\": false,\n          \"isCalculated\": false,\n          \"expression\": \"Issues\",\n          \"properties\": {}\n        },\n        {\n          \"name\": \"Writer\",\n          \"type\": \"VARCHAR\",\n          \"notNull\": false,\n          \"isCalculated\": false,\n          \"expression\": \"Writer\",\n          \"properties\": {}\n        }\n      ],\n      \"primaryKey\": \"\"\n    },\n    {\n      \"name\": \"publication\",\n      \"properties\": {},\n      \"refSql\": \"select * from \\\"wrenai\\\".spider.\\\"book_2-publication\\\"\",\n      \"columns\": [\n        {\n          \"name\": \"Publication_ID\",\n          \"type\": \"INTEGER\",\n          \"notNull\": false,\n          \"isCalculated\": false,\n          \"expression\": \"Publication_ID\",\n          \"properties\": {}\n        },\n        {\n          \"name\": \"Book_ID\",\n          \"type\": \"INTEGER\",\n          \"notNull\": false,\n          \"isCalculated\": false,\n          \"expression\": \"Book_ID\",\n          \"properties\": {}\n        },\n        {\n          \"name\": \"Publisher\",\n          \"type\": \"VARCHAR\",\n          \"notNull\": false,\n          \"isCalculated\": false,\n          \"expression\": \"Publisher\",\n          \"properties\": {}\n        },\n        {\n          \"name\": \"Publication_Date\",\n          \"type\": \"VARCHAR\",\n          \"notNull\": false,\n          \"isCalculated\": false,\n          \"expression\": \"Publication_Date\",\n          \"properties\": {}\n        },\n        {\n          \"name\": \"Price\",\n          \"type\": \"REAL\",\n          \"notNull\": false,\n          \"isCalculated\": false,\n          \"expression\": \"Price\",\n          \"properties\": {}\n        }\n      ],\n      \"primaryKey\": \"\"\n    }\n  ],\n  \"relationships\": [],\n  \"metrics\": [],\n  \"cumulativeMetrics\": [],\n  \"enumDefinitions\": [],\n  \"views\": [\n    {\n      \"name\": \"book\",\n      \"statement\": \"SELECT * FROM book\",\n      \"properties\": {\n        \"question\": \"How many books are there?\",\n        \"summary\": \"Retrieve the number of books\",\n        \"viewId\": \"fake-id-1\"\n      }\n    }\n  ],\n  \"macros\": []\n}\n"
  },
  {
    "path": "wren-ai-service/tests/data/config.test.yaml",
    "content": "type: llm\nprovider: litellm_llm\nmodels:\n- model: gpt-4.1-nano-2025-04-14\n  alias: default\n  kwargs:\n    max_tokens: 4096\n    n: 1\n    seed: 0\n    temperature: 0\n  timeout: 120\n\n---\ntype: embedder\nprovider: litellm_embedder\nmodels:\n- model: text-embedding-3-large\n  alias: default\n  timeout: 120\n\n---\ntype: engine\nprovider: wren_ui\nendpoint: http://localhost:3000\n\n---\ntype: document_store\nprovider: qdrant\nlocation: http://localhost:6333\nembedding_model_dim: 3072\ntimeout: 120\n\n---\ntype: pipeline\npipes:\n  - name: indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_correction\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: followup_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_answer\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: sql_explanation\n    llm: litellm_llm.default\n  - name: sql_regeneration\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: semantics_description\n    llm: litellm_llm.default\n  - name: relationship_recommendation\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: user_guide_assistance\n    llm: litellm_llm.default\n  - name: data_assistance\n    llm: litellm_llm.default\n    \n---\nsettings:\n  host: 127.0.0.1\n  port: 5556\n  column_indexing_batch_size: 50\n  doc_endpoint: https://docs.getwren.ai\n  is_oss: true\n  table_retrieval_size: 10\n  table_column_retrieval_size: 1000\n  query_cache_maxsize: 1000\n  query_cache_ttl: 3600\n  langfuse_host: https://cloud.langfuse.com\n  langfuse_enable: false\n  logging_level: INFO\n  development: false\n"
  },
  {
    "path": "wren-ai-service/tests/data/mock_pyproject.toml",
    "content": "[tool.poetry]\nversion = \"0.8.0-mock\"\n"
  },
  {
    "path": "wren-ai-service/tests/data/pairs.json",
    "content": "{\n    \"test\": [\n        {\n            \"id\": \"1\",\n            \"question\": \"What is the book?\",\n            \"sql\": \"SELECT * FROM book\"\n        },\n        {\n            \"id\": \"2\",\n            \"question\": \"What is the author?\",\n            \"sql\": \"SELECT * FROM author\"\n        }\n    ]\n}"
  },
  {
    "path": "wren-ai-service/tests/locust/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/tests/locust/config_users.json",
    "content": "[\n    {\n        \"user_class_name\": \"IndexingUser\",\n        \"fixed_count\": 0\n    },\n    {\n        \"user_class_name\": \"AskUser\",\n        \"fixed_count\": 0\n    },\n    {\n        \"user_class_name\": \"AskDetailsUser\",\n        \"fixed_count\": 0\n    },\n    {\n        \"user_class_name\": \"DummyUser\",\n        \"fixed_count\": 0\n    },\n    {\n        \"user_class_name\": \"DummyAskUser\",\n        \"fixed_count\": 100\n    }\n]"
  },
  {
    "path": "wren-ai-service/tests/locust/locust.conf",
    "content": "locustfile = tests/locust/locustfile.py\nheadless = true\nhost = http://localhost:5556\nusers = 100\nspawn-rate = 10\nrun-time = 60s\nconfig-users = tests/locust/config_users.json"
  },
  {
    "path": "wren-ai-service/tests/locust/locust_script.py",
    "content": "import json\nimport os\nimport time\nfrom pathlib import Path\n\nfrom src.utils import load_env_vars\n\nload_env_vars()\nfilename = f\"locust_report_{time.strftime(\"%Y%m%d_%H%M%S\")}\"\n\nif not Path(\"./outputs/locust\").exists():\n    Path(\"./outputs/locust\").mkdir(parents=True, exist_ok=True)\n\nos.system(\n    f\"\"\"\n    poetry run locust \\\n    --config tests/locust/locust.conf \\\n    --logfile outputs/locust/{filename}.log \\\n    --html outputs/locust/{filename}.html \\\n    --json > outputs/locust/{filename}.json\n    \"\"\"\n)\n\nwith open(f\"./outputs/locust/{filename}.json\", \"r\") as f:\n    test_results = json.load(f)\n\nformatted = {\n    \"llm provider\": os.getenv(\"LLM_PROVIDER\"),\n    \"generation model\": os.getenv(\"GENERATION_MODEL\"),\n    \"embedding model\": os.getenv(\"EMBEDDING_MODEL\"),\n    \"locustfile\": \"tests/locust/locustfile.py\",\n    \"test results\": test_results,\n}\nwith open(f\"./outputs/locust/{filename}.json\", \"w\") as f:\n    json.dump(formatted, f, indent=2)\n\nprint(f\"get the test results in {filename}.json and {filename}.html\")\n"
  },
  {
    "path": "wren-ai-service/tests/locust/locustfile.py",
    "content": "import json\nimport logging\nimport os\nimport time\nimport uuid\n\nimport orjson\nimport requests\nfrom locust import FastHttpUser, events, task\n\nfrom src.utils import load_env_vars\n\ndeployment_id = str(uuid.uuid4())\nmdl_str = \"\"\nfinished_ask_query = []\nsuccessful_ask_query = []\nfinished_ask_details_query = []\nsuccessful_ask_details_query = []\n\nload_env_vars()\n\nwith open(f\"tests/data/{os.getenv(\"DATASET_NAME\")}_mdl.json\", \"r\") as f:\n    mdl_str = orjson.dumps(json.load(f)).decode(\"utf-8\")\n\n\n@events.test_start.add_listener\ndef on_test_start(environment, **kwargs):\n    logging.info(f\"Using dataset: {os.getenv(\"DATASET_NAME\")}\")\n\n    requests.post(\n        f\"{environment.host}/v1/semantics-preparations\",\n        json={\n            \"mdl\": mdl_str,\n            \"id\": deployment_id,\n        },\n    )\n\n    status = \"indexing\"\n    while status == \"indexing\":\n        response = requests.get(\n            f\"{environment.host}/v1/semantics-preparations/{deployment_id}/status\",\n        )\n        status = response.json()[\"status\"]\n\n    logging.info(f\"Indexing status: {status}\")\n    logging.info(\"Indexing document completed. Start load testing.\")\n\n\n@events.test_stop.add_listener\ndef on_test_stop(environment, **kwargs):\n    logging.info(f\"Total finished ask queries: {len(finished_ask_query)}\")\n    logging.info(f\"Total successful ask queries: {len(successful_ask_query)}\")\n\n\nclass IndexingUser(FastHttpUser):\n    @task\n    def indexing(self):\n        semantics_preperation_id = str(uuid.uuid4())\n\n        with self.client.post(\n            url=\"/v1/semantics-preparations\",\n            json={\n                \"mdl\": mdl_str,\n                \"id\": semantics_preperation_id,\n            },\n            catch_response=True,\n        ) as response:\n            try:\n                assert response.status_code == 200\n                assert (\n                    json.loads(response.content.decode(\"utf-8\"))[\"id\"]\n                    == semantics_preperation_id\n                )\n            except AssertionError:\n                response.failure(response.content.decode(\"utf-8\"))\n\n        status = \"indexing\"\n        while status == \"indexing\":\n            with self.client.get(\n                url=f\"/v1/semantics-preparations/{semantics_preperation_id}/status\",\n                catch_response=True,\n            ) as response:\n                try:\n                    assert response.status_code == 200\n                    status = json.loads(response.content.decode(\"utf-8\"))[\"status\"]\n                    assert status in [\"indexing\", \"finished\"]\n                    response.success()\n                    time.sleep(1.0)\n                except AssertionError:\n                    response.failure(response.content.decode(\"utf-8\"))\n\n\nclass AskUser(FastHttpUser):\n    @task\n    def ask(self):\n        with self.client.post(\n            url=\"/v1/asks\",\n            json={\n                \"query\": \"How many books?\",\n                \"id\": deployment_id,\n            },\n            catch_response=True,\n        ) as response:\n            query_id = json.loads(response.content.decode(\"utf-8\"))[\"query_id\"]\n            try:\n                assert response.status_code == 200\n                assert query_id != \"\"\n                response.success()\n            except AssertionError:\n                response.failure(response.content.decode(\"utf-8\"))\n\n        status = \"understanding\"\n\n        while status in [\"understanding\", \"searching\", \"generating\"]:\n            with self.client.get(\n                url=f\"/v1/asks/{query_id}/result\",\n                catch_response=True,\n            ) as response:\n                try:\n                    assert response.status_code == 200\n                    status = json.loads(response.content.decode(\"utf-8\"))[\"status\"]\n                    assert status in [\n                        \"understanding\",\n                        \"searching\",\n                        \"generating\",\n                        \"finished\",\n                    ]\n                    response.success()\n                    if status == \"finished\":\n                        finished_ask_query.append(query_id)\n                        successful_ask_query.append(response.content.decode(\"utf-8\"))\n                    else:\n                        time.sleep(1.0)\n                except AssertionError:\n                    finished_ask_query.append(query_id)\n                    response.failure(response.content.decode(\"utf-8\"))\n\n\nclass DummyUser(FastHttpUser):\n    @task\n    def dummy(self):\n        self.client.get(url=\"/dev/dummy\")\n\n\nclass DummyAskUser(FastHttpUser):\n    @task\n    def ask(self):\n        with self.client.post(\n            url=\"/dev/dummy-asks\",\n            json={\n                \"query\": \"How many books?\",\n                \"id\": deployment_id,\n            },\n            catch_response=True,\n        ) as response:\n            query_id = json.loads(response.content.decode(\"utf-8\"))[\"query_id\"]\n            try:\n                assert response.status_code == 200\n                assert query_id != \"\"\n                response.success()\n            except AssertionError:\n                response.failure(response.content.decode(\"utf-8\"))\n\n        status = \"understanding\"\n\n        while status in [\"understanding\", \"searching\", \"generating\"]:\n            with self.client.get(\n                url=f\"/dev/dummy-asks/{query_id}/result\",\n                catch_response=True,\n            ) as response:\n                try:\n                    assert response.status_code == 200\n                    status = json.loads(response.content.decode(\"utf-8\"))[\"status\"]\n                    assert status in [\n                        \"understanding\",\n                        \"searching\",\n                        \"generating\",\n                        \"finished\",\n                    ]\n                    response.success()\n                    if status == \"finished\":\n                        finished_ask_query.append(query_id)\n                        successful_ask_query.append(response.content.decode(\"utf-8\"))\n                    else:\n                        time.sleep(1.0)\n                except AssertionError:\n                    finished_ask_query.append(query_id)\n                    response.failure(response.content.decode(\"utf-8\"))\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/tests/pytest/eval/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/tests/pytest/eval/test_metrics.py",
    "content": "import sys\nfrom pathlib import Path\n\nimport pandas as pd\nimport pytest\nfrom aioresponses import aioresponses\nfrom deepeval.test_case import LLMTestCase\n\nsys.path.append(f\"{Path().parent.resolve()}\")\nfrom eval.metrics import (\n    AccuracyMetric,\n    AnswerRelevancyMetric,\n    ContextualPrecisionMetric,\n    ContextualRecallMetric,\n    ContextualRelevancyMetric,\n    FaithfulnessMetric,\n)\n\n\n@pytest.fixture\ndef engine_config():\n    return {\n        \"mdl_json\": {},\n        \"api_endpoint\": \"http://example.com/endpoint\",\n        \"timeout\": 10,\n    }\n\n\n@pytest.fixture\ndef test_case():\n    return LLMTestCase(\n        input=\"This is a test case\",\n        actual_output=\"select foo, boo from t\",\n        expected_output=\"select foo, boo from t\",\n        context=[\"t.foo\", \"t.boo\"],\n        retrieval_context=[\"t.foo\", \"t.boo\"],\n        additional_metadata={},\n    )\n\n\n@pytest.fixture\ndef mocker():\n    with aioresponses() as m:\n        yield m\n\n\ndef _success_analysis_sql(m, engine_config, repeat=1):\n    for _ in range(repeat):\n        m.get(\n            f\"{engine_config['api_endpoint']}/v2/analysis/sql\",\n            payload=[\n                {\n                    \"selectItems\": [\n                        {\n                            \"exprSources\": [\n                                {\"sourceDataset\": \"t\", \"sourceColumn\": \"foo\"},\n                                {\"sourceDataset\": \"t\", \"sourceColumn\": \"boo\"},\n                            ]\n                        }\n                    ]\n                }\n            ],\n        )\n\n\ndef _success_retrive_data(m, ibis_config, repeat=1):\n    df = pd.DataFrame({\"foo\": [\"a\", \"b\"], \"boo\": [1, 2]}).to_dict(orient=\"split\")\n    for _ in range(repeat):\n        m.post(\n            f\"{ibis_config['api_endpoint']}/v3/connector/{ibis_config['data_source']}/query?limit={ibis_config['limit']}\",\n            payload={\n                \"data\": df.get(\"data\"),\n                \"columns\": df.get(\"columns\"),\n            },\n        )\n\n\ndef test_accuracy_metric(test_case, mocker):\n    ibis_config = {\n        \"api_endpoint\": \"http://example.com/endpoint\",\n        \"data_source\": \"bigquery\",\n        \"mdl_json\": {},\n        \"connection_info\": {\n            \"project_id\": \"fake-id\",\n            \"dataset_id\": \"fake-id\",\n            \"credentials\": \"fake-credentials\",\n        },\n        \"timeout\": 10,\n        \"limit\": 10,\n    }\n    _success_retrive_data(mocker, ibis_config, 2)\n\n    metric = AccuracyMetric(ibis_config)\n    metric.measure(test_case)\n    assert metric.is_successful()\n    assert metric.score == 1.0\n\n\ndef test_answer_relevancy_metric(engine_config, test_case, mocker):\n    _success_analysis_sql(mocker, engine_config, 2)\n\n    metric = AnswerRelevancyMetric(engine_config)\n    metric.measure(test_case)\n    assert metric.is_successful()\n    assert metric.score == 1.0\n\n\ndef test_faithfulness_metric(engine_config, test_case, mocker):\n    _success_analysis_sql(mocker, engine_config)\n\n    metric = FaithfulnessMetric(engine_config)\n    metric.measure(test_case)\n    assert metric.is_successful()\n    assert metric.score == 1.0\n\n\ndef test_contextual_relevancy_metric(test_case):\n    metric = ContextualRelevancyMetric()\n    metric.measure(test_case)\n    assert metric.is_successful()\n    assert metric.score == 1.0\n\n\ndef test_contextual_recall_metric(engine_config, test_case, mocker):\n    _success_analysis_sql(mocker, engine_config)\n\n    metric = ContextualRecallMetric(engine_config)\n    metric.measure(test_case)\n    assert metric.is_successful()\n    assert metric.score == 1.0\n\n\ndef test_contextual_precision_metric(test_case):\n    metric = ContextualPrecisionMetric()\n    metric.measure(test_case)\n    assert metric.is_successful()\n    assert metric.score == 1.0\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/pipelines/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/tests/pytest/pipelines/generation/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/tests/pytest/pipelines/generation/test_ask.py",
    "content": "import json\n\nimport orjson\nimport pytest\n\nfrom src.pipelines.generation.followup_sql_generation import FollowUpSQLGeneration\nfrom src.pipelines.generation.sql_correction import SQLCorrection\nfrom src.pipelines.generation.sql_generation import SQLGeneration\nfrom src.pipelines.retrieval.db_schema_retrieval import DbSchemaRetrieval\nfrom src.web.v1.services import Configuration\nfrom src.web.v1.services.ask import AskHistory\n\nGLOBAL_DATA = {\n    \"contexts\": None,\n}\n\n\n@pytest.fixture\ndef mdl_str():\n    with open(\"tests/data/book_2_mdl.json\", \"r\") as f:\n        return orjson.dumps(json.load(f)).decode(\"utf-8\")\n\n\n@pytest.fixture\ndef pipeline_components():\n    from src.config import settings\n    from src.providers import generate_components\n\n    return generate_components(settings.components)\n\n\n@pytest.mark.skip(\n    reason=\"Temporarily disabled as it depends on vector store and other tests\"\n)\n@pytest.mark.asyncio\nasync def test_retrieval_pipeline(pipeline_components):\n    retrieval_pipeline = DbSchemaRetrieval(**pipeline_components[\"db_schema_retrieval\"])\n\n    retrieval_result = await retrieval_pipeline.run(\n        \"How many books are there?\",\n    )\n\n    assert retrieval_result is not None\n    assert len(retrieval_result[\"construct_retrieval_results\"]) > 0\n\n    GLOBAL_DATA[\"contexts\"] = retrieval_result[\"construct_retrieval_results\"]\n\n\n@pytest.mark.skip(\n    reason=\"Temporarily disabled as it depends on vector store and other tests\"\n)\n@pytest.mark.asyncio\nasync def test_generation_pipeline():\n    generation_pipeline = SQLGeneration(**pipeline_components[\"sql_generation\"])\n    generation_result = await generation_pipeline.run(\n        \"How many authors are there?\",\n        contexts=GLOBAL_DATA[\"contexts\"],\n        configuration=Configuration(),\n    )\n\n    # TODO: we'll refactor almost all test case with a mock server, thus temporarily only assert it is not None.\n    assert generation_result[\"post_process\"][\"valid_generation_results\"] is not None\n    assert generation_result[\"post_process\"][\"invalid_generation_results\"] is not None\n\n    generation_result = await generation_pipeline.run(\n        \"How many authors are there?\",\n        contexts=GLOBAL_DATA[\"contexts\"],\n        configuration=Configuration(),\n    )\n\n    assert generation_result[\"post_process\"][\"valid_generation_results\"] is not None\n    assert generation_result[\"post_process\"][\"invalid_generation_results\"] is not None\n\n\n@pytest.mark.skip(\n    reason=\"Temporarily disabled as it depends on vector store and other tests\"\n)\n@pytest.mark.asyncio\nasync def test_followup_generation_pipeline():\n    generation_pipeline = FollowUpSQLGeneration(\n        **pipeline_components[\"followup_sql_generation\"]\n    )\n    generation_result = await generation_pipeline.run(\n        \"What are names of the books?\",\n        contexts=GLOBAL_DATA[\"contexts\"],\n        history=AskHistory(\n            sql=\"SELECT COUNT(*) FROM book\",\n            summary=\"Retrieve the number of books\",\n        ),\n        configuration=Configuration(),\n    )\n\n    # TODO: we'll refactor almost all test case with a mock server, thus temporarily only assert it is not None.\n    assert generation_result[\"post_process\"][\"valid_generation_results\"] is not None\n    assert generation_result[\"post_process\"][\"invalid_generation_results\"] is not None\n\n\n@pytest.mark.skip(\n    reason=\"Temporarily disabled as it depends on vector store and other tests\"\n)\n@pytest.mark.asyncio\nasync def test_sql_correction_pipeline():\n    sql_correction_pipeline = SQLCorrection(**pipeline_components[\"sql_correction\"])\n\n    sql_correction_result = await sql_correction_pipeline.run(\n        contexts=GLOBAL_DATA[\"contexts\"],\n        invalid_generation_results=[\n            {\n                \"sql\": \"Select count(*) from books\",\n                \"summary\": \"Retrieve the number of books\",\n                \"error\": 'ERROR:  com.google.cloud.bigquery.BigQueryException: Table \"books\" must be qualified with a dataset (e.g. dataset.table).',\n            }\n        ],\n    )\n\n    assert isinstance(\n        sql_correction_result[\"post_process\"][\"valid_generation_results\"], list\n    )\n    assert isinstance(\n        sql_correction_result[\"post_process\"][\"invalid_generation_results\"], list\n    )\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/pipelines/generation/test_semantics_enrichment.py",
    "content": "from src.pipelines.generation.semantics_description import output\n\n\ndef test_without_hallucination():\n    test_normalize = {\n        \"model1\": {\n            \"name\": \"model1\",\n            \"columns\": [{\"name\": \"column1\"}],\n        }\n    }\n    test_picked_models = [\n        {\n            \"name\": \"model1\",\n            \"columns\": [{\"name\": \"column1\"}],\n        }\n    ]\n\n    result = output(test_normalize, test_picked_models)\n\n    assert \"model1\" in result\n    assert result[\"model1\"][\"name\"] == \"model1\"\n    assert len(result[\"model1\"][\"columns\"]) == 1\n    assert result[\"model1\"][\"columns\"][0][\"name\"] == \"column1\"\n\n\ndef test_with_hallucination():\n    test_normalize = {\n        \"model1\": {\n            \"name\": \"model1\",\n            \"columns\": [{\"name\": \"column1\"}, {\"name\": \"$column2$\"}],\n        }\n    }\n    test_picked_models = [\n        {\n            \"name\": \"model1\",\n            \"columns\": [{\"name\": \"column1\"}, {\"name\": \"column2\"}],\n        }\n    ]\n\n    result = output(test_normalize, test_picked_models)\n\n    assert \"model1\" in result\n    assert result[\"model1\"][\"name\"] == \"model1\"\n    assert len(result[\"model1\"][\"columns\"]) == 1\n    assert result[\"model1\"][\"columns\"][0][\"name\"] == \"column1\"\n\n\ndef test_with_hallucination_and_no_columns():\n    test_normalize = {\n        \"model1\": {\n            \"name\": \"model1\",\n            \"columns\": [{\"name\": \"$column2$\"}],\n        }\n    }\n    test_picked_models = [\n        {\n            \"name\": \"model1\",\n            \"columns\": [{\"name\": \"column1\"}],\n        }\n    ]\n\n    result = output(test_normalize, test_picked_models)\n\n    assert \"model1\" in result\n    assert result[\"model1\"][\"name\"] == \"model1\"\n    assert len(result[\"model1\"][\"columns\"]) == 0\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/pipelines/indexing/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/tests/pytest/pipelines/indexing/test_db_schema.py",
    "content": "from unittest.mock import AsyncMock\n\nimport orjson\nimport pytest\nfrom haystack import Document\nfrom pytest_mock import MockFixture\n\nfrom src.pipelines.indexing.db_schema import DBSchema, DDLChunker\n\n\n@pytest.mark.asyncio\nasync def test_empty_mdl():\n    chunker = DDLChunker()\n    mdl = {\"models\": [], \"views\": [], \"relationships\": [], \"metrics\": []}\n\n    document = await chunker.run(mdl, column_batch_size=1)\n    assert document == {\"documents\": []}\n\n\n@pytest.mark.asyncio\nasync def test_single_model():\n    chunker = DDLChunker()\n    mdl = {\n        \"models\": [\n            {\n                \"name\": \"user\",\n                \"properties\": {\n                    \"description\": \"A table containing user information.\",\n                    \"displayName\": \"user\",\n                },\n            }\n        ],\n        \"views\": [],\n        \"relationships\": [],\n        \"metrics\": [],\n    }\n\n    actual = await chunker.run(mdl, column_batch_size=1)\n    assert len(actual[\"documents\"]) == 1\n\n    document: Document = actual[\"documents\"][0]\n    assert document.meta == {\"type\": \"TABLE_SCHEMA\", \"name\": \"user\"}\n    assert document.content == str(\n        {\n            \"type\": \"TABLE\",\n            \"comment\": \"\\n/* {'alias': 'user', 'description': 'A table containing user information.'} */\\n\",\n            \"name\": \"user\",\n        }\n    )\n\n\n@pytest.mark.asyncio\nasync def test_multiple_models():\n    chunker = DDLChunker()\n    mdl = {\n        \"models\": [\n            {\n                \"name\": \"user\",\n                \"properties\": {\n                    \"description\": \"A table containing user information.\",\n                    \"displayName\": \"user\",\n                },\n            },\n            {\n                \"name\": \"order\",\n                \"properties\": {\n                    \"description\": \"A table containing order details.\",\n                    \"displayName\": \"order\",\n                },\n            },\n        ],\n        \"views\": [],\n        \"relationships\": [],\n        \"metrics\": [],\n    }\n\n    actual = await chunker.run(mdl, column_batch_size=1)\n    assert len(actual[\"documents\"]) == 2\n\n    document_1: Document = actual[\"documents\"][0]\n    assert document_1.meta == {\"type\": \"TABLE_SCHEMA\", \"name\": \"user\"}\n    assert document_1.content == str(\n        {\n            \"type\": \"TABLE\",\n            \"comment\": \"\\n/* {'alias': 'user', 'description': 'A table containing user information.'} */\\n\",\n            \"name\": \"user\",\n        }\n    )\n\n    document_2: Document = actual[\"documents\"][1]\n    assert document_2.meta == {\"type\": \"TABLE_SCHEMA\", \"name\": \"order\"}\n    assert document_2.content == str(\n        {\n            \"type\": \"TABLE\",\n            \"comment\": \"\\n/* {'alias': 'order', 'description': 'A table containing order details.'} */\\n\",\n            \"name\": \"order\",\n        }\n    )\n\n\n@pytest.mark.asyncio\nasync def test_column_is_primary_key():\n    chunker = DDLChunker()\n    mdl = {\n        \"models\": [\n            {\n                \"name\": \"user\",\n                \"columns\": [\n                    {\n                        \"name\": \"id\",\n                        \"type\": \"INTEGER\",\n                    }\n                ],\n                \"primaryKey\": \"id\",\n            }\n        ],\n        \"views\": [],\n        \"relationships\": [],\n        \"metrics\": [],\n    }\n\n    actual = await chunker.run(mdl, column_batch_size=1)\n    assert len(actual[\"documents\"]) == 2\n\n    document_0: Document = actual[\"documents\"][0]\n    assert document_0.meta == {\"type\": \"TABLE_SCHEMA\", \"name\": \"user\"}\n    assert document_0.content == str(\n        {\n            \"type\": \"TABLE_COLUMNS\",\n            \"columns\": [\n                {\n                    \"type\": \"COLUMN\",\n                    \"comment\": \"\",\n                    \"name\": \"id\",\n                    \"data_type\": \"INTEGER\",\n                    \"is_primary_key\": True,\n                }\n            ],\n        }\n    )\n\n\n@pytest.mark.asyncio\nasync def test_column_with_properties():\n    chunker = DDLChunker()\n    mdl = {\n        \"models\": [\n            {\n                \"name\": \"user\",\n                \"columns\": [\n                    {\n                        \"name\": \"id\",\n                        \"type\": \"INTEGER\",\n                        \"properties\": {\n                            \"displayName\": \"iid\",\n                            \"description\": \"The unique identifier for a user.\",\n                        },\n                    }\n                ],\n            }\n        ],\n        \"views\": [],\n        \"relationships\": [],\n        \"metrics\": [],\n    }\n\n    actual = await chunker.run(mdl, column_batch_size=1)\n    assert len(actual[\"documents\"]) == 2\n\n    document_0: Document = actual[\"documents\"][0]\n    assert document_0.meta == {\"type\": \"TABLE_SCHEMA\", \"name\": \"user\"}\n    assert document_0.content == str(\n        {\n            \"type\": \"TABLE_COLUMNS\",\n            \"columns\": [\n                {\n                    \"type\": \"COLUMN\",\n                    \"comment\": '-- {\"alias\":\"iid\",\"description\":\"The unique identifier for a user.\"}\\n  ',\n                    \"name\": \"id\",\n                    \"data_type\": \"INTEGER\",\n                    \"is_primary_key\": False,\n                }\n            ],\n        }\n    )\n\n    document_1: Document = actual[\"documents\"][1]\n    assert document_1.meta == {\"type\": \"TABLE_SCHEMA\", \"name\": \"user\"}\n    assert document_1.content == str(\n        {\n            \"type\": \"TABLE\",\n            \"comment\": \"\\n/* {'alias': '', 'description': ''} */\\n\",\n            \"name\": \"user\",\n        }\n    )\n\n\n@pytest.mark.asyncio\nasync def test_column_with_nested_columns():\n    chunker = DDLChunker()\n    mdl = {\n        \"models\": [\n            {\n                \"name\": \"user\",\n                \"columns\": [\n                    {\n                        \"name\": \"id\",\n                        \"type\": \"INTEGER\",\n                        \"properties\": {\n                            \"displayName\": \"iid\",\n                            \"description\": \"The unique identifier for a user.\",\n                            \"nested.address\": {\"name\": \"address\", \"type\": \"VARCHAR\"},\n                            \"nested.orders\": {\"name\": \"orders\", \"type\": \"ARRAY\"},\n                        },\n                    }\n                ],\n            }\n        ],\n        \"views\": [],\n        \"relationships\": [],\n        \"metrics\": [],\n    }\n\n    actual = await chunker.run(mdl, column_batch_size=1)\n    assert len(actual[\"documents\"]) == 2\n\n    document_0: Document = actual[\"documents\"][0]\n    assert document_0.meta == {\"type\": \"TABLE_SCHEMA\", \"name\": \"user\"}\n    assert document_0.content == str(\n        {\n            \"type\": \"TABLE_COLUMNS\",\n            \"columns\": [\n                {\n                    \"type\": \"COLUMN\",\n                    \"comment\": '-- {\"alias\":\"iid\",\"description\":\"The unique identifier for a user.\",\"nested_columns\":{\"nested.address\":{\"name\":\"address\",\"type\":\"VARCHAR\"},\"nested.orders\":{\"name\":\"orders\",\"type\":\"ARRAY\"}}}\\n  ',\n                    \"name\": \"id\",\n                    \"data_type\": \"INTEGER\",\n                    \"is_primary_key\": False,\n                }\n            ],\n        }\n    )\n\n\n@pytest.mark.asyncio\nasync def test_column_with_calculated_property():\n    chunker = DDLChunker()\n    mdl = {\n        \"models\": [\n            {\n                \"name\": \"user\",\n                \"columns\": [\n                    {\n                        \"name\": \"id\",\n                        \"type\": \"INTEGER\",\n                        \"expression\": \"id + 1\",\n                        \"isCalculated\": True,\n                    }\n                ],\n            }\n        ],\n        \"views\": [],\n        \"relationships\": [],\n        \"metrics\": [],\n    }\n\n    actual = await chunker.run(mdl, column_batch_size=1)\n    assert len(actual[\"documents\"]) == 2\n\n    document_0: Document = actual[\"documents\"][0]\n    assert document_0.meta == {\"type\": \"TABLE_SCHEMA\", \"name\": \"user\"}\n    assert document_0.content == str(\n        {\n            \"type\": \"TABLE_COLUMNS\",\n            \"columns\": [\n                {\n                    \"type\": \"COLUMN\",\n                    \"comment\": \"-- This column is a Calculated Field\\n  -- column expression: id + 1\\n  \",\n                    \"name\": \"id\",\n                    \"data_type\": \"INTEGER\",\n                    \"is_primary_key\": False,\n                }\n            ],\n        }\n    )\n\n\n@pytest.mark.asyncio\nasync def test_column_with_relationship():\n    chunker = DDLChunker()\n    mdl = {\n        \"models\": [\n            {\n                \"name\": \"user\",\n                \"columns\": [\n                    {\n                        \"name\": \"id\",\n                        \"type\": \"INTEGER\",\n                    },\n                    {\n                        \"name\": \"order_id\",\n                        \"type\": \"INTEGER\",\n                        \"relationship\": \"relationship_1\",\n                    },\n                ],\n                \"primaryKey\": \"id\",\n            },\n            {\n                \"name\": \"order\",\n                \"columns\": [\n                    {\n                        \"name\": \"user_id\",\n                        \"type\": \"INTEGER\",\n                    }\n                ],\n                \"primaryKey\": \"user_id\",\n            },\n        ],\n        \"views\": [],\n        \"relationships\": [\n            {\n                \"name\": \"relationship_1\",\n                \"condition\": \"user.id = order.user_id\",\n                \"joinType\": \"ONE_TO_MANY\",\n                \"models\": [\"user\", \"order\"],\n            }\n        ],\n        \"metrics\": [],\n    }\n\n    actual = await chunker.run(mdl, column_batch_size=1)\n    assert len(actual[\"documents\"]) == 6\n\n    document_0: Document = actual[\"documents\"][0]\n    assert document_0.meta == {\"type\": \"TABLE_SCHEMA\", \"name\": \"user\"}\n    assert document_0.content == str(\n        {\n            \"type\": \"TABLE_COLUMNS\",\n            \"columns\": [\n                {\n                    \"type\": \"COLUMN\",\n                    \"comment\": \"\",\n                    \"name\": \"id\",\n                    \"data_type\": \"INTEGER\",\n                    \"is_primary_key\": True,\n                }\n            ],\n        }\n    )\n\n    document_1: Document = actual[\"documents\"][1]\n    assert document_1.meta == {\"type\": \"TABLE_SCHEMA\", \"name\": \"user\"}\n    assert document_1.content == str(\n        {\n            \"type\": \"TABLE_COLUMNS\",\n            \"columns\": [\n                {\n                    \"type\": \"FOREIGN_KEY\",\n                    \"comment\": '-- {\"condition\": user.id = order.user_id, \"joinType\": ONE_TO_MANY}\\n  ',\n                    \"constraint\": \"FOREIGN KEY (id) REFERENCES order(user_id)\",\n                    \"tables\": [\"user\", \"order\"],\n                }\n            ],\n        }\n    )\n\n    document_4: Document = actual[\"documents\"][4]\n    assert document_4.meta == {\"type\": \"TABLE_SCHEMA\", \"name\": \"order\"}\n    assert document_4.content == str(\n        {\n            \"type\": \"TABLE_COLUMNS\",\n            \"columns\": [\n                {\n                    \"type\": \"FOREIGN_KEY\",\n                    \"comment\": '-- {\"condition\": user.id = order.user_id, \"joinType\": ONE_TO_MANY}\\n  ',\n                    \"constraint\": \"FOREIGN KEY (user_id) REFERENCES user(id)\",\n                    \"tables\": [\"user\", \"order\"],\n                }\n            ],\n        }\n    )\n\n\n@pytest.mark.asyncio\nasync def test_column_batch_size():\n    chunker = DDLChunker()\n    mdl = {\n        \"models\": [\n            {\n                \"name\": \"user\",\n                \"columns\": [\n                    {\"name\": \"id\", \"type\": \"INTEGER\"},\n                    {\"name\": \"name\", \"type\": \"VARCHAR\"},\n                    {\"name\": \"age\", \"type\": \"INTEGER\"},\n                ],\n            }\n        ],\n        \"views\": [],\n        \"relationships\": [],\n        \"metrics\": [],\n    }\n    actual = await chunker.run(mdl, column_batch_size=2)\n    assert len(actual[\"documents\"]) == 3\n\n    document_0: Document = actual[\"documents\"][0]\n    assert document_0.meta == {\"type\": \"TABLE_SCHEMA\", \"name\": \"user\"}\n    assert document_0.content == str(\n        {\n            \"type\": \"TABLE_COLUMNS\",\n            \"columns\": [\n                {\n                    \"type\": \"COLUMN\",\n                    \"comment\": \"\",\n                    \"name\": \"id\",\n                    \"data_type\": \"INTEGER\",\n                    \"is_primary_key\": False,\n                },\n                {\n                    \"type\": \"COLUMN\",\n                    \"comment\": \"\",\n                    \"name\": \"name\",\n                    \"data_type\": \"VARCHAR\",\n                    \"is_primary_key\": False,\n                },\n            ],\n        }\n    )\n\n    document_1: Document = actual[\"documents\"][1]\n    assert document_1.meta == {\"type\": \"TABLE_SCHEMA\", \"name\": \"user\"}\n    assert document_1.content == str(\n        {\n            \"type\": \"TABLE_COLUMNS\",\n            \"columns\": [\n                {\n                    \"type\": \"COLUMN\",\n                    \"comment\": \"\",\n                    \"name\": \"age\",\n                    \"data_type\": \"INTEGER\",\n                    \"is_primary_key\": False,\n                }\n            ],\n        }\n    )\n\n\n@pytest.mark.asyncio\nasync def test_view():\n    chunker = DDLChunker()\n    mdl = {\n        \"models\": [],\n        \"views\": [{\"name\": \"view_1\", \"statement\": \"SELECT * FROM user\"}],\n        \"relationships\": [],\n        \"metrics\": [],\n    }\n    actual = await chunker.run(mdl, column_batch_size=1)\n    assert len(actual[\"documents\"]) == 1\n\n    document_0: Document = actual[\"documents\"][0]\n    assert document_0.meta == {\"type\": \"TABLE_SCHEMA\", \"name\": \"view_1\"}\n    assert document_0.content == str(\n        {\n            \"type\": \"VIEW\",\n            \"comment\": \"\",\n            \"name\": \"view_1\",\n            \"statement\": \"SELECT * FROM user\",\n        }\n    )\n\n\n@pytest.mark.asyncio\nasync def test_view_with_properties():\n    chunker = DDLChunker()\n    mdl = {\n        \"models\": [],\n        \"views\": [\n            {\n                \"name\": \"view_1\",\n                \"statement\": \"SELECT * FROM user\",\n                \"properties\": {\"description\": \"A view containing user information.\"},\n            }\n        ],\n        \"relationships\": [],\n        \"metrics\": [],\n    }\n    actual = await chunker.run(mdl, column_batch_size=1)\n    assert len(actual[\"documents\"]) == 1\n\n    document_0: Document = actual[\"documents\"][0]\n    assert document_0.meta == {\"type\": \"TABLE_SCHEMA\", \"name\": \"view_1\"}\n    assert document_0.content == str(\n        {\n            \"type\": \"VIEW\",\n            \"comment\": \"/* {'description': 'A view containing user information.'} */\\n\",\n            \"name\": \"view_1\",\n            \"statement\": \"SELECT * FROM user\",\n        }\n    )\n\n\n@pytest.mark.asyncio\nasync def test_metric():\n    chunker = DDLChunker()\n    mdl = {\n        \"models\": [],\n        \"views\": [],\n        \"relationships\": [],\n        \"metrics\": [\n            {\n                \"name\": \"metric_1\",\n                \"baseObject\": \"user\",\n                \"measure\": [\n                    {\"name\": \"age\", \"type\": \"INTEGER\", \"expression\": \"SUM(age)\"}\n                ],\n                \"dimension\": [\n                    {\"name\": \"gender\", \"type\": \"VARCHAR\"},\n                ],\n            }\n        ],\n    }\n    actual = await chunker.run(mdl, column_batch_size=1)\n    assert len(actual[\"documents\"]) == 1\n\n    document_0: Document = actual[\"documents\"][0]\n    assert document_0.meta == {\"type\": \"TABLE_SCHEMA\", \"name\": \"metric_1\"}\n    assert document_0.content == str(\n        {\n            \"type\": \"METRIC\",\n            \"comment\": \"\\n/* This table is a metric */\\n/* Metric Base Object: user */\\n\",\n            \"name\": \"metric_1\",\n            \"columns\": [\n                {\n                    \"type\": \"COLUMN\",\n                    \"comment\": \"-- This column is a dimension\\n  \",\n                    \"name\": \"gender\",\n                    \"data_type\": \"VARCHAR\",\n                },\n                {\n                    \"type\": \"COLUMN\",\n                    \"comment\": \"-- This column is a measure\\n  -- expression: SUM(age)\\n  \",\n                    \"name\": \"age\",\n                    \"data_type\": \"INTEGER\",\n                },\n            ],\n        }\n    )\n\n\n@pytest.mark.asyncio\nasync def test_pipeline_run(mocker: MockFixture):\n    test_mdl = {\n        \"models\": [\n            {\n                \"name\": \"user\",\n                \"columns\": [{\"name\": \"id\", \"type\": \"INTEGER\"}],\n                \"primaryKey\": \"id\",\n            },\n            {\n                \"name\": \"order\",\n                \"columns\": [{\"name\": \"user_id\", \"type\": \"INTEGER\"}],\n                \"primaryKey\": \"user_id\",\n            },\n        ],\n        \"views\": [\n            {\n                \"name\": \"view_1\",\n                \"statement\": \"SELECT * FROM user\",\n            }\n        ],\n        \"relationships\": [\n            {\n                \"name\": \"relationship_1\",\n                \"condition\": \"user.id = order.user_id\",\n                \"joinType\": \"ONE_TO_MANY\",\n                \"models\": [\"user\", \"order\"],\n            }\n        ],\n        \"metrics\": [\n            {\n                \"name\": \"metric_1\",\n                \"baseObject\": \"user\",\n                \"measure\": [\n                    {\"name\": \"age\", \"type\": \"INTEGER\", \"expression\": \"SUM(age)\"}\n                ],\n                \"dimension\": [{\"name\": \"gender\", \"type\": \"VARCHAR\"}],\n            }\n        ],\n    }\n\n    # Mock embedder provider\n    embedder_provider = mocker.patch(\"src.core.provider.EmbedderProvider\")\n    embedder = mocker.Mock()\n    mocker.patch.object(\n        embedder,\n        \"run\",\n        new_callable=AsyncMock,\n        side_effect=lambda documents: {\"documents\": documents},\n    )\n    embedder_provider.get_document_embedder.return_value = embedder\n\n    # Mock document store provider\n    document_store = mocker.Mock()\n    mocker.patch.object(\n        document_store, \"delete_documents\", new_callable=AsyncMock, return_value=None\n    )\n    mocker.patch.object(\n        document_store,\n        \"write_documents\",\n        new_callable=AsyncMock,\n        side_effect=lambda documents, *_, **__: len(documents),\n    )\n    document_store_provider = mocker.patch(\"src.core.provider.DocumentStoreProvider\")\n    document_store_provider.get_store.return_value = document_store\n\n    pipe = DBSchema(\n        embedder_provider=embedder_provider,\n        document_store_provider=document_store_provider,\n    )\n    result = await pipe.run(orjson.dumps(test_mdl), project_id=\"test-project\")\n    assert result is not None\n    assert result == {\"write\": {\"documents_written\": 6}}\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/pipelines/indexing/test_helper.py",
    "content": "from pytest_mock import MockerFixture\n\nfrom src.pipelines.indexing.utils.helper import (\n    COLUMN_COMMENT_HELPERS,\n    COLUMN_PREPROCESSORS,\n    MODEL_PREPROCESSORS,\n    Helper,\n    load_helpers,\n)\n\n\ndef test_helper():\n    test_helper = Helper(\n        condition=lambda x, **_: x.get(\"test\", False),\n        helper=lambda x, **_: x.get(\"value\", \"\"),\n    )\n\n    assert test_helper.condition({\"test\": True}) is True\n    assert test_helper.condition({\"test\": False}) is False\n\n    assert test_helper({\"test\": True, \"value\": \"test_value\"}) == \"test_value\"\n    assert test_helper({\"test\": False, \"value\": \"test_value\"}) == \"test_value\"\n\n\ndef test_column_properties_preprocessor():\n    helper = COLUMN_PREPROCESSORS[\"properties\"]\n\n    test_column = {\n        \"name\": \"test_column\",\n        \"properties\": {\"displayName\": \"Test Column\", \"description\": \"Test description\"},\n    }\n\n    assert helper.condition(test_column) is True\n    assert helper(test_column) == {\n        \"displayName\": \"Test Column\",\n        \"description\": \"Test description\",\n    }\n\n\ndef test_column_relationship_preprocessor():\n    helper = COLUMN_PREPROCESSORS[\"relationship\"]\n\n    test_column = {\n        \"name\": \"test_column\",\n        \"relationship\": \"test_relationship\",\n    }\n\n    assert helper.condition(test_column) is True\n    assert helper(test_column) == \"test_relationship\"\n\n\ndef test_column_expression_preprocessor():\n    helper = COLUMN_PREPROCESSORS[\"expression\"]\n\n    test_column = {\n        \"name\": \"test_column\",\n        \"expression\": \"SUM(value)\",\n    }\n\n    assert helper.condition(test_column) is True\n    assert helper(test_column) == \"SUM(value)\"\n\n\ndef test_column_is_calculated_preprocessor():\n    helper = COLUMN_PREPROCESSORS[\"isCalculated\"]\n\n    test_column = {\n        \"name\": \"test_column\",\n        \"isCalculated\": True,\n    }\n\n    assert helper.condition(test_column) is True\n    assert helper(test_column) is True\n\n\ndef test_properties_comment_helper():\n    helper = COLUMN_COMMENT_HELPERS[\"properties\"]\n\n    test_column = {\n        \"name\": \"test_column\",\n        \"properties\": {\n            \"displayName\": \"Test Column\",\n            \"description\": \"Test description\",\n        },\n    }\n\n    assert helper.condition(test_column) is True\n\n    expected_comment = '-- {\"alias\":\"Test Column\",\"description\":\"Test description\"}\\n  '\n    assert helper(test_column) == expected_comment\n\n\ndef test_calculated_field_helpers():\n    helper = COLUMN_COMMENT_HELPERS[\"isCalculated\"]\n\n    test_column = {\n        \"name\": \"calculated_column\",\n        \"isCalculated\": True,\n        \"expression\": \"SUM(value)\",\n    }\n\n    assert helper.condition(test_column) is True\n\n    expected_comment = (\n        \"-- This column is a Calculated Field\\n  -- column expression: SUM(value)\\n  \"\n    )\n    assert helper(test_column) == expected_comment\n\n\ndef test_load_helpers(mocker: MockerFixture):\n    mock_module = mocker.Mock()\n    mock_module.__path__ = [\"test/path\"]\n    mock_module.__name__ = \"test.package\"\n\n    mocker.patch(\"pkgutil.walk_packages\", return_value=[(None, \"test_module\", None)])\n\n    mock_test_module = mocker.Mock()\n    mock_test_module.MODEL_PREPROCESSORS = {\"test\": \"test_preprocessor\"}\n    mock_test_module.COLUMN_PREPROCESSORS = {\"test\": \"test_column_preprocessor\"}\n    mock_test_module.COLUMN_COMMENT_HELPERS = {\"test\": \"test_comment_helper\"}\n\n    mocker.patch(\"importlib.import_module\", side_effect=[mock_module, mock_test_module])\n\n    load_helpers(\"test.package\")\n\n    assert len(MODEL_PREPROCESSORS) == 1\n    assert MODEL_PREPROCESSORS.get(\"test\") == \"test_preprocessor\"\n    del MODEL_PREPROCESSORS[\"test\"]\n\n    assert len(COLUMN_PREPROCESSORS) == 5\n    assert COLUMN_PREPROCESSORS.get(\"test\") == \"test_column_preprocessor\"\n    del COLUMN_PREPROCESSORS[\"test\"]\n\n    assert len(COLUMN_COMMENT_HELPERS) == 3\n    assert COLUMN_COMMENT_HELPERS.get(\"test\") == \"test_comment_helper\"\n    del COLUMN_COMMENT_HELPERS[\"test\"]\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/pipelines/indexing/test_historical_questions.py",
    "content": "import json\nfrom unittest.mock import AsyncMock\n\nimport pytest\nfrom haystack import Document\nfrom pytest_mock import MockFixture\n\nfrom src.pipelines.indexing.historical_question import HistoricalQuestion, ViewChunker\n\n\ndef test_empty_views():\n    chunker = ViewChunker()\n    mdl = {\"views\": []}\n\n    document = chunker.run(mdl)\n    assert document == {\"documents\": []}\n\n\ndef test_single_view():\n    chunker = ViewChunker()\n    mdl = {\n        \"views\": [\n            {\n                \"name\": \"book\",\n                \"statement\": \"SELECT * FROM book\",\n                \"properties\": {\n                    \"question\": \"How many books are there?\",\n                    \"summary\": \"Retrieve the number of books\",\n                    \"viewId\": \"fake-id-1\",\n                },\n            }\n        ]\n    }\n\n    actual = chunker.run(mdl)\n    assert len(actual[\"documents\"]) == 1\n\n    document: Document = actual[\"documents\"][0]\n    assert document.meta == {\n        \"summary\": \"Retrieve the number of books\",\n        \"statement\": \"SELECT * FROM book\",\n        \"viewId\": \"fake-id-1\",\n    }\n    assert document.content == \"How many books are there?\"\n\n\ndef test_view_missing_properties():\n    chunker = ViewChunker()\n    mdl = {\n        \"views\": [\n            {\n                \"name\": \"book\",\n                \"statement\": \"SELECT * FROM book\",\n            }\n        ]\n    }\n\n    actual = chunker.run(mdl)\n    assert len(actual[\"documents\"]) == 1\n\n    document: Document = actual[\"documents\"][0]\n    assert document.meta == {\n        \"summary\": \"\",\n        \"statement\": \"SELECT * FROM book\",\n        \"viewId\": \"\",\n    }\n    assert document.content == \"\"\n\n\ndef test_view_missing_question():\n    chunker = ViewChunker()\n    mdl = {\n        \"views\": [\n            {\n                \"name\": \"book\",\n                \"statement\": \"SELECT * FROM book\",\n                \"properties\": {\n                    \"summary\": \"Retrieve the number of books\",\n                    \"viewId\": \"fake-id-1\",\n                },\n            }\n        ]\n    }\n\n    actual = chunker.run(mdl)\n    assert len(actual[\"documents\"]) == 1\n\n    document: Document = actual[\"documents\"][0]\n    assert document.meta == {\n        \"summary\": \"Retrieve the number of books\",\n        \"statement\": \"SELECT * FROM book\",\n        \"viewId\": \"fake-id-1\",\n    }\n    assert document.content == \"\"\n\n\ndef test_view_missing_summary():\n    chunker = ViewChunker()\n    mdl = {\n        \"views\": [\n            {\n                \"name\": \"book\",\n                \"statement\": \"SELECT * FROM book\",\n                \"properties\": {\n                    \"question\": \"How many books are there?\",\n                    \"viewId\": \"fake-id-1\",\n                },\n            }\n        ]\n    }\n\n    actual = chunker.run(mdl)\n    assert len(actual[\"documents\"]) == 1\n\n    document: Document = actual[\"documents\"][0]\n    assert document.meta == {\n        \"summary\": \"\",\n        \"statement\": \"SELECT * FROM book\",\n        \"viewId\": \"fake-id-1\",\n    }\n    assert document.content == \"How many books are there?\"\n\n\ndef test_view_missing_id():\n    chunker = ViewChunker()\n    mdl = {\n        \"views\": [\n            {\n                \"name\": \"book\",\n                \"statement\": \"SELECT * FROM book\",\n                \"properties\": {\n                    \"question\": \"How many books are there?\",\n                    \"summary\": \"Retrieve the number of books\",\n                },\n            }\n        ]\n    }\n\n    actual = chunker.run(mdl)\n    assert len(actual[\"documents\"]) == 1\n\n    document: Document = actual[\"documents\"][0]\n    assert document.meta == {\n        \"summary\": \"Retrieve the number of books\",\n        \"statement\": \"SELECT * FROM book\",\n        \"viewId\": \"\",\n    }\n    assert document.content == \"How many books are there?\"\n\n\ndef test_multi_views():\n    chunker = ViewChunker()\n    mdl = {\n        \"views\": [\n            {\n                \"name\": \"book-1\",\n                \"statement\": \"SELECT * FROM book\",\n                \"properties\": {\n                    \"question\": \"How many books are there?\",\n                    \"summary\": \"Retrieve the number of books\",\n                    \"viewId\": \"fake-id-1\",\n                },\n            },\n            {\n                \"name\": \"book-2\",\n                \"statement\": \"SELECT * FROM book\",\n                \"properties\": {\n                    \"question\": \"How many books are there?\",\n                    \"summary\": \"Retrieve the number of books\",\n                    \"viewId\": \"fake-id-2\",\n                },\n            },\n        ]\n    }\n\n    actual = chunker.run(mdl)\n    assert len(actual[\"documents\"]) == 2\n\n    document_1: Document = actual[\"documents\"][0]\n    assert document_1.meta == {\n        \"summary\": \"Retrieve the number of books\",\n        \"statement\": \"SELECT * FROM book\",\n        \"viewId\": \"fake-id-1\",\n    }\n    assert document_1.content == \"How many books are there?\"\n\n    document_2: Document = actual[\"documents\"][1]\n    assert document_2.meta == {\n        \"summary\": \"Retrieve the number of books\",\n        \"statement\": \"SELECT * FROM book\",\n        \"viewId\": \"fake-id-2\",\n    }\n    assert document_2.content == \"How many books are there?\"\n\n\ndef test_view_with_historical_query():\n    chunker = ViewChunker()\n    mdl = {\n        \"views\": [\n            {\n                \"name\": \"book\",\n                \"statement\": \"SELECT * FROM book where created_at = 2020\",\n                \"properties\": {\n                    \"question\": \"in 2020\",\n                    \"summary\": \"Retrieve the number of books in 2020\",\n                    \"viewId\": \"fake-id-1\",\n                    \"historical_queries\": [\"Retrieve the number of books\"],\n                },\n            }\n        ]\n    }\n\n    actual = chunker.run(mdl)\n    assert len(actual[\"documents\"]) == 1\n\n    document: Document = actual[\"documents\"][0]\n    assert document.meta == {\n        \"summary\": \"Retrieve the number of books in 2020\",\n        \"statement\": \"SELECT * FROM book where created_at = 2020\",\n        \"viewId\": \"fake-id-1\",\n    }\n    assert document.content == \"Retrieve the number of books in 2020\"\n\n\ndef test_view_with_historical_queries():\n    chunker = ViewChunker()\n    mdl = {\n        \"views\": [\n            {\n                \"name\": \"book\",\n                \"statement\": \"SELECT * FROM book where city = 'taipei' and created_at = 2020\",\n                \"properties\": {\n                    \"question\": \"in 2020\",\n                    \"summary\": \"Retrieve the number of books in taipei in 2020\",\n                    \"viewId\": \"fake-id-1\",\n                    \"historical_queries\": [\"Retrieve the number of books\", \"in taipei\"],\n                },\n            }\n        ]\n    }\n\n    actual = chunker.run(mdl)\n    assert len(actual[\"documents\"]) == 1\n\n    document: Document = actual[\"documents\"][0]\n    assert document.meta == {\n        \"summary\": \"Retrieve the number of books in taipei in 2020\",\n        \"statement\": \"SELECT * FROM book where city = 'taipei' and created_at = 2020\",\n        \"viewId\": \"fake-id-1\",\n    }\n    assert document.content == \"Retrieve the number of books in taipei in 2020\"\n\n\ndef test_view_with_project_id():\n    chunker = ViewChunker()\n    project_id = \"test-project\"\n    mdl = {\n        \"views\": [\n            {\n                \"name\": \"book\",\n                \"statement\": \"SELECT * FROM book\",\n                \"properties\": {\n                    \"question\": \"How many books are there?\",\n                    \"summary\": \"Retrieve the number of books\",\n                    \"viewId\": \"fake-id-1\",\n                },\n            }\n        ]\n    }\n\n    actual = chunker.run(mdl, project_id=project_id)\n    assert len(actual[\"documents\"]) == 1\n\n    document: Document = actual[\"documents\"][0]\n    assert document.meta == {\n        \"summary\": \"Retrieve the number of books\",\n        \"statement\": \"SELECT * FROM book\",\n        \"viewId\": \"fake-id-1\",\n        \"project_id\": project_id,\n    }\n    assert document.content == \"How many books are there?\"\n\n\n@pytest.mark.asyncio\nasync def test_pipeline_run(mocker: MockFixture):\n    # Mock embedder provider\n    embedder_provider = mocker.patch(\"src.core.provider.EmbedderProvider\")\n    embedder = mocker.Mock()\n    mocker.patch.object(\n        embedder,\n        \"run\",\n        new_callable=AsyncMock,\n        side_effect=lambda documents: {\"documents\": documents},\n    )\n    embedder_provider.get_document_embedder.return_value = embedder\n\n    # Mock document store provider\n    document_store = mocker.Mock()\n    mocker.patch.object(\n        document_store, \"delete_documents\", new_callable=AsyncMock, return_value=None\n    )\n    mocker.patch.object(\n        document_store,\n        \"write_documents\",\n        new_callable=AsyncMock,\n        side_effect=lambda documents, *_, **__: len(documents),\n    )\n    document_store_provider = mocker.patch(\"src.core.provider.DocumentStoreProvider\")\n    document_store_provider.get_store.return_value = document_store\n\n    pipeline = HistoricalQuestion(\n        embedder_provider=embedder_provider,\n        document_store_provider=document_store_provider,\n    )\n\n    test_mdl = {\n        \"models\": [],\n        \"views\": [\n            {\n                \"name\": \"test_view\",\n                \"statement\": \"SELECT * FROM test\",\n                \"properties\": {\n                    \"question\": \"Test question?\",\n                    \"summary\": \"Test summary\",\n                    \"viewId\": \"test-id\",\n                },\n            }\n        ],\n        \"relationships\": [],\n        \"metrics\": [],\n    }\n\n    result = await pipeline.run(json.dumps(test_mdl), project_id=\"test-project\")\n    assert result is not None\n    assert result == {\"write\": {\"documents_written\": 1}}\n\n\n@pytest.mark.asyncio\nasync def test_pipeline_run_embedder_error(mocker: MockFixture):\n    # Mock embedder provider\n    embedder_provider = mocker.patch(\"src.core.provider.EmbedderProvider\")\n    embedder = mocker.Mock()\n    mocker.patch.object(\n        embedder, \"run\", new_callable=AsyncMock, side_effect=Exception(\"Embedder error\")\n    )\n    embedder_provider.get_document_embedder.return_value = embedder\n\n    # Mock document store provider\n    document_store = mocker.Mock()\n    mocker.patch.object(\n        document_store, \"delete_documents\", new_callable=AsyncMock, return_value=None\n    )\n    mocker.patch.object(\n        document_store,\n        \"write_documents\",\n        new_callable=AsyncMock,\n        side_effect=lambda documents, *_, **__: len(documents),\n    )\n    document_store_provider = mocker.patch(\"src.core.provider.DocumentStoreProvider\")\n    document_store_provider.get_store.return_value = document_store\n\n    pipeline = HistoricalQuestion(\n        embedder_provider=embedder_provider,\n        document_store_provider=document_store_provider,\n    )\n\n    with pytest.raises(Exception) as excinfo:\n        await pipeline.run(json.dumps({}), project_id=\"test-project\")\n\n    assert str(excinfo.value) == \"Embedder error\"\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/pipelines/indexing/test_indexing.py",
    "content": "import pytest\nfrom haystack import Document\nfrom haystack.document_stores.types import DocumentStore\n\nfrom src.pipelines.indexing import AsyncDocumentWriter, DocumentCleaner, MDLValidator\n\n\nclass MockDocumentStore(DocumentStore):\n    \"\"\"Mock document store for testing\"\"\"\n\n    def __init__(self, documents=[]):\n        self.documents = documents\n        self.deleted = False\n\n    async def write_documents(self, documents, policy):\n        self.documents.extend(documents)\n        return len(documents)\n\n    async def delete_documents(self, filters=None):\n        self.deleted = True\n        self.documents = []\n\n    def to_dict(self):\n        return {}\n\n\n@pytest.mark.asyncio\nasync def test_document_cleaner():\n    store1 = MockDocumentStore([\"document 1\", \"document 2\"])\n    store2 = MockDocumentStore([\"document 1\", \"document 2\"])\n    cleaner = DocumentCleaner(stores=[store1, store2])\n\n    # Test without project_id\n    await cleaner.run()\n    assert store1.deleted\n    assert store2.deleted\n\n    # Test with project_id\n    await cleaner.run(project_id=\"123\")\n    assert store1.deleted\n    assert store2.deleted\n\n\ndef test_mdl_validator():\n    validator = MDLValidator()\n\n    # Test valid JSON with all fields\n    valid_mdl = \"\"\"\n    {\n        \"models\": [],\n        \"views\": [],\n        \"relationships\": [],\n        \"metrics\": []\n    }\n    \"\"\"\n    result = validator.run(valid_mdl)\n    assert \"mdl\" in result\n    assert all(\n        key in result[\"mdl\"] for key in [\"models\", \"views\", \"relationships\", \"metrics\"]\n    )\n\n    # Test JSON missing fields\n    minimal_mdl = \"{}\"\n    result = validator.run(minimal_mdl)\n    assert \"mdl\" in result\n    assert all(\n        key in result[\"mdl\"] for key in [\"models\", \"views\", \"relationships\", \"metrics\"]\n    )\n\n    # Test invalid JSON\n    with pytest.raises(ValueError):\n        validator.run(\"invalid json\")\n\n\n@pytest.mark.asyncio\nasync def test_async_document_writer():\n    store = MockDocumentStore()\n    writer = AsyncDocumentWriter(document_store=store)\n\n    docs = [Document(content=\"test1\"), Document(content=\"test2\")]\n\n    result = await writer.run(documents=docs)\n    assert result[\"documents_written\"] == 2\n    assert len(store.documents) == 2\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/pipelines/indexing/test_instructions.py",
    "content": "import pytest\n\nfrom src.config import settings\nfrom src.core.provider import DocumentStoreProvider\nfrom src.pipelines.indexing import Instructions\nfrom src.pipelines.indexing.instructions import Instruction\nfrom src.providers import generate_components\n\n\n@pytest.mark.asyncio\nasync def test_instructions_indexing():\n    pipe_components = generate_components(settings.components)\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"instructions_indexing\"\n    ][\"document_store_provider\"]\n    store = document_store_provider.get_store(\n        dataset_name=\"instructions\",\n        recreate_index=True,\n    )\n\n    instructions = Instructions(**pipe_components[\"instructions_indexing\"])\n    test_instructions = [\n        Instruction(\n            id=\"test-id-1\",\n            instruction=\"This is a test instruction\",\n            question=\"What is the test question?\",\n            is_default=False,\n        ),\n        Instruction(\n            id=\"test-id-2\",\n            instruction=\"This is another test instruction\",\n            question=\"What is another test question?\",\n            is_default=True,\n        ),\n    ]\n\n    await instructions.run(\n        project_id=\"fake-id\",\n        instructions=test_instructions,\n    )\n\n    assert await store.count_documents() == 2\n    documents = store.filter_documents()\n    for document in documents:\n        assert document.content, \"content should not be empty\"\n        assert document.meta, \"meta should not be empty\"\n        assert document.meta.get(\"instruction_id\"), \"instruction_id should be in meta\"\n        assert document.meta.get(\"instruction\"), \"instruction should be in meta\"\n        assert \"is_default\" in document.meta, \"is_default should be in meta\"\n\n\n@pytest.mark.asyncio\nasync def test_instructions_indexing_with_multiple_project_ids():\n    pipe_components = generate_components(settings.components)\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"instructions_indexing\"\n    ][\"document_store_provider\"]\n    store = document_store_provider.get_store(\n        dataset_name=\"instructions\",\n        recreate_index=True,\n    )\n\n    instructions = Instructions(**pipe_components[\"instructions_indexing\"])\n    test_instructions = [\n        Instruction(\n            id=\"test-id-1\",\n            instruction=\"This is a test instruction\",\n            question=\"What is the test question?\",\n        ),\n    ]\n\n    await instructions.run(\n        project_id=\"fake-id\",\n        instructions=test_instructions,\n    )\n\n    await instructions.run(\n        project_id=\"fake-id-2\",\n        instructions=test_instructions,\n    )\n\n    assert await store.count_documents() == 2\n    documents = store.filter_documents(\n        filters={\n            \"operator\": \"AND\",\n            \"conditions\": [\n                {\"field\": \"project_id\", \"operator\": \"==\", \"value\": \"fake-id\"},\n            ],\n        }\n    )\n    assert len(documents) == 1\n\n\n@pytest.mark.asyncio\nasync def test_instructions_deletion():\n    pipe_components = generate_components(settings.components)\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"instructions_indexing\"\n    ][\"document_store_provider\"]\n    store = document_store_provider.get_store(\n        dataset_name=\"instructions\",\n        recreate_index=True,\n    )\n\n    instructions = Instructions(**pipe_components[\"instructions_indexing\"])\n    test_instructions = [\n        Instruction(\n            id=\"test-id-1\",\n            instruction=\"This is a test instruction\",\n            question=\"What is the test question?\",\n        ),\n        Instruction(\n            id=\"test-id-2\",\n            instruction=\"This is another test instruction\",\n            question=\"What is another test question?\",\n        ),\n    ]\n\n    await instructions.run(\n        project_id=\"fake-id\",\n        instructions=test_instructions,\n    )\n\n    await instructions.clean(\n        instructions=[Instruction(id=\"test-id-1\")],\n        project_id=\"fake-id-2\",\n    )\n    assert await store.count_documents() == 2\n\n    await instructions.clean(\n        instructions=[Instruction(id=\"test-id-1\")],\n        project_id=\"fake-id\",\n    )\n    assert await store.count_documents() == 1\n\n    await instructions.clean(\n        instructions=[],\n        delete_all=True,\n        project_id=\"fake-id\",\n    )\n    assert await store.count_documents() == 0\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/pipelines/indexing/test_sql_pairs.py",
    "content": "import pytest\n\nfrom src.config import settings\nfrom src.core.provider import DocumentStoreProvider\nfrom src.pipelines.indexing import SqlPairs\nfrom src.providers import generate_components\n\n\n@pytest.mark.asyncio\nasync def test_sql_pairs_indexing_saving_to_document_store():\n    pipe_components = generate_components(settings.components)\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"sql_pairs_indexing\"\n    ][\"document_store_provider\"]\n    store = document_store_provider.get_store(\n        dataset_name=\"sql_pairs\",\n        recreate_index=True,\n    )\n\n    sql_pairs = SqlPairs(\n        **pipe_components[\"sql_pairs_indexing\"], sql_pairs_path=\"tests/data/pairs.json\"\n    )\n    await sql_pairs.run(\n        mdl_str='{\"models\": [{\"properties\": {\"boilerplate\": \"test\"}}]}',\n        project_id=\"fake-id\",\n    )\n\n    assert await store.count_documents() == 2\n    documents = store.filter_documents()\n    for document in documents:\n        assert document.content, \"content should not be empty\"\n        assert document.meta, \"meta should not be empty\"\n        assert document.meta.get(\"sql_pair_id\"), \"sql_pair_id should be in meta\"\n        assert document.meta.get(\"sql\"), \"sql should be in meta\"\n\n\n@pytest.mark.asyncio\nasync def test_sql_pairs_indexing_saving_to_document_store_with_multiple_project_ids():\n    pipe_components = generate_components(settings.components)\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"sql_pairs_indexing\"\n    ][\"document_store_provider\"]\n    store = document_store_provider.get_store(\n        dataset_name=\"sql_pairs\",\n        recreate_index=True,\n    )\n\n    sql_pairs = SqlPairs(\n        **pipe_components[\"sql_pairs_indexing\"], sql_pairs_path=\"tests/data/pairs.json\"\n    )\n    await sql_pairs.run(\n        mdl_str='{\"models\": [{\"properties\": {\"boilerplate\": \"test\"}}]}',\n        project_id=\"fake-id\",\n    )\n\n    await sql_pairs.run(\n        mdl_str='{\"models\": [{\"properties\": {\"boilerplate\": \"test\"}}]}',\n        project_id=\"fake-id-2\",\n    )\n\n    assert await store.count_documents() == 4\n    documents = store.filter_documents(\n        filters={\n            \"operator\": \"AND\",\n            \"conditions\": [\n                {\"field\": \"project_id\", \"operator\": \"==\", \"value\": \"fake-id\"},\n            ],\n        }\n    )\n    assert len(documents) == 2\n\n\n@pytest.mark.asyncio\nasync def test_sql_pairs_deletion():\n    pipe_components = generate_components(settings.components)\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"sql_pairs_indexing\"\n    ][\"document_store_provider\"]\n    store = document_store_provider.get_store(\n        dataset_name=\"sql_pairs\",\n        recreate_index=True,\n    )\n\n    pipe = SqlPairs(\n        **pipe_components[\"sql_pairs_indexing\"], sql_pairs_path=\"tests/data/pairs.json\"\n    )\n    await pipe.run(\n        mdl_str='{\"models\": [{\"properties\": {\"boilerplate\": \"test\"}}]}',\n        project_id=\"fake-id\",\n    )\n\n    await pipe.clean(sql_pairs=[], project_id=\"fake-id-2\")\n    assert await store.count_documents() == 2\n\n    await pipe.clean(sql_pairs=[], project_id=\"fake-id\")\n    assert await store.count_documents() == 2\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/pipelines/indexing/test_table_description.py",
    "content": "from unittest.mock import AsyncMock\n\nimport orjson\nimport pytest\nfrom haystack import Document\nfrom pytest_mock import MockFixture\n\nfrom src.pipelines.indexing.table_description import (\n    TableDescription,\n    TableDescriptionChunker,\n)\n\n\ndef test_empty_table_descriptions():\n    chunker = TableDescriptionChunker()\n    mdl = {\"models\": [], \"views\": [], \"relationships\": [], \"metrics\": []}\n\n    document = chunker.run(mdl)\n    assert document == {\"documents\": []}\n\n\ndef test_single_table_description():\n    chunker = TableDescriptionChunker()\n    mdl = {\n        \"models\": [\n            {\n                \"name\": \"user\",\n                \"properties\": {\"description\": \"A table containing user information.\"},\n            }\n        ],\n        \"views\": [],\n        \"relationships\": [],\n        \"metrics\": [],\n    }\n\n    actual = chunker.run(mdl)\n    assert len(actual[\"documents\"]) == 1\n\n    document: Document = actual[\"documents\"][0]\n    assert document.meta == {\"type\": \"TABLE_DESCRIPTION\", \"name\": \"user\"}\n    assert document.content == str(\n        {\n            \"name\": \"user\",\n            \"description\": \"A table containing user information.\",\n            \"columns\": \"\",\n        }\n    )\n\n\ndef test_multiple_table_descriptions():\n    chunker = TableDescriptionChunker()\n    mdl = {\n        \"models\": [\n            {\n                \"name\": \"user\",\n                \"properties\": {\"description\": \"A table containing user information.\"},\n            },\n            {\n                \"name\": \"order\",\n                \"properties\": {\"description\": \"A table containing order details.\"},\n            },\n        ],\n        \"views\": [],\n        \"relationships\": [],\n        \"metrics\": [],\n    }\n\n    actual = chunker.run(mdl)\n    assert len(actual[\"documents\"]) == 2\n\n    document_1: Document = actual[\"documents\"][0]\n    assert document_1.meta == {\n        \"type\": \"TABLE_DESCRIPTION\",\n        \"name\": \"user\",\n    }\n    assert document_1.content == str(\n        {\n            \"name\": \"user\",\n            \"description\": \"A table containing user information.\",\n            \"columns\": \"\",\n        }\n    )\n\n    document_2: Document = actual[\"documents\"][1]\n    assert document_2.meta == {\"type\": \"TABLE_DESCRIPTION\", \"name\": \"order\"}\n    assert document_2.content == str(\n        {\n            \"name\": \"order\",\n            \"description\": \"A table containing order details.\",\n            \"columns\": \"\",\n        }\n    )\n\n\ndef test_table_description_missing_name():\n    chunker = TableDescriptionChunker()\n    mdl = {\n        \"models\": [\n            {\n                \"properties\": {\"description\": \"A table without a name.\"},\n            }\n        ],\n        \"views\": [],\n        \"relationships\": [],\n        \"metrics\": [],\n    }\n\n    actual = chunker.run(mdl)\n    assert len(actual[\"documents\"]) == 0\n\n\ndef test_table_description_missing_description():\n    chunker = TableDescriptionChunker()\n    mdl = {\n        \"models\": [{\"name\": \"user\"}],\n        \"views\": [],\n        \"relationships\": [],\n        \"metrics\": [],\n    }\n\n    actual = chunker.run(mdl)\n    assert len(actual[\"documents\"]) == 1\n\n    document: Document = actual[\"documents\"][0]\n    assert document.meta == {\"type\": \"TABLE_DESCRIPTION\", \"name\": \"user\"}\n    assert document.content == str({\"name\": \"user\", \"description\": \"\", \"columns\": \"\"})\n\n\n@pytest.mark.asyncio\nasync def test_pipeline_run(mocker: MockFixture):\n    test_mdl = {\n        \"models\": [\n            {\n                \"name\": \"user\",\n                \"properties\": {\"description\": \"A table containing user information.\"},\n            },\n            {\n                \"name\": \"order\",\n                \"properties\": {\"description\": \"A table containing order details.\"},\n            },\n        ],\n        \"views\": [],\n        \"relationships\": [],\n        \"metrics\": [],\n    }\n\n    # Mock embedder provider\n    embedder_provider = mocker.patch(\"src.core.provider.EmbedderProvider\")\n    embedder = mocker.Mock()\n    mocker.patch.object(\n        embedder,\n        \"run\",\n        new_callable=AsyncMock,\n        side_effect=lambda documents: {\"documents\": documents},\n    )\n    embedder_provider.get_document_embedder.return_value = embedder\n\n    # Mock document store provider\n    document_store = mocker.Mock()\n    mocker.patch.object(\n        document_store, \"delete_documents\", new_callable=AsyncMock, return_value=None\n    )\n    mocker.patch.object(\n        document_store,\n        \"write_documents\",\n        new_callable=AsyncMock,\n        side_effect=lambda documents, *_, **__: len(documents),\n    )\n    document_store_provider = mocker.patch(\"src.core.provider.DocumentStoreProvider\")\n    document_store_provider.get_store.return_value = document_store\n\n    pipeline = TableDescription(\n        embedder_provider=embedder_provider,\n        document_store_provider=document_store_provider,\n    )\n\n    result = await pipeline.run(orjson.dumps(test_mdl), project_id=\"test-project\")\n    assert result is not None\n    assert result == {\"write\": {\"documents_written\": 2}}\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/pipelines/retrieval/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/tests/pytest/pipelines/retrieval/sql_function.py",
    "content": "from unittest.mock import AsyncMock, MagicMock\n\nimport pytest\n\nfrom src.pipelines.retrieval.sql_functions import SqlFunction, SqlFunctions\n\nMOCK_FUNCTION_DEFINITION = {\n    \"name\": \"test_func\",\n    \"param_types\": \"int,text\",\n    \"return_type\": \"boolean\",\n}\n\nMOCK_FUNCTION_LIST = [\n    {\"name\": \"func1\", \"param_types\": \"int\", \"return_type\": \"text\"},\n    {\"name\": \"func2\", \"param_types\": \"text,text\", \"return_type\": \"boolean\"},\n]\n\n\n@pytest.fixture\ndef mock_engine():\n    engine = MagicMock()\n    engine.get_func_list = AsyncMock(return_value=MOCK_FUNCTION_LIST)\n    return engine\n\n\n@pytest.fixture\ndef sql_functions_pipeline(mock_engine):\n    return SqlFunctions(engine=mock_engine)\n\n\ndef test_sql_function_init():\n    func = SqlFunction(MOCK_FUNCTION_DEFINITION)\n    expected = \"test_func($0: int, $1: text) -> boolean\"\n    assert str(func) == expected\n    assert repr(func) == expected\n\n\ndef test_sql_function_empty_params():\n    func = SqlFunction({\"name\": \"test_func\", \"return_type\": \"text\"})\n    assert str(func) == \"test_func(any) -> text\"\n\n\n@pytest.mark.asyncio\nasync def test_sql_functions_pipeline_run(sql_functions_pipeline):\n    result = await sql_functions_pipeline.run(\"postgres\")\n\n    assert len(result) == 2\n    assert str(result[0]) == \"func1($0: int) -> text\"\n    assert str(result[1]) == \"func2($0: text, $1: text) -> boolean\"\n\n    cached_result = await sql_functions_pipeline.run(\"postgres\")\n    assert result == cached_result\n\n    sql_functions_pipeline._components[\"engine\"].get_func_list.assert_called_once()\n\n\n@pytest.mark.asyncio\nasync def test_sql_functions_pipeline_different_datasource(sql_functions_pipeline):\n    await sql_functions_pipeline.run(\"postgres\")\n    await sql_functions_pipeline.run(\"mysql\")\n\n    assert sql_functions_pipeline._components[\"engine\"].get_func_list.call_count == 2\n\n\n@pytest.mark.asyncio\nasync def test_sql_functions_pipeline_case_insensitive(sql_functions_pipeline):\n    result1 = await sql_functions_pipeline.run(\"POSTGRES\")\n    result2 = await sql_functions_pipeline.run(\"postgres\")\n\n    assert sql_functions_pipeline._components[\"engine\"].get_func_list.call_count == 1\n    assert result1 == result2\n\n\ndef test_sql_function_param_type_none():\n    func = SqlFunction(\n        {\"name\": \"test_func\", \"param_types\": None, \"return_type\": \"text\"}\n    )\n    assert str(func) == \"test_func(any) -> text\"\n\n\ndef test_sql_function_return_type_none():\n    func = SqlFunction(\n        {\"name\": \"test_func\", \"param_types\": \"int,text\", \"return_type\": None}\n    )\n    assert str(func) == \"test_func($0: int, $1: text) -> any\"\n\n\ndef test_sql_function_return_type_same_as_args():\n    func = SqlFunction(\n        {\n            \"name\": \"test_func\",\n            \"param_types\": \"int,text\",\n            \"return_type\": \"same as arg types\",\n        }\n    )\n    assert str(func) == \"test_func($0: int, $1: text) -> ['int', 'text']\"\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/providers/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/tests/pytest/providers/test_loader.py",
    "content": "from src.providers import loader\n\n\ndef test_import_mods():\n    loader.import_mods(\"src.providers\")\n    assert len(loader.PROVIDERS) == 6\n\n\ndef test_get_provider():\n    loader.import_mods(\"src.providers\")\n\n    # llm provider\n    provider = loader.get_provider(\"litellm_llm\")\n    assert provider.__name__ == \"LitellmLLMProvider\"\n\n    # embedder provider\n    provider = loader.get_provider(\"litellm_embedder\")\n    assert provider.__name__ == \"LitellmEmbedderProvider\"\n\n    # document store provider\n    provider = loader.get_provider(\"qdrant\")\n    assert provider.__name__ == \"QdrantProvider\"\n\n    # engine provider\n    provider = loader.get_provider(\"wren_ui\")\n    assert provider.__name__ == \"WrenUI\"\n\n    provider = loader.get_provider(\"wren_ibis\")\n    assert provider.__name__ == \"WrenIbis\"\n\n    provider = loader.get_provider(\"wren_engine\")\n    assert provider.__name__ == \"WrenEngine\"\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/providers/test_providers.py",
    "content": "from pytest_mock import MockerFixture\n\nfrom src.core.engine import Engine\nfrom src.core.pipeline import PipelineComponent\nfrom src.core.provider import DocumentStoreProvider, EmbedderProvider, LLMProvider\nfrom src.providers import Configuration, generate_components, transform\n\n\ndef test_transform():\n    config = [\n        {\n            \"type\": \"llm\",\n            \"provider\": \"openai_llm\",\n            \"models\": [\n                {\"model\": \"gpt-4\", \"kwargs\": {\"temperature\": 0, \"max_tokens\": 4096}}\n            ],\n        },\n        {\n            \"type\": \"embedder\",\n            \"provider\": \"openai_embedder\",\n            \"models\": [{\"model\": \"text-embedding-ada-002\", \"dimension\": 1536}],\n        },\n        {\n            \"type\": \"document_store\",\n            \"provider\": \"qdrant\",\n            \"kwargs\": {\"host\": \"localhost\", \"port\": 6333},\n        },\n        {\n            \"type\": \"engine\",\n            \"provider\": \"wren_ui\",\n            \"kwargs\": {\"host\": \"localhost\", \"port\": 8000},\n        },\n        {\n            \"type\": \"pipeline\",\n            \"pipes\": [\n                {\n                    \"name\": \"indexing\",\n                    \"llm\": \"openai_llm.gpt-4\",\n                    \"embedder\": \"openai_embedder.text-embedding-ada-002\",\n                    \"document_store\": \"qdrant\",\n                    \"engine\": \"wren_ui\",\n                }\n            ],\n        },\n    ]\n\n    result = transform(config)\n\n    assert isinstance(result, Configuration)\n    assert \"openai_llm.gpt-4\" in result.providers[\"llm\"]\n    assert \"openai_embedder.text-embedding-ada-002\" in result.providers[\"embedder\"]\n    assert \"qdrant\" in result.providers[\"document_store\"]\n    assert \"wren_ui\" in result.providers[\"engine\"]\n    assert \"indexing\" in result.pipelines\n\n\ndef test_generate_components(mocker: MockerFixture):\n    # Mock the provider_factory to return mock objects\n    mocker.patch(\n        \"src.providers.provider_factory\",\n        side_effect=[\n            mocker.Mock(spec=EmbedderProvider),\n            mocker.Mock(spec=LLMProvider),\n            mocker.Mock(spec=DocumentStoreProvider),\n            mocker.Mock(spec=Engine),\n        ],\n    )\n\n    config = [\n        {\n            \"type\": \"llm\",\n            \"provider\": \"openai_llm\",\n            \"models\": [{\"model\": \"gpt-4\", \"kwargs\": {}}],\n        },\n        {\n            \"type\": \"embedder\",\n            \"provider\": \"openai_embedder\",\n            \"models\": [{\"model\": \"text-embedding-ada-002\", \"dimension\": 1536}],\n        },\n        {\"type\": \"document_store\", \"provider\": \"qdrant\", \"kwargs\": {}},\n        {\"type\": \"engine\", \"provider\": \"wren_ui\", \"kwargs\": {}},\n        {\n            \"type\": \"pipeline\",\n            \"pipes\": [\n                {\n                    \"name\": \"indexing\",\n                    \"llm\": \"openai_llm.gpt-4\",\n                    \"embedder\": \"openai_embedder.text-embedding-ada-002\",\n                    \"document_store\": \"qdrant\",\n                    \"engine\": \"wren_ui\",\n                }\n            ],\n        },\n    ]\n\n    result = generate_components(config)\n\n    assert \"indexing\" in result\n    assert isinstance(result[\"indexing\"], PipelineComponent)\n    assert isinstance(result[\"indexing\"].embedder_provider, EmbedderProvider)\n    assert isinstance(result[\"indexing\"].llm_provider, LLMProvider)\n    assert isinstance(result[\"indexing\"].document_store_provider, DocumentStoreProvider)\n    assert isinstance(result[\"indexing\"].engine, Engine)\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/services/__init__.py",
    "content": ""
  },
  {
    "path": "wren-ai-service/tests/pytest/services/mocks.py",
    "content": "from typing import Optional\n\nfrom src.pipelines import generation, retrieval\nfrom src.web.v1.services import Configuration\nfrom src.web.v1.services.ask import AskHistory\n\n\nclass RetrievalMock(retrieval.DbSchemaRetrieval):\n    def __init__(self, documents: list = []):\n        self._documents = documents\n\n    async def run(self, query: str, project_id: Optional[str] = None):\n        return {\"construct_retrieval_results\": self._documents}\n\n\nclass SqlPairsRetrievalMock(retrieval.SqlPairsRetrieval):\n    def __init__(self, documents: list = []):\n        self._documents = documents\n\n    async def run(self, query: str, project_id: Optional[str] = None):\n        return {\"formatted_output\": {\"documents\": self._documents}}\n\n\nclass InstructionsRetrievalMock(retrieval.Instructions):\n    def __init__(self, documents: list = []):\n        self._documents = documents\n\n    async def run(self, query: str, project_id: Optional[str] = None):\n        return {\"formatted_output\": {\"documents\": self._documents}}\n\n\nclass HistoricalQuestionMock(retrieval.HistoricalQuestionRetrieval):\n    def __init__(self, documents: list = []):\n        self._documents = documents\n\n    async def run(self, query: str, project_id: Optional[str] = None):\n        return {\"formatted_output\": {\"documents\": self._documents}}\n\n\nclass IntentClassificationMock(generation.IntentClassification):\n    def __init__(self, intent: str = \"TEXT_TO_SQL\"):\n        self._intent = intent\n\n    async def run(\n        self,\n        query: str,\n        project_id: Optional[str] = None,\n        histories: Optional[list[AskHistory]] = None,\n        configuration: Configuration | None = None,\n        sql_samples: Optional[list[dict]] = None,\n        instructions: Optional[list[dict]] = None,\n    ):\n        return {\"post_process\": {\"intent\": self._intent, \"db_schemas\": []}}\n\n\nclass GenerationMock(generation.SQLGeneration):\n    def __init__(self, valid: list = [], invalid: list = []):\n        self._valid = valid\n        self._invalid = invalid\n\n    async def run(\n        self,\n        query: str,\n        contexts: list[str],\n        exclude: list[dict],\n        project_id: str | None = None,\n        configuration: Configuration | None = None,\n    ):\n        return {\n            \"post_process\": {\n                \"valid_generation_results\": self._valid,\n                \"invalid_generation_results\": self._invalid,\n            }\n        }\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/services/test_ask.py",
    "content": "import json\nimport uuid\n\nimport orjson\nimport pytest\n\nfrom src.config import settings\nfrom src.pipelines import generation, indexing, retrieval\nfrom src.providers import generate_components\nfrom src.utils import fetch_wren_ai_docs\nfrom src.web.v1.services.ask import (\n    AskRequest,\n    AskResultRequest,\n    AskService,\n)\nfrom src.web.v1.services.semantics_preparation import (\n    SemanticsPreparationRequest,\n    SemanticsPreparationService,\n)\n\n\n@pytest.fixture\ndef ask_service():\n    pipe_components = generate_components(settings.components)\n    wren_ai_docs = fetch_wren_ai_docs(settings.doc_endpoint, settings.is_oss)\n\n    return AskService(\n        {\n            \"intent_classification\": generation.IntentClassification(\n                **pipe_components[\"intent_classification\"],\n                wren_ai_docs=wren_ai_docs,\n            ),\n            \"misleading_assistance\": generation.MisleadingAssistance(\n                **pipe_components[\"misleading_assistance\"],\n            ),\n            \"data_assistance\": generation.DataAssistance(\n                **pipe_components[\"data_assistance\"],\n            ),\n            \"user_guide_assistance\": generation.UserGuideAssistance(\n                **pipe_components[\"user_guide_assistance\"],\n                wren_ai_docs=wren_ai_docs,\n            ),\n            \"retrieval\": retrieval.DbSchemaRetrieval(\n                **pipe_components[\"db_schema_retrieval\"],\n            ),\n            \"historical_question\": retrieval.HistoricalQuestionRetrieval(\n                **pipe_components[\"historical_question_retrieval\"],\n            ),\n            \"sql_generation\": generation.SQLGeneration(\n                **pipe_components[\"sql_generation\"],\n            ),\n            \"sql_correction\": generation.SQLCorrection(\n                **pipe_components[\"sql_correction\"],\n            ),\n            \"sql_pairs_retrieval\": retrieval.SqlPairsRetrieval(\n                **pipe_components[\"sql_pairs_retrieval\"],\n            ),\n            \"instructions_retrieval\": retrieval.Instructions(\n                **pipe_components[\"instructions_retrieval\"],\n            ),\n        }\n    )\n\n\n@pytest.fixture\ndef indexing_service():\n    pipe_components = generate_components(settings.components)\n\n    return SemanticsPreparationService(\n        {\n            \"db_schema\": indexing.DBSchema(\n                **pipe_components[\"db_schema_indexing\"],\n            ),\n            \"historical_question\": indexing.HistoricalQuestion(\n                **pipe_components[\"historical_question_indexing\"],\n            ),\n            \"table_description\": indexing.TableDescription(\n                **pipe_components[\"table_description_indexing\"],\n            ),\n        }\n    )\n\n\n@pytest.fixture\ndef service_metadata():\n    return {\n        \"pipes_metadata\": {\n            \"mock\": {\n                \"generation_model\": \"mock-llm-model\",\n                \"generation_model_kwargs\": {},\n                \"embedding_model\": \"mock-embedding-model\",\n                \"embedding_model_dim\": 768,\n            },\n        },\n        \"service_version\": \"0.8.0-mock\",\n    }\n\n\n@pytest.fixture\ndef mdl_str():\n    with open(\"tests/data/book_2_mdl.json\", \"r\") as f:\n        return orjson.dumps(json.load(f)).decode(\"utf-8\")\n\n\n@pytest.mark.asyncio\nasync def test_ask_with_successful_query(\n    indexing_service: SemanticsPreparationService,\n    ask_service: AskService,\n    mdl_str: str,\n    service_metadata: dict,\n):\n    id = str(uuid.uuid4())\n    await indexing_service.prepare_semantics(\n        SemanticsPreparationRequest(\n            mdl=mdl_str,\n            mdl_hash=id,\n        ),\n        service_metadata=service_metadata,\n    )\n\n    # asking\n    query_id = str(uuid.uuid4())\n    ask_request = AskRequest(\n        query=\"How many books are there?\",\n        mdl_hash=id,\n    )\n    ask_request.query_id = query_id\n    await ask_service.ask(ask_request, service_metadata=service_metadata)\n\n    # getting ask result\n    ask_result_response = ask_service.get_ask_result(\n        AskResultRequest(\n            query_id=query_id,\n        )\n    )\n\n    # from Pao Sheng: I think it has a potential risk if a dangling status case happens.\n    # maybe we could consider adding an approach that if over a time limit,\n    # the process will throw an exception.\n    while (\n        ask_result_response.status != \"finished\"\n        and ask_result_response.status != \"failed\"\n    ):\n        ask_result_response = ask_service.get_ask_result(\n            AskResultRequest(\n                query_id=query_id,\n            )\n        )\n\n    # TODO: we'll refactor almost all test case with a mock server, thus temporarily only assert it is not None.\n    assert ask_result_response.status == \"finished\" or \"failed\"\n    # assert ask_result_response.response is not None\n    # assert ask_result_response.response[0].sql != \"\"\n    # assert ask_result_response.response[0].summary != \"\"\n    # assert ask_result_response.response[0].type == \"llm\" or \"view\"\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/services/test_instructions.py",
    "content": "import uuid\n\nimport pytest\n\nfrom src.config import settings\nfrom src.core.provider import DocumentStoreProvider\nfrom src.globals import create_service_container\nfrom src.providers import generate_components\nfrom src.web.v1.services.instructions import InstructionsService\n\n\n@pytest.fixture\ndef instructions_service():\n    pipe_components = generate_components(settings.components)\n    service_container = create_service_container(pipe_components, settings)\n\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"instructions_indexing\"\n    ][\"document_store_provider\"]\n    document_store_provider.get_store(\n        dataset_name=\"instructions\",\n        recreate_index=True,\n    )\n\n    return service_container.instructions_service\n\n\n@pytest.mark.asyncio\nasync def test_preparation(\n    instructions_service: InstructionsService,\n):\n    id = str(uuid.uuid4())\n    instructions = [\n        InstructionsService.Instruction(\n            id=\"1\",\n            instruction=\"This is a test instruction\",\n            questions=[\"What is the test question?\"],\n            is_default=False,\n        ),\n        InstructionsService.Instruction(\n            id=\"2\",\n            instruction=\"This is another test instruction\",\n            questions=[\"What is another test question?\"],\n            is_default=True,\n        ),\n    ]\n\n    request = InstructionsService.IndexRequest(\n        event_id=id,\n        instructions=instructions,\n        project_id=\"fake-id\",\n    )\n    await instructions_service.index(request)\n\n    response = instructions_service[id]\n\n    assert response.status == \"finished\"\n\n    pipe_components = generate_components(settings.components)\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"instructions_indexing\"\n    ][\"document_store_provider\"]\n    store = document_store_provider.get_store(\n        dataset_name=\"instructions\",\n    )\n    assert await store.count_documents() == 2\n\n\n@pytest.mark.asyncio\nasync def test_with_empty_questions(\n    instructions_service: InstructionsService,\n):\n    id = str(uuid.uuid4())\n\n    request = InstructionsService.IndexRequest(\n        event_id=id,\n        instructions=[\n            InstructionsService.Instruction(\n                id=\"1\",\n                instruction=\"This is a test instruction\",\n                questions=[],\n                is_default=False,\n            )\n        ],\n        project_id=\"fake-id\",\n    )\n\n    await instructions_service.index(request)\n    response = instructions_service[id]\n\n    assert response.status == \"finished\"\n    # No documents should be indexed since there were no questions\n    pipe_components = generate_components(settings.components)\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"instructions_indexing\"\n    ][\"document_store_provider\"]\n    store = document_store_provider.get_store(\n        dataset_name=\"instructions\",\n    )\n    assert await store.count_documents() == 0\n\n\n@pytest.mark.asyncio\nasync def test_with_empty_instructions(\n    instructions_service: InstructionsService,\n):\n    id = str(uuid.uuid4())\n\n    request = InstructionsService.IndexRequest(\n        event_id=id,\n        instructions=[],\n        project_id=\"fake-id\",\n    )\n\n    await instructions_service.index(request)\n    response = instructions_service[id]\n\n    assert response.status == \"finished\"\n\n\n@pytest.mark.asyncio\nasync def test_deletion(\n    instructions_service: InstructionsService,\n):\n    id = str(uuid.uuid4())\n    instructions = [\n        InstructionsService.Instruction(\n            id=\"1\",\n            instruction=\"This is a test instruction\",\n            questions=[\"What is the test question?\"],\n            is_default=False,\n        ),\n        InstructionsService.Instruction(\n            id=\"2\",\n            instruction=\"This is another test instruction\",\n            questions=[\"What is another test question?\"],\n            is_default=True,\n        ),\n    ]\n\n    index_request = InstructionsService.IndexRequest(\n        event_id=id,\n        instructions=instructions,\n        project_id=\"fake-id\",\n    )\n\n    await instructions_service.index(index_request)\n    response = instructions_service[id]\n\n    assert response.status == \"finished\"\n\n    id = str(uuid.uuid4())\n    delete_request = InstructionsService.DeleteRequest(\n        event_id=id,\n        instruction_ids=[\"1\", \"2\"],\n        project_id=\"fake-id\",\n    )\n\n    await instructions_service.delete(delete_request)\n    response = instructions_service[id]\n\n    assert response.status == \"finished\"\n\n    pipe_components = generate_components(settings.components)\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"instructions_indexing\"\n    ][\"document_store_provider\"]\n    store = document_store_provider.get_store(\n        dataset_name=\"instructions\",\n    )\n    assert await store.count_documents() == 0\n\n\n@pytest.mark.asyncio\nasync def test_delete_single_instruction(\n    instructions_service: InstructionsService,\n):\n    id = str(uuid.uuid4())\n    instructions = [\n        InstructionsService.Instruction(\n            id=\"1\",\n            instruction=\"This is a test instruction\",\n            questions=[\"What is the test question?\"],\n            is_default=False,\n        ),\n        InstructionsService.Instruction(\n            id=\"2\",\n            instruction=\"This is another test instruction\",\n            questions=[\"What is another test question?\"],\n            is_default=True,\n        ),\n    ]\n\n    index_request = InstructionsService.IndexRequest(\n        event_id=id,\n        instructions=instructions,\n        project_id=\"fake-id\",\n    )\n\n    await instructions_service.index(index_request)\n    response = instructions_service[id]\n    assert response.status == \"finished\"\n\n    id = str(uuid.uuid4())\n    delete_request = InstructionsService.DeleteRequest(\n        event_id=id,\n        instruction_ids=[\"1\"],\n        project_id=\"fake-id\",\n    )\n\n    await instructions_service.delete(delete_request)\n    response = instructions_service[id]\n    assert response.status == \"finished\"\n\n    pipe_components = generate_components(settings.components)\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"instructions_indexing\"\n    ][\"document_store_provider\"]\n    store = document_store_provider.get_store(\n        dataset_name=\"instructions\",\n    )\n    assert await store.count_documents() == 1\n\n\n@pytest.mark.asyncio\nasync def test_delete_cross_project_instruction(\n    instructions_service: InstructionsService,\n):\n    async def index_instructions(project_id: str):\n        id = str(uuid.uuid4())\n        instructions = [\n            InstructionsService.Instruction(\n                id=\"1\",\n                instruction=\"This is a test instruction\",\n                questions=[\"What is the test question?\"],\n                is_default=False,\n            ),\n        ]\n        index_request = InstructionsService.IndexRequest(\n            event_id=id,\n            instructions=instructions,\n            project_id=project_id,\n        )\n        await instructions_service.index(index_request)\n        response = instructions_service[id]\n        assert response.status == \"finished\"\n\n    await index_instructions(\"project-a\")\n    await index_instructions(\"project-b\")\n\n    id = str(uuid.uuid4())\n    delete_request = InstructionsService.DeleteRequest(\n        event_id=id,\n        instruction_ids=[\"1\"],\n        project_id=\"project-a\",\n    )\n    await instructions_service.delete(delete_request)\n    response = instructions_service[id]\n    assert response.status == \"finished\"\n\n    pipe_components = generate_components(settings.components)\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"instructions_indexing\"\n    ][\"document_store_provider\"]\n\n    store = document_store_provider.get_store(dataset_name=\"instructions\")\n    assert await store.count_documents() == 1\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/services/test_relationship_recommendation.py",
    "content": "from unittest.mock import AsyncMock\n\nimport pytest\n\nfrom src.web.v1.services.relationship_recommendation import RelationshipRecommendation\n\n\n@pytest.fixture\ndef mock_pipeline():\n    return AsyncMock()\n\n\n@pytest.fixture\ndef relationship_recommendation_service(mock_pipeline):\n    pipelines = {\"relationship_recommendation\": mock_pipeline}\n    return RelationshipRecommendation(pipelines)\n\n\n@pytest.mark.asyncio\nasync def test_recommend_success(relationship_recommendation_service, mock_pipeline):\n    request = RelationshipRecommendation.Input(id=\"test_id\", mdl='{\"key\": \"value\"}')\n    mock_pipeline.run.return_value = {\"validated\": {\"test\": \"data\"}}\n\n    await relationship_recommendation_service.recommend(request)\n    response = relationship_recommendation_service[request.id]\n\n    assert response.id == \"test_id\"\n    assert response.status == \"finished\"\n    assert response.response == {\"test\": \"data\"}\n    mock_pipeline.run.assert_called_once_with(mdl={\"key\": \"value\"}, language=\"English\")\n\n\n@pytest.mark.asyncio\nasync def test_recommend_invalid_mdl(relationship_recommendation_service):\n    request = RelationshipRecommendation.Input(id=\"test_id\", mdl=\"invalid_json\")\n\n    await relationship_recommendation_service.recommend(request)\n    response = relationship_recommendation_service[request.id]\n\n    assert response.id == \"test_id\"\n    assert response.status == \"failed\"\n    assert response.error.code == \"MDL_PARSE_ERROR\"\n    assert \"Failed to parse MDL\" in response.error.message\n\n\n@pytest.mark.asyncio\nasync def test_recommend_pipeline_error(\n    relationship_recommendation_service, mock_pipeline\n):\n    request = RelationshipRecommendation.Input(id=\"test_id\", mdl='{\"key\": \"value\"}')\n    mock_pipeline.run.side_effect = Exception(\"Pipeline error\")\n\n    await relationship_recommendation_service.recommend(request)\n    response = relationship_recommendation_service[request.id]\n\n    assert response.id == \"test_id\"\n    assert response.status == \"failed\"\n    assert response.error.code == \"OTHERS\"\n    assert (\n        \"An error occurred during relationship recommendation generation\"\n        in response.error.message\n    )\n\n\ndef test_getitem_existing(relationship_recommendation_service):\n    test_id = \"test_id\"\n    expected_response = RelationshipRecommendation.Resource(\n        id=test_id, status=\"finished\"\n    )\n    relationship_recommendation_service._cache[test_id] = expected_response\n\n    response = relationship_recommendation_service[test_id]\n\n    assert response == expected_response\n    assert response.id == test_id\n    assert response.status == \"finished\"\n\n\ndef test_getitem_not_found(relationship_recommendation_service):\n    id = \"non_existent_id\"\n\n    response = relationship_recommendation_service[id]\n\n    assert response.id == \"non_existent_id\"\n    assert response.status == \"failed\"\n    assert response.error.code == \"RESOURCE_NOT_FOUND\"\n    assert \"not found\" in response.error.message\n\n\ndef test_setitem(relationship_recommendation_service):\n    id = \"test_id\"\n    value = RelationshipRecommendation.Resource(id=\"test_id\", status=\"finished\")\n\n    relationship_recommendation_service[id] = value\n\n    assert relationship_recommendation_service._cache[\"test_id\"] == value\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/services/test_semantics_description.py",
    "content": "import asyncio\nfrom unittest.mock import AsyncMock\n\nimport orjson\nimport pytest\n\nfrom src.web.v1.services import SemanticsDescription\n\n\n@pytest.fixture\ndef service():\n    mock_pipeline = AsyncMock()\n    mock_pipeline.run.return_value = {\n        \"output\": {\n            \"model1\": {\n                \"columns\": [],\n                \"properties\": {\"description\": \"Test description\"},\n            }\n        }\n    }\n\n    pipelines = {\"semantics_description\": mock_pipeline}\n    return SemanticsDescription(pipelines=pipelines)\n\n\n@pytest.mark.asyncio\nasync def test_generate_semantics_description(\n    service: SemanticsDescription,\n):\n    service[\"test_id\"] = SemanticsDescription.Resource(id=\"test_id\")\n    request = SemanticsDescription.GenerateRequest(\n        id=\"test_id\",\n        user_prompt=\"Describe the model\",\n        selected_models=[\"model1\"],\n        mdl='{\"models\": [{\"name\": \"model1\", \"columns\": [{\"name\": \"column1\", \"type\": \"varchar\", \"notNull\": false}]}]}',\n    )\n\n    await service.generate(request)\n    response = service[request.id]\n\n    assert response.id == \"test_id\"\n    assert response.status == \"finished\"\n    assert response.response == {\n        \"model1\": {\n            \"columns\": [],\n            \"properties\": {\"description\": \"Test description\"},\n        }\n    }\n    assert response.error is None\n\n\n@pytest.mark.asyncio\nasync def test_generate_semantics_description_with_invalid_mdl(\n    service: SemanticsDescription,\n):\n    service[\"test_id\"] = SemanticsDescription.Resource(id=\"test_id\")\n    request = SemanticsDescription.GenerateRequest(\n        id=\"test_id\",\n        user_prompt=\"Describe the model\",\n        selected_models=[\"model1\"],\n        mdl=\"invalid_json\",\n    )\n\n    await service.generate(request)\n    response = service[request.id]\n\n    assert response.id == \"test_id\"\n    assert response.status == \"failed\"\n    assert response.response is None\n    assert response.error.code == \"MDL_PARSE_ERROR\"\n    assert \"Failed to parse MDL\" in response.error.message\n\n\n@pytest.mark.asyncio\nasync def test_generate_semantics_description_with_exception(\n    service: SemanticsDescription,\n):\n    service[\"test_id\"] = SemanticsDescription.Resource(id=\"test_id\")\n    request = SemanticsDescription.GenerateRequest(\n        id=\"test_id\",\n        user_prompt=\"Describe the model\",\n        selected_models=[\"model1\"],\n        mdl='{\"models\": [{\"name\": \"model1\", \"columns\": [{\"name\": \"column1\", \"type\": \"varchar\", \"notNull\": false}]}]}',\n    )\n\n    service._pipelines[\"semantics_description\"].run.side_effect = Exception(\n        \"Test exception\"\n    )\n\n    await service.generate(request)\n    response = service[request.id]\n\n    assert response.id == \"test_id\"\n    assert response.status == \"failed\"\n    assert response.response is None\n    assert response.error.code == \"OTHERS\"\n    assert (\n        \"An error occurred during semantics description generation\"\n        in response.error.message\n    )\n\n\ndef test_get_semantics_description_result(\n    service: SemanticsDescription,\n):\n    expected_response = SemanticsDescription.Resource(\n        id=\"test_id\",\n        status=\"finished\",\n        response={\"model1\": {\"description\": \"Test description\"}},\n    )\n    service[\"test_id\"] = expected_response\n\n    result = service[\"test_id\"]\n\n    assert result == expected_response\n\n\ndef test_get_non_existent_semantics_description_result(\n    service: SemanticsDescription,\n):\n    result = service[\"non_existent_id\"]\n\n    assert result.id == \"non_existent_id\"\n    assert result.status == \"failed\"\n    assert result.response is None\n    assert result.error.code == \"RESOURCE_NOT_FOUND\"\n    assert \"not found\" in result.error.message\n\n\n@pytest.mark.asyncio\nasync def test_batch_processing_with_multiple_models(\n    service: SemanticsDescription,\n):\n    service[\"test_id\"] = SemanticsDescription.Resource(id=\"test_id\")\n    request = SemanticsDescription.GenerateRequest(\n        id=\"test_id\",\n        user_prompt=\"Describe the models\",\n        selected_models=[\"model1\", \"model2\", \"model3\"],\n        mdl='{\"models\": [{\"name\": \"model1\", \"columns\": [{\"name\": \"column1\", \"type\": \"varchar\", \"notNull\": false}]}, {\"name\": \"model2\", \"columns\": [{\"name\": \"column1\", \"type\": \"varchar\", \"notNull\": false}]}, {\"name\": \"model3\", \"columns\": [{\"name\": \"column1\", \"type\": \"varchar\", \"notNull\": false}]}]}',\n    )\n\n    # Mock pipeline responses for each chunk\n    service._pipelines[\"semantics_description\"].run.side_effect = [\n        {\"output\": {\"model1\": {\"description\": \"Description 1\"}}},\n        {\"output\": {\"model2\": {\"description\": \"Description 2\"}}},\n        {\"output\": {\"model3\": {\"description\": \"Description 3\"}}},\n    ]\n\n    await service.generate(request)\n    response = service[request.id]\n\n    assert response.id == \"test_id\"\n    assert response.status == \"finished\"\n    assert response.response == {\n        \"model1\": {\"description\": \"Description 1\"},\n        \"model2\": {\"description\": \"Description 2\"},\n        \"model3\": {\"description\": \"Description 3\"},\n    }\n\n    chunks = service._chunking(orjson.loads(request.mdl), request)\n    assert len(chunks) == 3  # Default chunk_size=1\n    assert all(\"user_prompt\" in chunk for chunk in chunks)\n    assert all(\"mdl\" in chunk for chunk in chunks)\n    assert [len(chunk[\"selected_models\"]) for chunk in chunks] == [1, 1, 1]\n\n\ndef test_batch_processing_with_custom_chunk_size(\n    service: SemanticsDescription,\n):\n    service[\"test_id\"] = SemanticsDescription.Resource(id=\"test_id\")\n    request = SemanticsDescription.GenerateRequest(\n        id=\"test_id\",\n        user_prompt=\"Describe the models\",\n        selected_models=[\"model1\", \"model2\", \"model3\", \"model4\"],\n        mdl='{\"models\": [{\"name\": \"model1\", \"columns\": [{\"name\": \"column1\", \"type\": \"varchar\", \"notNull\": false}]}, {\"name\": \"model2\", \"columns\": [{\"name\": \"column1\", \"type\": \"varchar\", \"notNull\": false}]}, {\"name\": \"model3\", \"columns\": [{\"name\": \"column1\", \"type\": \"varchar\", \"notNull\": false}]}, {\"name\": \"model4\", \"columns\": [{\"name\": \"column1\", \"type\": \"varchar\", \"notNull\": false}]}]}',\n    )\n\n    # Test chunking with custom chunk size\n    chunks = service._chunking(orjson.loads(request.mdl), request, chunk_size=2)\n\n    assert len(chunks) == 4\n    assert [len(chunk[\"selected_models\"]) for chunk in chunks] == [1, 1, 1, 1]\n    assert chunks[0][\"selected_models\"] == [\"model1\"]\n    assert chunks[1][\"selected_models\"] == [\"model2\"]\n    assert chunks[2][\"selected_models\"] == [\"model3\"]\n    assert chunks[3][\"selected_models\"] == [\"model4\"]\n\n\n@pytest.mark.asyncio\nasync def test_batch_processing_partial_failure(\n    service: SemanticsDescription,\n):\n    service[\"test_id\"] = SemanticsDescription.Resource(id=\"test_id\")\n    request = SemanticsDescription.GenerateRequest(\n        id=\"test_id\",\n        user_prompt=\"Describe the models\",\n        selected_models=[\"model1\", \"model2\"],\n        mdl='{\"models\": [{\"name\": \"model1\", \"columns\": [{\"name\": \"column1\", \"type\": \"varchar\", \"notNull\": false}]}, {\"name\": \"model2\", \"columns\": [{\"name\": \"column1\", \"type\": \"varchar\", \"notNull\": false}]}]}',\n    )\n\n    # Mock first chunk succeeds, second chunk fails\n    service._pipelines[\"semantics_description\"].run.side_effect = [\n        {\"output\": {\"model1\": {\"description\": \"Description 1\"}}},\n        Exception(\"Failed processing model2\"),\n    ]\n\n    await service.generate(request)\n    response = service[request.id]\n\n    assert response.id == \"test_id\"\n    assert response.status == \"failed\"\n    assert response.error.code == \"OTHERS\"\n    assert \"Failed processing model2\" in response.error.message\n\n\n@pytest.mark.asyncio\nasync def test_concurrent_updates_no_race_condition(\n    service: SemanticsDescription,\n):\n    test_id = \"concurrent_test\"\n    service[test_id] = SemanticsDescription.Resource(id=test_id)\n\n    request = SemanticsDescription.GenerateRequest(\n        id=test_id,\n        user_prompt=\"Test concurrent updates\",\n        selected_models=[\"model1\", \"model2\", \"model3\", \"model4\", \"model5\"],\n        mdl='{\"models\": [{\"name\": \"model1\", \"columns\": [{\"name\": \"column1\", \"type\": \"varchar\", \"notNull\": false}]}, {\"name\": \"model2\", \"columns\": [{\"name\": \"column1\", \"type\": \"varchar\", \"notNull\": false}]}, {\"name\": \"model3\", \"columns\": [{\"name\": \"column1\", \"type\": \"varchar\", \"notNull\": false}]}, {\"name\": \"model4\", \"columns\": [{\"name\": \"column1\", \"type\": \"varchar\", \"notNull\": false}]}, {\"name\": \"model5\", \"columns\": [{\"name\": \"column1\", \"type\": \"varchar\", \"notNull\": false}]}]}',\n    )\n\n    # Mock pipeline responses with delays to simulate concurrent execution\n    async def delayed_response(model_num, delay=0.1):\n        await asyncio.sleep(delay)  # Add delay to increase chance of race condition\n        return {\n            \"output\": {f\"model{model_num}\": {\"description\": f\"Description {model_num}\"}}\n        }\n\n    service._pipelines[\"semantics_description\"].run.side_effect = [\n        await delayed_response(1),\n        await delayed_response(2),\n        await delayed_response(3),\n        await delayed_response(4),\n        await delayed_response(5),\n    ]\n\n    # Generate response which will process chunks concurrently\n    await service.generate(request)\n    response = service[request.id]\n\n    assert response.status == \"finished\"\n    assert response.response is not None\n    assert len(response.response) == 5\n    assert all(f\"model{i}\" in response.response for i in range(1, 6))\n    assert all(\n        response.response[f\"model{i}\"][\"description\"] == f\"Description {i}\"\n        for i in range(1, 6)\n    )\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/services/test_sql_pairs.py",
    "content": "import uuid\n\nimport pytest\n\nfrom src.config import settings\nfrom src.core.provider import DocumentStoreProvider\nfrom src.globals import create_service_container\nfrom src.providers import generate_components\nfrom src.web.v1.services.sql_pairs import SqlPair, SqlPairsService\n\n\n@pytest.fixture\ndef sql_pairs_service():\n    pipe_components = generate_components(settings.components)\n    service_container = create_service_container(pipe_components, settings)\n\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"sql_pairs_indexing\"\n    ][\"document_store_provider\"]\n    document_store_provider.get_store(\n        dataset_name=\"sql_pairs\",\n        recreate_index=True,\n    )\n\n    return service_container.sql_pairs_service\n\n\n@pytest.mark.asyncio\nasync def test_preparation(\n    sql_pairs_service: SqlPairsService,\n):\n    id = str(uuid.uuid4())\n    sql_pairs = [\n        SqlPair(sql=\"SELECT * FROM book\", id=\"1\", question=\"What is the book?\"),\n        SqlPair(sql=\"SELECT * FROM author\", id=\"2\", question=\"What is the author?\"),\n    ]\n\n    request = SqlPairsService.IndexRequest(\n        id=id,\n        sql_pairs=sql_pairs,\n        project_id=\"fake-id\",\n    )\n    await sql_pairs_service.index(request)\n\n    response = sql_pairs_service[id]\n\n    assert response.status == \"finished\"\n\n    pipe_components = generate_components(settings.components)\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"sql_pairs_indexing\"\n    ][\"document_store_provider\"]\n    store = document_store_provider.get_store(\n        dataset_name=\"sql_pairs\",\n    )\n    assert await store.count_documents() == 2\n\n\n@pytest.mark.asyncio\nasync def test_with_empty_question(\n    sql_pairs_service: SqlPairsService,\n):\n    id = str(uuid.uuid4())\n\n    request = SqlPairsService.IndexRequest(\n        id=id,\n        sql_pairs=[SqlPair(sql=\"SELECT * FROM book\", id=\"1\", question=\"\")],\n        project_id=\"fake-id\",\n    )\n\n    await sql_pairs_service.index(request)\n    response = sql_pairs_service[id]\n\n    assert response.status == \"failed\"\n    assert response.error is not None\n    assert response.error.code == \"OTHERS\"\n    assert \"error occurred during SQL pairs indexing\" in response.error.message\n\n    pipe_components = generate_components(settings.components)\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"sql_pairs_indexing\"\n    ][\"document_store_provider\"]\n    store = document_store_provider.get_store(\n        dataset_name=\"sql_pairs\",\n    )\n    assert await store.count_documents() == 0\n\n\n@pytest.mark.asyncio\nasync def test_with_empty_sql_pairs(\n    sql_pairs_service: SqlPairsService,\n):\n    id = str(uuid.uuid4())\n\n    request = SqlPairsService.IndexRequest(\n        id=id,\n        sql_pairs=[],\n        project_id=\"fake-id\",\n    )\n\n    await sql_pairs_service.index(request)\n    response = sql_pairs_service[id]\n\n    assert response.status == \"finished\"\n\n\n@pytest.mark.asyncio\nasync def test_deletion(\n    sql_pairs_service: SqlPairsService,\n):\n    id = str(uuid.uuid4())\n    sql_pairs = [\n        SqlPair(sql=\"SELECT * FROM book\", id=\"1\", question=\"What is the book?\"),\n        SqlPair(sql=\"SELECT * FROM author\", id=\"2\", question=\"What is the author?\"),\n    ]\n\n    index_request = SqlPairsService.IndexRequest(\n        id=id,\n        sql_pairs=sql_pairs,\n        project_id=\"fake-id\",\n    )\n\n    await sql_pairs_service.index(index_request)\n    response = sql_pairs_service[id]\n\n    assert response.status == \"finished\"\n\n    id = str(uuid.uuid4())\n    delete_request = SqlPairsService.DeleteRequest(\n        id=id,\n        sql_pair_ids=[\"1\", \"2\"],\n        project_id=\"fake-id\",\n    )\n\n    await sql_pairs_service.delete(delete_request)\n    response = sql_pairs_service[id]\n\n    assert response.status == \"finished\"\n\n    pipe_components = generate_components(settings.components)\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"sql_pairs_indexing\"\n    ][\"document_store_provider\"]\n    store = document_store_provider.get_store(\n        dataset_name=\"sql_pairs\",\n    )\n    assert await store.count_documents() == 0\n\n\n@pytest.mark.asyncio\nasync def test_delete_single_sql_pair(\n    sql_pairs_service: SqlPairsService,\n):\n    id = str(uuid.uuid4())\n    sql_pairs = [\n        SqlPair(sql=\"SELECT * FROM book\", id=\"1\", question=\"What is the book?\"),\n        SqlPair(sql=\"SELECT * FROM author\", id=\"2\", question=\"What is the author?\"),\n    ]\n\n    index_request = SqlPairsService.IndexRequest(\n        id=id,\n        sql_pairs=sql_pairs,\n        project_id=\"fake-id\",\n    )\n\n    await sql_pairs_service.index(index_request)\n    response = sql_pairs_service[id]\n    assert response.status == \"finished\"\n\n    id = str(uuid.uuid4())\n    delete_request = SqlPairsService.DeleteRequest(\n        id=id,\n        sql_pair_ids=[\"1\"],\n        project_id=\"fake-id\",\n    )\n\n    await sql_pairs_service.delete(delete_request)\n    response = sql_pairs_service[id]\n    assert response.status == \"finished\"\n\n    pipe_components = generate_components(settings.components)\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"sql_pairs_indexing\"\n    ][\"document_store_provider\"]\n    store = document_store_provider.get_store(\n        dataset_name=\"sql_pairs\",\n    )\n    assert await store.count_documents() == 1\n\n\n@pytest.mark.asyncio\nasync def test_delete_cross_project_sql_pair(\n    sql_pairs_service: SqlPairsService,\n):\n    async def index_sql_pairs(project_id: str):\n        id = str(uuid.uuid4())\n        sql_pairs = [\n            SqlPair(sql=\"SELECT * FROM book\", id=\"1\", question=\"What is the book?\"),\n        ]\n        index_request = SqlPairsService.IndexRequest(\n            id=id,\n            sql_pairs=sql_pairs,\n            project_id=project_id,\n        )\n        await sql_pairs_service.index(index_request)\n        response = sql_pairs_service[id]\n        assert response.status == \"finished\"\n\n    await index_sql_pairs(\"project-a\")\n    await index_sql_pairs(\"project-b\")\n\n    id = str(uuid.uuid4())\n    delete_request = SqlPairsService.DeleteRequest(\n        id=id,\n        sql_pair_ids=[\"1\"],\n        project_id=\"project-a\",\n    )\n    await sql_pairs_service.delete(delete_request)\n    response = sql_pairs_service[id]\n    assert response.status == \"finished\"\n\n    pipe_components = generate_components(settings.components)\n    document_store_provider: DocumentStoreProvider = pipe_components[\n        \"sql_pairs_indexing\"\n    ][\"document_store_provider\"]\n\n    store = document_store_provider.get_store(dataset_name=\"sql_pairs\")\n    assert await store.count_documents() == 1\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/test_config.py",
    "content": "from unittest.mock import mock_open, patch\n\nimport yaml\n\nfrom src.config import Settings\n\n\ndef test_settings_default_values():\n    with patch(\"src.config.Settings.config_loader\", return_value=[]):\n        settings = Settings()\n        assert settings.host == \"127.0.0.1\"\n        assert settings.port == 5555\n\n        assert settings.column_indexing_batch_size == 50\n        assert settings.table_retrieval_size == 10\n        assert settings.table_column_retrieval_size == 100\n\n        assert settings.query_cache_ttl == 3600\n        assert settings.query_cache_maxsize == 1_000_000\n\n        assert settings.langfuse_host == \"https://cloud.langfuse.com\"\n        assert settings.langfuse_enable is True\n\n        assert settings.logging_level == \"INFO\"\n        assert settings.development is False\n\n        assert settings.config_path == \"config.yaml\"\n\n\ndef test_settings_env_var_override():\n    env_vars = {\n        \"WREN_AI_SERVICE_HOST\": \"0.0.0.0\",\n        \"WREN_AI_SERVICE_PORT\": \"8000\",\n        \"LOGGING_LEVEL\": \"DEBUG\",\n    }\n\n    with patch(\"src.config.Settings.config_loader\", return_value=[]), patch.dict(\n        \"os.environ\", env_vars\n    ):\n        settings = Settings()\n        assert settings.host == env_vars[\"WREN_AI_SERVICE_HOST\"]\n        assert settings.port == int(env_vars[\"WREN_AI_SERVICE_PORT\"])\n        assert settings.logging_level == env_vars[\"LOGGING_LEVEL\"]\n\n\ndef test_settings_env_dev_override():\n    # Mock the content of .env.dev file\n    mock_env_dev_content = \"\"\"\n    WREN_AI_SERVICE_HOST=localhost\n    WREN_AI_SERVICE_PORT=7000\n    LOGGING_LEVEL=WARNING\n    \"\"\"\n\n    # Mock the load_dotenv function\n    with patch(\"src.config.Settings.config_loader\", return_value=[]), patch(\n        \"src.config.load_dotenv\"\n    ) as mock_load_dotenv:\n        # Set up the mock to load our custom environment variables\n        def side_effect(path, override):\n            import os\n\n            for line in mock_env_dev_content.strip().split(\"\\n\"):\n                key, value = line.strip().split(\"=\")\n                os.environ[key] = value\n\n        mock_load_dotenv.side_effect = side_effect\n\n        settings = Settings()\n\n        assert settings.host == \"localhost\"\n        assert settings.port == 7000\n        assert settings.logging_level == \"WARNING\"\n\n\ndef test_settings_yaml_config_override():\n    # Mock YAML config content\n    mock_yaml_content = \"\"\"\n    settings:\n      host: 192.168.1.100\n      port: 9000\n      column_indexing_batch_size: 75\n      table_retrieval_size: 15\n      logging_level: ERROR\n      development: true\n    \"\"\"\n\n    # Patch the open function to return our mock YAML content\n    with patch(\"builtins.open\", mock_open(read_data=mock_yaml_content)):\n        # Patch os.path.exists to return True for our config file\n        with patch(\"os.path.exists\", return_value=True):\n            settings = Settings()\n\n            assert settings.host == \"192.168.1.100\"\n            assert settings.port == 9000\n            assert settings.column_indexing_batch_size == 75\n            assert settings.table_retrieval_size == 15\n            assert settings.logging_level == \"ERROR\"\n            assert settings.development is True\n\n            # Check that a value not in the YAML config remains at its default\n            assert settings.query_cache_maxsize == 1_000_000\n\n\ndef test_settings_components():\n    mock_config_content = [\n        {\n            \"settings\": {\n                \"host\": \"0.0.0.0\",\n                \"port\": 8000,\n                \"column_indexing_batch_size\": 100,\n                \"table_retrieval_size\": 20,\n                \"logging_level\": \"DEBUG\",\n            }\n        },\n        {\n            \"type\": \"llm\",\n            \"provider\": \"openai_llm\",\n            \"models\": [{\"model\": \"gpt-4\", \"kwargs\": {}}],\n        },\n    ]\n\n    with patch(\n        \"builtins.open\",\n        new_callable=mock_open,\n        read_data=yaml.dump_all(mock_config_content),\n    ):\n        settings = Settings()\n        assert len(settings._components) == 1\n        assert settings._components[0][\"type\"] == \"llm\"\n        assert settings._components[0][\"provider\"] == \"openai_llm\"\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/test_main.py",
    "content": "import json\nimport os\nimport uuid\n\nimport orjson\nimport pytest\nfrom fastapi.testclient import TestClient\n\n\n@pytest.fixture(scope=\"module\", autouse=True)\ndef app():\n    os.environ[\"CONFIG_PATH\"] = \"tests/data/config.test.yaml\"\n    from src.__main__ import app\n\n    yield app\n    # Clean up (if necessary)\n    del os.environ[\"CONFIG_PATH\"]\n\n\nGLOBAL_DATA = {\n    \"semantics_preperation_id\": str(uuid.uuid4()),\n    \"query_id\": None,\n}\n\n\ndef test_semantics_preparation(app):\n    with TestClient(app) as client:\n        semantics_preperation_id = GLOBAL_DATA[\"semantics_preperation_id\"]\n\n        with open(\"tests/data/book_2_mdl.json\", \"r\") as f:\n            mdl_str = orjson.dumps(json.load(f)).decode(\"utf-8\")\n\n        response = client.post(\n            url=\"/v1/semantics-preparations\",\n            json={\n                \"mdl\": mdl_str,\n                \"id\": semantics_preperation_id,\n            },\n        )\n\n        assert response.status_code == 200\n        assert response.json()[\"id\"] == semantics_preperation_id\n\n        status = \"indexing\"\n\n        while status == \"indexing\":\n            response = client.get(\n                url=f\"/v1/semantics-preparations/{semantics_preperation_id}/status\"\n            )\n\n            assert response.status_code == 200\n            assert response.json()[\"status\"] in [\"indexing\", \"finished\", \"failed\"]\n            status = response.json()[\"status\"]\n\n        assert status == \"finished\"\n\n\ndef test_asks_with_successful_query(app):\n    with TestClient(app) as client:\n        semantics_preparation_id = GLOBAL_DATA[\"semantics_preperation_id\"]\n\n        response = client.post(\n            url=\"/v1/asks\",\n            json={\n                \"query\": \"How many books are there?\",\n                \"id\": semantics_preparation_id,\n            },\n        )\n\n        assert response.status_code == 200\n        assert response.json()[\"query_id\"] != \"\"\n\n        query_id = response.json()[\"query_id\"]\n        GLOBAL_DATA[\"query_id\"] = query_id\n\n        response = client.get(url=f\"/v1/asks/{query_id}/result\")\n        while (\n            response.json()[\"status\"] != \"finished\"\n            and response.json()[\"status\"] != \"failed\"\n        ):\n            response = client.get(url=f\"/v1/asks/{query_id}/result\")\n\n        # TODO: we'll refactor almost all test case with a mock server, thus temporarily only assert the status is finished or failed.\n        assert response.status_code == 200\n        assert response.json()[\"status\"] == \"finished\" or \"failed\"\n        # for r in response.json()[\"response\"]:\n        #     assert r[\"sql\"] is not None and r[\"sql\"] != \"\"\n        #     assert r[\"summary\"] is not None and r[\"summary\"] != \"\"\n\n\ndef test_stop_asks(app):\n    with TestClient(app) as client:\n        query_id = GLOBAL_DATA[\"query_id\"]\n\n        response = client.patch(\n            url=f\"/v1/asks/{query_id}\",\n            json={\n                \"status\": \"stopped\",\n            },\n        )\n\n        assert response.status_code == 200\n        assert response.json()[\"query_id\"] == query_id\n\n        response = client.get(url=f\"/v1/asks/{query_id}/result\")\n        while response.json()[\"status\"] != \"stopped\":\n            response = client.get(url=f\"/v1/asks/{query_id}/result\")\n\n        assert response.status_code == 200\n        assert response.json()[\"status\"] == \"stopped\"\n\n\ndef test_web_error_handler(app):\n    with TestClient(app) as client:\n        response = client.post(\n            url=\"/v1/asks\",\n            json={},\n        )\n\n        assert response.status_code == 400\n        assert response.json()[\"detail\"] != \"\"\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/test_usecases.py",
    "content": "import argparse\nimport asyncio\nimport base64\nimport json\nimport os\nimport time\nimport uuid\nfrom datetime import datetime\n\nimport aiohttp\nimport orjson\nimport requests\nimport sqlparse\nimport yaml\nfrom dotenv import load_dotenv\n\nload_dotenv(\".env.dev\", override=True)\n\nWREN_AI_SERVICE_BASE_URL = \"http://localhost:5556\"\nWREN_ENGINE_API_URL = \"http://localhost:8080\"\n\n\ndef _get_connection_info(data_source: str):\n    if data_source == \"bigquery\":\n        return {\n            \"project_id\": os.getenv(\"bigquery.project-id\"),\n            \"dataset_id\": os.getenv(\"bigquery.dataset-id\"),\n            \"credentials\": os.getenv(\"bigquery.credentials-key\"),\n        }\n    elif data_source == \"postgres\":\n        return {\n            \"host\": os.getenv(\"postgres.host\"),\n            \"port\": os.getenv(\"postgres.port\"),\n            \"database\": os.getenv(\"postgres.database\"),\n            \"user\": os.getenv(\"postgres.user\"),\n            \"password\": os.getenv(\"postgres.password\"),\n        }\n\n\ndef _prepare_duckdb(dataset_name: str):\n    assert dataset_name in [\"ecommerce\", \"hr\"]\n\n    init_sqls = {\n        \"ecommerce\": \"\"\"\nCREATE TABLE olist_customers_dataset AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_customers_dataset.parquet');\nCREATE TABLE olist_order_items_dataset AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_order_items_dataset.parquet');\nCREATE TABLE olist_orders_dataset AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_orders_dataset.parquet');\nCREATE TABLE olist_order_payments_dataset AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_order_payments_dataset.parquet');\nCREATE TABLE olist_products_dataset AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_products_dataset.parquet');\nCREATE TABLE olist_order_reviews_dataset AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_order_reviews_dataset.parquet');\nCREATE TABLE olist_geolocation_dataset AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_geolocation_dataset.parquet');\nCREATE TABLE olist_sellers_dataset AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_sellers_dataset.parquet');\nCREATE TABLE product_category_name_translation AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/product_category_name_translation.parquet');\n\"\"\",\n        \"hr\": \"\"\"\nCREATE TABLE salaries AS FROM read_parquet('https://assets.getwren.ai/sample_data/employees/salaries.parquet');\nCREATE TABLE titles AS FROM read_parquet('https://assets.getwren.ai/sample_data/employees/titles.parquet');\nCREATE TABLE dept_emp AS FROM read_parquet('https://assets.getwren.ai/sample_data/employees/dept_emp.parquet');\nCREATE TABLE departments AS FROM read_parquet('https://assets.getwren.ai/sample_data/employees/departments.parquet');\nCREATE TABLE employees AS FROM read_parquet('https://assets.getwren.ai/sample_data/employees/employees.parquet');\nCREATE TABLE dept_manager AS FROM read_parquet('https://assets.getwren.ai/sample_data/employees/dept_manager.parquet');\n\"\"\",\n    }\n\n    with open(\"./tools/dev/etc/duckdb-init.sql\", \"w\") as f:\n        f.write(\"\")\n\n    response = requests.put(\n        f\"{WREN_ENGINE_API_URL}/v1/data-source/duckdb/settings/init-sql\",\n        data=init_sqls[dataset_name],\n    )\n\n    assert response.status_code == 200, response.text\n\n\ndef _update_wren_engine_configs(configs: list[dict]):\n    response = requests.patch(\n        f\"{WREN_ENGINE_API_URL}/v1/config\",\n        json=configs,\n    )\n\n    assert response.status_code == 200\n\n\ndef _replace_wren_engine_env_variables(engine_type: str, data: dict):\n    assert engine_type in (\"wren_engine\", \"wren_ibis\")\n\n    with open(\"config.yaml\", \"r\") as f:\n        configs = list(yaml.safe_load_all(f))\n\n        for config in configs:\n            if config.get(\"type\") == \"engine\" and config.get(\"provider\") == engine_type:\n                for key, value in data.items():\n                    config[key] = value\n            if \"pipes\" in config:\n                for i, pipe in enumerate(config[\"pipes\"]):\n                    if \"engine\" in pipe and pipe[\"name\"] != \"sql_functions_retrieval\":\n                        config[\"pipes\"][i][\"engine\"] = engine_type\n\n    with open(\"config.yaml\", \"w\") as f:\n        yaml.safe_dump_all(configs, f, default_flow_style=False)\n\n\ndef is_ai_service_ready(url: str):\n    try:\n        response = requests.get(f\"{url}/health\")\n        return response.status_code == 200\n    except requests.exceptions.ConnectionError:\n        return False\n\n\ndef test_load_mdl_and_questions(usecases: list[str]):\n    mdls_and_questions = {}\n    for usecase in usecases:\n        try:\n            with open(f\"tests/data/usecases/{usecase}/mdl.json\", \"r\") as f:\n                mdl_str = orjson.dumps(json.load(f)).decode(\"utf-8\")\n\n            with open(f\"tests/data/usecases/{usecase}/questions.yaml\", \"r\") as f:\n                questions = yaml.safe_load(f)\n\n            mdls_and_questions[usecase] = {\n                \"mdl_str\": mdl_str,\n                \"questions\": [question[\"question\"] for question in questions],\n            }\n        except FileNotFoundError:\n            raise Exception(\n                f\"tests/data/usecases/{usecase}/mdl.json or tests/data/usecases/{usecase}/questions.yaml not found\"\n            )\n\n    return mdls_and_questions\n\n\ndef setup_datasource(mdl_str: str, dataset: str, dataset_type: str, url: str):\n    assert dataset_type in [\"bigquery\", \"duckdb\"]\n\n    manifest = base64.b64encode(mdl_str.encode(\"utf-8\")).decode(\"utf-8\")\n    if dataset_type == \"bigquery\":\n        connection_info = _get_connection_info(dataset_type)\n        _replace_wren_engine_env_variables(\n            \"wren_ibis\",\n            {\n                \"manifest\": manifest,\n                \"source\": dataset_type,\n                \"connection_info\": base64.b64encode(\n                    orjson.dumps(connection_info)\n                ).decode(),\n            },\n        )\n    elif dataset_type == \"duckdb\":\n        _update_wren_engine_configs(\n            [\n                {\n                    \"name\": \"duckdb.connector.init-sql-path\",\n                    \"value\": \"/usr/src/app/etc/duckdb-init.sql\",\n                },\n            ]\n        )\n        _prepare_duckdb(dataset)\n        _replace_wren_engine_env_variables(\"wren_engine\", {\"manifest\": manifest})\n\n    ready = False\n    while not ready:\n        ready = is_ai_service_ready(url)\n        time.sleep(1)\n\n\ndef deploy_mdl(mdl_str: str, url: str):\n    semantics_preperation_id = str(uuid.uuid4())\n    response = requests.post(\n        f\"{url}/v1/semantics-preparations\",\n        json={\"mdl\": mdl_str, \"id\": semantics_preperation_id},\n    )\n    assert response.status_code == 200\n\n    status = \"indexing\"\n    while status == \"indexing\":\n        response = requests.get(\n            f\"{url}/v1/semantics-preparations/{semantics_preperation_id}/status\"\n        )\n\n        assert response.status_code == 200\n        status = response.json()[\"status\"]\n\n    assert status == \"finished\"\n\n    return semantics_preperation_id\n\n\nasync def ask_question(\n    question: str, url: str, semantics_preperation_id: str, lang: str = \"English\"\n):\n    print(f\"preparing to ask question: {question}\")\n    async with aiohttp.ClientSession() as session:\n        start = time.time()\n        response = await session.post(\n            f\"{url}/v1/asks\",\n            json={\n                \"query\": question,\n                \"id\": semantics_preperation_id,\n                \"configurations\": {\"language\": lang},\n            },\n        )\n        assert response.status == 200\n\n        query_id = (await response.json())[\"query_id\"]\n\n        response = await session.get(f\"{url}/v1/asks/{query_id}/result\")\n        while (await response.json())[\"status\"] != \"finished\" and (\n            await response.json()\n        )[\"status\"] != \"failed\":\n            response = await session.get(f\"{url}/v1/asks/{query_id}/result\")\n\n        assert response.status == 200\n\n        result = await response.json()\n        result[\"time\"] = time.time() - start\n\n        print(f\"got the result of question: {question}\")\n        return result\n\n\nasync def ask_questions(\n    questions: list[str], url: str, semantics_preperation_id: str, lang: str = \"English\"\n):\n    tasks = []\n    for question in questions:\n        task = asyncio.ensure_future(\n            ask_question(question, url, semantics_preperation_id, lang)\n        )\n        tasks.append(task)\n        await asyncio.sleep(10)\n\n    return await asyncio.gather(*tasks)\n\n\ndef str_presenter(dumper, data):\n    \"\"\"configures yaml for dumping multiline strings\n    Ref: https://stackoverflow.com/questions/8640959/how-can-i-control-what-scalar-form-pyyaml-uses-for-my-data\"\"\"\n    if len(data.splitlines()) > 1:  # check for multiline string\n        return dumper.represent_scalar(\"tag:yaml.org,2002:str\", data, style=\"|\")\n    return dumper.represent_scalar(\"tag:yaml.org,2002:str\", data)\n\n\nif __name__ == \"__main__\":\n    usecase_to_dataset_type = {\n        \"hubspot\": \"bigquery\",\n        \"ga4\": \"bigquery\",\n        \"woocommerce\": \"bigquery\",\n        \"stripe\": \"bigquery\",\n        \"ecommerce\": \"duckdb\",\n        # \"hr\": \"duckdb\",\n        \"facebook_marketing\": \"bigquery\",\n        \"google_ads\": \"bigquery\",\n    }\n    usecases = list(usecase_to_dataset_type.keys())\n\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\n        \"--usecases\",\n        type=str,\n        nargs=\"+\",\n        default=[\"all\"],\n        choices=[\"all\"] + usecases,\n    )\n    parser.add_argument(\n        \"--lang\",\n        type=str,\n        choices=[\"en\", \"zh-TW\", \"zh-CN\"],\n        default=\"en\",\n    )\n    args = parser.parse_args()\n\n    if \"all\" not in args.usecases:\n        usecases = args.usecases\n\n    lang = {\n        \"en\": \"English\",\n        \"zh-TW\": \"Traditional Chinese\",\n        \"zh-CN\": \"Simplified Chinese\",\n    }[args.lang]\n\n    assert is_ai_service_ready(\n        WREN_AI_SERVICE_BASE_URL\n    ), \"WrenAI AI service is not running, please start it first via 'just up && just start'\"\n\n    mdls_and_questions_by_usecase = test_load_mdl_and_questions(usecases)\n\n    final_results = {}\n    for usecase, data in mdls_and_questions_by_usecase.items():\n        print(f\"testing usecase: {usecase}\")\n\n        setup_datasource(\n            data[\"mdl_str\"],\n            usecase,\n            usecase_to_dataset_type[usecase],\n            WREN_AI_SERVICE_BASE_URL,\n        )\n\n        semantics_preperation_id = deploy_mdl(data[\"mdl_str\"], WREN_AI_SERVICE_BASE_URL)\n\n        # ask questions\n        results = asyncio.run(\n            ask_questions(\n                data[\"questions\"],\n                WREN_AI_SERVICE_BASE_URL,\n                semantics_preperation_id,\n                lang,\n            )\n        )\n        assert len(results) == len(data[\"questions\"])\n\n        final_results[usecase] = {\n            \"results\": [],\n        }\n        # count the number of results that are failed\n        for question, result in zip(data[\"questions\"], results):\n            if (\n                result.get(\"status\") == \"finished\"\n                and not result.get(\"error\")\n                and result.get(\"response\", [])\n            ):\n                result[\"response\"][0][\"sql\"] = sqlparse.format(\n                    result[\"response\"][0][\"sql\"],\n                    reindent=True,\n                    keyword_case=\"upper\",\n                )\n\n            final_results[usecase][\"results\"].append(\n                {\n                    \"question\": question,\n                    \"result\": result,\n                }\n            )\n\n        final_results[usecase][\"total\"] = len(results)\n        final_results[usecase][\"failed\"] = sum(\n            1 for result in results if result[\"status\"] == \"failed\"\n        )\n\n    # write final_results to a json file\n    if not os.path.exists(\"outputs\"):\n        os.makedirs(\"outputs\")\n\n    with open(\n        f\"outputs/usecases_final_results_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.yaml\",\n        \"w\",\n    ) as f:\n        yaml.add_representer(str, str_presenter)\n        yaml.representer.SafeRepresenter.add_representer(\n            str, str_presenter\n        )  # to use with safe_dum\n        yaml.safe_dump(final_results, f, sort_keys=False, allow_unicode=True)\n"
  },
  {
    "path": "wren-ai-service/tests/pytest/test_utils.py",
    "content": "import asyncio\nimport os\nfrom dataclasses import asdict\n\nimport pytest\nfrom pytest_mock import MockFixture\n\nimport src.utils as utils\nfrom src.core.pipeline import PipelineComponent\nfrom src.globals import ServiceMetadata, create_service_metadata\nfrom src.pipelines.indexing import clean_display_name\n\n\ndef _mock(mocker: MockFixture) -> tuple:\n    llm_provider = mocker.patch(\"src.core.provider.LLMProvider\")\n    mocker.patch(\n        \"src.core.provider.LLMProvider.get_model\", return_value=\"mock-llm-model\"\n    )\n    mocker.patch(\n        \"src.core.provider.LLMProvider.get_model_kwargs\",\n        return_value={},\n    )\n\n    embedder_provider = mocker.patch(\"src.core.provider.EmbedderProvider\")\n    mocker.patch(\n        \"src.core.provider.EmbedderProvider.get_model\",\n        return_value=\"mock-embedding-model\",\n    )\n    mocker.patch(\n        \"src.core.provider.EmbedderProvider.get_model_dimension\",\n        return_value=768,\n    )\n\n    return llm_provider, embedder_provider\n\n\n@pytest.fixture\ndef service_metadata(mocker: MockFixture):\n    current_path = os.path.dirname(__file__)\n\n    return create_service_metadata(\n        pipe_components={\"mock\": PipelineComponent(*_mock(mocker))},\n        pyproject_path=os.path.join(current_path, \"../data/mock_pyproject.toml\"),\n    )\n\n\ndef test_service_metadata(service_metadata: ServiceMetadata):\n    assert service_metadata.pipes_metadata == {\n        \"mock\": {\n            \"llm_model\": \"mock-llm-model\",\n            \"llm_model_kwargs\": {},\n            \"embedding_model\": \"mock-embedding-model\",\n        },\n    }\n\n    assert service_metadata.service_version == \"0.8.0-mock\"\n\n\ndef test_trace_metadata(service_metadata: ServiceMetadata, mocker: MockFixture):\n    function = mocker.patch(\n        \"src.utils.langfuse_context.update_current_trace\", return_value=None\n    )\n\n    class Request:\n        project_id = \"mock-project-id\"\n        thread_id = \"mock-thread-id\"\n        mdl_hash = \"mock-mdl-hash\"\n        query = \"mock-user-query\"\n\n    @utils.trace_metadata\n    async def my_function(_: str, b: Request, **kwargs):\n        return \"Hello, World!\"\n\n    asyncio.run(my_function(\"\", Request(), service_metadata=asdict(service_metadata)))\n\n    function.assert_called_once_with(\n        user_id=None,\n        session_id=\"mock-thread-id\",\n        release=service_metadata.service_version,\n        metadata={\n            \"mdl_hash\": \"mock-mdl-hash\",\n            \"project_id\": \"mock-project-id\",\n            \"query\": \"mock-user-query\",\n            **service_metadata.pipes_metadata,\n        },\n    )\n\n\ndef test_clean_display_name():\n    # Test empty and None cases\n    assert clean_display_name(\"\") == \"\"\n\n    # Test simple valid names (should remain unchanged)\n    assert clean_display_name(\"valid_name\") == \"valid_name\"\n    assert clean_display_name(\"ValidName\") == \"ValidName\"\n    assert clean_display_name(\"valid123\") == \"valid123\"\n\n    # Test prefix invalid characters - numbers and special chars\n    assert clean_display_name(\"123name\") == \"_123name\"\n    assert clean_display_name(\"-name\") == \"_name\"\n    assert clean_display_name(\"&name\") == \"_name\"\n    assert clean_display_name(\"%name\") == \"_name\"\n    assert clean_display_name(\"=name\") == \"_name\"\n    assert clean_display_name(\"+name\") == \"_name\"\n    assert clean_display_name(\"'name\") == \"_name\"\n    assert clean_display_name('\"name') == \"_name\"\n    assert clean_display_name(\"<name\") == \"_name\"\n    assert clean_display_name(\">name\") == \"_name\"\n    assert clean_display_name(\"#name\") == \"_name\"\n    assert clean_display_name(\"|name\") == \"_name\"\n    assert clean_display_name(\"!name\") == \"_name\"\n    assert clean_display_name(\"(name\") == \"_name\"\n    assert clean_display_name(\")name\") == \"_name\"\n    assert clean_display_name(\"*name\") == \"_name\"\n    assert clean_display_name(\",name\") == \"_name\"\n    assert clean_display_name(\"/name\") == \"_name\"\n    assert clean_display_name(\".name\") == \"_name\"\n    assert clean_display_name(\";name\") == \"_name\"\n    assert clean_display_name(\"[name\") == \"_name\"\n    assert clean_display_name(\"\\\\name\") == \"_name\"\n    assert clean_display_name(\"]name\") == \"_name\"\n    assert clean_display_name(\"^name\") == \"_name\"\n    assert clean_display_name(\"{name\") == \"_name\"\n    assert clean_display_name(\"}name\") == \"_name\"\n    assert clean_display_name(\"~name\") == \"_name\"\n\n    # Test middle invalid characters\n    assert clean_display_name(\"na-me\") == \"na_me\"\n    assert clean_display_name(\"na&me\") == \"na_me\"\n    assert clean_display_name(\"na%me\") == \"na_me\"\n    assert clean_display_name(\"na=me\") == \"na_me\"\n    assert clean_display_name(\"na+me\") == \"na_me\"\n    assert clean_display_name(\"na'me\") == \"na_me\"\n    assert clean_display_name('na\"me') == \"na_me\"\n    assert clean_display_name(\"na<me\") == \"na_me\"\n    assert clean_display_name(\"na>me\") == \"na_me\"\n    assert clean_display_name(\"na#me\") == \"na_me\"\n    assert clean_display_name(\"na|me\") == \"na_me\"\n    assert clean_display_name(\"na!me\") == \"na_me\"\n    assert clean_display_name(\"na(me\") == \"na_me\"\n    assert clean_display_name(\"na)me\") == \"na_me\"\n    assert clean_display_name(\"na/me\") == \"na_me\"\n    assert clean_display_name(\"na.me\") == \"na_me\"\n    assert clean_display_name(\"na?me\") == \"na_me\"\n    assert clean_display_name(\"na[me\") == \"na_me\"\n    assert clean_display_name(\"na\\\\me\") == \"na_me\"\n    assert clean_display_name(\"na]me\") == \"na_me\"\n    assert clean_display_name(\"na^me\") == \"na_me\"\n    assert clean_display_name(\"na`me\") == \"na_me\"\n    assert clean_display_name(\"na{me\") == \"na_me\"\n    assert clean_display_name(\"na}me\") == \"na_me\"\n    assert clean_display_name(\"na~me\") == \"na_me\"\n\n    # Test suffix invalid characters\n    assert clean_display_name(\"name-\") == \"name_\"\n    assert clean_display_name(\"name&\") == \"name_\"\n    assert clean_display_name(\"name%\") == \"name_\"\n    assert clean_display_name(\"name=\") == \"name_\"\n    assert clean_display_name(\"name+\") == \"name_\"\n    assert clean_display_name(\"name:\") == \"name_\"\n    assert clean_display_name(\"name'\") == \"name_\"\n    assert clean_display_name('name\"') == \"name_\"\n    assert clean_display_name(\"name<\") == \"name_\"\n    assert clean_display_name(\"name>\") == \"name_\"\n    assert clean_display_name(\"name#\") == \"name_\"\n    assert clean_display_name(\"name|\") == \"name_\"\n    assert clean_display_name(\"name!\") == \"name_\"\n    assert clean_display_name(\"name(\") == \"name_\"\n    assert clean_display_name(\"name)\") == \"name_\"\n    assert clean_display_name(\"name,\") == \"name_\"\n    assert clean_display_name(\"name.\") == \"name_\"\n    assert clean_display_name(\"name/\") == \"name_\"\n    assert clean_display_name(\"name@\") == \"name_\"\n    assert clean_display_name(\"name[\") == \"name_\"\n    assert clean_display_name(\"name\\\\\") == \"name_\"\n    assert clean_display_name(\"name]\") == \"name_\"\n    assert clean_display_name(\"name^\") == \"name_\"\n    assert clean_display_name(\"name{\") == \"name_\"\n    assert clean_display_name(\"name}\") == \"name_\"\n    assert clean_display_name(\"name~\") == \"name_\"\n\n    # Test single character cases\n    assert clean_display_name(\"1\") == \"_\"\n    assert clean_display_name(\"-\") == \"_\"\n    assert clean_display_name(\".\") == \"_\"\n    assert clean_display_name(\"a\") == \"a\"  # valid single character\n\n    # Test multiple consecutive underscores collapse\n    assert (\n        clean_display_name(\"na--me\") == \"na_me\"\n    )  # middle chars become underscores, then collapsed\n    assert (\n        clean_display_name(\"na..me\") == \"na_me\"\n    )  # dots become underscores, then collapsed\n\n    # Test complex cases with multiple invalid characters\n    assert clean_display_name(\"123-test.name@\") == \"_123_test_name_\"\n    assert clean_display_name(\".table.name.\") == \"_table_name_\"\n    assert clean_display_name(\"!@#$%^&*()\") == \"_\"\n\n    # Test underscore collapsing in complex scenarios\n    result = clean_display_name(\"!@#$%^&*()\")\n    assert result == \"_\"  # All get replaced, then collapsed\n\n    # Test real-world examples\n    assert clean_display_name(\"user.email\") == \"user_email\"\n    assert (\n        clean_display_name(\"order-total\") == \"order_total\"\n    )  # prefix 'o' stays, '-' becomes '_'\n    assert clean_display_name(\"2023_sales\") == \"_2023_sales\"\n    assert clean_display_name(\"product_name!\") == \"product_name_\"\n"
  },
  {
    "path": "wren-ai-service/tools/.env.example",
    "content": "bigquery.project-id=\nbigquery.dataset-id=\nbigquery.credentials-key=\npostgres.host=postgres\npostgres.port=5432\npostgres.database=test\npostgres.user=postgres\npostgres.password=postgres"
  },
  {
    "path": "wren-ai-service/tools/config/config.example.yaml",
    "content": "type: llm\nprovider: litellm_llm\ntimeout: 120\nmodels:\n  - alias: default\n    model: gpt-4.1-nano-2025-04-14\n    context_window_size: 1000000\n    kwargs:\n      max_tokens: 4096\n      n: 1\n      seed: 0\n      temperature: 0\n  - model: gpt-4.1-mini-2025-04-14\n    context_window_size: 1000000\n    kwargs:\n      max_tokens: 4096\n      n: 1\n      seed: 0\n      temperature: 0\n  - model: gpt-4.1-2025-04-14\n    context_window_size: 1000000\n    kwargs:\n      max_tokens: 4096\n      n: 1\n      seed: 0\n      temperature: 0\n  - model: gpt-5-nano-2025-08-07\n    context_window_size: 380000\n    kwargs:\n      max_completion_tokens: 4096\n      n: 1\n      seed: 0\n      reasoning_effort: minimal\n  - model: gpt-5-mini-2025-08-07\n    context_window_size: 380000\n    kwargs:\n      max_completion_tokens: 4096\n      n: 1\n      seed: 0\n      reasoning_effort: minimal\n  - model: gpt-5-2025-08-07\n    context_window_size: 380000\n    kwargs:\n      max_completion_tokens: 4096\n      n: 1\n      seed: 0\n      reasoning_effort: minimal\n---\ntype: embedder\nprovider: litellm_embedder\nmodels:\n  - model: text-embedding-3-large\n    alias: default\n    timeout: 120\n\n---\ntype: engine\nprovider: wren_ui\nendpoint: http://localhost:3000\n\n---\ntype: engine\nprovider: wren_ibis\nendpoint: http://localhost:8000\nsource: bigquery\nmanifest: \"\" # base64 encoded string of the MDL\nconnection_info: \"\" # base64 encoded string of the connection info\n\n---\ntype: engine\nprovider: wren_engine\nendpoint: http://localhost:8080\nmanifest: \"\"\n\n---\ntype: document_store\nprovider: qdrant\nlocation: http://localhost:6333\nembedding_model_dim: 3072\ntimeout: 120\nrecreate_index: false\n\n---\ntype: pipeline\npipes:\n  - name: db_schema_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: table_description_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_correction\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: followup_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_answer\n    llm: litellm_llm.default\n  - name: semantics_description\n    llm: litellm_llm.default\n  - name: relationship_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: chart_generation\n    llm: litellm_llm.default\n  - name: chart_adjustment\n    llm: litellm_llm.default\n  - name: intent_classification\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: misleading_assistance\n    llm: litellm_llm.default\n  - name: data_assistance\n    llm: litellm_llm.default\n  - name: sql_pairs_indexing\n    document_store: qdrant\n    embedder: litellm_embedder.default\n  - name: sql_pairs_retrieval\n    document_store: qdrant\n    embedder: litellm_embedder.default\n    llm: litellm_llm.default\n  - name: preprocess_sql_data\n    llm: litellm_llm.default\n  - name: sql_executor\n    engine: wren_ui\n  - name: user_guide_assistance\n    llm: litellm_llm.default\n  - name: sql_question_generation\n    llm: litellm_llm.default\n  - name: sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: followup_sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: sql_regeneration\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: evaluation\n    llm: litellm_llm.default\n  - name: instructions_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: instructions_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_functions_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n  - name: project_meta_indexing\n    document_store: qdrant\n  - name: sql_tables_extraction\n    llm: litellm_llm.default\n  - name: sql_diagnosis\n    llm: litellm_llm.default\n  - name: sql_knowledge_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n\n---\nsettings:\n  host: 127.0.0.1\n  port: 5556\n  doc_endpoint: https://docs.getwren.ai\n  is_oss: true\n  engine_timeout: 30\n  column_indexing_batch_size: 50\n  table_retrieval_size: 10\n  table_column_retrieval_size: 100\n  allow_intent_classification: true\n  allow_sql_generation_reasoning: true\n  allow_sql_functions_retrieval: true\n  enable_column_pruning: false\n  max_sql_correction_retries: 3\n  query_cache_maxsize: 1000\n  query_cache_ttl: 3600\n  langfuse_host: https://cloud.langfuse.com\n  langfuse_enable: true\n  logging_level: DEBUG\n  development: true\n  historical_question_retrieval_similarity_threshold: 0.9\n  sql_pairs_similarity_threshold: 0.7\n  sql_pairs_retrieval_max_size: 10\n  instructions_similarity_threshold: 0.7\n  instructions_top_k: 10\n"
  },
  {
    "path": "wren-ai-service/tools/config/config.full.yaml",
    "content": "type: llm\nprovider: litellm_llm\ntimeout: 120\nmodels:\n  - alias: default\n    model: gpt-4.1-nano-2025-04-14\n    context_window_size: 1000000\n    kwargs:\n      max_tokens: 4096\n      n: 1\n      seed: 0\n      temperature: 0\n  - model: gpt-4.1-mini-2025-04-14\n    context_window_size: 1000000\n    kwargs:\n      max_tokens: 4096\n      n: 1\n      seed: 0\n      temperature: 0\n  - model: gpt-4.1-2025-04-14\n    context_window_size: 1000000\n    kwargs:\n      max_tokens: 4096\n      n: 1\n      seed: 0\n      temperature: 0\n  - model: gpt-5-nano-2025-08-07\n    context_window_size: 380000\n    kwargs:\n      max_completion_tokens: 4096\n      n: 1\n      seed: 0\n      reasoning_effort: minimal\n  - model: gpt-5-mini-2025-08-07\n    context_window_size: 380000\n    kwargs:\n      max_completion_tokens: 4096\n      n: 1\n      seed: 0\n      reasoning_effort: minimal\n  - model: gpt-5-2025-08-07\n    context_window_size: 380000\n    kwargs:\n      max_completion_tokens: 4096\n      n: 1\n      seed: 0\n      reasoning_effort: minimal\n---\ntype: embedder\nprovider: litellm_embedder\nmodels:\n  - model: text-embedding-3-large\n    alias: default\n    timeout: 120\n\n---\ntype: engine\nprovider: wren_ui\nendpoint: http://localhost:3000\n\n---\ntype: engine\nprovider: wren_ibis\nendpoint: http://localhost:8000\nsource: bigquery\nmanifest: \"\" # base64 encoded string of the MDL\nconnection_info: \"\" # base64 encoded string of the connection info\n\n---\ntype: engine\nprovider: wren_engine\nendpoint: http://localhost:8080\nmanifest: \"\"\n\n---\ntype: document_store\nprovider: qdrant\nlocation: http://localhost:6333\nembedding_model_dim: 3072\ntimeout: 120\nrecreate_index: false\n\n---\ntype: pipeline\npipes:\n  - name: db_schema_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: table_description_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: db_schema_retrieval\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: historical_question_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_correction\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: followup_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: sql_answer\n    llm: litellm_llm.default\n  - name: semantics_description\n    llm: litellm_llm.default\n  - name: relationship_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation\n    llm: litellm_llm.default\n  - name: question_recommendation_sql_generation\n    llm: litellm_llm.default\n    engine: wren_ui\n    document_store: qdrant\n  - name: chart_generation\n    llm: litellm_llm.default\n  - name: chart_adjustment\n    llm: litellm_llm.default\n  - name: intent_classification\n    llm: litellm_llm.default\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: misleading_assistance\n    llm: litellm_llm.default\n  - name: data_assistance\n    llm: litellm_llm.default\n  - name: sql_pairs_indexing\n    document_store: qdrant\n    embedder: litellm_embedder.default\n  - name: sql_pairs_retrieval\n    document_store: qdrant\n    embedder: litellm_embedder.default\n    llm: litellm_llm.default\n  - name: preprocess_sql_data\n    llm: litellm_llm.default\n  - name: sql_executor\n    engine: wren_ui\n  - name: user_guide_assistance\n    llm: litellm_llm.default\n  - name: sql_question_generation\n    llm: litellm_llm.default\n  - name: sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: followup_sql_generation_reasoning\n    llm: litellm_llm.default\n  - name: sql_regeneration\n    llm: litellm_llm.default\n    engine: wren_ui\n  - name: evaluation\n    llm: litellm_llm.default\n  - name: instructions_indexing\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: instructions_retrieval\n    embedder: litellm_embedder.default\n    document_store: qdrant\n  - name: sql_functions_retrieval\n    engine: wren_ibis\n    document_store: qdrant\n  - name: project_meta_indexing\n    document_store: qdrant\n  - name: sql_tables_extraction\n    llm: litellm_llm.default\n  - name: sql_diagnosis\n    llm: litellm_llm.default\n\n---\nsettings:\n  host: 127.0.0.1\n  port: 5556\n  doc_endpoint: https://docs.getwren.ai\n  is_oss: true\n  engine_timeout: 30\n  column_indexing_batch_size: 50\n  table_retrieval_size: 10\n  table_column_retrieval_size: 100\n  query_cache_maxsize: 1000\n  allow_intent_classification: true\n  allow_sql_generation_reasoning: true\n  allow_sql_functions_retrieval: true\n  enable_column_pruning: false\n  max_sql_correction_retries: 3\n  query_cache_ttl: 3600\n  langfuse_host: https://cloud.langfuse.com\n  langfuse_enable: true\n  logging_level: INFO\n  development: false\n  historical_question_retrieval_similarity_threshold: 0.9\n  sql_pairs_similarity_threshold: 0.7\n  sql_pairs_retrieval_max_size: 10\n  instructions_similarity_threshold: 0.7\n  instructions_top_k: 10\n"
  },
  {
    "path": "wren-ai-service/tools/dev/config.properties.example",
    "content": "node.environment=production\nwren.directory=/usr/src/app/etc/mdl\nwren.experimental-enable-dynamic-fields=true\nwren.datasource.type=duckdb\nduckdb.connector.init-sql-path=/usr/src/app/etc/duckdb/init.sql\nduckdb.storage.access-key=\nduckdb.storage.secret-key=\n"
  },
  {
    "path": "wren-ai-service/tools/dev/docker-compose-dev.yaml",
    "content": "version: \"3.8\"\n\nvolumes:\n  data:\n\nnetworks:\n  wren:\n    driver: bridge\n\nservices:\n  wren-engine:\n    image: ghcr.io/canner/wren-engine:${WREN_ENGINE_VERSION}\n    pull_policy: always\n    platform: ${PLATFORM}\n    ports:\n      - ${WREN_ENGINE_SQL_PORT}:${WREN_ENGINE_SQL_PORT}\n      - ${WREN_ENGINE_PORT}:${WREN_ENGINE_PORT}\n    volumes:\n      - ./etc:/usr/src/app/etc\n    networks:\n      - wren\n\n  ibis-server:\n    image: ghcr.io/canner/wren-engine-ibis:${IBIS_SERVER_VERSION}\n    pull_policy: always\n    platform: ${PLATFORM}\n    ports:\n      - ${IBIS_SERVER_PORT}:${IBIS_SERVER_PORT}\n    environment:\n      WREN_ENGINE_ENDPOINT: http://wren-engine:${WREN_ENGINE_PORT}\n      LOG_LEVEL: DEBUG\n    networks:\n      - wren\n\n  qdrant:\n    image: qdrant/qdrant:v1.11.0\n    pull_policy: always\n    ports:\n      - 6333:6333\n      - 6334:6334\n    networks:\n      - wren\n\n  wren-ui:\n    image: ghcr.io/canner/wren-ui:${WREN_UI_VERSION}\n    pull_policy: always\n    platform: ${PLATFORM}\n    environment:\n      DB_TYPE: sqlite\n      # /app is the working directory in the container\n      SQLITE_FILE: /app/data/db.sqlite3\n      WREN_ENGINE_ENDPOINT: http://wren-engine:${WREN_ENGINE_PORT}\n      WREN_AI_ENDPOINT: http://host.docker.internal:${WREN_AI_SERVICE_PORT}\n      IBIS_SERVER_ENDPOINT: http://ibis-server:${IBIS_SERVER_PORT}\n      GENERATION_MODEL: ${GENERATION_MODEL}\n      # telemetry\n      WREN_ENGINE_PORT: ${WREN_ENGINE_PORT}\n      WREN_AI_SERVICE_VERSION: ${WREN_AI_SERVICE_VERSION}\n      WREN_UI_VERSION: ${WREN_UI_VERSION}\n      WREN_ENGINE_VERSION: ${WREN_ENGINE_VERSION}\n      USER_UUID: ${USER_UUID}\n      POSTHOG_API_KEY: ${POSTHOG_API_KEY}\n      POSTHOG_HOST: ${POSTHOG_HOST}\n      TELEMETRY_ENABLED: ${TELEMETRY_ENABLED}\n      # client side\n      NEXT_PUBLIC_USER_UUID: ${USER_UUID}\n      NEXT_PUBLIC_POSTHOG_API_KEY: ${POSTHOG_API_KEY}\n      NEXT_PUBLIC_POSTHOG_HOST: ${POSTHOG_HOST}\n      NEXT_PUBLIC_TELEMETRY_ENABLED: ${TELEMETRY_ENABLED}\n      # configs\n      WREN_PRODUCT_VERSION: ${WREN_PRODUCT_VERSION}\n\n    ports:\n      - ${WREN_UI_PORT}:3000\n    volumes:\n      - ./etc:/app/data\n    networks:\n      - wren\n    depends_on:\n      - wren-engine\n      - ibis-server\n\n  postgres:\n    image: postgres:14-alpine\n    platform: ${PLATFORM}\n    ports:\n      - 5432:5432\n    volumes:\n      - data:/var/lib/postgresql/data\n    environment:\n      - POSTGRES_PASSWORD=postgres\n      - POSTGRES_USER=postgres\n      - POSTGRES_DB=test\n      - PGDATA=/var/lib/postgresql/data/pgdata\n    networks:\n      - wren\n"
  },
  {
    "path": "wren-ai-service/tools/mdl_to_str.py",
    "content": "import argparse\n\nimport orjson\n\n\ndef to_str(mdl: dict) -> str:\n    \"\"\"Convert MDL dictionary to string format with proper escaping.\n\n    Args:\n        mdl (dict): The MDL dictionary containing schema information\n\n    Returns:\n        str: Properly escaped string representation of the MDL\n\n    Example:\n        mdl = {\n            \"schema\": \"public\",\n            \"models\": [\n                {\"name\": \"table1\"}\n            ]\n        }\n        result = to_str(mdl)\n        # Returns escaped string representation\n    \"\"\"\n\n    mdl_str = orjson.dumps(mdl).decode(\"utf-8\")\n\n    mdl_str = mdl_str.replace(\"\\\\\", \"\\\\\\\\\")  # Escape backslashes\n    mdl_str = mdl_str.replace('\"', '\\\\\"')  # Escape double quotes\n\n    return mdl_str\n\n\ndef _args():\n    parser = argparse.ArgumentParser(\n        description=\"Convert MDL JSON file to escaped string format\"\n    )\n    parser.add_argument(\"-p\", \"--path\", help=\"Path to input MDL JSON file\")\n    return parser.parse_args()\n\n\nif __name__ == \"__main__\":\n    args = _args()\n    mdl = orjson.loads(open(args.path).read())\n    print(to_str(mdl))\n"
  },
  {
    "path": "wren-ai-service/tools/run_sql.py",
    "content": "import argparse\nimport base64\nimport json\nimport os\nimport time\nfrom typing import Dict, Optional\n\nimport orjson\nimport pandas as pd\nimport requests\nimport yaml\nfrom dotenv import load_dotenv\n\nload_dotenv(\"tools/.env\", override=True)\n\nWREN_ENGINE_API_URL = \"http://localhost:8080\"\nWREN_IBIS_API_URL = \"http://localhost:8000\"\nDATA_SOURCES = [\"duckdb\", \"bigquery\", \"postgres\"]\n\n\ndef _get_connection_info(data_source: str):\n    if data_source == \"bigquery\":\n        return {\n            \"project_id\": os.getenv(\"bigquery.project-id\"),\n            \"dataset_id\": os.getenv(\"bigquery.dataset-id\"),\n            \"credentials\": os.getenv(\"bigquery.credentials-key\"),\n        }\n    elif data_source == \"postgres\":\n        return {\n            \"host\": os.getenv(\"postgres.host\"),\n            \"port\": os.getenv(\"postgres.port\"),\n            \"database\": os.getenv(\"postgres.database\"),\n            \"user\": os.getenv(\"postgres.user\"),\n            \"password\": os.getenv(\"postgres.password\"),\n        }\n\n\ndef get_data_from_wren_engine(\n    sql: str,\n    dataset_type: str,\n    manifest: dict,\n    limit: int = 100,\n    return_df: bool = True,\n):\n    if dataset_type == \"duckdb\":\n        response = requests.get(\n            f\"{WREN_ENGINE_API_URL}/v1/mdl/preview\",\n            json={\n                \"sql\": sql,\n                \"manifest\": manifest,\n                \"limit\": limit,\n            },\n        )\n\n        assert response.status_code == 200, response.text\n\n        data = response.json()\n\n        if return_df:\n            column_names = [col[\"name\"] for col in data[\"columns\"]]\n\n            return pd.DataFrame(data[\"data\"], columns=column_names)\n        else:\n            return data\n    else:\n        response = requests.post(\n            f\"{WREN_IBIS_API_URL}/v3/connector/{dataset_type}/query?limit={limit}\",\n            json={\n                \"sql\": sql,\n                \"manifestStr\": base64.b64encode(orjson.dumps(manifest)).decode(),\n                \"connectionInfo\": _get_connection_info(dataset_type),\n            },\n        )\n\n        assert response.status_code == 200, response.text\n\n        data = response.json()\n\n        if return_df:\n            column_names = [col for col in data[\"columns\"]]\n\n            return pd.DataFrame(data[\"data\"], columns=column_names)\n        else:\n            return data\n\n\ndef _update_wren_engine_configs(configs: list[dict]):\n    response = requests.patch(\n        f\"{WREN_ENGINE_API_URL}/v1/config\",\n        json=configs,\n    )\n\n    assert response.status_code == 200\n\n\ndef _prepare_duckdb(dataset_name: str):\n    assert dataset_name in [\"ecommerce\", \"hr\"]\n\n    init_sqls = {\n        \"ecommerce\": \"\"\"\nCREATE TABLE olist_customers_dataset AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_customers_dataset.parquet');\nCREATE TABLE olist_order_items_dataset AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_order_items_dataset.parquet');\nCREATE TABLE olist_orders_dataset AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_orders_dataset.parquet');\nCREATE TABLE olist_order_payments_dataset AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_order_payments_dataset.parquet');\nCREATE TABLE olist_products_dataset AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_products_dataset.parquet');\nCREATE TABLE olist_order_reviews_dataset AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_order_reviews_dataset.parquet');\nCREATE TABLE olist_geolocation_dataset AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_geolocation_dataset.parquet');\nCREATE TABLE olist_sellers_dataset AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_sellers_dataset.parquet');\nCREATE TABLE product_category_name_translation AS FROM read_parquet('https://assets.getwren.ai/sample_data/brazilian-ecommerce/product_category_name_translation.parquet');\n\"\"\",\n        \"hr\": \"\"\"\nCREATE TABLE salaries AS FROM read_parquet('https://assets.getwren.ai/sample_data/employees/salaries.parquet');\nCREATE TABLE titles AS FROM read_parquet('https://assets.getwren.ai/sample_data/employees/titles.parquet');\nCREATE TABLE dept_emp AS FROM read_parquet('https://assets.getwren.ai/sample_data/employees/dept_emp.parquet');\nCREATE TABLE departments AS FROM read_parquet('https://assets.getwren.ai/sample_data/employees/departments.parquet');\nCREATE TABLE employees AS FROM read_parquet('https://assets.getwren.ai/sample_data/employees/employees.parquet');\nCREATE TABLE dept_manager AS FROM read_parquet('https://assets.getwren.ai/sample_data/employees/dept_manager.parquet');\n\"\"\",\n    }\n\n    with open(\"./tools/dev/etc/duckdb-init.sql\", \"w\") as f:\n        f.write(\"\")\n\n    response = requests.put(\n        f\"{WREN_ENGINE_API_URL}/v1/data-source/duckdb/settings/init-sql\",\n        data=init_sqls[dataset_name],\n    )\n\n    assert response.status_code == 200, response.text\n\n\ndef _replace_wren_engine_env_variables(engine_type: str, data: dict):\n    assert engine_type in (\"wren_engine\", \"wren_ibis\")\n\n    with open(\"config.yaml\", \"r\") as f:\n        configs = list(yaml.safe_load_all(f))\n\n        for config in configs:\n            if config.get(\"type\") == \"engine\" and config.get(\"provider\") == engine_type:\n                for key, value in data.items():\n                    config[key] = value\n            if \"pipes\" in config:\n                for i, pipe in enumerate(config[\"pipes\"]):\n                    if \"engine\" in pipe and pipe[\"name\"] != \"sql_functions_retrieval\":\n                        config[\"pipes\"][i][\"engine\"] = engine_type\n\n    with open(\"config.yaml\", \"w\") as f:\n        yaml.safe_dump_all(configs, f, default_flow_style=False)\n\n\ndef rerun_wren_engine(mdl_json: Dict, dataset_type: str, dataset: Optional[str] = None):\n    assert dataset_type in DATA_SOURCES\n\n    SOURCE = dataset_type\n    MANIFEST = base64.b64encode(orjson.dumps(mdl_json)).decode()\n    if dataset_type == \"duckdb\":\n        _update_wren_engine_configs(\n            [\n                {\n                    \"name\": \"duckdb.connector.init-sql-path\",\n                    \"value\": \"/usr/src/app/etc/duckdb-init.sql\",\n                },\n            ]\n        )\n\n        _prepare_duckdb(dataset)\n        _replace_wren_engine_env_variables(\"wren_engine\", {\"manifest\": MANIFEST})\n    else:\n        WREN_IBIS_CONNECTION_INFO = base64.b64encode(\n            orjson.dumps(_get_connection_info(dataset_type))\n        ).decode()\n\n        _replace_wren_engine_env_variables(\n            \"wren_ibis\",\n            {\n                \"manifest\": MANIFEST,\n                \"source\": SOURCE,\n                \"connection_info\": WREN_IBIS_CONNECTION_INFO,\n            },\n        )\n\n    # wait for wren-ai-service to restart\n    time.sleep(5)\n\n\ndef main():\n    parser = argparse.ArgumentParser(\n        description=\"Execute SQL query against MDL manifest\"\n    )\n\n    parser.add_argument(\n        \"--mdl-path\",\n        type=str,\n        required=True,\n        help=\"Path to MDL JSON file\",\n    )\n\n    parser.add_argument(\n        \"--data-source\",\n        type=str,\n        default=\"bigquery\",\n        choices=[\"bigquery\", \"duckdb\", \"postgres\"],\n        help=\"Data source (default: bigquery)\",\n    )\n\n    parser.add_argument(\n        \"--sample-dataset\",\n        type=str,\n        default=\"ecommerce\",\n        choices=[\"ecommerce\", \"hr\", \"\"],\n        help=\"Sample dataset (default: ecommerce)\",\n    )\n\n    args = parser.parse_args()\n\n    mdl_path = args.mdl_path\n    data_source = args.data_source\n    sample_dataset = args.sample_dataset\n\n    # Load MDL JSON file\n    try:\n        with open(mdl_path, \"r\") as f:\n            mdl_json = json.load(f)\n    except FileNotFoundError:\n        print(f\"Error: MDL file not found at {mdl_path}\")\n        return\n    except json.JSONDecodeError:\n        print(f\"Error: Invalid JSON in MDL file {mdl_path}\")\n        return\n\n    rerun_wren_engine(mdl_json, data_source, sample_dataset)\n\n    # Execute query\n    print(\"Enter SQL query (end with semicolon on a new line to execute, 'q' to quit):\")\n    lines = []\n    while True:\n        line = input()\n        if line.strip() == \"q\":\n            break\n        if line.strip() == \";\":\n            command = \"\\n\".join(lines)\n            lines = []\n            try:\n                df = get_data_from_wren_engine(\n                    sql=command,\n                    dataset_type=data_source,\n                    manifest=mdl_json,\n                    limit=50,\n                )\n                print(f\"\\nExecution result:\\n{df.to_string()}\\n\")\n            except Exception as e:\n                print(f\"\\nError executing query: {str(e)}\")\n        else:\n            lines.append(line)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "wren-launcher/.golangci.yml",
    "content": "# golangci-lint configuration for WrenAI wren-launcher\nversion: \"2\"\n\nrun:\n  timeout: 5m\n\nlinters:\n  enable:\n    - errcheck\n    - govet\n    - ineffassign\n    - staticcheck\n    - unused\n    - misspell\n    - unconvert\n    - gosec\n    - dupl\n    - goconst\n    - gocyclo\n    - bodyclose\n    - whitespace\n\nissues:\n  max-issues-per-linter: 0\n  max-same-issues: 0\n"
  },
  {
    "path": "wren-launcher/Makefile",
    "content": "BINARY_NAME=wren-launcher\n\n# Build targets\nbuild:\n\tenv GOARCH=amd64 GOOS=darwin CGO_ENABLED=1 go build -o dist/${BINARY_NAME}-darwin main.go\n\tenv GOARCH=arm64 GOOS=darwin CGO_ENABLED=1 go build -o dist/${BINARY_NAME}-darwin-arm64 main.go\n\tenv GOARCH=amd64 GOOS=linux CGO_ENABLED=0 go build -o dist/${BINARY_NAME}-linux main.go\n\tenv GOARCH=arm64 GOOS=linux CGO_ENABLED=0 go build -o dist/${BINARY_NAME}-linux-arm64 main.go\n\tenv GOARCH=amd64 GOOS=windows CGO_ENABLED=0 go build -o dist/${BINARY_NAME}-windows.exe main.go\n\tcd ./dist; chmod +x ${BINARY_NAME}-darwin && chmod +x ${BINARY_NAME}-darwin-arm64 && chmod +x ${BINARY_NAME}-linux && chmod +x ${BINARY_NAME}-linux-arm64 \\\n\t&& tar zcvf ${BINARY_NAME}-darwin.tar.gz ${BINARY_NAME}-darwin \\\n\t&& tar zcvf ${BINARY_NAME}-darwin-arm64.tar.gz ${BINARY_NAME}-darwin-arm64 \\\n\t&& tar zcvf ${BINARY_NAME}-linux.tar.gz ${BINARY_NAME}-linux \\\n\t&& tar zcvf ${BINARY_NAME}-linux-arm64.tar.gz ${BINARY_NAME}-linux-arm64 \\\n\t&& zip ${BINARY_NAME}-windows.zip ${BINARY_NAME}-windows.exe\n\nclean:\n\tgo clean\n\trm -rf dist\n\nrebuild: clean build\n\n# Code quality targets\n.PHONY: fmt\nfmt:\n\tgo fmt ./...\n\n.PHONY: imports\nimports:\n\t$(shell go env GOPATH)/bin/goimports -w .\n\n.PHONY: vet\nvet:\n\tgo vet ./...\n\n.PHONY: lint\nlint:\n\tgolangci-lint run\n\n.PHONY: lint-fix\nlint-fix:\n\tgolangci-lint run --fix\n\n.PHONY: check\ncheck: fmt vet lint\n\n.PHONY: fix\nfix: fmt imports lint-fix\n\n.PHONY: test\ntest:\n\tgo test ./...\n\n.PHONY: help\nhelp:\n\t@echo \"Available targets:\"\n\t@echo \"  build      - Build binaries for all platforms\"\n\t@echo \"  clean      - Clean build artifacts\"\n\t@echo \"  rebuild    - Clean and build\"\n\t@echo \"  fmt        - Format Go code\"\n\t@echo \"  imports    - Fix imports\"\n\t@echo \"  vet        - Run go vet\"\n\t@echo \"  lint       - Run golangci-lint\"\n\t@echo \"  lint-fix   - Run golangci-lint with auto-fix\"\n\t@echo \"  check      - Run fmt, vet, and lint\"\n\t@echo \"  fix        - Run fmt, imports, and lint-fix\"\n\t@echo \"  test       - Run tests\"\n\t@echo \"  help       - Show this help\"\n"
  },
  {
    "path": "wren-launcher/README.md",
    "content": "## How to build\n```bash\n# mac\ngo build main.go\n# windows\nenv GOOS=windows GOARCH=amd64 go build main.go\n```\n\n## Code Quality\n```bash\nmake check  # Run all checks (fmt, vet, lint)\nmake test   # Run tests\nmake fmt    # Format code\nmake vet    # Run go vet\nmake lint   # Run golangci-lint\n```\n\n## Continuous Integration\n\nThis project uses GitHub Actions for CI/CD. The workflow runs automatically on:\n\n- **Push to main branch**: Runs all checks and tests\n- **Pull Request with label `launcher`**: Runs all checks and tests when PR is labeled\n- **Manual trigger**: Can be triggered manually via GitHub Actions UI\n\n### CI Jobs:\n\n1. **Lint and Test**: \n   - Code formatting check\n   - Go vet analysis\n   - golangci-lint checks\n   - Unit tests\n   - All quality checks\n\n2. **Security Scan**: \n   - Gosec security analysis\n   - Go module verification\n\n## How to update dependencies\n\n```bash\n# Update a single dependency\ngo get example.com/some/package@latest\n\n# Update all dependencies\ngo get -u ./...\n\n# Clean up and ensure the module files are correct\ngo mod tidy\n\n# Verify the updates\ngo test ./...\n\n```\n"
  },
  {
    "path": "wren-launcher/commands/dbt/README.md",
    "content": "# Requirement for DBT project\nThis part outlines some requirements for the target dbt project:\n- Ensure the DBT project is qualified and generates the required files:\n  - `catalog.json`\n  - `manifest.json`\n  Execute the following commands:\n\t```\n\tdbt build\n\tdbt docs generate\n\t```\n- Prepare the profile of the dbt project for the connection info of your database.\n  - `profiles.yml`\n\n\n# How to Support a New Data Source\n\nThis document outlines the steps required to add support for a new data source to the dbt project converter.\nThe target data source must be supported by both dbt and the Wren engine:\n- [dbt supported databases](https://docs.getdbt.com/docs/supported-data-platforms)\n- [Wren engine supported data sources](https://docs.getwren.ai/oss/wren_engine_api#tag/AthenaConnectionInfo)\n\n## 1. Implement the DataSource Interface\n\nThe first step is to define a new struct for your data source and implement the `DataSource` interface defined in `data_source.go`.\n\nThe `DataSource` interface is as follows:\n\n```go\ntype DataSource interface {\n    GetType() string\n    Validate() error\n    MapType(sourceType string) string\n}\n```\n\n### Steps:\n\n1.  **Define Your Struct**: Create a new struct that represents the connection properties for your data source. The fields in this struct should correspond to the properties defined in the [Wren engine's API documentation](https://docs.getwren.ai/oss/wren_engine_api#tag/SnowflakeConnectionInfo) for the target data source.\n\n    For example, to add support for `Snowflake`, you would define the following struct:\n\n    ```go\n    type WrenSnowflakeDataSource struct {\n        Account   string `json:\"account\"`\n        User      string `json:\"user\"`\n        Password  string `json:\"password\"`\n        Database  string `json:\"database\"`\n        Warehouse string `json:\"warehouse\"`\n        // ... other properties\n    }\n    ```\n\n2.  **Implement `GetType()`**: This method should return a string that identifies your data source type (e.g., `\"snowflake\"`).\n\n3.  **Implement `Validate()`**: This method should check if the essential properties of your data source are set and valid. Return an error if validation fails.\n\n4.  **Implement `MapType()`**: This method is crucial for mapping data types from the source system (as defined in `catalog.json`) to Wren's supported data types (e.g., `integer`, `varchar`, `timestamp`).\n\n## 2. Add Conversion Logic in `data_source.go`\n\nAfter implementing the interface, you need to integrate your new data source into the conversion logic. This is done by updating the `convertConnectionToDataSource` function in `data_source.go`.\n\nAdd a new `case` to the `switch` statement that matches the `type` field from the dbt `profiles.yml` file. This new case will be responsible for creating an instance of your new data source struct from the dbt connection details.\n\n### Example:\n\n```go\n// in data_source.go\n\nfunc convertConnectionToDataSource(conn DbtConnection, dbtHomePath, profileName, outputName string) (DataSource, error) {\n\tswitch strings.ToLower(conn.Type) {\n\tcase \"postgres\", \"postgresql\":\n\t\treturn convertToPostgresDataSource(conn)\n\tcase \"duckdb\":\n\t\treturn convertToLocalFileDataSource(conn, dbtHomePath)\n    // Add your new case here\n\tcase \"snowflake\":\n\t\treturn convertToSnowflakeDataSource(conn) // Implement this function\n\tdefault:\n\t\t// ...\n\t}\n}\n\n// Implement the conversion function\nfunc convertToSnowflakeDataSource(conn DbtConnection) (*WrenSnowflakeDataSource, error) {\n    // Logic to extract snowflake properties from conn\n    // and return a new *WrenSnowflakeDataSource\n}\n```\n\n## 3. Handle the New Data Source in `ConvertDbtProjectCore`\n\nThe `ConvertDbtProjectCore` function in `converter.go` is responsible for generating the `wren-datasource.json` file. You must add your new data source to the `switch` statement within this function to ensure it is correctly serialized.\n\n### Steps:\n\n1.  **Locate the `switch` statement**: Find the `switch typedDS := ds.(type)` block inside `ConvertDbtProjectCore`.\n2.  **Add a new `case`**: Add a new `case` for your data source struct. Inside this case, construct the `wrenDataSource` map with the correct `type` and `properties`.\n\n### Example:\n\n```go\n// in converter.go's ConvertDbtProjectCore function\n\n// ...\n\t\t\tswitch typedDS := ds.(type) {\n\t\t\tcase *WrenPostgresDataSource:\n\t\t\t\t// ...\n\t\t\tcase *WrenLocalFileDataSource:\n\t\t\t\t// ...\n            // Add your new case here\n\t\t\tcase *WrenSnowflakeDataSource:\n\t\t\t\twrenDataSource = map[string]interface{}{\n\t\t\t\t\t\"type\": \"snowflake\",\n\t\t\t\t\t\"properties\": map[string]interface{}{\n\t\t\t\t\t\t\"account\":  typedDS.Account,\n\t\t\t\t\t\t\"user\":     typedDS.User,\n\t\t\t\t\t\t\"password\": typedDS.Password,\n\t\t\t\t\t\t\"database\": typedDS.Database,\n                        \"warehouse\": typedDS.Warehouse,\n\t\t\t\t\t\t// ... other properties\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\t// ...\n\t\t\t}\n// ...\n```\n\n**Note on File-Based Data Sources**: If your data source is file-based (like `duckdb`), you also need to add logic to set the `localStoragePath` variable correctly within `ConvertDbtProjectCore`. This path tells the Wren engine where to find the data files.\n"
  },
  {
    "path": "wren-launcher/commands/dbt/converter.go",
    "content": "package dbt\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/pterm/pterm\"\n)\n\n// Note: All struct definitions (WrenMDLManifest, WrenModel, etc.) are defined\n// in wren_mdl.go to prevent \"redeclared in this block\" compilation errors.\n\n// ConvertOptions holds the options for dbt project conversion\ntype ConvertOptions struct {\n\tProjectPath          string\n\tOutputDir            string\n\tProfileName          string\n\tTarget               string\n\tRequireCatalog       bool // if true, missing catalog.json is an error; if false, it's a warning\n\tUsedByContainer      bool // if true, used by container, no need to print usage info\n\tIncludeStagingModels bool // if true, staging models will be included in the conversion\n}\n\n// ConvertResult holds the result of dbt project conversion\ntype ConvertResult struct {\n\tLocalStoragePath    string\n\tDataSourceGenerated bool\n\tModelsCount         int\n}\n\n// ConvertDbtProjectCore contains the core logic for converting dbt projects\n// This function is used by both DbtAutoConvert and processDbtProject\n//\n//nolint:gocyclo // This function has high cyclomatic complexity due to extensive dbt project validation and conversion logic\nfunc ConvertDbtProjectCore(opts ConvertOptions) (*ConvertResult, error) {\n\t// Validate dbt project\n\tif !IsDbtProjectValid(opts.ProjectPath) {\n\t\treturn nil, fmt.Errorf(\"invalid dbt project path: %s\", opts.ProjectPath)\n\t}\n\n\t// Create output directory if it doesn't exist\n\tif err := os.MkdirAll(opts.OutputDir, 0750); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create output directory: %w\", err)\n\t}\n\n\tpterm.Info.Printf(\"Processing dbt project at: %s\\n\", opts.ProjectPath)\n\tpterm.Info.Printf(\"Output directory: %s\\n\", opts.OutputDir)\n\n\t// Search for profiles.yml\n\tprofilesPath, err := FindProfilesFile(opts.ProjectPath)\n\tif err != nil {\n\t\tpterm.Warning.Printf(\"Warning: Could not find profiles.yml: %v\\n\", err)\n\t\tpterm.Info.Println(\"Skipping data source conversion...\")\n\t}\n\n\t// Search for catalog.json, manifest.json, and semantic_manifest.json in target directory\n\ttargetDir := filepath.Join(opts.ProjectPath, \"target\")\n\tcatalogPath := filepath.Join(targetDir, \"catalog.json\")\n\tmanifestPath := filepath.Join(targetDir, \"manifest.json\")\n\tsemanticManifestPath := filepath.Join(targetDir, \"semantic_manifest.json\")\n\n\tif !FileExists(catalogPath) {\n\t\tif opts.RequireCatalog {\n\t\t\treturn nil, fmt.Errorf(\"catalog.json not found at: %s. Hint: Run 'dbt docs generate' to create catalog.json\", catalogPath)\n\t\t} else {\n\t\t\tpterm.Warning.Printf(\"Warning: catalog.json not found at: %s\\n\", catalogPath)\n\t\t\tpterm.Info.Println(\"Hint: Run 'dbt docs generate' to create catalog.json\")\n\t\t\treturn &ConvertResult{LocalStoragePath: \".\"}, nil\n\t\t}\n\t}\n\n\t// Check for manifest.json (optional but recommended for descriptions and relationships)\n\tvar manifestPathForConversion string\n\tif FileExists(manifestPath) {\n\t\tpterm.Info.Printf(\"Found manifest.json at: %s\\n\", manifestPath)\n\t\tmanifestPathForConversion = manifestPath\n\t} else {\n\t\tpterm.Warning.Printf(\"Warning: manifest.json not found at: %s\\n\", manifestPath)\n\t\tpterm.Info.Println(\"Model descriptions, column descriptions, and relationships will not be included\")\n\t}\n\n\t// Check for semantic_manifest.json (optional)\n\tvar semanticManifestPathForConversion string\n\tif FileExists(semanticManifestPath) {\n\t\tpterm.Info.Printf(\"Found semantic_manifest.json at: %s\\n\", semanticManifestPath)\n\t\tsemanticManifestPathForConversion = semanticManifestPath\n\t} else {\n\t\tpterm.Info.Println(\"semantic_manifest.json not found, skipping metric and primary key conversion.\")\n\t}\n\n\t// Convert profiles.yml to WrenDataSource (if profiles found)\n\tvar dataSourceGenerated bool\n\tvar ds DataSource\n\tlocalStoragePath := \".\" // default value\n\n\tif profilesPath != \"\" {\n\t\tpterm.Info.Printf(\"Found profiles.yml at: %s\\n\", profilesPath)\n\n\t\t// Analyze profiles\n\t\tprofiles, err := AnalyzeDbtProfiles(profilesPath)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to analyze profiles: %w\", err)\n\t\t}\n\n\t\t// Display available profiles if no specific profile is requested\n\t\tif opts.ProfileName == \"\" {\n\t\t\tpterm.Info.Println(\"Available profiles:\")\n\t\t\tfor name := range profiles.Profiles {\n\t\t\t\tpterm.Info.Printf(\"  - %s\\n\", name)\n\t\t\t}\n\t\t\tpterm.Info.Println(\"Using first available profile (specify --profile to select a specific one)\")\n\t\t}\n\n\t\t// Get active data sources\n\t\tdataSources, err := GetActiveDataSources(profiles, opts.ProjectPath, opts.ProfileName, opts.Target)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to get data sources: %w\", err)\n\t\t}\n\n\t\tif len(dataSources) == 0 {\n\t\t\tpterm.Warning.Println(\"Warning: No active data sources found\")\n\t\t\tdataSourceGenerated = false\n\t\t} else {\n\t\t\t// Use the first data source\n\t\t\tds = dataSources[0]\n\n\t\t\t// Check if the first data source is duckdb (local file)\n\t\t\tif localFileDS, ok := dataSources[0].(*WrenLocalFileDataSource); ok {\n\t\t\t\tlocalStoragePath = localFileDS.Url\n\t\t\t\tpterm.Info.Printf(\"Found DuckDB data source, using local storage path: %s\\n\", localStoragePath)\n\t\t\t}\n\n\t\t\t// Create WrenDataSource JSON\n\t\t\tvar wrenDataSource map[string]interface{}\n\n\t\t\tswitch typedDS := ds.(type) {\n\t\t\tcase *WrenPostgresDataSource:\n\t\t\t\tvar host string\n\t\t\t\tif opts.UsedByContainer {\n\t\t\t\t\thost = handleLocalhostForContainer(typedDS.Host)\n\t\t\t\t} else {\n\t\t\t\t\thost = typedDS.Host\n\t\t\t\t}\n\t\t\t\twrenDataSource = map[string]interface{}{\n\t\t\t\t\t\"type\": \"postgres\",\n\t\t\t\t\t\"properties\": map[string]interface{}{\n\t\t\t\t\t\t\"host\":     host,\n\t\t\t\t\t\t\"port\":     typedDS.Port,\n\t\t\t\t\t\t\"database\": typedDS.Database,\n\t\t\t\t\t\t\"user\":     typedDS.User,\n\t\t\t\t\t\t\"password\": typedDS.Password,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\tcase *WrenMSSQLDataSource:\n\t\t\t\tvar host string\n\t\t\t\tif opts.UsedByContainer {\n\t\t\t\t\thost = handleLocalhostForContainer(typedDS.Host)\n\t\t\t\t} else {\n\t\t\t\t\thost = typedDS.Host\n\t\t\t\t}\n\t\t\t\twrenDataSource = map[string]interface{}{\n\t\t\t\t\t\"type\": \"mssql\",\n\t\t\t\t\t\"properties\": map[string]interface{}{\n\t\t\t\t\t\t\"host\":        host,\n\t\t\t\t\t\t\"port\":        typedDS.Port,\n\t\t\t\t\t\t\"database\":    typedDS.Database,\n\t\t\t\t\t\t\"user\":        typedDS.User,\n\t\t\t\t\t\t\"password\":    typedDS.Password,\n\t\t\t\t\t\t\"tds_version\": typedDS.TdsVersion,\n\t\t\t\t\t\t\"driver\":      typedDS.Driver,\n\t\t\t\t\t\t\"kwargs\":      typedDS.Kwargs,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\tcase *WrenLocalFileDataSource:\n\t\t\t\tvar url string\n\t\t\t\tif opts.UsedByContainer {\n\t\t\t\t\t// For container usage, the file path will be mounted to the following path\n\t\t\t\t\turl = \"/usr/src/app/data\"\n\t\t\t\t} else {\n\t\t\t\t\turl = typedDS.Url\n\t\t\t\t}\n\t\t\t\twrenDataSource = map[string]interface{}{\n\t\t\t\t\t\"type\": \"local_file\",\n\t\t\t\t\t\"properties\": map[string]interface{}{\n\t\t\t\t\t\t\"url\":    url,\n\t\t\t\t\t\t\"format\": typedDS.Format,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\tcase *WrenBigQueryDataSource:\n\t\t\t\twrenDataSource = map[string]interface{}{\n\t\t\t\t\t\"type\": \"bigquery\",\n\t\t\t\t\t\"properties\": map[string]interface{}{\n\t\t\t\t\t\t\"project_id\":  typedDS.Project,\n\t\t\t\t\t\t\"dataset_id\":  typedDS.Dataset,\n\t\t\t\t\t\t\"credentials\": typedDS.Credentials,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\tcase *WrenMysqlDataSource:\n\t\t\t\twrenDataSource = map[string]interface{}{\n\t\t\t\t\t\"type\": \"mysql\",\n\t\t\t\t\t\"properties\": map[string]interface{}{\n\t\t\t\t\t\t\"host\":     typedDS.Host,\n\t\t\t\t\t\t\"port\":     typedDS.Port,\n\t\t\t\t\t\t\"database\": typedDS.Database,\n\t\t\t\t\t\t\"user\":     typedDS.User,\n\t\t\t\t\t\t\"password\": typedDS.Password,\n\t\t\t\t\t\t\"sslMode\":  typedDS.SslMode,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\tpterm.Warning.Printf(\"Warning: Unsupported data source type: %s\\n\", ds.GetType())\n\t\t\t\twrenDataSource = map[string]interface{}{\n\t\t\t\t\t\"type\":       ds.GetType(),\n\t\t\t\t\t\"properties\": map[string]interface{}{},\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Write WrenDataSource JSON\n\t\t\tdataSourcePath := filepath.Join(opts.OutputDir, \"wren-datasource.json\")\n\t\t\tdataSourceJSON, err := json.MarshalIndent(wrenDataSource, \"\", \"  \")\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to marshal data source JSON: %w\", err)\n\t\t\t}\n\n\t\t\tif err := os.WriteFile(dataSourcePath, dataSourceJSON, 0600); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to write data source file: %w\", err)\n\t\t\t}\n\n\t\t\tpterm.Success.Printf(\"✓ WrenDataSource saved to: %s\\n\", dataSourcePath)\n\t\t\tdataSourceGenerated = true\n\t\t}\n\t}\n\n\t// Convert catalog.json to Wren MDL\n\tpterm.Info.Printf(\"Converting catalog.json from: %s\\n\", catalogPath)\n\n\t// Create a default data source if none was found\n\tif ds == nil {\n\t\tds = &DefaultDataSource{}\n\t}\n\n\tmanifest, err := ConvertDbtCatalogToWrenMDL(catalogPath, ds, manifestPathForConversion, semanticManifestPathForConversion, opts.IncludeStagingModels)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to convert catalog: %w\", err)\n\t}\n\n\t// Write Wren MDL JSON\n\tmdlPath := filepath.Join(opts.OutputDir, \"wren-mdl.json\")\n\tmdlJSON, err := json.MarshalIndent(manifest, \"\", \"  \")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to marshal MDL JSON: %w\", err)\n\t}\n\n\tif err := os.WriteFile(mdlPath, mdlJSON, 0600); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to write MDL file: %w\", err)\n\t}\n\n\tpterm.Success.Printf(\"✓ Wren MDL saved to: %s\\n\", mdlPath)\n\n\t// Summary\n\tpterm.Success.Println(\"\\n🎉 Conversion completed successfully!\")\n\tpterm.Info.Printf(\"Models converted: %d\\n\", len(manifest.Models))\n\tpterm.Info.Printf(\"Relationships generated: %d\\n\", len(manifest.Relationships))\n\tpterm.Info.Printf(\"Metrics generated: %d\\n\", len(manifest.Metrics))\n\tpterm.Info.Printf(\"Enums generated: %d\\n\", len(manifest.EnumDefinitions))\n\n\tif dataSourceGenerated {\n\t\tpterm.Info.Println(\"Generated files:\")\n\t\tpterm.Info.Printf(\"  - WrenDataSource: %s\\n\", filepath.Join(opts.OutputDir, \"wren-datasource.json\"))\n\t\tpterm.Info.Printf(\"  - Wren MDL: %s\\n\", filepath.Join(opts.OutputDir, \"wren-mdl.json\"))\n\t} else {\n\t\tpterm.Info.Println(\"Generated files:\")\n\t\tpterm.Info.Printf(\"  - Wren MDL: %s\\n\", filepath.Join(opts.OutputDir, \"wren-mdl.json\"))\n\t\tif profilesPath != \"\" {\n\t\t\tpterm.Warning.Println(\"  - WrenDataSource: Not generated (no compatible data sources found)\")\n\t\t} else {\n\t\t\tpterm.Warning.Println(\"  - WrenDataSource: Not generated (profiles.yml not found)\")\n\t\t}\n\t}\n\n\treturn &ConvertResult{\n\t\tLocalStoragePath:    localStoragePath,\n\t\tDataSourceGenerated: dataSourceGenerated,\n\t\tModelsCount:         len(manifest.Models),\n\t}, nil\n}\n\nfunc handleLocalhostForContainer(host string) string {\n\t// If the host is localhost, we need to handle it for container usage\n\tif host == \"localhost\" || host == \"127.0.0.1\" {\n\t\t// For container usage, we can use the host network or a specific IP.\n\t\t// \"host.docker.internal\" is a special DNS name that resolves to the internal IP address of the host.\n\t\t// It's supported on Docker Desktop for Mac and Windows, and in Docker Engine 20.10+ for Linux.\n\t\t// This makes it a reliable default for accessing host services from within a container.\n\t\treturn \"host.docker.internal\"\n\t}\n\treturn host\n}\n\n// ConvertDbtCatalogToWrenMDL is the main function to convert a dbt catalog into a Wren MDL manifest.\n// It orchestrates the reading of dbt artifacts and processes each dbt node to convert it into a Wren model.\nfunc ConvertDbtCatalogToWrenMDL(catalogPath string, dataSource DataSource, manifestPath string, semanticManifestPath string, includeStagingModels bool) (*WrenMDLManifest, error) {\n\t// --- 1. Read and Parse All Necessary DBT Artifact Files ---\n\n\t// Read and unmarshal the primary catalog.json file.\n\tcatalogBytes, err := os.ReadFile(filepath.Clean(catalogPath))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read catalog file %s: %w\", catalogPath, err)\n\t}\n\tvar catalogData map[string]interface{}\n\tif err := json.Unmarshal(catalogBytes, &catalogData); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse catalog JSON: %w\", err)\n\t}\n\n\t// Read and unmarshal the manifest.json file, which contains rich metadata.\n\tvar manifestData map[string]interface{}\n\tif manifestPath != \"\" {\n\t\tpterm.Info.Printf(\"Reading manifest.json for descriptions and relationships from: %s\\n\", manifestPath)\n\t\tmanifestBytes, err := os.ReadFile(filepath.Clean(manifestPath)) // #nosec G304 -- manifestPath is controlled by application\n\t\tif err != nil {\n\t\t\tpterm.Warning.Printf(\"Could not read manifest file %s: %v. Descriptions and relationships will be missing.\\n\", manifestPath, err)\n\t\t} else if err := json.Unmarshal(manifestBytes, &manifestData); err != nil {\n\t\t\tpterm.Warning.Printf(\"Could not parse manifest file %s: %v. Descriptions and relationships will be missing.\\n\", manifestPath, err)\n\t\t}\n\t}\n\n\t// Read and unmarshal the semantic_manifest.json file for metrics and primary keys.\n\tvar semanticManifestData map[string]interface{}\n\tif semanticManifestPath != \"\" {\n\t\tsemanticBytes, err := os.ReadFile(filepath.Clean(semanticManifestPath))\n\t\tif err != nil {\n\t\t\tpterm.Warning.Printf(\"Could not read semantic_manifest.json: %v. Metrics and primary keys will be missing.\\n\", err)\n\t\t} else if err := json.Unmarshal(semanticBytes, &semanticManifestData); err != nil {\n\t\t\tpterm.Warning.Printf(\"Could not parse semantic_manifest.json: %v. Metrics and primary keys will be missing.\\n\", err)\n\t\t}\n\t}\n\n\t// --- 2. Initialize Wren Manifest and Pre-process Metadata ---\n\n\tmanifest := &WrenMDLManifest{\n\t\tJsonSchema:      \"https://raw.githubusercontent.com/Canner/WrenAI/main/wren-mdl/mdl.schema.json\",\n\t\tCatalog:         \"wren\",\n\t\tSchema:          \"public\",\n\t\tEnumDefinitions: []EnumDefinition{},\n\t\tModels:          []WrenModel{},\n\t\tRelationships:   []Relationship{},\n\t\tMetrics:         []Metric{},\n\t\tViews:           []View{},\n\t\tDataSource:      dataSource.GetType(),\n\t}\n\n\t// Create lookup maps to store pre-processed information for quick access.\n\tenumValueToNameMap := make(map[string]string)\n\tcolumnToEnumNameMap := make(map[string]string)\n\tcolumnToNotNullMap := make(map[string]bool)\n\tmodelToPrimaryKeyMap := make(map[string]string)\n\n\t// Pre-process the manifest to extract test data (enums, not-null constraints).\n\tif manifestData != nil {\n\t\tpreprocessManifestForTests(manifestData, &manifest.EnumDefinitions, enumValueToNameMap, columnToEnumNameMap, columnToNotNullMap)\n\t}\n\n\t// Pre-process the semantic manifest to extract primary key information.\n\tif semanticManifestData != nil {\n\t\tpreprocessSemanticManifestForPrimaryKeys(semanticManifestData, modelToPrimaryKeyMap)\n\t}\n\n\t// --- 3. Convert dbt Nodes to Wren Models ---\n\n\tnodesValue, exists := catalogData[\"nodes\"]\n\tif !exists {\n\t\treturn nil, fmt.Errorf(\"no 'nodes' section found in catalog\")\n\t}\n\tnodesMap, ok := nodesValue.(map[string]interface{})\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"invalid 'nodes' format in catalog\")\n\t}\n\n\t// Iterate through each node in the catalog and convert it to a Wren model.\n\tfor nodeKey, nodeValue := range nodesMap {\n\t\tnodeMap, ok := nodeValue.(map[string]interface{})\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\t// We are only interested in nodes that represent dbt models.\n\t\tif !strings.HasPrefix(nodeKey, \"model.\") {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Skip staging models if the user has opted to exclude them.\n\t\tmodelName := getModelNameFromNodeKey(nodeKey)\n\t\tif !includeStagingModels && (strings.HasPrefix(modelName, \"stg_\") || strings.HasPrefix(modelName, \"staging_\")) {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Perform the conversion for the single node.\n\t\tmodel, err := convertDbtNodeToWrenModel(nodeKey, nodeMap, dataSource, manifestData, columnToEnumNameMap, columnToNotNullMap, modelToPrimaryKeyMap)\n\t\tif err != nil {\n\t\t\tpterm.Warning.Printf(\"Failed to convert model %s: %v\\n\", nodeKey, err)\n\t\t\tcontinue\n\t\t}\n\t\tmanifest.Models = append(manifest.Models, *model)\n\t}\n\n\t// --- 4. Generate Relationships and Metrics ---\n\n\t// Generate relationships between models based on the dbt manifest.\n\tif manifestData != nil {\n\t\tmanifest.Relationships = generateRelationships(manifestData)\n\t}\n\n\t// Generate metrics from the semantic manifest.\n\tif semanticManifestData != nil {\n\t\tmanifest.Metrics = convertDbtMetricsToWrenMetrics(semanticManifestData)\n\t}\n\n\treturn manifest, nil\n}\n\n// preprocessManifestForTests extracts information from dbt tests (like 'not_null' and 'accepted_values')\n// and populates maps that will be used later during model conversion.\nfunc preprocessManifestForTests(manifestData map[string]interface{}, enums *[]EnumDefinition, enumValueToNameMap, columnToEnumNameMap map[string]string, columnToNotNullMap map[string]bool) {\n\tnodes, ok := manifestData[\"nodes\"].(map[string]interface{})\n\tif !ok {\n\t\treturn\n\t}\n\n\tfor nodeKey, nodeValue := range nodes {\n\t\tnodeMap, ok := nodeValue.(map[string]interface{})\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Process tests defined directly on model columns.\n\t\tif strings.HasPrefix(nodeKey, \"model.\") {\n\t\t\tmodelName := getModelNameFromNodeKey(nodeKey)\n\t\t\tif columns, ok := nodeMap[\"columns\"].(map[string]interface{}); ok {\n\t\t\t\tfor columnName, colData := range columns {\n\t\t\t\t\tif colMap, ok := colData.(map[string]interface{}); ok {\n\t\t\t\t\t\tprocessColumnForTests(nodeKey, modelName, columnName, colMap, enums, enumValueToNameMap, columnToEnumNameMap, columnToNotNullMap)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Process compiled test nodes which are separate entries in the manifest.\n\t\tif strings.HasPrefix(nodeKey, \"test.\") {\n\t\t\ttestMeta, _ := nodeMap[\"test_metadata\"].(map[string]interface{})\n\t\t\ttestName := getStringFromMap(testMeta, \"name\", \"\")\n\t\t\tattachedNodeID := getStringFromMap(nodeMap, \"attached_node\", \"\")\n\t\t\tcolumnName := getStringFromMap(nodeMap, \"column_name\", \"\")\n\n\t\t\tif attachedNodeID != \"\" && columnName != \"\" {\n\t\t\t\tcolumnKey := fmt.Sprintf(\"%s.%s\", attachedNodeID, columnName)\n\t\t\t\tmodelName := getModelNameFromNodeKey(attachedNodeID)\n\n\t\t\t\tif testName == \"not_null\" {\n\t\t\t\t\tcolumnToNotNullMap[columnKey] = true\n\t\t\t\t}\n\n\t\t\t\tif testName == \"accepted_values\" {\n\t\t\t\t\tif kwargs, ok := testMeta[\"kwargs\"].(map[string]interface{}); ok {\n\t\t\t\t\t\tif values, ok := kwargs[\"values\"].([]interface{}); ok && len(values) > 0 {\n\t\t\t\t\t\t\tcreateOrLinkEnum(modelName, columnName, columnKey, values, enums, enumValueToNameMap, columnToEnumNameMap)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// preprocessSemanticManifestForPrimaryKeys extracts primary key information from the semantic manifest.\nfunc preprocessSemanticManifestForPrimaryKeys(semanticData map[string]interface{}, modelToPrimaryKeyMap map[string]string) {\n\tsemanticModels, ok := semanticData[\"semantic_models\"].([]interface{})\n\tif !ok {\n\t\treturn\n\t}\n\n\tfor _, sm := range semanticModels {\n\t\tsmMap, ok := sm.(map[string]interface{})\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\n\t\tvar modelName string\n\t\tif nr, ok := smMap[\"node_relation\"].(map[string]interface{}); ok {\n\t\t\tmodelName = getStringFromMap(nr, \"alias\", \"\")\n\t\t}\n\n\t\tif entities, ok := smMap[\"entities\"].([]interface{}); ok {\n\t\t\tfor _, entity := range entities {\n\t\t\t\tif entityMap, ok := entity.(map[string]interface{}); ok {\n\t\t\t\t\tif getStringFromMap(entityMap, \"type\", \"\") == \"primary\" {\n\t\t\t\t\t\tpk := getStringFromMap(entityMap, \"expr\", \"\")\n\t\t\t\t\t\tif modelName != \"\" && pk != \"\" {\n\t\t\t\t\t\t\tmodelToPrimaryKeyMap[modelName] = pk\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// generateRelationships iterates through the manifest and creates relationship definitions.\nfunc generateRelationships(manifestData map[string]interface{}) []Relationship {\n\tvar relationships []Relationship\n\tif nodes, ok := manifestData[\"nodes\"].(map[string]interface{}); ok {\n\t\tfor nodeKey, nodeValue := range nodes {\n\t\t\tnodeMap, ok := nodeValue.(map[string]interface{})\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Case 1: Handle tests on model columns (including structs)\n\t\t\tif strings.HasPrefix(nodeKey, \"model.\") {\n\t\t\t\tfromModelName := getModelNameFromNodeKey(nodeKey)\n\t\t\t\tif fromModelName == \"\" {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif columns, ok := nodeMap[\"columns\"].(map[string]interface{}); ok {\n\t\t\t\t\tfor columnName, colData := range columns {\n\t\t\t\t\t\tif colMap, ok := colData.(map[string]interface{}); ok {\n\t\t\t\t\t\t\trelationships = append(relationships, parseTestsForRelationships(fromModelName, columnName, colMap)...)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Case 2: Handle compiled test nodes for simple columns\n\t\t\tif strings.HasPrefix(nodeKey, \"test.\") {\n\t\t\t\tif testMeta, ok := nodeMap[\"test_metadata\"].(map[string]interface{}); ok {\n\t\t\t\t\tif getStringFromMap(testMeta, \"name\", \"\") == \"relationships\" {\n\t\t\t\t\t\tif kwargs, ok := testMeta[\"kwargs\"].(map[string]interface{}); ok {\n\t\t\t\t\t\t\ttoRef := getStringFromMap(kwargs, \"to\", \"\")\n\t\t\t\t\t\t\ttoField := getStringFromMap(kwargs, \"field\", \"\")\n\t\t\t\t\t\t\ttoModelName := parseRef(toRef)\n\t\t\t\t\t\t\tfromColumnName := getStringFromMap(nodeMap, \"column_name\", \"\")\n\t\t\t\t\t\t\tattachedNodeID := getStringFromMap(nodeMap, \"attached_node\", \"\")\n\t\t\t\t\t\t\tfromModelName := getModelNameFromNodeKey(attachedNodeID)\n\n\t\t\t\t\t\t\tif toModelName != \"\" && toField != \"\" && fromModelName != \"\" && fromColumnName != \"\" {\n\t\t\t\t\t\t\t\trel := Relationship{\n\t\t\t\t\t\t\t\t\tName:      fmt.Sprintf(\"%s_to_%s_by_%s\", fromModelName, toModelName, fromColumnName),\n\t\t\t\t\t\t\t\t\tModels:    []string{fromModelName, toModelName},\n\t\t\t\t\t\t\t\t\tJoinType:  \"MANY_TO_ONE\",\n\t\t\t\t\t\t\t\t\tCondition: fmt.Sprintf(\"\\\"%s\\\".\\\"%s\\\" = \\\"%s\\\".\\\"%s\\\"\", fromModelName, fromColumnName, toModelName, toField),\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\trelationships = append(relationships, rel)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tseen := make(map[string]struct{}, len(relationships))\n\t// if relationship is empty, return empty slice instead of nil\n\tunique := []Relationship{}\n\tfor _, r := range relationships {\n\t\tkey := r.Name + \"|\" + r.JoinType + \"|\" + r.Condition\n\t\tif _, ok := seen[key]; ok {\n\t\t\tcontinue\n\t\t}\n\t\tseen[key] = struct{}{}\n\t\tunique = append(unique, r)\n\t}\n\treturn unique\n}\n\n// parseTestsForRelationships is a helper function to extract relationship tests from a column or its fields.\nfunc parseTestsForRelationships(fromModelName, columnName string, colMap map[string]interface{}) []Relationship {\n\tvar relationships []Relationship\n\t// Case 1: Tests are directly on the column.\n\tif tests, ok := colMap[\"tests\"].([]interface{}); ok {\n\t\trelationships = append(relationships, extractRelationshipsFromTests(fromModelName, columnName, tests)...)\n\t}\n\t// Case 2: Tests are on fields within a struct column.\n\tif fields, ok := colMap[\"fields\"].([]interface{}); ok {\n\t\tfor _, fieldData := range fields {\n\t\t\tif fieldMap, ok := fieldData.(map[string]interface{}); ok {\n\t\t\t\tfieldName := getStringFromMap(fieldMap, \"name\", \"\")\n\t\t\t\tif fieldName == \"\" {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif tests, ok := fieldMap[\"tests\"].([]interface{}); ok {\n\t\t\t\t\trelationships = append(relationships, extractRelationshipsFromTests(fromModelName, fieldName, tests)...)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn relationships\n}\n\n// extractRelationshipsFromTests extracts relationship info from a 'tests' array.\nfunc extractRelationshipsFromTests(fromModelName, fromColumnName string, tests []interface{}) []Relationship {\n\t// if relationship is empty, return empty slice instead of nil\n\trelationships := []Relationship{}\n\tfor _, test := range tests {\n\t\tif relTest, ok := test.(map[string]interface{}); ok {\n\t\t\tif relData, ok := relTest[\"relationships\"].(map[string]interface{}); ok {\n\t\t\t\ttoRef := getStringFromMap(relData, \"to\", \"\")\n\t\t\t\ttoField := getStringFromMap(relData, \"field\", \"\")\n\t\t\t\ttoModelName := parseRef(toRef)\n\n\t\t\t\tif toModelName != \"\" && toField != \"\" {\n\t\t\t\t\trel := Relationship{\n\t\t\t\t\t\tName:      fmt.Sprintf(\"%s_to_%s_by_%s\", fromModelName, toModelName, fromColumnName),\n\t\t\t\t\t\tModels:    []string{fromModelName, toModelName},\n\t\t\t\t\t\tJoinType:  \"MANY_TO_ONE\",\n\t\t\t\t\t\tCondition: fmt.Sprintf(\"\\\"%s\\\".\\\"%s\\\" = \\\"%s\\\".\\\"%s\\\"\", fromModelName, fromColumnName, toModelName, toField),\n\t\t\t\t\t}\n\t\t\t\t\trelationships = append(relationships, rel)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn relationships\n}\n\n// createOrLinkEnum is a helper to de-duplicate and manage enum creation based on 'accepted_values' tests.\nfunc createOrLinkEnum(modelName, columnName, columnKey string, values []interface{}, allEnums *[]EnumDefinition, enumValueToNameMap, columnToEnumNameMap map[string]string) {\n\tvar strValues []string\n\tvar enumValues []EnumValue\n\tfor _, v := range values {\n\t\tif s, ok := v.(string); ok {\n\t\t\tstrValues = append(strValues, s)\n\t\t\tenumValues = append(enumValues, EnumValue{Name: s})\n\t\t}\n\t}\n\tif len(strValues) == 0 {\n\t\treturn\n\t}\n\tsort.Strings(strValues)\n\tvalueKey := strings.Join(strValues, \",\")\n\n\tenumName, exists := enumValueToNameMap[valueKey]\n\tif !exists {\n\t\tenumName = fmt.Sprintf(\"%s_%s_Enum\", modelName, columnName)\n\t\t// Sanitize enum name to be a valid identifier\n\t\tre := regexp.MustCompile(`[^a-zA-Z0-9_]`)\n\t\tenumName = re.ReplaceAllString(enumName, \"_\")\n\t\tif len(enumName) > 0 && enumName[0] >= '0' && enumName[0] <= '9' {\n\t\t\tenumName = \"_\" + enumName\n\t\t}\n\t\t*allEnums = append(*allEnums, EnumDefinition{\n\t\t\tName:   enumName,\n\t\t\tValues: enumValues,\n\t\t})\n\t\tenumValueToNameMap[valueKey] = enumName\n\t}\n\tcolumnToEnumNameMap[columnKey] = enumName\n}\n\n// processColumnForTests finds tests in a column definition (including nested fields) and processes them.\nfunc processColumnForTests(nodeKey, modelName, columnName string, colMap map[string]interface{}, allEnums *[]EnumDefinition, enumValueToNameMap, columnToEnumNameMap map[string]string, columnToNotNullMap map[string]bool) {\n\t// Helper to handle the actual test processing for a given column/field\n\tprocessTests := func(currentColumnKey, currentColumnName string, tests []interface{}) {\n\t\tfor _, test := range tests {\n\t\t\t// Handle not_null test (string format)\n\t\t\tif testStr, ok := test.(string); ok && testStr == \"not_null\" {\n\t\t\t\tcolumnToNotNullMap[currentColumnKey] = true\n\t\t\t}\n\n\t\t\t// Handle tests in map format (e.g., accepted_values)\n\t\t\tif testMap, ok := test.(map[string]interface{}); ok {\n\t\t\t\tif accepted, ok := testMap[\"accepted_values\"].(map[string]interface{}); ok {\n\t\t\t\t\tif values, ok := accepted[\"values\"].([]interface{}); ok && len(values) > 0 {\n\t\t\t\t\t\tcreateOrLinkEnum(modelName, currentColumnName, currentColumnKey, values, allEnums, enumValueToNameMap, columnToEnumNameMap)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Case 1: Tests are directly on the column itself.\n\tif tests, ok := colMap[\"tests\"].([]interface{}); ok {\n\t\tcolumnKey := fmt.Sprintf(\"%s.%s\", nodeKey, columnName)\n\t\tprocessTests(columnKey, columnName, tests)\n\t}\n\n\t// Case 2: The column is a struct, and tests are on its fields.\n\tif fields, ok := colMap[\"fields\"].([]interface{}); ok {\n\t\tfor _, fieldData := range fields {\n\t\t\tif fieldMap, ok := fieldData.(map[string]interface{}); ok {\n\t\t\t\tfieldName := getStringFromMap(fieldMap, \"name\", \"\")\n\t\t\t\tif fieldName == \"\" {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif tests, ok := fieldMap[\"tests\"].([]interface{}); ok {\n\t\t\t\t\t// The unique key for a field is based on the field name.\n\t\t\t\t\tcolumnKey := fmt.Sprintf(\"%s.%s\", nodeKey, fieldName)\n\t\t\t\t\tprocessTests(columnKey, fieldName, tests)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// convertDbtMetricsToWrenMetrics converts dbt metrics from the semantic manifest into the Wren MDL format.\n// It serves as the main entry point for metric conversion, orchestrating the creation of lookup tables\n// and processing each metric definition.\nfunc convertDbtMetricsToWrenMetrics(semanticData map[string]interface{}) []Metric {\n\tvar wrenMetrics []Metric\n\n\t// --- 1. Pre-process semantic models to build fast lookup maps ---\n\t// These maps are essential for quickly finding the model a measure belongs to and its details.\n\tmeasureToModelMap, measureDataLookup := buildMeasureLookups(semanticData)\n\n\t// --- 2. Iterate through each metric and convert it ---\n\tmetrics, ok := semanticData[\"metrics\"].([]interface{})\n\tif !ok {\n\t\t// If there's no 'metrics' array, there's nothing to do.\n\t\treturn wrenMetrics\n\t}\n\n\tfor _, m := range metrics {\n\t\tmetricMap, ok := m.(map[string]interface{})\n\t\tif !ok {\n\t\t\tcontinue // Skip if the item is not a valid map.\n\t\t}\n\n\t\t// --- 3. Extract basic metric information ---\n\t\tmetricName := getStringFromMap(metricMap, \"name\", \"\")\n\t\tif metricName == \"\" {\n\t\t\tcontinue // A metric must have a name.\n\t\t}\n\n\t\twrenMetric := Metric{\n\t\t\tName:        metricName,\n\t\t\tDisplayName: getStringFromMap(metricMap, \"label\", metricName),\n\t\t\tDescription: getStringFromMap(metricMap, \"description\", \"\"),\n\t\t}\n\n\t\ttypeParams, _ := metricMap[\"type_params\"].(map[string]interface{})\n\n\t\t// --- 4. Determine the base model and time dimensions for the metric ---\n\t\tbaseModel := findBaseModelForMetric(typeParams, measureToModelMap)\n\t\tif baseModel == \"\" {\n\t\t\tpterm.Warning.Printf(\"Could not find a parent model for metric '%s'\\n\", metricName)\n\t\t\tcontinue // Skip metric if we can't associate it with a model.\n\t\t}\n\n\t\twrenMetric.Models = []string{baseModel}\n\t\twrenMetric.Dimensions = findTimeDimensionsForModel(semanticData, baseModel)\n\n\t\t// --- 5. Build the specific aggregation expression based on the metric type ---\n\t\tmetricType := getStringFromMap(metricMap, \"type\", \"\")\n\t\twrenMetric.Aggregation = buildAggregationExpression(metricType, typeParams, measureDataLookup)\n\n\t\t// --- 6. Final validation before adding to the list ---\n\t\t// A metric is only valid if it has a base model and a valid aggregation expression.\n\t\tif wrenMetric.Aggregation != \"\" && len(wrenMetric.Models) > 0 {\n\t\t\twrenMetrics = append(wrenMetrics, wrenMetric)\n\t\t}\n\t}\n\n\treturn wrenMetrics\n}\n\n// buildMeasureLookups preprocesses the semantic models to create two essential maps:\n// 1. measureToModelMap: Maps a measure's name to the name of the model it belongs to.\n// 2. measureDataLookup: Maps a measure's name to its full data map for easy access to properties like `agg` and `expr`.\nfunc buildMeasureLookups(semanticData map[string]interface{}) (map[string]string, map[string]map[string]interface{}) {\n\tmeasureToModelMap := make(map[string]string)\n\tmeasureDataLookup := make(map[string]map[string]interface{})\n\n\tsemanticModels, ok := semanticData[\"semantic_models\"].([]interface{})\n\tif !ok {\n\t\treturn measureToModelMap, measureDataLookup\n\t}\n\n\tfor _, sm := range semanticModels {\n\t\tsmMap, ok := sm.(map[string]interface{})\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\n\t\tmodelName := getStringFromMap(smMap, \"name\", \"\")\n\t\tif modelName == \"\" {\n\t\t\tcontinue\n\t\t}\n\n\t\tif measures, ok := smMap[\"measures\"].([]interface{}); ok {\n\t\t\tfor _, m := range measures {\n\t\t\t\tif measureMap, ok := m.(map[string]interface{}); ok {\n\t\t\t\t\tmeasureName := getStringFromMap(measureMap, \"name\", \"\")\n\t\t\t\t\tif measureName != \"\" {\n\t\t\t\t\t\tmeasureToModelMap[measureName] = modelName\n\t\t\t\t\t\tmeasureDataLookup[measureName] = measureMap\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn measureToModelMap, measureDataLookup\n}\n\n// findBaseModelForMetric identifies the underlying base model for a given metric\n// by looking at its \"input_measures\".\nfunc findBaseModelForMetric(typeParams map[string]interface{}, measureToModelMap map[string]string) string {\n\tinputMeasuresValue, ok := typeParams[\"input_measures\"]\n\tif !ok {\n\t\t// Fallback for simple metrics that use \"measure\" instead of \"input_measures\"\n\t\tif measureValue, ok := typeParams[\"measure\"]; ok {\n\t\t\tif measureMap, ok := measureValue.(map[string]interface{}); ok {\n\t\t\t\tmeasureName := getStringFromMap(measureMap, \"name\", \"\")\n\t\t\t\tif model, exists := measureToModelMap[measureName]; exists {\n\t\t\t\t\treturn model\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn \"\"\n\t}\n\n\tinputMeasuresList, ok := inputMeasuresValue.([]interface{})\n\tif !ok || len(inputMeasuresList) == 0 {\n\t\treturn \"\"\n\t}\n\n\t// Assume all measures for a given metric come from the same base model.\n\t// We only need to find the first valid one.\n\tfor _, inputMeasure := range inputMeasuresList {\n\t\tif imMap, ok := inputMeasure.(map[string]interface{}); ok {\n\t\t\timName := getStringFromMap(imMap, \"name\", \"\")\n\t\t\tif model, exists := measureToModelMap[imName]; exists {\n\t\t\t\treturn model // Return the first model we find.\n\t\t\t}\n\t\t}\n\t}\n\treturn \"\"\n}\n\n// findTimeDimensionsForModel scans the semantic models to find all columns\n// marked with type \"time\" for a specific model name.\nfunc findTimeDimensionsForModel(semanticData map[string]interface{}, baseModelName string) []string {\n\tvar timeDimensions []string\n\tsemanticModels, ok := semanticData[\"semantic_models\"].([]interface{})\n\tif !ok {\n\t\treturn timeDimensions\n\t}\n\n\tfor _, sm := range semanticModels {\n\t\tsmMap, ok := sm.(map[string]interface{})\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\n\t\tif getStringFromMap(smMap, \"name\", \"\") == baseModelName {\n\t\t\tif dims, ok := smMap[\"dimensions\"].([]interface{}); ok {\n\t\t\t\tfor _, d := range dims {\n\t\t\t\t\tif dimMap, ok := d.(map[string]interface{}); ok {\n\t\t\t\t\t\tif getStringFromMap(dimMap, \"type\", \"\") == \"time\" {\n\t\t\t\t\t\t\ttimeDimensions = append(timeDimensions, getStringFromMap(dimMap, \"name\", \"\"))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak // Found the model, no need to continue looping.\n\t\t}\n\t}\n\treturn timeDimensions\n}\n\n// buildAggregationExpression constructs the SQL aggregation string for a Wren metric\n// based on its dbt type ('simple', 'ratio', or 'derived').\nfunc buildAggregationExpression(metricType string, typeParams map[string]interface{}, measureDataLookup map[string]map[string]interface{}) string {\n\tswitch metricType {\n\tcase \"simple\":\n\t\t// A simple metric is a direct aggregation of one measure (e.g., SUM(revenue)).\n\t\tif measure, ok := typeParams[\"measure\"].(map[string]interface{}); ok {\n\t\t\tmeasureName := getStringFromMap(measure, \"name\", \"\")\n\t\t\tif measureData, ok := measureDataLookup[measureName]; ok {\n\t\t\t\tagg := getStringFromMap(measureData, \"agg\", \"sum\")         // Default to SUM\n\t\t\t\texpr := getStringFromMap(measureData, \"expr\", measureName) // Fallback to measure name\n\t\t\t\treturn fmt.Sprintf(\"%s(%s)\", strings.ToUpper(agg), expr)\n\t\t\t}\n\t\t}\n\tcase \"ratio\":\n\t\t// A ratio metric is a division of two measures (e.g., SUM(profit) / SUM(revenue)).\n\t\tnum, numOK := typeParams[\"numerator\"].(map[string]interface{})\n\t\tden, denOK := typeParams[\"denominator\"].(map[string]interface{})\n\t\tif !numOK || !denOK {\n\t\t\treturn \"\"\n\t\t}\n\n\t\tnumName := getStringFromMap(num, \"name\", \"\")\n\t\tdenName := getStringFromMap(den, \"name\", \"\")\n\t\tnumData, numDataOK := measureDataLookup[numName]\n\t\tdenData, denDataOK := measureDataLookup[denName]\n\n\t\tif numDataOK && denDataOK {\n\t\t\tnumAgg := strings.ToUpper(getStringFromMap(numData, \"agg\", \"sum\"))\n\t\t\tdenAgg := strings.ToUpper(getStringFromMap(denData, \"agg\", \"sum\"))\n\t\t\tnumExpr := getStringFromMap(numData, \"expr\", numName)\n\t\t\tdenExpr := getStringFromMap(denData, \"expr\", denName)\n\t\t\treturn fmt.Sprintf(\"(%s(%s)) / (%s(%s))\", numAgg, numExpr, denAgg, denExpr)\n\t\t}\n\tcase \"derived\":\n\t\t// A derived metric uses a freeform SQL expression.\n\t\treturn getStringFromMap(typeParams, \"expr\", \"\")\n\t}\n\treturn \"\" // Return empty string if no valid aggregation could be built.\n}\n\n// extractDescriptionsFromManifest parses the manifest.json data to find the\n// model-level description and a map of all column-level descriptions.\nfunc extractDescriptionsFromManifest(manifestData map[string]interface{}, nodeKey string) (string, map[string]string) {\n\tif manifestData == nil {\n\t\treturn \"\", nil\n\t}\n\n\tnodes, ok := manifestData[\"nodes\"].(map[string]interface{})\n\tif !ok {\n\t\treturn \"\", nil\n\t}\n\n\tmanifestNode, ok := nodes[nodeKey].(map[string]interface{})\n\tif !ok {\n\t\treturn \"\", nil\n\t}\n\n\t// Extract the top-level model description\n\tmodelDescription := getStringFromMap(manifestNode, \"description\", \"\")\n\tcolumnDescriptions := make(map[string]string)\n\n\tmanifestColumns, ok := manifestNode[\"columns\"].(map[string]interface{})\n\tif !ok {\n\t\t// Return the model description even if columns aren't found\n\t\treturn modelDescription, nil\n\t}\n\n\t// Iterate through columns to extract their descriptions\n\tfor colName, colData := range manifestColumns {\n\t\tif colMap, ok := colData.(map[string]interface{}); ok {\n\t\t\tif description := getStringFromMap(colMap, \"description\", \"\"); description != \"\" {\n\t\t\t\tcolumnDescriptions[colName] = description\n\t\t\t}\n\t\t}\n\t}\n\n\treturn modelDescription, columnDescriptions\n}\n\n// buildWrenColumn creates a single WrenColumn from its corresponding dbt column data map.\n// It populates the name, type, and properties like enums, descriptions, and comments.\nfunc buildWrenColumn(colMap map[string]interface{}, nodeKey string, dataSource DataSource, columnDescriptions map[string]string, columnToEnumNameMap map[string]string, columnToNotNullMap map[string]bool) WrenColumn {\n\tcolumnName := getStringFromMap(colMap, \"name\", \"\")\n\tcolumnKey := fmt.Sprintf(\"%s.%s\", nodeKey, columnName)\n\n\tcolumn := WrenColumn{\n\t\tName:        columnName,\n\t\tDisplayName: getStringFromMap(getMapFromMap(colMap, \"meta\", nil), \"label\", \"\"),\n\t\tType:        dataSource.MapType(getStringFromMap(colMap, \"type\", \"\")),\n\t\tNotNull:     columnToNotNullMap[columnKey], // Defaults to false if not found\n\t}\n\n\t// Use a temporary map to build the properties\n\tproperties := make(map[string]string)\n\tif description, exists := columnDescriptions[column.Name]; exists && description != \"\" {\n\t\tproperties[\"description\"] = description\n\t}\n\tif comment := getStringFromMap(colMap, \"comment\", \"\"); comment != \"\" {\n\t\tproperties[\"comment\"] = comment\n\t}\n\n\t// Assign an enum if one was derived from dbt tests\n\t// TODO: enum isn't implemented in Wren yet, putting this here for future use\n\tif enumName, ok := columnToEnumNameMap[columnKey]; ok {\n\t\tproperties[\"enumDefinition\"] = enumName\n\t}\n\n\t// Assign the properties map only if it's not empty\n\tif len(properties) > 0 {\n\t\tcolumn.Properties = properties\n\t}\n\n\treturn column\n}\n\n// convertAndSortColumns extracts, sorts, and converts dbt columns to the WrenColumn format.\nfunc convertAndSortColumns(nodeData map[string]interface{}, nodeKey string, dataSource DataSource, columnDescriptions map[string]string, columnToEnumNameMap map[string]string, columnToNotNullMap map[string]bool) ([]WrenColumn, error) {\n\tcolumnsValue, exists := nodeData[\"columns\"]\n\tif !exists {\n\t\treturn nil, fmt.Errorf(\"no columns found for model %s\", nodeKey)\n\t}\n\n\tcolumnsMap, ok := columnsValue.(map[string]interface{})\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"invalid columns format for model %s\", nodeKey)\n\t}\n\n\t// Convert map to a slice for sorting\n\tvar columnsData []map[string]interface{}\n\tfor _, colValue := range columnsMap {\n\t\tif colMap, ok := colValue.(map[string]interface{}); ok {\n\t\t\tcolumnsData = append(columnsData, colMap)\n\t\t}\n\t}\n\n\t// Sort columns by the 'index' field, falling back to name\n\tsort.Slice(columnsData, func(i, j int) bool {\n\t\tindexI, okI := columnsData[i][\"index\"].(float64)\n\t\tindexJ, okJ := columnsData[j][\"index\"].(float64)\n\t\tif okI && okJ {\n\t\t\treturn indexI < indexJ\n\t\t}\n\t\treturn getStringFromMap(columnsData[i], \"name\", \"\") < getStringFromMap(columnsData[j], \"name\", \"\")\n\t})\n\n\t// Build the final slice of WrenColumns\n\tvar wrenColumns []WrenColumn\n\tfor _, colMap := range columnsData {\n\t\tif getStringFromMap(colMap, \"name\", \"\") == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tcolumn := buildWrenColumn(colMap, nodeKey, dataSource, columnDescriptions, columnToEnumNameMap, columnToNotNullMap)\n\t\twrenColumns = append(wrenColumns, column)\n\t}\n\n\treturn wrenColumns, nil\n}\n\n// convertDbtNodeToWrenModel converts a single dbt node to a Wren model.\n// This function now orchestrates calls to helpers to perform the conversion.\nfunc convertDbtNodeToWrenModel(nodeKey string, nodeData map[string]interface{}, dataSource DataSource, manifestData map[string]interface{}, columnToEnumNameMap map[string]string, columnToNotNullMap map[string]bool, modelToPrimaryKeyMap map[string]string) (*WrenModel, error) {\n\tmodelName := getModelNameFromNodeKey(nodeKey)\n\tif modelName == \"\" {\n\t\treturn nil, fmt.Errorf(\"invalid node key format: %s\", nodeKey)\n\t}\n\n\t// --- 1. Extract Metadata and Table Reference ---\n\tmetadataValue, exists := nodeData[\"metadata\"]\n\tif !exists {\n\t\treturn nil, fmt.Errorf(\"no metadata found for model %s\", nodeKey)\n\t}\n\tmetadata, ok := metadataValue.(map[string]interface{})\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"invalid metadata format for model %s\", nodeKey)\n\t}\n\ttableRef := TableReference{\n\t\tTable:   getStringFromMap(metadata, \"name\", modelName),\n\t\tCatalog: getStringFromMap(metadata, \"database\", \"\"),\n\t\tSchema:  getStringFromMap(metadata, \"schema\", \"\"),\n\t}\n\n\t// --- 2. Extract Descriptions from Manifest ---\n\tmodelDescription, columnDescriptions := extractDescriptionsFromManifest(manifestData, nodeKey)\n\n\t// --- 3. Convert and Sort Columns ---\n\twrenColumns, err := convertAndSortColumns(nodeData, nodeKey, dataSource, columnDescriptions, columnToEnumNameMap, columnToNotNullMap)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// --- 4. Assemble the Final WrenModel ---\n\tmodel := &WrenModel{\n\t\tName:           modelName,\n\t\tTableReference: tableRef,\n\t\tColumns:        wrenColumns,\n\t}\n\n\t// Set primary key if available\n\tif pk, ok := modelToPrimaryKeyMap[modelName]; ok {\n\t\tmodel.PrimaryKey = pk\n\t}\n\n\t// Set model description if available\n\tif modelDescription != \"\" {\n\t\tmodel.Properties = map[string]string{\"description\": modelDescription}\n\t}\n\n\treturn model, nil\n}\n\n// getStringFromMap safely extracts a string value from a map\nfunc getStringFromMap(m map[string]interface{}, key, defaultValue string) string {\n\tif m == nil {\n\t\treturn defaultValue\n\t}\n\tif value, exists := m[key]; exists {\n\t\tif str, ok := value.(string); ok {\n\t\t\treturn str\n\t\t}\n\t}\n\treturn defaultValue\n}\n\n// getMapFromMap safely extracts a map value from a map\nfunc getMapFromMap(m map[string]interface{}, key string, defaultValue map[string]interface{}) map[string]interface{} {\n\tif value, exists := m[key]; exists {\n\t\tif str, ok := value.(map[string]interface{}); ok {\n\t\t\treturn str\n\t\t}\n\t}\n\treturn defaultValue\n}\n\n// getModelNameFromNodeKey extracts the model name from a dbt node key.\n// e.g., \"model.jaffle_shop.customers\" -> \"customers\"\nfunc getModelNameFromNodeKey(nodeKey string) string {\n\tparts := strings.Split(nodeKey, \".\")\n\tif len(parts) > 0 {\n\t\treturn parts[len(parts)-1]\n\t}\n\treturn \"\"\n}\n\nvar refRegex = regexp.MustCompile(`ref\\s*\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)`)\n\n// parseRef extracts the model name from a dbt ref string.\n// e.g., \"ref('stg_orders')\"\nfunc parseRef(refStr string) string {\n\t// Use the precompiled regex to find matches.\n\tmatches := refRegex.FindStringSubmatch(refStr)\n\tif len(matches) > 1 {\n\t\t// The first submatch (index 1) is the captured group,\n\t\t// which is the model name we want.\n\t\treturn matches[1]\n\t}\n\treturn \"\"\n}\n"
  },
  {
    "path": "wren-launcher/commands/dbt/data_source.go",
    "content": "package dbt\n\nimport (\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pterm/pterm\"\n)\n\n// Constants for data types\nconst (\n\tintegerType     = \"integer\"\n\tsmallintType    = \"smallint\"\n\tbigintType      = \"bigint\"\n\tfloatType       = \"float\"\n\tdecimalType     = \"decimal\"\n\tvarcharType     = \"varchar\"\n\tcharType        = \"char\"\n\ttextType        = \"text\"\n\tdateType        = \"date\"\n\ttimestampType   = \"timestamp\"\n\ttimestamptzType = \"timestamptz\"\n\tdoubleType      = \"double\"\n\tbooleanType     = \"boolean\"\n\tjsonType        = \"json\"\n\tintervalType    = \"interval\"\n\tpostgresType    = \"postgres\"\n)\n\n// Constants for SQL data types\nconst (\n\tintegerSQL   = \"INTEGER\"\n\tintSQL       = \"INT\"\n\tbigintSQL    = \"BIGINT\"\n\tvarcharSQL   = \"VARCHAR\"\n\ttextSQL      = \"TEXT\"\n\tstringSQL    = \"STRING\"\n\tdateSQL      = \"DATE\"\n\ttimestampSQL = \"TIMESTAMP\"\n\tdatetimeSQL  = \"DATETIME\"\n\tdoubleSQL    = \"DOUBLE\"\n\tfloatSQL     = \"FLOAT\"\n\tnumericSQL   = \"NUMERIC\"\n\tdecimalSQL   = \"DECIMAL\"\n\tbooleanSQL   = \"BOOLEAN\"\n\tboolSQL      = \"BOOL\"\n\tjsonSQL      = \"JSON\"\n)\n\n// DataSource is a common interface for all data source types\ntype DataSource interface {\n\tGetType() string\n\tValidate() error\n\tMapType(sourceType string) string\n}\n\n// FromDbtProfiles converts DBT profiles to DataSources\n// Returns a DataSource slice since a profile may contain multiple outputs\nfunc FromDbtProfiles(profiles *DbtProfiles) ([]DataSource, error) {\n\tif profiles == nil {\n\t\treturn nil, fmt.Errorf(\"profiles cannot be nil\")\n\t}\n\n\tvar dataSources []DataSource\n\n\t// Iterate through all profiles\n\tfor profileName, profile := range profiles.Profiles {\n\t\t// Iterate through each profile's outputs\n\t\tfor outputName, connection := range profile.Outputs {\n\t\t\tdataSource, err := convertConnectionToDataSource(connection, \"\", profileName, outputName)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to convert connection %s.%s: %w\", profileName, outputName, err)\n\t\t\t}\n\t\t\tif dataSource != nil {\n\t\t\t\tdataSources = append(dataSources, dataSource)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn dataSources, nil\n}\n\n// convertConnectionToDataSource converts connection to corresponding DataSource based on connection type\nfunc convertConnectionToDataSource(conn DbtConnection, dbtHomePath, profileName, outputName string) (DataSource, error) {\n\tswitch strings.ToLower(conn.Type) {\n\tcase postgresType, \"postgresql\":\n\t\treturn convertToPostgresDataSource(conn)\n\tcase \"duckdb\":\n\t\treturn convertToLocalFileDataSource(conn, dbtHomePath)\n\tcase \"sqlserver\":\n\t\treturn convertToMSSQLDataSource(conn)\n\tcase \"mysql\":\n\t\treturn convertToMysqlDataSource(conn)\n\tcase \"bigquery\":\n\t\t// Pass the dbtHomePath to the BigQuery converter\n\t\treturn convertToBigQueryDataSource(conn, dbtHomePath)\n\tdefault:\n\t\t// For unsupported database types, we can choose to ignore or return error\n\t\t// Here we choose to return nil and log a warning\n\t\tpterm.Warning.Printf(\"Unsupported database type '%s' for %s.%s\\n\", conn.Type, profileName, outputName)\n\t\treturn nil, nil\n\t}\n}\n\n// convertToPostgresDataSource converts to PostgreSQL data source\nfunc convertToPostgresDataSource(conn DbtConnection) (*WrenPostgresDataSource, error) {\n\t// For PostgreSQL, prefer dbname over database field\n\tdbName := conn.DbName\n\tif dbName == \"\" {\n\t\tdbName = conn.Database\n\t}\n\n\tpterm.Info.Printf(\"Converting Postgres data source: %s:%d/%s\\n\", conn.Host, conn.Port, dbName)\n\tport := strconv.Itoa(conn.Port)\n\tif conn.Port == 0 {\n\t\tport = \"5432\"\n\t}\n\n\tds := &WrenPostgresDataSource{\n\t\tHost:     conn.Host,\n\t\tPort:     port,\n\t\tDatabase: dbName,\n\t\tUser:     conn.User,\n\t\tPassword: conn.Password,\n\t}\n\n\treturn ds, nil\n}\n\nfunc convertToMSSQLDataSource(conn DbtConnection) (*WrenMSSQLDataSource, error) {\n\tport := strconv.Itoa(conn.Port)\n\tif conn.Port == 0 {\n\t\tport = \"1433\"\n\t}\n\n\tds := &WrenMSSQLDataSource{\n\t\tDatabase:   conn.Database,\n\t\tHost:       conn.Server,\n\t\tPort:       port,\n\t\tUser:       conn.User,\n\t\tPassword:   conn.Password,\n\t\tTdsVersion: \"8.0\",                           // the default tds version for Wren engine image\n\t\tDriver:     \"ODBC Driver 18 for SQL Server\", // the driver used by Wren engine image\n\t\tKwargs:     map[string]interface{}{\"TrustServerCertificate\": \"YES\"},\n\t}\n\n\treturn ds, nil\n}\n\n// convertToLocalFileDataSource converts to local file data source\nfunc convertToLocalFileDataSource(conn DbtConnection, dbtHome string) (*WrenLocalFileDataSource, error) {\n\t// For file types, we need to get URL and format info from Additional fields\n\t// or use some conventional field names\n\n\tresolvePath := func(path string) string {\n\t\tif filepath.IsAbs(path) {\n\t\t\treturn filepath.Dir(path)\n\t\t}\n\t\trelativeDir := filepath.Dir(path)\n\t\tif dbtHome != \"\" {\n\t\t\treturn filepath.Join(dbtHome, relativeDir)\n\t\t}\n\t\treturn relativeDir\n\t}\n\n\tvar url, format string\n\n\t// Try to get file path from different fields\n\tif conn.Path != \"\" {\n\t\turl = resolvePath(conn.Path)\n\t} else if file, exists := conn.Additional[\"file\"]; exists {\n\t\tif fileStr, ok := file.(string); ok {\n\t\t\turl = resolvePath(fileStr)\n\t\t}\n\t}\n\n\t// Try to get format information\n\tformat = \"duckdb\" // Default to duckdb if not specified\n\n\tif url == \"\" {\n\t\treturn nil, fmt.Errorf(\"file path not found in connection configuration\")\n\t}\n\n\treturn &WrenLocalFileDataSource{\n\t\tUrl:    url,\n\t\tFormat: format,\n\t}, nil\n}\n\nfunc convertToMysqlDataSource(conn DbtConnection) (*WrenMysqlDataSource, error) {\n\tpterm.Info.Printf(\"Converting MySQL data source: %s:%d/%s\\n\", conn.Host, conn.Port, conn.Database)\n\n\tsslMode := \"ENABLED\" // Default SSL mode\n\tif conn.SslDisable {\n\t\tsslMode = \"DISABLED\"\n\t}\n\tport := strconv.Itoa(conn.Port)\n\tif conn.Port == 0 {\n\t\tport = \"3306\"\n\t}\n\n\tds := &WrenMysqlDataSource{\n\t\tHost:     conn.Host,\n\t\tPort:     port,\n\t\tDatabase: conn.Database,\n\t\tUser:     conn.User,\n\t\tPassword: conn.Password,\n\t\tSslMode:  sslMode,\n\t}\n\n\treturn ds, nil\n}\n\n// convertToBigQueryDataSource converts to BigQuery data source\nfunc convertToBigQueryDataSource(conn DbtConnection, dbtHomePath string) (*WrenBigQueryDataSource, error) {\n\tmethod := strings.ToLower(strings.TrimSpace(conn.Method))\n\tvar credentials string\n\n\t// Helper: validate JSON and base64 encode\n\tencodeJSON := func(b []byte) (string, error) {\n\t\tvar js map[string]interface{}\n\t\tif err := json.Unmarshal(b, &js); err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"service account JSON is invalid: %w\", err)\n\t\t}\n\t\treturn base64.StdEncoding.EncodeToString(b), nil\n\t}\n\n\tswitch method {\n\tcase \"service-account-json\":\n\t\t// Extract inline JSON from Additional[\"keyfile_json\"]\n\t\tvar keyfileJSON string\n\t\tif kfj, exists := conn.Additional[\"keyfile_json\"]; exists {\n\t\t\tif kfjStr, ok := kfj.(string); ok {\n\t\t\t\tkeyfileJSON = kfjStr\n\t\t\t}\n\t\t}\n\t\tif keyfileJSON == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"bigquery: method 'service-account-json' requires 'keyfile_json'\")\n\t\t}\n\t\tenc, err := encodeJSON([]byte(keyfileJSON))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tcredentials = enc\n\tcase \"service-account\", \"\":\n\t\t// Prefer structured field; fall back to Additional[\"keyfile\"]\n\t\tkeyfilePath := strings.TrimSpace(conn.Keyfile)\n\t\tif keyfilePath == \"\" {\n\t\t\tif kf, ok := conn.Additional[\"keyfile\"]; ok {\n\t\t\t\tif kfStr, ok := kf.(string); ok {\n\t\t\t\t\tkeyfilePath = strings.TrimSpace(kfStr)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif keyfilePath == \"\" {\n\t\t\t// If method was omitted (\"\"), try as a fallback to inline json\n\t\t\tif kfj, ok := conn.Additional[\"keyfile_json\"]; ok {\n\t\t\t\tif kfjStr, ok := kfj.(string); ok && kfjStr != \"\" {\n\t\t\t\t\tenc, err := encodeJSON([]byte(kfjStr))\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t}\n\t\t\t\t\tcredentials = enc\n\t\t\t\t}\n\t\t\t}\n\t\t\tif credentials == \"\" {\n\t\t\t\treturn nil, fmt.Errorf(\"bigquery: method 'service-account' requires 'keyfile' path\")\n\t\t\t}\n\t\t} else {\n\t\t\t// If keyfile path is not absolute, join it\n\t\t\t// with the dbt project's home directory path.\n\t\t\tresolvedKeyfilePath := keyfilePath\n\t\t\tif !filepath.IsAbs(keyfilePath) && dbtHomePath != \"\" {\n\t\t\t\tresolvedKeyfilePath = filepath.Join(dbtHomePath, keyfilePath)\n\t\t\t}\n\n\t\t\tcleanPath := filepath.Clean(resolvedKeyfilePath)\n\t\t\tb, err := os.ReadFile(cleanPath)\n\t\t\tif err != nil {\n\t\t\t\t// Update the error message to show the path that was attempted\n\t\t\t\treturn nil, fmt.Errorf(\"failed to read keyfile '%s': %w\", cleanPath, err)\n\t\t\t}\n\t\t\tenc, err := encodeJSON(b)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tcredentials = enc\n\t\t}\n\tcase \"oauth\":\n\t\tpterm.Warning.Println(\"bigquery: oauth auth method is not supported; skipping data source\")\n\t\treturn nil, nil\n\tdefault:\n\t\tpterm.Warning.Printf(\"bigquery: unsupported auth method '%s'; supported: service-account, service-account-json\\n\", method)\n\t\treturn nil, nil\n\t}\n\n\tds := &WrenBigQueryDataSource{\n\t\tProject:     conn.Project,\n\t\tDataset:     conn.Dataset,\n\t\tCredentials: credentials,\n\t}\n\treturn ds, nil\n}\n\ntype WrenLocalFileDataSource struct {\n\tUrl    string `json:\"url\"`\n\tFormat string `json:\"format\"`\n}\n\n// GetType implements DataSource interface\nfunc (ds *WrenLocalFileDataSource) GetType() string {\n\treturn \"local_file\"\n}\n\n// Validate implements DataSource interface\nfunc (ds *WrenLocalFileDataSource) Validate() error {\n\tif ds.Url == \"\" {\n\t\treturn fmt.Errorf(\"file URL cannot be empty\")\n\t}\n\tif ds.Format == \"\" {\n\t\treturn fmt.Errorf(\"file format cannot be empty\")\n\t}\n\treturn nil\n}\n\nfunc (ds *WrenLocalFileDataSource) MapType(sourceType string) string {\n\t// Convert to uppercase for consistent mapping\n\tsourceType = strings.ToUpper(sourceType)\n\n\tswitch sourceType {\n\tcase integerSQL, intSQL, bigintSQL:\n\t\treturn integerType\n\tcase varcharSQL, textSQL, stringSQL:\n\t\treturn varcharType\n\tcase dateSQL:\n\t\treturn dateType\n\tcase timestampSQL, datetimeSQL:\n\t\treturn timestampType\n\tcase doubleSQL, floatSQL, numericSQL, decimalSQL:\n\t\treturn doubleType\n\tcase booleanSQL, boolSQL:\n\t\treturn booleanType\n\tdefault:\n\t\t// Return the original type if no mapping is found\n\t\treturn strings.ToLower(sourceType)\n\t}\n}\n\ntype WrenPostgresDataSource struct {\n\tHost     string `json:\"host\"`\n\tPort     string `json:\"port\"`\n\tDatabase string `json:\"database\"`\n\tUser     string `json:\"user\"`\n\tPassword string `json:\"password\"`\n}\n\n// GetType implements DataSource interface\nfunc (ds *WrenPostgresDataSource) GetType() string {\n\treturn postgresType\n}\n\n// Validate implements DataSource interface\nfunc (ds *WrenPostgresDataSource) Validate() error {\n\tif ds.Host == \"\" {\n\t\treturn fmt.Errorf(\"host cannot be empty\")\n\t}\n\tif ds.Database == \"\" {\n\t\treturn fmt.Errorf(\"database cannot be empty\")\n\t}\n\tif ds.User == \"\" {\n\t\treturn fmt.Errorf(\"user cannot be empty\")\n\t}\n\tif ds.Port == \"\" {\n\t\treturn fmt.Errorf(\"port must be specified\")\n\t}\n\tport, err := strconv.Atoi(ds.Port)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"port must be a valid number\")\n\t}\n\tif port <= 0 || port > 65535 {\n\t\treturn fmt.Errorf(\"port must be between 1 and 65535\")\n\t}\n\treturn nil\n}\n\nfunc (ds *WrenPostgresDataSource) MapType(sourceType string) string {\n\t// This method is not used in WrenPostgresDataSource, but required by DataSource interface\n\treturn sourceType\n}\n\ntype WrenMSSQLDataSource struct {\n\tDatabase   string                 `json:\"database\"`\n\tHost       string                 `json:\"host\"`\n\tPort       string                 `json:\"port\"`\n\tUser       string                 `json:\"user\"`\n\tPassword   string                 `json:\"password\"`\n\tTdsVersion string                 `json:\"tds_version\"`\n\tDriver     string                 `json:\"driver\"`\n\tKwargs     map[string]interface{} `json:\"kwargs\"`\n}\n\nfunc (ds *WrenMSSQLDataSource) GetType() string {\n\treturn \"mssql\"\n}\n\nfunc (ds *WrenMSSQLDataSource) Validate() error {\n\tif ds.Host == \"\" {\n\t\treturn fmt.Errorf(\"host cannot be empty\")\n\t}\n\tif ds.Database == \"\" {\n\t\treturn fmt.Errorf(\"database cannot be empty\")\n\t}\n\tif ds.User == \"\" {\n\t\treturn fmt.Errorf(\"user cannot be empty\")\n\t}\n\tif ds.Port == \"\" {\n\t\treturn fmt.Errorf(\"port must be specified\")\n\t}\n\tport, err := strconv.Atoi(ds.Port)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"port must be a valid number\")\n\t}\n\tif port <= 0 || port > 65535 {\n\t\treturn fmt.Errorf(\"port must be between 1 and 65535\")\n\t}\n\tif ds.Password == \"\" {\n\t\treturn fmt.Errorf(\"password cannot be empty\")\n\t}\n\treturn nil\n}\n\nfunc (ds *WrenMSSQLDataSource) MapType(sourceType string) string {\n\t// This method is not used in WrenMSSQLDataSource, but required by DataSource interface\n\tswitch strings.ToLower(sourceType) {\n\tcase charType, \"nchar\":\n\t\treturn charType\n\tcase varcharType, \"nvarchar\":\n\t\treturn varcharType\n\tcase textType, \"ntext\":\n\t\treturn textType\n\tcase \"bit\", \"tinyint\":\n\t\treturn booleanType\n\tcase \"smallint\":\n\t\treturn smallintType\n\tcase \"int\":\n\t\treturn integerType\n\tcase \"bigint\":\n\t\treturn bigintType\n\tcase booleanType:\n\t\treturn booleanType\n\tcase \"float\", \"real\":\n\t\treturn floatType\n\tcase \"decimal\", \"numeric\", \"money\", \"smallmoney\":\n\t\treturn decimalType\n\tcase \"date\":\n\t\treturn dateType\n\tcase \"datetime\", \"datetime2\", \"smalldatetime\":\n\t\treturn timestampType\n\tcase \"time\":\n\t\treturn intervalType\n\tcase \"datetimeoffset\":\n\t\treturn timestamptzType\n\tcase \"json\":\n\t\treturn jsonType\n\tdefault:\n\t\treturn strings.ToLower(sourceType)\n\t}\n}\n\ntype WrenMysqlDataSource struct {\n\tDatabase string `json:\"database\"`\n\tHost     string `json:\"host\"`\n\tPassword string `json:\"password\"`\n\tPort     string `json:\"port\"`\n\tUser     string `json:\"user\"`\n\tSslCA    string `json:\"ssl_ca,omitempty\"`   // Optional SSL CA file for MySQL\n\tSslMode  string `json:\"ssl_mode,omitempty\"` // Optional SSL mode for MySQL\n}\n\n// GetType implements DataSource interface\nfunc (ds *WrenMysqlDataSource) GetType() string {\n\treturn \"mysql\"\n}\n\n// Validate implements DataSource interface\nfunc (ds *WrenMysqlDataSource) Validate() error {\n\tif ds.Host == \"\" {\n\t\treturn fmt.Errorf(\"host cannot be empty\")\n\t}\n\tif ds.Database == \"\" {\n\t\treturn fmt.Errorf(\"database cannot be empty\")\n\t}\n\tif ds.User == \"\" {\n\t\treturn fmt.Errorf(\"user cannot be empty\")\n\t}\n\tif ds.Port == \"\" {\n\t\treturn fmt.Errorf(\"port must be specified\")\n\t}\n\tport, err := strconv.Atoi(ds.Port)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"port must be a valid number\")\n\t}\n\tif port <= 0 || port > 65535 {\n\t\treturn fmt.Errorf(\"port must be between 1 and 65535\")\n\t}\n\treturn nil\n}\n\nfunc (ds *WrenMysqlDataSource) MapType(sourceType string) string {\n\t// This method is not used in WrenMysqlDataSource, but required by DataSource interface\n\tsourceType = strings.ToUpper(sourceType)\n\tswitch sourceType {\n\tcase \"CHAR\":\n\t\treturn \"char\"\n\tcase \"VARCHAR\":\n\t\treturn varcharType\n\tcase \"TEXT\", \"TINYTEXT\", \"MEDIUMTEXT\", \"LONGTEXT\", \"ENUM\", \"SET\":\n\t\treturn \"text\"\n\tcase \"BIT\", \"TINYINT\":\n\t\treturn \"TINYINT\"\n\tcase \"SMALLINT\":\n\t\treturn \"SMALLINT\"\n\tcase \"MEDIUMINT\", \"INT\", integerSQL:\n\t\treturn \"INTEGER\"\n\tcase \"BIGINT\":\n\t\treturn \"BIGINT\"\n\tcase \"FLOAT\", \"DOUBLE\":\n\t\treturn \"DOUBLE\"\n\tcase decimalSQL, \"NUMERIC\":\n\t\treturn decimalSQL\n\tcase dateSQL:\n\t\treturn dateSQL\n\tcase datetimeSQL:\n\t\treturn datetimeSQL\n\tcase \"TIMESTAMP\":\n\t\treturn \"TIMESTAMPTZ\"\n\tcase booleanSQL, \"BOOL\":\n\t\treturn booleanSQL\n\tcase jsonSQL:\n\t\treturn jsonSQL\n\tdefault:\n\t\t// Return the original type if no mapping is found\n\t\treturn strings.ToLower(sourceType)\n\t}\n}\n\ntype WrenBigQueryDataSource struct {\n\tProject     string `json:\"project_id\"`\n\tDataset     string `json:\"dataset_id\"`\n\tCredentials string `json:\"credentials\"`\n}\n\n// GetType implements DataSource interface\nfunc (ds *WrenBigQueryDataSource) GetType() string {\n\treturn \"bigquery\"\n}\n\n// Validate implements DataSource interface\nfunc (ds *WrenBigQueryDataSource) Validate() error {\n\tif strings.TrimSpace(ds.Project) == \"\" {\n\t\treturn fmt.Errorf(\"project_id cannot be empty\")\n\t}\n\tif strings.TrimSpace(ds.Dataset) == \"\" {\n\t\treturn fmt.Errorf(\"dataset_id cannot be empty\")\n\t}\n\tif strings.TrimSpace(ds.Credentials) == \"\" {\n\t\treturn fmt.Errorf(\"credentials cannot be empty\")\n\t}\n\treturn nil\n}\n\n// MapType implements DataSource interface\nfunc (ds *WrenBigQueryDataSource) MapType(sourceType string) string {\n\tswitch strings.ToUpper(sourceType) {\n\tcase \"INT64\", \"INTEGER\":\n\t\treturn integerType\n\tcase \"FLOAT64\", \"FLOAT\":\n\t\treturn doubleType\n\tcase \"STRING\":\n\t\treturn varcharType\n\tcase \"BOOL\", \"BOOLEAN\":\n\t\treturn booleanType\n\tcase \"DATE\":\n\t\treturn dateType\n\tcase \"TIMESTAMP\", \"DATETIME\":\n\t\treturn timestampType\n\tcase \"NUMERIC\", \"DECIMAL\", \"BIGNUMERIC\":\n\t\treturn doubleType\n\tcase \"BYTES\":\n\t\treturn varcharType\n\tcase \"JSON\":\n\t\treturn varcharType\n\tdefault:\n\t\treturn strings.ToLower(sourceType)\n\t}\n}\n\n// GetActiveDataSources gets active data sources based on specified profile and target\n// If profileName is empty, it will use the first found profile\n// If targetName is empty, it will use the profile's default target\nfunc GetActiveDataSources(profiles *DbtProfiles, dbtHomePath, profileName, targetName string) ([]DataSource, error) {\n\tif profiles == nil {\n\t\treturn nil, fmt.Errorf(\"profiles cannot be nil\")\n\t}\n\n\t// If no profile is specified, use the first one\n\tif profileName == \"\" {\n\t\tfor name := range profiles.Profiles {\n\t\t\tprofileName = name\n\t\t\tbreak\n\t\t}\n\t}\n\n\tprofile, exists := profiles.Profiles[profileName]\n\tif !exists {\n\t\treturn nil, fmt.Errorf(\"profile '%s' not found\", profileName)\n\t}\n\n\t// If no target is specified, use the default one\n\tif targetName == \"\" {\n\t\ttargetName = profile.Target\n\t}\n\n\tconnection, exists := profile.Outputs[targetName]\n\tif !exists {\n\t\treturn nil, fmt.Errorf(\"target '%s' not found in profile '%s'\", targetName, profileName)\n\t}\n\n\tdataSource, err := convertConnectionToDataSource(connection, dbtHomePath, profileName, targetName)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to convert connection %s.%s: %w\", profileName, targetName, err)\n\t}\n\n\tif dataSource == nil {\n\t\treturn []DataSource{}, nil\n\t}\n\n\treturn []DataSource{dataSource}, nil\n}\n\n// GetDataSourceByType gets all data sources of specified type from profiles\nfunc GetDataSourceByType(profiles *DbtProfiles, dsType string) ([]DataSource, error) {\n\tdataSources, err := FromDbtProfiles(profiles)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar filtered []DataSource\n\tfor _, ds := range dataSources {\n\t\tif ds.GetType() == dsType {\n\t\t\tfiltered = append(filtered, ds)\n\t\t}\n\t}\n\n\treturn filtered, nil\n}\n\n// ValidateAllDataSources validates all converted data sources\nfunc ValidateAllDataSources(profiles *DbtProfiles) error {\n\tdataSources, err := FromDbtProfiles(profiles)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar errors []error\n\tfor i, ds := range dataSources {\n\t\tif err := ds.Validate(); err != nil {\n\t\t\terrors = append(errors, fmt.Errorf(\"data source %d (%s): %w\", i, ds.GetType(), err))\n\t\t}\n\t}\n\n\tif len(errors) > 0 {\n\t\tvar errorMsg string\n\t\tfor _, err := range errors {\n\t\t\terrorMsg += err.Error() + \"; \"\n\t\t}\n\t\treturn fmt.Errorf(\"validation errors: %s\", errorMsg)\n\t}\n\n\treturn nil\n}\n\n// DefaultDataSource is a default data source when no profiles.yml is found\ntype DefaultDataSource struct{}\n\n// GetType implements DataSource interface\nfunc (d *DefaultDataSource) GetType() string {\n\treturn \"default\"\n}\n\n// Validate implements DataSource interface\nfunc (d *DefaultDataSource) Validate() error {\n\treturn nil\n}\n\nfunc (d *DefaultDataSource) MapType(sourceType string) string {\n\t// Default type mapping\n\tswitch strings.ToLower(sourceType) {\n\tcase \"integer\", \"int\", \"bigint\", \"int64\":\n\t\treturn \"integer\"\n\tcase \"varchar\", \"text\", \"string\", \"char\":\n\t\treturn varcharType\n\tcase \"timestamp\", \"datetime\", \"date\":\n\t\treturn \"timestamp\"\n\tcase \"double\", \"float\", \"decimal\", \"numeric\":\n\t\treturn \"double\"\n\tcase \"boolean\", \"bool\":\n\t\treturn \"boolean\"\n\tdefault:\n\t\treturn strings.ToLower(sourceType)\n\t}\n}\n"
  },
  {
    "path": "wren-launcher/commands/dbt/data_source_test.go",
    "content": "package dbt\n\nimport (\n\t\"encoding/base64\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n)\n\n// Test constants\nconst (\n\ttestHost     = \"localhost\"\n\ttestUser     = \"test_user\"\n\ttestPassword = \"test_pass\"\n\tpgType       = \"postgres\"\n\tduckdbType   = \"duckdb\"\n)\n\n// Helper function to validate PostgreSQL data source\nfunc validatePostgresDataSource(t *testing.T, ds *WrenPostgresDataSource, expectedDB string) {\n\tt.Helper()\n\n\tif ds.Host != testHost {\n\t\tt.Errorf(\"Expected host '%s', got '%s'\", testHost, ds.Host)\n\t}\n\tif ds.Port != \"5432\" {\n\t\tt.Errorf(\"Expected port 5432, got %s\", ds.Port)\n\t}\n\tif ds.Database != expectedDB {\n\t\tt.Errorf(\"Expected database '%s', got '%s'\", expectedDB, ds.Database)\n\t}\n\tif ds.User != testUser {\n\t\tt.Errorf(\"Expected user '%s', got '%s'\", testUser, ds.User)\n\t}\n\tif ds.Password != testPassword {\n\t\tt.Errorf(\"Expected password '%s', got '%s'\", testPassword, ds.Password)\n\t}\n\n\t// Test validation\n\tif err := ds.Validate(); err != nil {\n\t\tt.Errorf(\"Validation failed: %v\", err)\n\t}\n\n\t// Test type\n\tif ds.GetType() != pgType {\n\t\tt.Errorf(\"Expected type '%s', got '%s'\", pgType, ds.GetType())\n\t}\n}\n\nfunc TestFromDbtProfiles_Postgres(t *testing.T) {\n\t// Test PostgreSQL connection conversion\n\tprofiles := &DbtProfiles{\n\t\tProfiles: map[string]DbtProfile{\n\t\t\t\"test_profile\": {\n\t\t\t\tTarget: \"dev\",\n\t\t\t\tOutputs: map[string]DbtConnection{\n\t\t\t\t\t\"dev\": {\n\t\t\t\t\t\tType:     pgType,\n\t\t\t\t\t\tHost:     testHost,\n\t\t\t\t\t\tPort:     5432,\n\t\t\t\t\t\tDatabase: \"test_db\",\n\t\t\t\t\t\tUser:     testUser,\n\t\t\t\t\t\tPassword: testPassword,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tdataSources, err := FromDbtProfiles(profiles)\n\tif err != nil {\n\t\tt.Fatalf(\"FromDbtProfiles failed: %v\", err)\n\t}\n\n\tif len(dataSources) != 1 {\n\t\tt.Fatalf(\"Expected 1 data source, got %d\", len(dataSources))\n\t}\n\n\tds, ok := dataSources[0].(*WrenPostgresDataSource)\n\tif !ok {\n\t\tt.Fatalf(\"Expected WrenPostgresDataSource, got %T\", dataSources[0])\n\t}\n\n\tvalidatePostgresDataSource(t, ds, \"test_db\")\n}\n\nfunc TestFromDbtProfiles_PostgresWithDefaultPort(t *testing.T) {\n\t// Test PostgreSQL connection conversion when port is not specified\n\tprofiles := &DbtProfiles{\n\t\tProfiles: map[string]DbtProfile{\n\t\t\t\"test_profile\": {\n\t\t\t\tTarget: \"dev\",\n\t\t\t\tOutputs: map[string]DbtConnection{\n\t\t\t\t\t\"dev\": {\n\t\t\t\t\t\tType:     \"postgres\",\n\t\t\t\t\t\tHost:     \"localhost\",\n\t\t\t\t\t\tPort:     5432,\n\t\t\t\t\t\tDbName:   \"jaffle_shop\", // Using dbname instead of database\n\t\t\t\t\t\tUser:     \"test_user\",\n\t\t\t\t\t\tPassword: \"test_pass\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tdataSources, err := FromDbtProfiles(profiles)\n\tif err != nil {\n\t\tt.Fatalf(\"FromDbtProfiles failed: %v\", err)\n\t}\n\n\tif len(dataSources) != 1 {\n\t\tt.Fatalf(\"Expected 1 data source, got %d\", len(dataSources))\n\t}\n\n\tds, ok := dataSources[0].(*WrenPostgresDataSource)\n\tif !ok {\n\t\tt.Fatalf(\"Expected WrenPostgresDataSource, got %T\", dataSources[0])\n\t}\n\n\tif ds.Host != \"localhost\" {\n\t\tt.Errorf(\"Expected host 'localhost', got '%s'\", ds.Host)\n\t}\n\tif ds.Port != \"5432\" {\n\t\tt.Errorf(\"Expected port 5432, got %s\", ds.Port)\n\t}\n\tif ds.Database != \"jaffle_shop\" {\n\t\tt.Errorf(\"Expected database 'jaffle_shop', got '%s'\", ds.Database)\n\t}\n\tif ds.User != \"test_user\" {\n\t\tt.Errorf(\"Expected user 'test_user', got '%s'\", ds.User)\n\t}\n\tif ds.Password != \"test_pass\" {\n\t\tt.Errorf(\"Expected password 'test_pass', got '%s'\", ds.Password)\n\t}\n\n\t// Test validation\n\tif err := ds.Validate(); err != nil {\n\t\tt.Errorf(\"Validation failed: %v\", err)\n\t}\n\n\t// Test type\n\tif ds.GetType() != \"postgres\" {\n\t\tt.Errorf(\"Expected type 'postgres', got '%s'\", ds.GetType())\n\t}\n}\n\nfunc TestFromDbtProfiles_LocalFile(t *testing.T) {\n\t// Test local file connection conversion\n\tprofiles := &DbtProfiles{\n\t\tProfiles: map[string]DbtProfile{\n\t\t\t\"test_profile\": {\n\t\t\t\tTarget: \"dev\",\n\t\t\t\tOutputs: map[string]DbtConnection{\n\t\t\t\t\t\"dev\": {\n\t\t\t\t\t\tType: duckdbType,\n\t\t\t\t\t\tPath: \"/abs_path/jaffle_shop.duckdb\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tdataSources, err := FromDbtProfiles(profiles)\n\tif err != nil {\n\t\tt.Fatalf(\"FromDbtProfiles failed: %v\", err)\n\t}\n\n\tif len(dataSources) != 1 {\n\t\tt.Fatalf(\"Expected 1 data source, got %d\", len(dataSources))\n\t}\n\n\tds, ok := dataSources[0].(*WrenLocalFileDataSource)\n\tif !ok {\n\t\tt.Fatalf(\"Expected WrenLocalFileDataSource, got %T\", dataSources[0])\n\t}\n\n\tif filepath.ToSlash(ds.Url) != \"/abs_path\" {\n\t\tt.Errorf(\"Expected url '/abs_path', got '%s'\", ds.Url)\n\t}\n\tif ds.Format != duckdbType {\n\t\tt.Errorf(\"Expected format '%s', got '%s'\", duckdbType, ds.Format)\n\t}\n\n\t// Test validation\n\tif err := ds.Validate(); err != nil {\n\t\tt.Errorf(\"Validation failed: %v\", err)\n\t}\n\n\t// Test type\n\tif ds.GetType() != \"local_file\" {\n\t\tt.Errorf(\"Expected type 'local_file', got '%s'\", ds.GetType())\n\t}\n}\n\nfunc TestFromDbtProfiles_UnsupportedType(t *testing.T) {\n\t// Test unsupported database type\n\tprofiles := &DbtProfiles{\n\t\tProfiles: map[string]DbtProfile{\n\t\t\t\"test_profile\": {\n\t\t\t\tTarget: \"dev\",\n\t\t\t\tOutputs: map[string]DbtConnection{\n\t\t\t\t\t\"dev\": {\n\t\t\t\t\t\tType: \"unsupported_db\",\n\t\t\t\t\t\tHost: \"localhost\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tdataSources, err := FromDbtProfiles(profiles)\n\tif err != nil {\n\t\tt.Fatalf(\"FromDbtProfiles failed: %v\", err)\n\t}\n\n\t// Unsupported types should be ignored, returning empty list\n\tif len(dataSources) != 0 {\n\t\tt.Fatalf(\"Expected 0 data sources for unsupported type, got %d\", len(dataSources))\n\t}\n}\n\nfunc TestFromMssqlProfiles(t *testing.T) {\n\t// Test MSSQL connection conversion\n\tprofiles := &DbtProfiles{\n\t\tProfiles: map[string]DbtProfile{\n\t\t\t\"test_profile\": {\n\t\t\t\tTarget: \"dev\",\n\t\t\t\tOutputs: map[string]DbtConnection{\n\t\t\t\t\t\"dev\": {\n\t\t\t\t\t\tType:     \"sqlserver\",\n\t\t\t\t\t\tServer:   testHost,\n\t\t\t\t\t\tPort:     1433,\n\t\t\t\t\t\tDatabase: \"test_db\",\n\t\t\t\t\t\tUser:     testUser,\n\t\t\t\t\t\tPassword: testPassword,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tdataSources, err := FromDbtProfiles(profiles)\n\tif err != nil {\n\t\tt.Fatalf(\"FromDbtProfiles failed: %v\", err)\n\t}\n\n\tif len(dataSources) != 1 {\n\t\tt.Fatalf(\"Expected 1 data source, got %d\", len(dataSources))\n\t}\n\n\tds, ok := dataSources[0].(*WrenMSSQLDataSource)\n\tif !ok {\n\t\tt.Fatalf(\"Expected WrenMSSQLDataSource, got %T\", dataSources[0])\n\t}\n\n\tif ds.Host != testHost {\n\t\tt.Errorf(\"Expected host '%s', got '%s'\", testHost, ds.Host)\n\t}\n\n\tif ds.Port != \"1433\" {\n\t\tt.Errorf(\"Expected port 1433, got %s\", ds.Port)\n\t}\n\n\tif ds.Database != \"test_db\" {\n\t\tt.Errorf(\"Expected database 'test_db', got '%s'\", ds.Database)\n\t}\n\n\tif ds.User != testUser {\n\t\tt.Errorf(\"Expected user '%s', got '%s'\", testUser, ds.User)\n\t}\n\n\tif ds.Password != testPassword {\n\t\tt.Errorf(\"Expected password '%s', got '%s'\", testPassword, ds.Password)\n\t}\n\n\tif ds.TdsVersion != \"8.0\" {\n\t\tt.Errorf(\"Expected TDS version '8.0', got '%s'\", ds.TdsVersion)\n\t}\n\n\tif ds.Driver != \"ODBC Driver 18 for SQL Server\" {\n\t\tt.Errorf(\"Expected driver 'ODBC Driver 18 for SQL Server', got '%s'\", ds.Driver)\n\t}\n\n\tif ds.Kwargs[\"TrustServerCertificate\"] != \"YES\" {\n\t\tt.Errorf(\"Expected TrustServerCertificate 'YES', got '%s'\", ds.Kwargs[\"TrustServerCertificate\"])\n\t}\n}\n\nfunc TestFromDbtProfiles_NilProfiles(t *testing.T) {\n\t// Test nil profiles\n\t_, err := FromDbtProfiles(nil)\n\tif err == nil {\n\t\tt.Fatal(\"Expected error for nil profiles\")\n\t}\n}\n\nfunc TestValidateAllDataSources(t *testing.T) {\n\t// Test valid profiles\n\tvalidProfiles := &DbtProfiles{\n\t\tProfiles: map[string]DbtProfile{\n\t\t\t\"valid_project\": {\n\t\t\t\tTarget: \"dev\",\n\t\t\t\tOutputs: map[string]DbtConnection{\n\t\t\t\t\t\"dev\": {\n\t\t\t\t\t\tType:     \"postgres\",\n\t\t\t\t\t\tHost:     \"localhost\",\n\t\t\t\t\t\tPort:     5432,\n\t\t\t\t\t\tDatabase: \"test_db\",\n\t\t\t\t\t\tUser:     \"user\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\terr := ValidateAllDataSources(validProfiles)\n\tif err != nil {\n\t\tt.Errorf(\"ValidateAllDataSources failed for valid profiles: %v\", err)\n\t}\n\n\t// Test invalid profiles\n\tinvalidProfiles := &DbtProfiles{\n\t\tProfiles: map[string]DbtProfile{\n\t\t\t\"invalid_project\": {\n\t\t\t\tTarget: \"dev\",\n\t\t\t\tOutputs: map[string]DbtConnection{\n\t\t\t\t\t\"dev\": {\n\t\t\t\t\t\tType: \"postgres\",\n\t\t\t\t\t\tHost: \"localhost\",\n\t\t\t\t\t\t// Missing required fields\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\terr = ValidateAllDataSources(invalidProfiles)\n\tif err == nil {\n\t\tt.Error(\"ValidateAllDataSources should fail for invalid profiles\")\n\t}\n}\n\nfunc TestFromDbtProfiles_BigQuery(t *testing.T) {\n\ttempDir, err := os.MkdirTemp(\"\", \"test-dbt-home\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\tif err := os.RemoveAll(tempDir); err != nil {\n\t\t\tt.Logf(\"Failed to remove temporary directory %s: %v\", tempDir, err)\n\t\t}\n\t}()\n\n\tt.Run(\"service-account-json\", func(t *testing.T) {\n\t\tkeyfileContent := `{\"type\": \"service_account\", \"project_id\": \"test-project\", \"private_key_id\": \"test-key-id\", \"private_key\": \"test-private-key\", \"client_email\": \"test-client-email\", \"client_id\": \"test-client-id\", \"auth_uri\": \"test-auth-uri\", \"token_uri\": \"test-token-uri\", \"auth_provider_x509_cert_url\": \"test-cert-url\", \"client_x509_cert_url\": \"test-client-cert-url\"}` // #nosec G101\n\t\tprofiles := &DbtProfiles{\n\t\t\tProfiles: map[string]DbtProfile{\n\t\t\t\t\"test_profile\": {\n\t\t\t\t\tTarget: \"dev\",\n\t\t\t\t\tOutputs: map[string]DbtConnection{\n\t\t\t\t\t\t\"dev\": {\n\t\t\t\t\t\t\tType:    \"bigquery\",\n\t\t\t\t\t\t\tMethod:  \"service-account-json\",\n\t\t\t\t\t\t\tProject: \"test-project\",\n\t\t\t\t\t\t\tDataset: \"test-dataset\",\n\t\t\t\t\t\t\tAdditional: map[string]interface{}{\n\t\t\t\t\t\t\t\t\"keyfile_json\": keyfileContent,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\n\t\tdataSources, err := GetActiveDataSources(profiles, \"\", \"test_profile\", \"dev\")\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"GetActiveDataSources failed: %v\", err)\n\t\t}\n\n\t\tif len(dataSources) != 1 {\n\t\t\tt.Fatalf(\"Expected 1 data source, got %d\", len(dataSources))\n\t\t}\n\n\t\tds, ok := dataSources[0].(*WrenBigQueryDataSource)\n\t\tif !ok {\n\t\t\tt.Fatalf(\"Expected WrenBigQueryDataSource, got %T\", dataSources[0])\n\t\t}\n\n\t\tif ds.Project != \"test-project\" {\n\t\t\tt.Errorf(\"Expected project 'test-project', got '%s'\", ds.Project)\n\t\t}\n\n\t\tif ds.Dataset != \"test-dataset\" {\n\t\t\tt.Errorf(\"Expected dataset 'test-dataset', got '%s'\", ds.Dataset)\n\t\t}\n\n\t\tencodedContent, _ := base64.StdEncoding.DecodeString(ds.Credentials)\n\t\tif string(encodedContent) != keyfileContent {\n\t\t\tt.Errorf(\"Expected base64-encoded keyfile JSON content, got different content\")\n\t\t}\n\t})\n\n\tt.Run(\"service-account-with-absolute-keyfile-path\", func(t *testing.T) {\n\t\tkeyfileContent := `{\"type\": \"service_account\"}` // #nosec G101\n\t\tkeyfilePath := filepath.Join(tempDir, \"keyfile.json\")\n\t\tif err := os.WriteFile(keyfilePath, []byte(keyfileContent), 0600); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tprofiles := &DbtProfiles{\n\t\t\tProfiles: map[string]DbtProfile{\n\t\t\t\t\"test_profile\": {\n\t\t\t\t\tTarget: \"dev\",\n\t\t\t\t\tOutputs: map[string]DbtConnection{\n\t\t\t\t\t\t\"dev\": {\n\t\t\t\t\t\t\tType:    \"bigquery\",\n\t\t\t\t\t\t\tMethod:  \"service-account\",\n\t\t\t\t\t\t\tProject: \"test-project\",\n\t\t\t\t\t\t\tDataset: \"test-dataset\",\n\t\t\t\t\t\t\tKeyfile: keyfilePath,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\n\t\tdataSources, err := GetActiveDataSources(profiles, \"\", \"test_profile\", \"dev\")\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"GetActiveDataSources failed: %v\", err)\n\t\t}\n\n\t\tif len(dataSources) != 1 {\n\t\t\tt.Fatalf(\"Expected 1 data source, got %d\", len(dataSources))\n\t\t}\n\n\t\tds, ok := dataSources[0].(*WrenBigQueryDataSource)\n\t\tif !ok {\n\t\t\tt.Fatalf(\"Expected WrenBigQueryDataSource, got %T\", dataSources[0])\n\t\t}\n\n\t\tencodedContent, _ := base64.StdEncoding.DecodeString(ds.Credentials)\n\t\tif string(encodedContent) != keyfileContent {\n\t\t\tt.Errorf(\"Expected base64-encoded keyfile content, got different content\")\n\t\t}\n\t})\n\n\tt.Run(\"service-account-with-relative-keyfile-path\", func(t *testing.T) {\n\t\tdbtHomePath := tempDir\n\t\tkeyfileContent := `{\"type\": \"service_account\"}` // #nosec G101\n\t\tkeyfilePath := \"keys/keyfile.json\"\n\t\tfullKeyfilePath := filepath.Join(dbtHomePath, keyfilePath)\n\n\t\tif err := os.MkdirAll(filepath.Dir(fullKeyfilePath), 0750); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif err := os.WriteFile(fullKeyfilePath, []byte(keyfileContent), 0600); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tprofiles := &DbtProfiles{\n\t\t\tProfiles: map[string]DbtProfile{\n\t\t\t\t\"test_profile\": {\n\t\t\t\t\tTarget: \"dev\",\n\t\t\t\t\tOutputs: map[string]DbtConnection{\n\t\t\t\t\t\t\"dev\": {\n\t\t\t\t\t\t\tType:    \"bigquery\",\n\t\t\t\t\t\t\tMethod:  \"service-account\",\n\t\t\t\t\t\t\tProject: \"test-project\",\n\t\t\t\t\t\t\tDataset: \"test-dataset\",\n\t\t\t\t\t\t\tKeyfile: keyfilePath,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\n\t\tdataSources, err := GetActiveDataSources(profiles, dbtHomePath, \"test_profile\", \"dev\")\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"GetActiveDataSources failed: %v\", err)\n\t\t}\n\n\t\tif len(dataSources) != 1 {\n\t\t\tt.Fatalf(\"Expected 1 data source, got %d\", len(dataSources))\n\t\t}\n\n\t\tds, ok := dataSources[0].(*WrenBigQueryDataSource)\n\t\tif !ok {\n\t\t\tt.Fatalf(\"Expected WrenBigQueryDataSource, got %T\", dataSources[0])\n\t\t}\n\n\t\tencodedContent, _ := base64.StdEncoding.DecodeString(ds.Credentials)\n\t\tif string(encodedContent) != keyfileContent {\n\t\t\tt.Errorf(\"Expected base64-encoded keyfile content, got different content\")\n\t\t}\n\t})\n}\n\nfunc TestBigQueryDataSourceValidation(t *testing.T) {\n\ttests := []struct {\n\t\tname    string\n\t\tds      *WrenBigQueryDataSource\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tname: \"valid\",\n\t\t\tds: &WrenBigQueryDataSource{\n\t\t\t\tProject:     \"test-project\",\n\t\t\t\tDataset:     \"test-dataset\",\n\t\t\t\tCredentials: \"dGVzdC1jcmVkZW50aWFscw==\", // \"test-credentials\"\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"invalid - missing project\",\n\t\t\tds: &WrenBigQueryDataSource{\n\t\t\t\tProject:     \"\",\n\t\t\t\tDataset:     \"test-dataset\",\n\t\t\t\tCredentials: \"dGVzdC1jcmVkZW50aWFscw==\",\n\t\t\t},\n\t\t\twantErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"invalid - missing dataset\",\n\t\t\tds: &WrenBigQueryDataSource{\n\t\t\t\tProject:     \"test-project\",\n\t\t\t\tDataset:     \"\",\n\t\t\t\tCredentials: \"dGVzdC1jcmVkZW50aWFscw==\",\n\t\t\t},\n\t\t\twantErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"invalid - missing credentials\",\n\t\t\tds: &WrenBigQueryDataSource{\n\t\t\t\tProject:     \"test-project\",\n\t\t\t\tDataset:     \"test-dataset\",\n\t\t\t\tCredentials: \"\",\n\t\t\t},\n\t\t\twantErr: true,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\terr := tt.ds.Validate()\n\t\t\tif (err != nil) != tt.wantErr {\n\t\t\t\tt.Errorf(\"Validate() error = %v, wantErr %v\", err, tt.wantErr)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestPostgresDataSourceValidation(t *testing.T) {\n\tvalidDS := &WrenPostgresDataSource{\n\t\tHost:     testHost,\n\t\tPort:     \"5432\",\n\t\tDatabase: \"test\",\n\t\tUser:     \"user\",\n\t}\n\n\tinvalidCases := []struct {\n\t\tname string\n\t\tds   Validator\n\t}{\n\t\t{\n\t\t\t\"empty host\",\n\t\t\t&WrenPostgresDataSource{\n\t\t\t\tPort:     \"5432\",\n\t\t\t\tDatabase: \"test\",\n\t\t\t\tUser:     \"user\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"empty database\",\n\t\t\t&WrenPostgresDataSource{\n\t\t\t\tHost: testHost,\n\t\t\t\tPort: \"5432\",\n\t\t\t\tUser: \"user\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t\"invalid port\",\n\t\t\t&WrenPostgresDataSource{\n\t\t\t\tHost:     testHost,\n\t\t\t\tPort:     \"0\",\n\t\t\t\tDatabase: \"test\",\n\t\t\t\tUser:     \"user\",\n\t\t\t},\n\t\t},\n\t}\n\n\ttestDataSourceValidation(t, \"postgres\", validDS, invalidCases)\n}\n\nfunc TestMysqlDataSourceValidation(t *testing.T) {\n\t// Test MySQL data source validation\n\ttests := []struct {\n\t\tname    string\n\t\tds      *WrenMysqlDataSource\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tname: \"valid\",\n\t\t\tds: &WrenMysqlDataSource{\n\t\t\t\tHost:     \"localhost\",\n\t\t\t\tPort:     \"3306\",\n\t\t\t\tDatabase: \"test\",\n\t\t\t\tUser:     \"user\",\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"empty host\",\n\t\t\tds: &WrenMysqlDataSource{\n\t\t\t\tPort:     \"3306\",\n\t\t\t\tDatabase: \"test\",\n\t\t\t\tUser:     \"user\",\n\t\t\t},\n\t\t\twantErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"empty database\",\n\t\t\tds: &WrenMysqlDataSource{\n\t\t\t\tHost: \"localhost\",\n\t\t\t\tPort: \"3306\",\n\t\t\t\tUser: \"user\",\n\t\t\t},\n\t\t\twantErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"invalid port\",\n\t\t\tds: &WrenMysqlDataSource{\n\t\t\t\tHost:     \"localhost\",\n\t\t\t\tPort:     \"\",\n\t\t\t\tDatabase: \"test\",\n\t\t\t\tUser:     \"user\",\n\t\t\t},\n\t\t\twantErr: true,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\terr := tt.ds.Validate()\n\t\t\tif (err != nil) != tt.wantErr {\n\t\t\t\tt.Errorf(\"Validate() error = %v, wantErr %v\", err, tt.wantErr)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestGetActiveDataSources(t *testing.T) {\n\tprofiles := &DbtProfiles{\n\t\tProfiles: map[string]DbtProfile{\n\t\t\t\"project1\": {\n\t\t\t\tTarget: \"dev\",\n\t\t\t\tOutputs: map[string]DbtConnection{\n\t\t\t\t\t\"dev\": {\n\t\t\t\t\t\tType:     \"postgres\",\n\t\t\t\t\t\tHost:     \"localhost\",\n\t\t\t\t\t\tPort:     5432,\n\t\t\t\t\t\tDatabase: \"dev_db\",\n\t\t\t\t\t\tUser:     \"dev_user\",\n\t\t\t\t\t},\n\t\t\t\t\t\"prod\": {\n\t\t\t\t\t\tType:     \"postgres\",\n\t\t\t\t\t\tHost:     \"prod-host\",\n\t\t\t\t\t\tPort:     5432,\n\t\t\t\t\t\tDatabase: \"prod_db\",\n\t\t\t\t\t\tUser:     \"prod_user\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\t// Test getting default target\n\tdataSources, err := GetActiveDataSources(profiles, \"\", \"project1\", \"\")\n\tif err != nil {\n\t\tt.Fatalf(\"GetActiveDataSources failed: %v\", err)\n\t}\n\tif len(dataSources) != 1 {\n\t\tt.Fatalf(\"Expected 1 data source, got %d\", len(dataSources))\n\t}\n\n\tds := dataSources[0].(*WrenPostgresDataSource)\n\tif ds.Database != \"dev_db\" {\n\t\tt.Errorf(\"Expected dev database, got %s\", ds.Database)\n\t}\n\n\t// Test specified target\n\tdataSources, err = GetActiveDataSources(profiles, \"\", \"project1\", \"prod\")\n\tif err != nil {\n\t\tt.Fatalf(\"GetActiveDataSources failed: %v\", err)\n\t}\n\tif len(dataSources) != 1 {\n\t\tt.Fatalf(\"Expected 1 data source, got %d\", len(dataSources))\n\t}\n\n\tds = dataSources[0].(*WrenPostgresDataSource)\n\tif ds.Database != \"prod_db\" {\n\t\tt.Errorf(\"Expected prod database, got %s\", ds.Database)\n\t}\n\n\t// Test nonexistent profile\n\t_, err = GetActiveDataSources(profiles, \"\", \"nonexistent\", \"\")\n\tif err == nil {\n\t\tt.Error(\"Expected error for nonexistent profile\")\n\t}\n\n\t// Test nonexistent target\n\t_, err = GetActiveDataSources(profiles, \"\", \"project1\", \"nonexistent\")\n\tif err == nil {\n\t\tt.Error(\"Expected error for nonexistent target\")\n\t}\n}\n\nfunc TestGetDataSourceByType(t *testing.T) {\n\tprofiles := &DbtProfiles{\n\t\tProfiles: map[string]DbtProfile{\n\t\t\t\"mixed_project\": {\n\t\t\t\tTarget: \"dev\",\n\t\t\t\tOutputs: map[string]DbtConnection{\n\t\t\t\t\t\"postgres_dev\": {\n\t\t\t\t\t\tType:     \"postgres\",\n\t\t\t\t\t\tHost:     \"localhost\",\n\t\t\t\t\t\tPort:     5432,\n\t\t\t\t\t\tDatabase: \"dev_db\",\n\t\t\t\t\t\tUser:     \"user\",\n\t\t\t\t\t},\n\t\t\t\t\t\"file_dev\": {\n\t\t\t\t\t\tType: duckdbType,\n\t\t\t\t\t\tPath: \"/data/test.csv\",\n\t\t\t\t\t},\n\t\t\t\t\t\"postgres_prod\": {\n\t\t\t\t\t\tType:     \"postgres\",\n\t\t\t\t\t\tHost:     \"prod-host\",\n\t\t\t\t\t\tPort:     5432,\n\t\t\t\t\t\tDatabase: \"prod_db\",\n\t\t\t\t\t\tUser:     \"user\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\t// Test getting postgres type\n\tpostgresSources, err := GetDataSourceByType(profiles, \"postgres\")\n\tif err != nil {\n\t\tt.Fatalf(\"GetDataSourceByType failed: %v\", err)\n\t}\n\tif len(postgresSources) != 2 {\n\t\tt.Fatalf(\"Expected 2 postgres data sources, got %d\", len(postgresSources))\n\t}\n\n\t// Test getting local_file type\n\tfileSources, err := GetDataSourceByType(profiles, \"local_file\")\n\tif err != nil {\n\t\tt.Fatalf(\"GetDataSourceByType failed: %v\", err)\n\t}\n\tif len(fileSources) != 1 {\n\t\tt.Fatalf(\"Expected 1 file data source, got %d\", len(fileSources))\n\t}\n\n\t// Test getting nonexistent type\n\tnonexistentSources, err := GetDataSourceByType(profiles, \"nonexistent\")\n\tif err != nil {\n\t\tt.Fatalf(\"GetDataSourceByType failed: %v\", err)\n\t}\n\tif len(nonexistentSources) != 0 {\n\t\tt.Fatalf(\"Expected 0 nonexistent data sources, got %d\", len(nonexistentSources))\n\t}\n}\n\nfunc TestMapType(t *testing.T) {\n\ttests := []struct {\n\t\tname       string\n\t\tdataSource DataSource\n\t\tsourceType string\n\t\twant       string\n\t}{\n\t\t{\n\t\t\tname:       \"BigQuery INT64 to integer\",\n\t\t\tdataSource: &WrenBigQueryDataSource{},\n\t\t\tsourceType: \"INT64\",\n\t\t\twant:       \"integer\",\n\t\t},\n\t\t{\n\t\t\tname:       \"BigQuery STRING to varchar\",\n\t\t\tdataSource: &WrenBigQueryDataSource{},\n\t\t\tsourceType: \"STRING\",\n\t\t\twant:       \"varchar\",\n\t\t},\n\t\t{\n\t\t\tname:       \"LocalFile INTEGER to integer\",\n\t\t\tdataSource: &WrenLocalFileDataSource{},\n\t\t\tsourceType: \"INTEGER\",\n\t\t\twant:       \"integer\",\n\t\t},\n\t\t{\n\t\t\tname:       \"LocalFile VARCHAR to varchar\",\n\t\t\tdataSource: &WrenLocalFileDataSource{},\n\t\t\tsourceType: \"VARCHAR\",\n\t\t\twant:       \"varchar\",\n\t\t},\n\t\t{\n\t\t\tname:       \"DefaultDataSource int to integer\",\n\t\t\tdataSource: &DefaultDataSource{},\n\t\t\tsourceType: \"int\",\n\t\t\twant:       \"integer\",\n\t\t},\n\t\t{\n\t\t\tname:       \"PostgresDataSource (no mapping)\",\n\t\t\tdataSource: &WrenPostgresDataSource{},\n\t\t\tsourceType: \"unknown_type\",\n\t\t\twant:       \"unknown_type\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tgot := tt.dataSource.MapType(tt.sourceType)\n\t\t\tif got != tt.want {\n\t\t\t\tt.Errorf(\"MapType(%s) = %s; want %s\", tt.sourceType, got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Validator interface for data sources\ntype Validator interface {\n\tValidate() error\n}\n\n// Helper function to test data source validation\nfunc testDataSourceValidation(t *testing.T, testName string, validDS Validator, invalidDSCases []struct {\n\tname string\n\tds   Validator\n}) {\n\tt.Helper()\n\n\tt.Run(testName+\" valid\", func(t *testing.T) {\n\t\tif err := validDS.Validate(); err != nil {\n\t\t\tt.Errorf(\"Valid data source validation failed: %v\", err)\n\t\t}\n\t})\n\n\tfor _, tt := range invalidDSCases {\n\t\tt.Run(testName+\" \"+tt.name, func(t *testing.T) {\n\t\t\tif err := tt.ds.Validate(); err == nil {\n\t\t\t\tt.Errorf(\"Expected validation error for %s, but got none\", tt.name)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "wren-launcher/commands/dbt/profiles.go",
    "content": "package dbt\n\n// DbtProfiles represents the structure of dbt profiles.yml\ntype DbtProfiles struct {\n\tConfig   map[string]interface{} `yaml:\"config\" json:\"config,omitempty\"`\n\tProfiles map[string]DbtProfile  `yaml:\",inline\" json:\"profiles\"`\n}\n\n// DbtProfile represents a single profile in profiles.yml\ntype DbtProfile struct {\n\tTarget  string                   `yaml:\"target\" json:\"target\"`\n\tOutputs map[string]DbtConnection `yaml:\"outputs\" json:\"outputs\"`\n}\n\n// DbtConnection represents a database connection configuration\ntype DbtConnection struct {\n\tType     string `yaml:\"type\" json:\"type\"`\n\tHost     string `yaml:\"host,omitempty\" json:\"host,omitempty\"`\n\tServer   string `yaml:\"server,omitempty\" json:\"server,omitempty\"` // MSSQL\n\tPort     int    `yaml:\"port,omitempty\" json:\"port,omitempty\"`\n\tUser     string `yaml:\"user,omitempty\" json:\"user,omitempty\"`\n\tPassword string `yaml:\"password,omitempty\" json:\"password,omitempty\"`\n\tDbName   string `yaml:\"dbname,omitempty\" json:\"dbname,omitempty\"` // Postgres\n\tDatabase string `yaml:\"database,omitempty\" json:\"database,omitempty\"`\n\tSchema   string `yaml:\"schema,omitempty\" json:\"schema,omitempty\"`\n\t// Additional fields for different database types\n\tProject   string `yaml:\"project,omitempty\" json:\"project,omitempty\"`     // BigQuery\n\tDataset   string `yaml:\"dataset,omitempty\" json:\"dataset,omitempty\"`     // BigQuery\n\tKeyfile   string `yaml:\"keyfile,omitempty\" json:\"keyfile,omitempty\"`     // BigQuery\n\tMethod    string `yaml:\"method,omitempty\" json:\"method,omitempty\"`       // BigQuery\n\tAccount   string `yaml:\"account,omitempty\" json:\"account,omitempty\"`     // Snowflake\n\tWarehouse string `yaml:\"warehouse,omitempty\" json:\"warehouse,omitempty\"` // Snowflake\n\tRole      string `yaml:\"role,omitempty\" json:\"role,omitempty\"`           // Snowflake\n\tKeepAlive bool   `yaml:\"keepalive,omitempty\" json:\"keepalive,omitempty\"` // Postgres\n\n\tSearchPath string `yaml:\"search_path,omitempty\" json:\"search_path,omitempty\"` // Postgres\n\tSSLMode    string `yaml:\"sslmode,omitempty\" json:\"sslmode,omitempty\"`         // Postgres\n\n\tSslDisable bool `yaml:\"ssl_disable,omitempty\" json:\"ssl_disable,omitempty\"` // MySQL\n\n\tPath string `yaml:\"path,omitempty\" json:\"path,omitempty\"` // DuckDB\n\t// Flexible additional properties\n\tAdditional map[string]interface{} `yaml:\",inline\" json:\"additional,omitempty\"`\n}\n"
  },
  {
    "path": "wren-launcher/commands/dbt/profiles_analyzer.go",
    "content": "package dbt\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strconv\"\n\n\t\"gopkg.in/yaml.v3\"\n)\n\n// AnalyzeDbtProfiles reads and analyzes a dbt profiles.yml file\nfunc AnalyzeDbtProfiles(profilesPath string) (*DbtProfiles, error) {\n\t// Read the profiles.yml file\n\tdata, err := os.ReadFile(profilesPath) // #nosec G304 -- profilesPath is controlled by application\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read profiles file %s: %w\", profilesPath, err)\n\t}\n\n\t// Parse YAML\n\tvar rawProfiles map[string]interface{}\n\tif err := yaml.Unmarshal(data, &rawProfiles); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse YAML in file %s: %w\", profilesPath, err)\n\t}\n\n\t// Convert to structured format\n\tprofiles := &DbtProfiles{\n\t\tProfiles: make(map[string]DbtProfile),\n\t}\n\n\t// Extract config if present\n\tif config, exists := rawProfiles[\"config\"]; exists {\n\t\tif configMap, ok := config.(map[string]interface{}); ok {\n\t\t\tprofiles.Config = configMap\n\t\t}\n\t\tdelete(rawProfiles, \"config\")\n\t}\n\n\t// Process each profile\n\tfor profileName, profileData := range rawProfiles {\n\t\tif profileMap, ok := profileData.(map[string]interface{}); ok {\n\t\t\tprofile, err := parseProfile(profileMap)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to parse profile %s: %w\", profileName, err)\n\t\t\t}\n\t\t\tprofiles.Profiles[profileName] = *profile\n\t\t}\n\t}\n\n\treturn profiles, nil\n}\n\n// parseProfile converts a raw profile map to DbtProfile struct\nfunc parseProfile(profileMap map[string]interface{}) (*DbtProfile, error) {\n\tprofile := &DbtProfile{\n\t\tOutputs: make(map[string]DbtConnection),\n\t}\n\n\t// Extract target\n\tif target, exists := profileMap[\"target\"]; exists {\n\t\tif targetStr, ok := target.(string); ok {\n\t\t\tprofile.Target = targetStr\n\t\t}\n\t}\n\n\t// Extract outputs\n\tif outputs, exists := profileMap[\"outputs\"]; exists {\n\t\tif outputsMap, ok := outputs.(map[string]interface{}); ok {\n\t\t\tfor outputName, outputData := range outputsMap {\n\t\t\t\tif outputMap, ok := outputData.(map[string]interface{}); ok {\n\t\t\t\t\tconnection, err := parseConnection(outputMap)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, fmt.Errorf(\"failed to parse output %s: %w\", outputName, err)\n\t\t\t\t\t}\n\t\t\t\t\tprofile.Outputs[outputName] = *connection\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn profile, nil\n}\n\n// parseConnection converts a raw connection map to DbtConnection struct\nfunc parseConnection(connectionMap map[string]interface{}) (*DbtConnection, error) {\n\tconnection := &DbtConnection{\n\t\tAdditional: make(map[string]interface{}),\n\t}\n\n\t// Helper function to safely extract string values\n\tgetString := func(key string) string {\n\t\tif value, exists := connectionMap[key]; exists {\n\t\t\tif str, ok := value.(string); ok {\n\t\t\t\treturn str\n\t\t\t}\n\t\t}\n\t\treturn \"\"\n\t}\n\n\t// Helper function to safely extract int values\n\tgetInt := func(key string) int {\n\t\tif value, exists := connectionMap[key]; exists {\n\t\t\tswitch v := value.(type) {\n\t\t\tcase int:\n\t\t\t\treturn v\n\t\t\tcase float64:\n\t\t\t\treturn int(v)\n\t\t\tcase int64:\n\t\t\t\treturn int(v)\n\t\t\tcase string:\n\t\t\t\tif i, err := strconv.Atoi(v); err == nil {\n\t\t\t\t\treturn i\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn 0\n\t}\n\n\t// Helper function to safely extract bool values\n\tgetBool := func(key string) bool {\n\t\tif value, exists := connectionMap[key]; exists {\n\t\t\tif b, ok := value.(bool); ok {\n\t\t\t\treturn b\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n\t// Extract standard fields\n\tconnection.Type = getString(\"type\")\n\tconnection.Host = getString(\"host\")\n\tconnection.Port = getInt(\"port\")\n\tconnection.User = getString(\"user\")\n\tconnection.Password = getString(\"password\")\n\tconnection.Database = getString(\"database\")\n\tconnection.DbName = getString(\"dbname\") // PostgreSQL specific\n\tconnection.Schema = getString(\"schema\")\n\n\t// Extract database-specific fields\n\tconnection.Project = getString(\"project\")\n\tconnection.Dataset = getString(\"dataset\")\n\tconnection.Keyfile = getString(\"keyfile\")\n\tconnection.Method = getString(\"method\")\n\tconnection.Account = getString(\"account\")\n\tconnection.Warehouse = getString(\"warehouse\")\n\tconnection.Role = getString(\"role\")\n\tconnection.KeepAlive = getBool(\"keepalive\")\n\tconnection.SearchPath = getString(\"search_path\")\n\tconnection.SSLMode = getString(\"sslmode\")\n\tconnection.Path = getString(\"path\")\n\tconnection.SslDisable = getBool(\"ssl_disable\") // MySQL specific\n\tconnection.Server = getString(\"server\")\n\n\t// Store any additional fields that weren't mapped\n\tknownFields := map[string]bool{\n\t\t\"type\": true, \"host\": true, \"port\": true, \"user\": true, \"password\": true,\n\t\t\"database\": true, \"dbname\": true, \"schema\": true, \"project\": true, \"dataset\": true,\n\t\t\"keyfile\": true, \"method\": true, \"account\": true, \"warehouse\": true, \"role\": true,\n\t\t\"keepalive\": true, \"search_path\": true, \"sslmode\": true, \"path\": true, \"server\": true, \"ssl_disable\": true,\n\t}\n\n\tfor key, value := range connectionMap {\n\t\tif !knownFields[key] {\n\t\t\tconnection.Additional[key] = value\n\t\t}\n\t}\n\n\t// Clean up empty Additional map\n\tif len(connection.Additional) == 0 {\n\t\tconnection.Additional = nil\n\t}\n\n\treturn connection, nil\n}\n\n// GetDefaultProfilesPath returns the default path to dbt profiles.yml\nfunc GetDefaultProfilesPath() string {\n\thomeDir, err := os.UserHomeDir()\n\tif err != nil {\n\t\treturn \"\"\n\t}\n\n\tif runtime.GOOS == \"windows\" {\n\t\treturn filepath.Join(homeDir, \".dbt\", \"profiles.yml\")\n\t}\n\treturn filepath.Join(homeDir, \".dbt\", \"profiles.yml\")\n}\n\n// FindProfilesFile searches for profiles.yml in common locations\nfunc FindProfilesFile(projectPath string) (string, error) {\n\t// Try locations in order of preference\n\tsearchPaths := []string{\n\t\t// Current directory\n\t\tfilepath.Join(projectPath, \"profiles.yml\"),\n\t\t// Project .dbt directory\n\t\tfilepath.Join(projectPath, \".dbt\", \"profiles.yml\"),\n\t\t// User home .dbt directory\n\t\tGetDefaultProfilesPath(),\n\t}\n\n\tfor _, path := range searchPaths {\n\t\tif FileExists(path) {\n\t\t\treturn path, nil\n\t\t}\n\t}\n\n\treturn \"\", fmt.Errorf(\"profiles.yml not found in any of the expected locations: %v\", searchPaths)\n}\n"
  },
  {
    "path": "wren-launcher/commands/dbt/utils.go",
    "content": "package dbt\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n)\n\n// isDbtProjectValid checks if the given path is a valid dbt project directory\nfunc IsDbtProjectValid(projectPath string) bool {\n\t// Check if path exists and is a directory\n\tif !DirExists(projectPath) {\n\t\treturn false\n\t}\n\n\t// Check for dbt_project.yml (required file for dbt projects)\n\tdbtProjectFile := filepath.Join(projectPath, \"dbt_project.yml\")\n\treturn FileExists(dbtProjectFile)\n}\n\n// DirExists checks if a directory exists\nfunc DirExists(path string) bool {\n\tinfo, err := os.Stat(path)\n\tif os.IsNotExist(err) {\n\t\treturn false\n\t}\n\treturn info.IsDir()\n}\n\n// FileExists checks if a file exists\nfunc FileExists(path string) bool {\n\tinfo, err := os.Stat(path)\n\tif os.IsNotExist(err) {\n\t\treturn false\n\t}\n\treturn !info.IsDir()\n}\n"
  },
  {
    "path": "wren-launcher/commands/dbt/wren_mdl.go",
    "content": "package dbt\n\n// WrenMDLManifest represents the complete Wren MDL structure\ntype WrenMDLManifest struct {\n\tJsonSchema      string           `json:\"$schema\"`\n\tCatalog         string           `json:\"catalog\"`\n\tSchema          string           `json:\"schema\"`\n\tEnumDefinitions []EnumDefinition `json:\"enumDefinitions,omitempty\"`\n\tModels          []WrenModel      `json:\"models\"`\n\tRelationships   []Relationship   `json:\"relationships\"`\n\tMetrics         []Metric         `json:\"metrics,omitempty\"`\n\tViews           []View           `json:\"views\"`\n\tDataSource      string           `json:\"dataSource,omitempty\"`\n}\n\n// EnumDefinition represents a named list of values that can be used by columns.\ntype EnumDefinition struct {\n\tName   string      `json:\"name\"`\n\tValues []EnumValue `json:\"values\"`\n}\n\ntype EnumValue struct {\n\tName  string `json:\"name\"`\n\tValue string `json:\"value,omitempty\"`\n}\n\n// WrenModel represents a model in the Wren MDL format\ntype WrenModel struct {\n\tName           string            `json:\"name\"`\n\tTableReference TableReference    `json:\"tableReference\"`\n\tColumns        []WrenColumn      `json:\"columns\"`\n\tPrimaryKey     string            `json:\"primaryKey,omitempty\"`\n\tCached         bool              `json:\"cached,omitempty\"`\n\tRefreshTime    string            `json:\"refreshTime,omitempty\"`\n\tProperties     map[string]string `json:\"properties,omitempty\"`\n}\n\n// TableReference represents a reference to a table\ntype TableReference struct {\n\tCatalog string `json:\"catalog,omitempty\"`\n\tSchema  string `json:\"schema,omitempty\"`\n\tTable   string `json:\"table\"`\n}\n\n// WrenColumn represents a column in the Wren MDL format\ntype WrenColumn struct {\n\tName         string            `json:\"name\"`\n\tDisplayName  string            `json:\"displayName,omitempty\"`\n\tType         string            `json:\"type\"`\n\tRelationship string            `json:\"relationship,omitempty\"`\n\tIsCalculated bool              `json:\"isCalculated,omitempty\"`\n\tNotNull      bool              `json:\"notNull,omitempty\"`\n\tExpression   *string           `json:\"expression,omitempty\"`\n\tProperties   map[string]string `json:\"properties,omitempty\"`\n}\n\n// Relationship represents a relationship between models\ntype Relationship struct {\n\tName       string            `json:\"name\"`\n\tModels     []string          `json:\"models\"`\n\tJoinType   string            `json:\"joinType\"`\n\tCondition  string            `json:\"condition\"`\n\tProperties map[string]string `json:\"properties,omitempty\"`\n}\n\n// Metric defines a business-level calculation in Wren MDL.\ntype Metric struct {\n\tName        string   `json:\"name\"`\n\tModels      []string `json:\"models\"`\n\tDimensions  []string `json:\"dimensions\"`\n\tAggregation string   `json:\"aggregation\"`\n\tDisplayName string   `json:\"displayName\"`\n\tDescription string   `json:\"description,omitempty\"`\n}\n\n// View represents a view in the Wren MDL format\ntype View struct {\n\tName       string            `json:\"name\"`\n\tStatement  string            `json:\"statement\"`\n\tProperties map[string]string `json:\"properties,omitempty\"`\n}\n"
  },
  {
    "path": "wren-launcher/commands/dbt.go",
    "content": "package commands\n\nimport (\n\t\"flag\"\n\t\"os\"\n\n\t\"github.com/Canner/WrenAI/wren-launcher/commands/dbt\"\n\t\"github.com/pterm/pterm\"\n)\n\n// DbtAutoConvert automatically searches for dbt profiles and catalog.json,\n// then converts them to WrenDataSource and Wren MDL format\nfunc DbtAutoConvert() {\n\tvar opts struct {\n\t\tProjectPath          string\n\t\tOutputDir            string\n\t\tProfileName          string\n\t\tTarget               string\n\t\tIncludeStagingModels bool\n\t}\n\n\t// Define command line flags\n\tflag.StringVar(&opts.ProjectPath, \"path\", \"\", \"Path to the dbt project root directory\")\n\tflag.StringVar(&opts.OutputDir, \"output\", \"\", \"Output directory for generated JSON files\")\n\tflag.StringVar(&opts.ProfileName, \"profile\", \"\", \"Specific profile name to use (optional, uses first found if not provided)\")\n\tflag.StringVar(&opts.Target, \"target\", \"\", \"Specific target to use (optional, uses profile default if not provided)\")\n\tflag.BoolVar(&opts.IncludeStagingModels, \"include-staging-models\", false, \"If set, staging models will be included during conversion\")\n\tflag.Parse()\n\n\t// Validate required parameters\n\tif opts.ProjectPath == \"\" {\n\t\tpterm.Error.Println(\"Error: --path parameter is required\")\n\t\tpterm.Info.Println(\"Usage: wren-launcher dbt-auto-convert --path /path/to/dbt/project --output /path/to/output\")\n\t\tos.Exit(1)\n\t}\n\n\tif opts.OutputDir == \"\" {\n\t\tpterm.Error.Println(\"Error: --output parameter is required\")\n\t\tpterm.Info.Println(\"Usage: wren-launcher dbt-auto-convert --path /path/to/dbt/project --output /path/to/output\")\n\t\tos.Exit(1)\n\t}\n\n\t// ConvertOptions struct for core conversion logic\n\tconvertOpts := dbt.ConvertOptions{\n\t\tProjectPath:          opts.ProjectPath,\n\t\tOutputDir:            opts.OutputDir,\n\t\tProfileName:          opts.ProfileName,\n\t\tTarget:               opts.Target,\n\t\tRequireCatalog:       true, // DbtAutoConvert requires catalog.json to exist\n\t\tIncludeStagingModels: opts.IncludeStagingModels,\n\t}\n\n\t// Call the core conversion logic\n\t_, err := dbt.ConvertDbtProjectCore(convertOpts)\n\tif err != nil {\n\t\tpterm.Error.Printf(\"Error: Conversion failed: %v\\n\", err)\n\t\tos.Exit(1)\n\t}\n}\n\n// DbtConvertProject is a public wrapper function for processDbtProject to use\n// It converts a dbt project without requiring catalog.json to exist\nfunc DbtConvertProject(projectPath, outputDir, profileName, target string, usedByContainer bool, IncludeStagingModels bool) (*dbt.ConvertResult, error) {\n\tconvertOpts := dbt.ConvertOptions{\n\t\tProjectPath:          projectPath,\n\t\tOutputDir:            outputDir,\n\t\tProfileName:          profileName,\n\t\tTarget:               target,\n\t\tRequireCatalog:       false, // Allow processDbtProject to continue without catalog.json\n\t\tUsedByContainer:      usedByContainer,\n\t\tIncludeStagingModels: IncludeStagingModels,\n\t}\n\n\treturn dbt.ConvertDbtProjectCore(convertOpts)\n}\n"
  },
  {
    "path": "wren-launcher/commands/launch.go",
    "content": "package commands\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/Canner/WrenAI/wren-launcher/config\"\n\tutils \"github.com/Canner/WrenAI/wren-launcher/utils\"\n\t\"github.com/common-nighthawk/go-figure\"\n\t\"github.com/manifoldco/promptui\"\n\t\"github.com/pterm/pterm\"\n\topenai \"github.com/sashabaranov/go-openai\"\n)\n\nfunc prepareProjectDir() string {\n\t// create a project directory under ~/.wrenai\n\thomedir, err := os.UserHomeDir()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tprojectDir := path.Join(homedir, \".wrenai\")\n\n\tif _, err := os.Stat(projectDir); os.IsNotExist(err) {\n\t\tif err := os.Mkdir(projectDir, 0750); err != nil {\n\t\t\treturn \"\"\n\t\t}\n\t}\n\n\treturn projectDir\n}\n\nfunc evaluateTelemetryPreferences() (bool, error) {\n\t// let users know we're asking for telemetry consent\n\tdisableTelemetry := config.IsTelemetryDisabled()\n\tif disableTelemetry {\n\t\tfmt.Println(\"You have disabled telemetry, Wren AI will not collect any data.\")\n\t\treturn false, nil\n\t}\n\tfmt.Println(\"Wren AI relies on anonymous usage statistics to continuously improve.\")\n\tfmt.Println(\"You can opt out of sharing these statistics by manually adding flag `--disable-telemetry` as described at https://docs.getwren.ai/oss/overview/telemetry\")\n\treturn true, nil\n}\n\nfunc askForLLMProvider() (string, error) {\n\t// let users know we're asking for a LLM provider\n\tpterm.Warning.Println(\"We highly recommend using OpenAI models with Wren AI, especially the latest models.\")\n\tpterm.Warning.Println(\"These models have been extensively tested to ensure optimal performance and compatibility.\")\n\tpterm.Warning.Println(\"While it is technically possible to integrate other AI models, please note that they have not been fully tested with our system.\")\n\tpterm.Warning.Println(\"Therefore, using alternative models is at your own risk and may result in unexpected behavior or suboptimal performance.\")\n\tfmt.Println(\"\")\n\tfmt.Println(\"Please provide the LLM provider you want to use\")\n\tfmt.Println(\"You can learn more about how to set up custom LLMs at https://docs.getwren.ai/oss/ai_service/guide/custom_llm#running-wren-ai-with-your-custom-llm-or-document-store\")\n\n\tprompt := promptui.Select{\n\t\tLabel: \"Select an LLM provider\",\n\t\tItems: []string{\"OpenAI\", \"Custom\"},\n\t}\n\n\t_, result, err := prompt.Run()\n\n\tif err != nil {\n\t\tfmt.Printf(\"Prompt failed %v\\n\", err)\n\t\treturn \"\", err\n\t}\n\n\treturn result, nil\n}\n\nfunc askForAPIKey() (string, error) {\n\t// let users know we're asking for an API key\n\tfmt.Println(\"Please provide your OpenAI API key\")\n\tfmt.Println(\"Please use the key with full permission, more details at https://help.openai.com/en/articles/8867743-assign-api-key-permissions\")\n\n\tvalidate := func(input string) error {\n\t\t// check if input is a valid API key\n\t\t// OpenAI API keys are starting with \"sk-\"\n\t\tif !strings.HasPrefix(input, \"sk-\") {\n\t\t\treturn errors.New(\"invalid API key\")\n\t\t}\n\t\treturn nil\n\t}\n\n\tprompt := promptui.Prompt{\n\t\tLabel:    \"OpenAI API key\",\n\t\tValidate: validate,\n\t\tMask:     '*',\n\t}\n\n\tresult, err := prompt.Run()\n\n\tif err != nil {\n\t\tfmt.Printf(\"Prompt failed %v\\n\", err)\n\t\treturn \"\", err\n\t}\n\n\treturn result, nil\n}\n\nfunc askForGenerationModel() (string, error) {\n\t// let users know we're asking for a generation model\n\tfmt.Println(\"Please provide the generation model you want to use\")\n\tfmt.Println(\"You can learn more about OpenAI's generation models at https://platform.openai.com/docs/models/models\")\n\n\tprompt := promptui.Select{\n\t\tLabel: \"Select an OpenAI's generation model\",\n\t\tItems: []string{\"gpt-4.1\", \"gpt-4.1-mini\", \"gpt-4.1-nano\", \"gpt-5\", \"gpt-5-mini\", \"gpt-5-nano\"},\n\t}\n\n\t_, result, err := prompt.Run()\n\n\tif err != nil {\n\t\tfmt.Printf(\"Prompt failed %v\\n\", err)\n\t\treturn \"\", err\n\t}\n\n\treturn result, nil\n}\n\nfunc askForDbtProjectPath() (string, error) {\n\t// let users know we're asking for a dbt project path\n\tfmt.Println(\"Please provide the dbt project path you want to convert\")\n\tfmt.Println(\"This should be the root directory of your dbt project containing dbt_project.yml\")\n\tfmt.Println(\"Press Enter to ignore this step if you don't have a dbt project to convert.\")\n\n\tprompt := promptui.Prompt{\n\t\tLabel:   \"dbt project path (leave empty to skip)\",\n\t\tDefault: \"\",\n\t}\n\n\tresult, err := prompt.Run()\n\n\tif err != nil {\n\t\tfmt.Printf(\"Prompt failed %v\\n\", err)\n\t\treturn \"\", err\n\t}\n\n\treturn result, nil\n}\n\nfunc askForDbtProfileName() (string, error) {\n\t// let users know we're asking for a dbt profile name\n\tfmt.Println(\"Please provide the dbt profile name you want to use\")\n\tfmt.Println(\"This should be the profile name defined in your profiles.yml file\")\n\tfmt.Println(\"Press Enter to use the default profile.\")\n\n\tprompt := promptui.Prompt{\n\t\tLabel:   \"dbt profile name (leave empty to use default)\",\n\t\tDefault: \"\",\n\t}\n\n\tresult, err := prompt.Run()\n\n\tif err != nil {\n\t\tfmt.Printf(\"Prompt failed %v\\n\", err)\n\t\treturn \"\", err\n\t}\n\n\treturn result, nil\n}\n\nfunc askForDbtTarget() (string, error) {\n\t// let users know we're asking for a dbt target\n\tfmt.Println(\"Please provide the dbt target you want to use\")\n\tfmt.Println(\"This should be the target name defined in your profiles.yml file\")\n\tfmt.Println(\"Press Enter to use the default target.\")\n\n\tprompt := promptui.Prompt{\n\t\tLabel:   \"dbt target (leave empty to use default)\",\n\t\tDefault: \"\",\n\t}\n\n\tresult, err := prompt.Run()\n\n\tif err != nil {\n\t\tfmt.Printf(\"Prompt failed %v\\n\", err)\n\t\treturn \"\", err\n\t}\n\n\treturn result, nil\n}\n\nfunc askForIncludeStagingModels() (bool, error) {\n\tprompt := promptui.Select{\n\t\tLabel: \"Include staging models (stg_*, staging_*)?\",\n\t\tItems: []string{\"No\", \"Yes\"},\n\t}\n\t_, result, err := prompt.Run()\n\tif err != nil {\n\t\treturn false, err\n\t}\n\treturn result == \"Yes\", nil\n}\n\nfunc Launch() {\n\t// recover from panic\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tpterm.Error.Println(\"An error occurred:\", r)\n\t\t\tvar dummy string\n\t\t\t_, _ = fmt.Scanf(\"%s\", &dummy)\n\t\t}\n\t}()\n\n\t// Setup a channel to receive a signal\n\tdone := make(chan os.Signal, 1)\n\n\tsignal.Notify(done, os.Interrupt)\n\n\t// Fire off a goroutine to loop until that channel receives a signal.\n\t// When a signal is received simply exit the program\n\tgo func() {\n\t\tfor range done {\n\t\t\tos.Exit(0)\n\t\t}\n\t}()\n\t// print Wren AI header\n\tfmt.Println(strings.Repeat(\"=\", 55))\n\tmyFigure := figure.NewFigure(\"WrenAI\", \"\", true)\n\tmyFigure.Print()\n\tfmt.Println(strings.Repeat(\"=\", 55))\n\n\t// prepare a project directory\n\tpterm.Info.Println(\"Preparing project directory\")\n\tprojectDir := prepareProjectDir()\n\n\t// get platform\n\tplatform := config.GetPlatform()\n\tif platform != \"linux/amd64\" && platform != \"linux/arm64\" {\n\t\tpterm.Error.Println(\"Invalid platform, valid values are: linux/amd64, linux/arm64\")\n\t\tos.Exit(1)\n\t}\n\tpterm.Info.Println(\"Platform: \", platform)\n\n\t// get experimental engine rust version\n\texperimentalEngineRustVersion := config.IsExperimentalEngineRustVersion()\n\tpterm.Info.Println(\"Use Experimental Rust Engine: \", experimentalEngineRustVersion)\n\n\t// ask for LLM provider\n\tpterm.Print(\"\\n\")\n\tllmProvider, shouldReturn := getLLMProvider()\n\tif shouldReturn {\n\t\treturn\n\t}\n\topenaiApiKey := \"\"\n\topenaiGenerationModel := \"\"\n\tif strings.ToLower(llmProvider) == \"openai\" {\n\t\t// if openaiApiKey is not provided, ask for it\n\t\t// ask for OpenAI API key\n\t\topenaiApiKey, shouldReturn = getOpenaiApiKey()\n\t\tif shouldReturn {\n\t\t\treturn\n\t\t}\n\n\t\t// check if OpenAI API key is valid\n\t\tshouldReturn = validateOpenaiApiKey(openaiApiKey)\n\t\tif shouldReturn {\n\t\t\treturn\n\t\t}\n\n\t\t// ask for OpenAI generation model\n\t\tpterm.Print(\"\\n\")\n\t\topenaiGenerationModel, shouldReturn = getOpenaiGenerationModel()\n\t\tif shouldReturn {\n\t\t\treturn\n\t\t}\n\n\t\t// prepare config.yaml file for OpenAI\n\t\terr := utils.PrepareConfigFileForOpenAI(projectDir, openaiGenerationModel)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t}\n\n\t// ask for telemetry consent\n\tpterm.Print(\"\\n\")\n\ttelemetryEnabled, err := evaluateTelemetryPreferences()\n\n\tif err != nil {\n\t\tpterm.Error.Println(\"Failed to get API key\")\n\t\tpanic(err)\n\t}\n\n\t// check if docker daemon is running, if not, open it and loop to check again\n\tpterm.Info.Println(\"Checking if Docker daemon is running\")\n\tfor {\n\t\t_, err = utils.CheckDockerDaemonRunning()\n\t\tif err == nil {\n\t\t\tbreak\n\t\t}\n\n\t\tpterm.Info.Println(\"Docker daemon is not running, opening Docker Desktop\")\n\t\terr = utils.OpenDockerDaemon()\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\n\t\ttime.Sleep(5 * time.Second)\n\t}\n\n\t// download docker-compose file and env file template for Wren AI\n\tpterm.Info.Println(\"Downloading docker-compose file and env file\")\n\t// find an available port\n\tuiPort := utils.FindAvailablePort(3000)\n\taiPort := utils.FindAvailablePort(5555)\n\n\tvar localStorage string\n\tif config.IsDbtEnabled() {\n\t\tlocalStorage, err = processDbtProject(projectDir)\n\t\tif err != nil {\n\t\t\tpterm.Error.Println(\"Failed to process dbt project:\", err)\n\t\t\tpanic(err)\n\t\t}\n\t} else {\n\t\tlocalStorage = \"\"\n\t}\n\t// process dbt project conversion\n\n\terr = utils.PrepareDockerFiles(\n\t\topenaiApiKey,\n\t\topenaiGenerationModel,\n\t\tuiPort,\n\t\taiPort,\n\t\tprojectDir,\n\t\ttelemetryEnabled,\n\t\tllmProvider,\n\t\tplatform,\n\t\tlocalStorage,\n\t)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// launch Wren AI\n\tpterm.Info.Println(\"Launching Wren AI\")\n\tconst projectName string = \"wrenai\"\n\terr = utils.RunDockerCompose(projectName, projectDir, llmProvider)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tpterm.Info.Println(\"Wren AI is starting, please wait for a moment...\")\n\tuiUrl := fmt.Sprintf(\"http://localhost:%d\", uiPort)\n\taiUrl := fmt.Sprintf(\"http://localhost:%d\", aiPort)\n\t// wait until checking if CheckUIServiceStarted return without error\n\t// if timeout 2 minutes, panic\n\ttimeoutTime := time.Now().Add(2 * time.Minute)\n\tfor {\n\t\tif time.Now().After(timeoutTime) {\n\t\t\tpanic(\"Timeout\")\n\t\t}\n\n\t\t// check if ui is ready\n\t\terr := utils.CheckUIServiceStarted(uiUrl)\n\t\tif err == nil {\n\t\t\tpterm.Info.Println(\"UI Service is ready\")\n\t\t\tbreak\n\t\t}\n\t\ttime.Sleep(5 * time.Second)\n\t}\n\n\t// wait until checking if CheckWrenAIStarted return without error\n\t// if timeout 30 minutes, panic\n\ttimeoutTime = time.Now().Add(30 * time.Minute)\n\tfor {\n\t\tif time.Now().After(timeoutTime) {\n\t\t\tpanic(\"Timeout\")\n\t\t}\n\n\t\t// check if ai service is ready\n\t\terr := utils.CheckAIServiceStarted(aiUrl)\n\t\tif err == nil {\n\t\t\tpterm.Info.Println(\"AI Service is Ready\")\n\t\t\tbreak\n\t\t}\n\t\ttime.Sleep(5 * time.Second)\n\t}\n\n\t// open browser\n\tpterm.Info.Println(\"Opening browser\")\n\t_ = utils.Openbrowser(uiUrl)\n\n\tpterm.Info.Println(\"You can now safely close this terminal window\")\n\tvar dummy string\n\t_, _ = fmt.Scanf(\"%s\", &dummy)\n}\n\nfunc getOpenaiGenerationModel() (string, bool) {\n\t// get openai generation model from initialize arguments\n\topenaiGenerationModel := config.GetOpenaiGenerationModel()\n\tif openaiGenerationModel == \"\" {\n\t\t// not provided in args, ask user to provide openai generation model\n\t\topenaiGenerationModel, _ = askForGenerationModel()\n\t} else {\n\t\t// validate if input args is a valid generation model\n\t\tpterm.Info.Println(\"OpenAI generation model is provided\")\n\t\tvalidModels := map[string]bool{\n\t\t\t\"gpt-4.1\":      true,\n\t\t\t\"gpt-4.1-mini\": true,\n\t\t\t\"gpt-4.1-nano\": true,\n\t\t\t\"gpt-5\":        true,\n\t\t\t\"gpt-5-mini\":   true,\n\t\t\t\"gpt-5-nano\":   true,\n\t\t}\n\t\tif !validModels[openaiGenerationModel] {\n\t\t\tpterm.Error.Println(\"Invalid generation model\", openaiGenerationModel)\n\t\t\treturn \"\", true\n\t\t}\n\t}\n\treturn openaiGenerationModel, false\n}\n\nfunc getOpenaiApiKey() (string, bool) {\n\t// get openai api key from initialize arguments\n\topenaiApiKey := config.GetOpenaiAPIKey()\n\n\tif openaiApiKey == \"\" {\n\t\t// not provided in args, ask user to provide openai api key\n\t\tpterm.Print(\"\\n\")\n\t\topenaiApiKey, _ = askForAPIKey()\n\t} else {\n\t\t// validate if input args is a valid API key\n\t\tif !strings.HasPrefix(openaiApiKey, \"sk-\") {\n\t\t\tpterm.Error.Println(\"Invalid API key, API key should start with 'sk-'\")\n\t\t\treturn \"\", true\n\t\t}\n\t\tpterm.Info.Println(\"OpenAI API key is provided\")\n\t}\n\treturn openaiApiKey, false\n}\n\nfunc getLLMProvider() (string, bool) {\n\t// get llm provider from initialize arguments\n\tllmProvider := config.GetLLMProvider()\n\tif llmProvider == \"\" {\n\t\t// not provided in args, ask user to provide llm provider\n\t\tresult, err := askForLLMProvider()\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tllmProvider = result\n\t} else {\n\t\t// validate if input args is a valid LLM provider\n\t\tvalidProvider := map[string]bool{\n\t\t\t\"openai\": true,\n\t\t\t\"custom\": true,\n\t\t}\n\t\tif !validProvider[llmProvider] {\n\t\t\tpterm.Error.Println(\"Invalid LLM provider\", llmProvider, \"valid values are: openai, custom\")\n\t\t\treturn \"\", true\n\t\t}\n\t}\n\treturn llmProvider, false\n}\n\nfunc validateOpenaiApiKey(apiKey string) bool {\n\t// validate if input api key is valid by sending a hello request\n\tpterm.Info.Println(\"Sending a hello request to OpenAI...\")\n\tclient := openai.NewClient(apiKey)\n\tresp, err := client.CreateChatCompletion(\n\t\tcontext.Background(),\n\t\topenai.ChatCompletionRequest{\n\t\t\tModel: openai.GPT4oMini20240718,\n\t\t\tMessages: []openai.ChatCompletionMessage{\n\t\t\t\t{\n\t\t\t\t\tRole:    openai.ChatMessageRoleUser,\n\t\t\t\t\tContent: \"Hello!\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t)\n\n\t// insufficient credit balance error\n\tif err != nil {\n\t\tpterm.Error.Println(\"Invalid API key\", err)\n\t\t_, _ = fmt.Scanln()\n\t\treturn true\n\t}\n\n\tpterm.Info.Println(\"Valid API key, Response:\", resp.Choices[0].Message.Content)\n\treturn false\n}\n\nfunc getDbtProfileAndTarget() (string, string, error) {\n\t// ask for profile name and target\n\tprofileName, err := askForDbtProfileName()\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to get dbt profile name: %w\", err)\n\t}\n\n\t// if profile name is empty, doesn't ask for target\n\tvar target string\n\tif profileName == \"\" {\n\t\ttarget = \"\" // use default target\n\t} else {\n\t\ttarget, err = askForDbtTarget()\n\t\tif err != nil {\n\t\t\treturn \"\", \"\", fmt.Errorf(\"failed to get dbt target: %w\", err)\n\t\t}\n\t}\n\treturn profileName, target, nil\n}\n\nfunc processDbtProject(projectDir string) (string, error) {\n\t// ask for dbt project path\n\tdbtProjectPath, err := askForDbtProjectPath()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to get dbt project path: %w\", err)\n\t}\n\n\t// if user provides empty path, skip dbt conversion\n\tif strings.TrimSpace(dbtProjectPath) == \"\" {\n\t\tpterm.Info.Println(\"Skipping dbt project conversion\")\n\t\treturn \".\", nil // return default local storage path\n\t}\n\n\t// create target directory in project dir\n\ttargetDir := filepath.Join(projectDir, \"target\")\n\terr = os.MkdirAll(targetDir, 0750)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to create target directory: %w\", err)\n\t}\n\n\tprofileName, target, err := getDbtProfileAndTarget()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\t// Ask the user whether to include staging models\n\tincludeStagingModels, err := askForIncludeStagingModels()\n\tif err != nil {\n\t\tpterm.Warning.Println(\"Could not get staging model preference, defaulting to 'No'.\")\n\t\tincludeStagingModels = false\n\t}\n\n\t// Use the core conversion function from dbt package, passing the user's choice\n\tresult, err := DbtConvertProject(dbtProjectPath, targetDir, profileName, target, true, includeStagingModels)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to convert dbt project: %w\", err)\n\t}\n\n\tpterm.Info.Printf(\"Successfully processed dbt project to target directory: %s\\n\", targetDir)\n\n\treturn result.LocalStoragePath, nil\n}\n"
  },
  {
    "path": "wren-launcher/config/config.go",
    "content": "package config\n\nimport (\n\t\"flag\"\n\t\"runtime\"\n)\n\n// Platform constants\nconst (\n\tplatformLinuxAmd64 = \"linux/amd64\"\n\tplatformLinuxArm64 = \"linux/arm64\"\n)\n\n// private variable within the config package\nvar disableTelemetry bool\nvar openaiAPIKey string\nvar openaiGenerationModel string\nvar llmProvider string\nvar experimentalEngineRustVersion bool\nvar platform string\nvar enableDbt bool\n\n// InitFlags initializes the flag\nfunc InitFlags() {\n\tflag.BoolVar(&disableTelemetry, \"disable-telemetry\", false, \"Disable telemetry if set to true\")\n\tflag.StringVar(&llmProvider, \"llm-provider\", \"\", \"The LLM provider to use, valid values are: openai, custom\")\n\tflag.StringVar(&openaiAPIKey, \"openai-api-key\", \"\", \"The OPENAI API key\")\n\tflag.StringVar(&openaiGenerationModel, \"openai-generation-model\", \"\", \"The OPENAI generation model, valid values are: gpt-4.1, gpt-4.1-mini, gpt-4.1-nano\")\n\tflag.BoolVar(&experimentalEngineRustVersion, \"experimental-engine-rust-version\", true, \"Use the experimental Rust version of the Wren Engine\")\n\tflag.StringVar(&platform, \"platform\", GetPlatform(), \"The platform to use, valid values are: linux/amd64, linux/arm64\")\n\tflag.BoolVar(&enableDbt, \"enable-dbt\", false, \"Enable dbt support if set to true\")\n}\n\nfunc IsExperimentalEngineRustVersion() bool {\n\treturn experimentalEngineRustVersion\n}\n\nfunc GetPlatform() string {\n\tswitch runtime.GOOS {\n\tcase \"darwin\":\n\t\tif runtime.GOARCH == \"arm64\" {\n\t\t\treturn platformLinuxArm64\n\t\t}\n\t\treturn platformLinuxAmd64\n\tcase \"linux\":\n\t\tif runtime.GOARCH == \"arm64\" {\n\t\t\treturn platformLinuxArm64\n\t\t}\n\t\treturn platformLinuxAmd64\n\tcase \"windows\":\n\t\treturn platformLinuxAmd64 // Windows typically uses amd64\n\tdefault:\n\t\treturn platformLinuxAmd64 // Default to amd64 for unknown platforms\n\t}\n}\n\n// IsTelemetryDisabled exposes the state of the telemetry flag\nfunc IsTelemetryDisabled() bool {\n\treturn disableTelemetry\n}\n\nfunc GetOpenaiAPIKey() string {\n\treturn openaiAPIKey\n}\n\nfunc GetOpenaiGenerationModel() string {\n\treturn openaiGenerationModel\n}\n\nfunc GetLLMProvider() string {\n\treturn llmProvider\n}\n\nfunc IsDbtEnabled() bool {\n\treturn enableDbt\n}\n"
  },
  {
    "path": "wren-launcher/go.mod",
    "content": "module github.com/Canner/WrenAI/wren-launcher\n\ngo 1.24.9\n\nrequire (\n\tgithub.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be\n\tgithub.com/docker/compose/v2 v2.40.2\n\tgithub.com/docker/docker v28.5.1+incompatible\n\tgithub.com/google/uuid v1.6.0\n\tgithub.com/manifoldco/promptui v0.9.0\n\tgithub.com/sashabaranov/go-openai v1.36.0\n)\n\nrequire (\n\tatomicgo.dev/cursor v0.2.0 // indirect\n\tatomicgo.dev/keyboard v0.2.9 // indirect\n\tatomicgo.dev/schedule v0.1.0 // indirect\n\tgithub.com/AlecAivazis/survey/v2 v2.3.7 // indirect\n\tgithub.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect\n\tgithub.com/DefangLabs/secret-detector v0.0.0-20250403165618-22662109213e // indirect\n\tgithub.com/Masterminds/semver/v3 v3.4.0 // indirect\n\tgithub.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect\n\tgithub.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect\n\tgithub.com/aws/aws-sdk-go-v2 v1.30.3 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/config v1.27.27 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/credentials v1.17.27 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/sso v1.22.4 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect\n\tgithub.com/aws/smithy-go v1.20.3 // indirect\n\tgithub.com/beorn7/perks v1.0.1 // indirect\n\tgithub.com/buger/goterm v1.0.4 // indirect\n\tgithub.com/cenkalti/backoff/v4 v4.3.0 // indirect\n\tgithub.com/cespare/xxhash/v2 v2.3.0 // indirect\n\tgithub.com/compose-spec/compose-go/v2 v2.9.0 // indirect\n\tgithub.com/containerd/console v1.0.5 // indirect\n\tgithub.com/containerd/containerd/api v1.9.0 // indirect\n\tgithub.com/containerd/containerd/v2 v2.1.5 // indirect\n\tgithub.com/containerd/continuity v0.4.5 // indirect\n\tgithub.com/containerd/errdefs v1.0.0 // indirect\n\tgithub.com/containerd/errdefs/pkg v0.3.0 // indirect\n\tgithub.com/containerd/platforms v1.0.0-rc.1 // indirect\n\tgithub.com/containerd/ttrpc v1.2.7 // indirect\n\tgithub.com/containerd/typeurl/v2 v2.2.3 // indirect\n\tgithub.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect\n\tgithub.com/docker/buildx v0.29.1 // indirect\n\tgithub.com/docker/cli-docs-tool v0.10.0 // indirect\n\tgithub.com/docker/distribution v2.8.3+incompatible // indirect\n\tgithub.com/docker/docker-credential-helpers v0.9.3 // indirect\n\tgithub.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect\n\tgithub.com/docker/go-metrics v0.0.1 // indirect\n\tgithub.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203 // indirect\n\tgithub.com/emicklei/go-restful/v3 v3.11.0 // indirect\n\tgithub.com/fsnotify/fsevents v0.2.0 // indirect\n\tgithub.com/fvbommel/sortorder v1.1.0 // indirect\n\tgithub.com/fxamacker/cbor/v2 v2.7.0 // indirect\n\tgithub.com/go-openapi/jsonpointer v0.21.0 // indirect\n\tgithub.com/go-openapi/jsonreference v0.20.2 // indirect\n\tgithub.com/go-openapi/swag v0.23.0 // indirect\n\tgithub.com/go-viper/mapstructure/v2 v2.4.0 // indirect\n\tgithub.com/gofrs/flock v0.12.1 // indirect\n\tgithub.com/golang-jwt/jwt/v5 v5.2.2 // indirect\n\tgithub.com/golang/protobuf v1.5.4 // indirect\n\tgithub.com/google/gnostic-models v0.6.8 // indirect\n\tgithub.com/google/go-cmp v0.7.0 // indirect\n\tgithub.com/google/gofuzz v1.2.0 // indirect\n\tgithub.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect\n\tgithub.com/gookit/color v1.5.4 // indirect\n\tgithub.com/gorilla/mux v1.8.1 // indirect\n\tgithub.com/gorilla/websocket v1.5.0 // indirect\n\tgithub.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect\n\tgithub.com/hashicorp/errwrap v1.1.0 // indirect\n\tgithub.com/hashicorp/go-cleanhttp v0.5.2 // indirect\n\tgithub.com/hashicorp/go-multierror v1.1.1 // indirect\n\tgithub.com/hashicorp/go-version v1.7.0 // indirect\n\tgithub.com/in-toto/in-toto-golang v0.9.0 // indirect\n\tgithub.com/inconshreveable/mousetrap v1.1.0 // indirect\n\tgithub.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf // indirect\n\tgithub.com/jonboulle/clockwork v0.5.0 // indirect\n\tgithub.com/josharian/intern v1.0.0 // indirect\n\tgithub.com/json-iterator/go v1.1.12 // indirect\n\tgithub.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect\n\tgithub.com/klauspost/compress v1.18.0 // indirect\n\tgithub.com/lithammer/fuzzysearch v1.1.8 // indirect\n\tgithub.com/mailru/easyjson v0.7.7 // indirect\n\tgithub.com/mattn/go-colorable v0.1.13 // indirect\n\tgithub.com/mattn/go-isatty v0.0.20 // indirect\n\tgithub.com/mattn/go-runewidth v0.0.16 // indirect\n\tgithub.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect\n\tgithub.com/miekg/pkcs11 v1.1.1 // indirect\n\tgithub.com/mitchellh/go-ps v1.0.0 // indirect\n\tgithub.com/mitchellh/hashstructure/v2 v2.0.2 // indirect\n\tgithub.com/moby/buildkit v0.25.1 // indirect\n\tgithub.com/moby/go-archive v0.1.0 // indirect\n\tgithub.com/moby/locker v1.0.1 // indirect\n\tgithub.com/moby/patternmatcher v0.6.0 // indirect\n\tgithub.com/moby/spdystream v0.5.0 // indirect\n\tgithub.com/moby/sys/atomicwriter v0.1.0 // indirect\n\tgithub.com/moby/sys/capability v0.4.0 // indirect\n\tgithub.com/moby/sys/mountinfo v0.7.2 // indirect\n\tgithub.com/moby/sys/sequential v0.6.0 // indirect\n\tgithub.com/moby/sys/signal v0.7.1 // indirect\n\tgithub.com/moby/sys/symlink v0.3.0 // indirect\n\tgithub.com/moby/sys/user v0.4.0 // indirect\n\tgithub.com/moby/sys/userns v0.1.0 // indirect\n\tgithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect\n\tgithub.com/modern-go/reflect2 v1.0.2 // indirect\n\tgithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect\n\tgithub.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect\n\tgithub.com/pelletier/go-toml v1.9.5 // indirect\n\tgithub.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect\n\tgithub.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect\n\tgithub.com/prometheus/client_golang v1.22.0 // indirect\n\tgithub.com/prometheus/client_model v0.6.1 // indirect\n\tgithub.com/prometheus/common v0.62.0 // indirect\n\tgithub.com/prometheus/procfs v0.15.1 // indirect\n\tgithub.com/rivo/uniseg v0.4.4 // indirect\n\tgithub.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect\n\tgithub.com/secure-systems-lab/go-securesystemslib v0.6.0 // indirect\n\tgithub.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b // indirect\n\tgithub.com/shibumi/go-pathspec v1.3.0 // indirect\n\tgithub.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect\n\tgithub.com/spf13/cobra v1.10.1 // indirect\n\tgithub.com/spf13/pflag v1.0.10 // indirect\n\tgithub.com/stretchr/testify v1.11.1 // indirect\n\tgithub.com/theupdateframework/notary v0.7.0 // indirect\n\tgithub.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 // indirect\n\tgithub.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323 // indirect\n\tgithub.com/tonistiigi/fsutil v0.0.0-20250605211040-586307ad452f // indirect\n\tgithub.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0 // indirect\n\tgithub.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect\n\tgithub.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab // indirect\n\tgithub.com/x448/float16 v0.8.4 // indirect\n\tgithub.com/xhit/go-str2duration/v2 v2.1.0 // indirect\n\tgithub.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect\n\tgithub.com/zclconf/go-cty v1.17.0 // indirect\n\tgo.opentelemetry.io/auto/sdk v1.1.0 // indirect\n\tgo.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect\n\tgo.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect\n\tgo.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect\n\tgo.opentelemetry.io/proto/otlp v1.5.0 // indirect\n\tgo.uber.org/mock v0.6.0 // indirect\n\tgo.yaml.in/yaml/v3 v3.0.4 // indirect\n\tgolang.org/x/crypto v0.45.0 // indirect\n\tgolang.org/x/net v0.47.0 // indirect\n\tgolang.org/x/oauth2 v0.30.0 // indirect\n\tgolang.org/x/term v0.37.0 // indirect\n\tgolang.org/x/text v0.31.0 // indirect\n\tgoogle.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect\n\tgoogle.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect\n\tgoogle.golang.org/grpc v1.74.2 // indirect\n\tgoogle.golang.org/protobuf v1.36.9 // indirect\n\tgopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect\n\tgopkg.in/inf.v0 v0.9.1 // indirect\n\tgopkg.in/ini.v1 v1.67.0 // indirect\n\tk8s.io/api v0.32.3 // indirect\n\tk8s.io/apimachinery v0.32.3 // indirect\n\tk8s.io/client-go v0.32.3 // indirect\n\tk8s.io/klog/v2 v2.130.1 // indirect\n\tk8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect\n\tk8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect\n\tsigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect\n\tsigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect\n\tsigs.k8s.io/yaml v1.4.0 // indirect\n\ttags.cncf.io/container-device-interface v1.0.1 // indirect\n)\n\nrequire (\n\tgithub.com/Microsoft/go-winio v0.6.2 // indirect\n\tgithub.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect\n\tgithub.com/containerd/log v0.1.0 // indirect\n\tgithub.com/distribution/reference v0.6.0 // indirect\n\tgithub.com/docker/cli v28.5.1+incompatible\n\tgithub.com/docker/go-connections v0.6.0 // indirect\n\tgithub.com/docker/go-units v0.5.0 // indirect\n\tgithub.com/felixge/httpsnoop v1.0.4 // indirect\n\tgithub.com/go-logr/logr v1.4.3 // indirect\n\tgithub.com/go-logr/stdr v1.2.2 // indirect\n\tgithub.com/gogo/protobuf v1.3.2 // indirect\n\tgithub.com/mattn/go-shellwords v1.0.12 // indirect\n\tgithub.com/moby/docker-image-spec v1.3.1 // indirect\n\tgithub.com/moby/term v0.5.2 // indirect\n\tgithub.com/morikuni/aec v1.0.0 // indirect\n\tgithub.com/opencontainers/go-digest v1.0.0 // indirect\n\tgithub.com/opencontainers/image-spec v1.1.1 // indirect\n\tgithub.com/pkg/errors v0.9.1 // indirect\n\tgithub.com/pterm/pterm v0.12.79\n\tgithub.com/sirupsen/logrus v1.9.3 // indirect\n\tgo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect\n\tgo.opentelemetry.io/otel v1.36.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect\n\tgo.opentelemetry.io/otel/metric v1.36.0 // indirect\n\tgo.opentelemetry.io/otel/sdk v1.36.0 // indirect\n\tgo.opentelemetry.io/otel/trace v1.36.0 // indirect\n\tgolang.org/x/sync v0.18.0 // indirect\n\tgolang.org/x/sys v0.38.0 // indirect\n\tgolang.org/x/time v0.11.0 // indirect\n\tgopkg.in/yaml.v3 v3.0.1\n)\n"
  },
  {
    "path": "wren-launcher/go.sum",
    "content": "atomicgo.dev/assert v0.0.2 h1:FiKeMiZSgRrZsPo9qn/7vmr7mCsh5SZyXY4YGYiYwrg=\natomicgo.dev/assert v0.0.2/go.mod h1:ut4NcI3QDdJtlmAxQULOmA13Gz6e2DWbSAS8RUOmNYQ=\natomicgo.dev/cursor v0.2.0 h1:H6XN5alUJ52FZZUkI7AlJbUc1aW38GWZalpYRPpoPOw=\natomicgo.dev/cursor v0.2.0/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU=\natomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8=\natomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ=\natomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs=\natomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU=\ngithub.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=\ngithub.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=\ngithub.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=\ngithub.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=\ngithub.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=\ngithub.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=\ngithub.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=\ngithub.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=\ngithub.com/DefangLabs/secret-detector v0.0.0-20250403165618-22662109213e h1:rd4bOvKmDIx0WeTv9Qz+hghsgyjikFiPrseXHlKepO0=\ngithub.com/DefangLabs/secret-detector v0.0.0-20250403165618-22662109213e/go.mod h1:blbwPQh4DTlCZEfk1BLU4oMIhLda2U+A840Uag9DsZw=\ngithub.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs=\ngithub.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8=\ngithub.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII=\ngithub.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k=\ngithub.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI=\ngithub.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c=\ngithub.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE=\ngithub.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi+zB4=\ngithub.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY=\ngithub.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=\ngithub.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=\ngithub.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=\ngithub.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=\ngithub.com/Microsoft/hcsshim v0.13.0 h1:/BcXOiS6Qi7N9XqUcv27vkIuVOkBEcWstd2pMlWSeaA=\ngithub.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH6HAaclpEok=\ngithub.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=\ngithub.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=\ngithub.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d h1:hi6J4K6DKrR4/ljxn6SF6nURyu785wKMuQcjt7H3VCQ=\ngithub.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=\ngithub.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=\ngithub.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=\ngithub.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=\ngithub.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=\ngithub.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc=\ngithub.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=\ngithub.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=\ngithub.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=\ngithub.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=\ngithub.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=\ngithub.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk=\ngithub.com/aws/aws-sdk-go-v2 v1.30.3 h1:jUeBtG0Ih+ZIFH0F4UkmL9w3cSpaMv9tYYDbzILP8dY=\ngithub.com/aws/aws-sdk-go-v2 v1.30.3/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc=\ngithub.com/aws/aws-sdk-go-v2/config v1.27.27 h1:HdqgGt1OAP0HkEDDShEl0oSYa9ZZBSOmKpdpsDMdO90=\ngithub.com/aws/aws-sdk-go-v2/config v1.27.27/go.mod h1:MVYamCg76dFNINkZFu4n4RjDixhVr51HLj4ErWzrVwg=\ngithub.com/aws/aws-sdk-go-v2/credentials v1.17.27 h1:2raNba6gr2IfA0eqqiP2XiQ0UVOpGPgDSi0I9iAP+UI=\ngithub.com/aws/aws-sdk-go-v2/credentials v1.17.27/go.mod h1:gniiwbGahQByxan6YjQUMcW4Aov6bLC3m+evgcoN4r4=\ngithub.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 h1:KreluoV8FZDEtI6Co2xuNk/UqI9iwMrOx/87PBNIKqw=\ngithub.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11/go.mod h1:SeSUYBLsMYFoRvHE0Tjvn7kbxaUhl75CJi1sbfhMxkU=\ngithub.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 h1:SoNJ4RlFEQEbtDcCEt+QG56MY4fm4W8rYirAmq+/DdU=\ngithub.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15/go.mod h1:U9ke74k1n2bf+RIgoX1SXFed1HLs51OgUSs+Ph0KJP8=\ngithub.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 h1:C6WHdGnTDIYETAm5iErQUiVNsclNx9qbJVPIt03B6bI=\ngithub.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15/go.mod h1:ZQLZqhcu+JhSrA9/NXRm8SkDvsycE+JkV3WGY41e+IM=\ngithub.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=\ngithub.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=\ngithub.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 h1:dT3MqvGhSoaIhRseqw2I0yH81l7wiR2vjs57O51EAm8=\ngithub.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3/go.mod h1:GlAeCkHwugxdHaueRr4nhPuY+WW+gR8UjlcqzPr1SPI=\ngithub.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 h1:HGErhhrxZlQ044RiM+WdoZxp0p+EGM62y3L6pwA4olE=\ngithub.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17/go.mod h1:RkZEx4l0EHYDJpWppMJ3nD9wZJAa8/0lq9aVC+r2UII=\ngithub.com/aws/aws-sdk-go-v2/service/sso v1.22.4 h1:BXx0ZIxvrJdSgSvKTZ+yRBeSqqgPM89VPlulEcl37tM=\ngithub.com/aws/aws-sdk-go-v2/service/sso v1.22.4/go.mod h1:ooyCOXjvJEsUw7x+ZDHeISPMhtwI3ZCB7ggFMcFfWLU=\ngithub.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 h1:yiwVzJW2ZxZTurVbYWA7QOrAaCYQR72t0wrSBfoesUE=\ngithub.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4/go.mod h1:0oxfLkpz3rQ/CHlx5hB7H69YUpFiI1tql6Q6Ne+1bCw=\ngithub.com/aws/aws-sdk-go-v2/service/sts v1.30.3 h1:ZsDKRLXGWHk8WdtyYMoGNO7bTudrvuKpDKgMVRlepGE=\ngithub.com/aws/aws-sdk-go-v2/service/sts v1.30.3/go.mod h1:zwySh8fpFyXp9yOr/KVzxOl8SRqgf/IDw5aUt9UKFcQ=\ngithub.com/aws/smithy-go v1.20.3 h1:ryHwveWzPV5BIof6fyDvor6V3iUL7nTfiTKXHiW05nE=\ngithub.com/aws/smithy-go v1.20.3/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=\ngithub.com/beorn7/perks v0.0.0-20150223135152-b965b613227f/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=\ngithub.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=\ngithub.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=\ngithub.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=\ngithub.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=\ngithub.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw=\ngithub.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=\ngithub.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=\ngithub.com/buger/goterm v1.0.4 h1:Z9YvGmOih81P0FbVtEYTFF6YsSgxSUKEhf/f9bTMXbY=\ngithub.com/buger/goterm v1.0.4/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE=\ngithub.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0 h1:s7+5BfS4WFJoVF9pnB8kBk03S7pZXRdKamnV0FOl5Sc=\ngithub.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=\ngithub.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ=\ngithub.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=\ngithub.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o=\ngithub.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=\ngithub.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=\ngithub.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=\ngithub.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=\ngithub.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=\ngithub.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=\ngithub.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=\ngithub.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=\ngithub.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=\ngithub.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=\ngithub.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=\ngithub.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e85keuznYcH5rqI438v41pKcBl4ZxQ=\ngithub.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=\ngithub.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=\ngithub.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=\ngithub.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL2kskAlV9ckgEsNQXscjIaLiOYiZ75d4e94E6dcQ=\ngithub.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w=\ngithub.com/compose-spec/compose-go/v2 v2.9.0 h1:UHSv/QHlo6QJtrT4igF1rdORgIUhDo1gWuyJUoiNNIM=\ngithub.com/compose-spec/compose-go/v2 v2.9.0/go.mod h1:Oky9AZGTRB4E+0VbTPZTUu4Kp+oEMMuwZXZtPPVT1iE=\ngithub.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=\ngithub.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=\ngithub.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=\ngithub.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc=\ngithub.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=\ngithub.com/containerd/containerd/api v1.9.0 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0=\ngithub.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI=\ngithub.com/containerd/containerd/v2 v2.1.5 h1:pWSmPxUszaLZKQPvOx27iD4iH+aM6o0BoN9+hg77cro=\ngithub.com/containerd/containerd/v2 v2.1.5/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=\ngithub.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=\ngithub.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=\ngithub.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=\ngithub.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=\ngithub.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=\ngithub.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=\ngithub.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=\ngithub.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=\ngithub.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=\ngithub.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=\ngithub.com/containerd/nydus-snapshotter v0.15.2 h1:qsHI4M+Wwrf6Jr4eBqhNx8qh+YU0dSiJ+WPmcLFWNcg=\ngithub.com/containerd/nydus-snapshotter v0.15.2/go.mod h1:FfwH2KBkNYoisK/e+KsmNr7xTU53DmnavQHMFOcXwfM=\ngithub.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E=\ngithub.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=\ngithub.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y=\ngithub.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8=\ngithub.com/containerd/stargz-snapshotter v0.16.3 h1:zbQMm8dRuPHEOD4OqAYGajJJUwCeUzt4j7w9Iaw58u4=\ngithub.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8=\ngithub.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU=\ngithub.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ=\ngithub.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=\ngithub.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=\ngithub.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=\ngithub.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=\ngithub.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=\ngithub.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=\ngithub.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=\ngithub.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=\ngithub.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=\ngithub.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=\ngithub.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=\ngithub.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=\ngithub.com/docker/buildx v0.29.1 h1:58hxM5Z4mnNje3G5NKfULT9xCr8ooM8XFtlfUK9bKaA=\ngithub.com/docker/buildx v0.29.1/go.mod h1:J4EFv6oxlPiV1MjO0VyJx2u5tLM7ImDEl9zyB8d4wPI=\ngithub.com/docker/cli v28.5.1+incompatible h1:ESutzBALAD6qyCLqbQSEf1a/U8Ybms5agw59yGVc+yY=\ngithub.com/docker/cli v28.5.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=\ngithub.com/docker/cli-docs-tool v0.10.0 h1:bOD6mKynPQgojQi3s2jgcUWGp/Ebqy1SeCr9VfKQLLU=\ngithub.com/docker/cli-docs-tool v0.10.0/go.mod h1:5EM5zPnT2E7yCLERZmrDA234Vwn09fzRHP4aX1qwp1U=\ngithub.com/docker/compose/v2 v2.40.2 h1:h2bDBJkOuqmj93XvT2oI0ArPQonE0lGtWiILXdiXvbA=\ngithub.com/docker/compose/v2 v2.40.2/go.mod h1:CbSJpKGw20LInVsPjglZ8z7Squ3OBQOD7Ux5nkjGfIU=\ngithub.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=\ngithub.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=\ngithub.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=\ngithub.com/docker/docker v28.5.1+incompatible h1:Bm8DchhSD2J6PsFzxC35TZo4TLGR2PdW/E69rU45NhM=\ngithub.com/docker/docker v28.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=\ngithub.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=\ngithub.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=\ngithub.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=\ngithub.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q=\ngithub.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=\ngithub.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=\ngithub.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=\ngithub.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=\ngithub.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=\ngithub.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=\ngithub.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=\ngithub.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=\ngithub.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=\ngithub.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=\ngithub.com/dvsekhvalnov/jose2go v0.0.0-20170216131308-f21a8cedbbae/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM=\ngithub.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203 h1:XBBHcIb256gUJtLmY22n99HaZTz+r2Z51xUPi01m3wg=\ngithub.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203/go.mod h1:E1jcSv8FaEny+OP/5k9UxZVw9YFWGj7eI4KR/iOBqCg=\ngithub.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=\ngithub.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=\ngithub.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=\ngithub.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=\ngithub.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=\ngithub.com/fsnotify/fsevents v0.2.0 h1:BRlvlqjvNTfogHfeBOFvSC9N0Ddy+wzQCQukyoD7o/c=\ngithub.com/fsnotify/fsevents v0.2.0/go.mod h1:B3eEk39i4hz8y1zaWS/wPrAP4O6wkIl7HQwKBr1qH/w=\ngithub.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=\ngithub.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw=\ngithub.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=\ngithub.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=\ngithub.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=\ngithub.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=\ngithub.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=\ngithub.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=\ngithub.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=\ngithub.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=\ngithub.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=\ngithub.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=\ngithub.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=\ngithub.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=\ngithub.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=\ngithub.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=\ngithub.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=\ngithub.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=\ngithub.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=\ngithub.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=\ngithub.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=\ngithub.com/go-sql-driver/mysql v1.3.0 h1:pgwjLi/dvffoP9aabwkT3AKpXQM93QARkjFhDDqC1UE=\ngithub.com/go-sql-driver/mysql v1.3.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=\ngithub.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=\ngithub.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=\ngithub.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=\ngithub.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=\ngithub.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=\ngithub.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=\ngithub.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=\ngithub.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=\ngithub.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=\ngithub.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=\ngithub.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=\ngithub.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=\ngithub.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=\ngithub.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=\ngithub.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=\ngithub.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=\ngithub.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=\ngithub.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=\ngithub.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93 h1:jc2UWq7CbdszqeH6qu1ougXMIUBfSy8Pbh/anURYbGI=\ngithub.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=\ngithub.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=\ngithub.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=\ngithub.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=\ngithub.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=\ngithub.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=\ngithub.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=\ngithub.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=\ngithub.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=\ngithub.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=\ngithub.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=\ngithub.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=\ngithub.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=\ngithub.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=\ngithub.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=\ngithub.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=\ngithub.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=\ngithub.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=\ngithub.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=\ngithub.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=\ngithub.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA=\ngithub.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M=\ngithub.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=\ngithub.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=\ngithub.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=\ngithub.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=\ngithub.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=\ngithub.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=\ngithub.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=\ngithub.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=\ngithub.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=\ngithub.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=\ngithub.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=\ngithub.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=\ngithub.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=\ngithub.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=\ngithub.com/in-toto/in-toto-golang v0.9.0 h1:tHny7ac4KgtsfrG6ybU8gVOZux2H8jN05AXJ9EBM1XU=\ngithub.com/in-toto/in-toto-golang v0.9.0/go.mod h1:xsBVrVsHNsB61++S6Dy2vWosKhuA3lUTQd+eF9HdeMo=\ngithub.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=\ngithub.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=\ngithub.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=\ngithub.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s=\ngithub.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4=\ngithub.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8 h1:CZkYfurY6KGhVtlalI4QwQ6T0Cu6iuY3e0x5RLu96WE=\ngithub.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo=\ngithub.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d h1:jRQLvyVGL+iVtDElaEIDdKwpPqUIZJfzkNLV34htpEc=\ngithub.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=\ngithub.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=\ngithub.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=\ngithub.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=\ngithub.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=\ngithub.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=\ngithub.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=\ngithub.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=\ngithub.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=\ngithub.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=\ngithub.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=\ngithub.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=\ngithub.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=\ngithub.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=\ngithub.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=\ngithub.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=\ngithub.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=\ngithub.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=\ngithub.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=\ngithub.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=\ngithub.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=\ngithub.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=\ngithub.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=\ngithub.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=\ngithub.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=\ngithub.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=\ngithub.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=\ngithub.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=\ngithub.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=\ngithub.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=\ngithub.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=\ngithub.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=\ngithub.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=\ngithub.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=\ngithub.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=\ngithub.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=\ngithub.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=\ngithub.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM=\ngithub.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=\ngithub.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=\ngithub.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=\ngithub.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=\ngithub.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=\ngithub.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=\ngithub.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=\ngithub.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=\ngithub.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=\ngithub.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=\ngithub.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=\ngithub.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=\ngithub.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=\ngithub.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=\ngithub.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=\ngithub.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=\ngithub.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=\ngithub.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=\ngithub.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=\ngithub.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=\ngithub.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=\ngithub.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=\ngithub.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=\ngithub.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=\ngithub.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=\ngithub.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=\ngithub.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=\ngithub.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=\ngithub.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=\ngithub.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=\ngithub.com/moby/buildkit v0.25.1 h1:j7IlVkeNbEo+ZLoxdudYCHpmTsbwKvhgc/6UJ/mY/o8=\ngithub.com/moby/buildkit v0.25.1/go.mod h1:phM8sdqnvgK2y1dPDnbwI6veUCXHOZ6KFSl6E164tkc=\ngithub.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=\ngithub.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=\ngithub.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=\ngithub.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo=\ngithub.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=\ngithub.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=\ngithub.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=\ngithub.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=\ngithub.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=\ngithub.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=\ngithub.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=\ngithub.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=\ngithub.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk=\ngithub.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=\ngithub.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=\ngithub.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=\ngithub.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=\ngithub.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=\ngithub.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0=\ngithub.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8=\ngithub.com/moby/sys/symlink v0.3.0 h1:GZX89mEZ9u53f97npBy4Rc3vJKj7JBDj/PN2I22GrNU=\ngithub.com/moby/sys/symlink v0.3.0/go.mod h1:3eNdhduHmYPcgsJtZXW1W4XUJdZGBIkttZ8xKqPUJq0=\ngithub.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=\ngithub.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=\ngithub.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=\ngithub.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=\ngithub.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=\ngithub.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=\ngithub.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=\ngithub.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=\ngithub.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=\ngithub.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=\ngithub.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=\ngithub.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=\ngithub.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=\ngithub.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=\ngithub.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=\ngithub.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=\ngithub.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=\ngithub.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=\ngithub.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=\ngithub.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=\ngithub.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=\ngithub.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=\ngithub.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=\ngithub.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=\ngithub.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=\ngithub.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=\ngithub.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=\ngithub.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=\ngithub.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=\ngithub.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=\ngithub.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=\ngithub.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=\ngithub.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=\ngithub.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=\ngithub.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=\ngithub.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=\ngithub.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=\ngithub.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=\ngithub.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=\ngithub.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=\ngithub.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=\ngithub.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=\ngithub.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/prometheus/client_golang v0.9.0-pre1.0.20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=\ngithub.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=\ngithub.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=\ngithub.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=\ngithub.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=\ngithub.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=\ngithub.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=\ngithub.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=\ngithub.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=\ngithub.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=\ngithub.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=\ngithub.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=\ngithub.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=\ngithub.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=\ngithub.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=\ngithub.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=\ngithub.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=\ngithub.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=\ngithub.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=\ngithub.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=\ngithub.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=\ngithub.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=\ngithub.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI=\ngithub.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg=\ngithub.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE=\ngithub.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU=\ngithub.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE=\ngithub.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8=\ngithub.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s=\ngithub.com/pterm/pterm v0.12.79 h1:lH3yrYMhdpeqX9y5Ep1u7DejyHy7NSQg9qrBjF9dFT4=\ngithub.com/pterm/pterm v0.12.79/go.mod h1:1v/gzOF1N0FsjbgTHZ1wVycRkKiatFvJSJC4IGaQAAo=\ngithub.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=\ngithub.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=\ngithub.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=\ngithub.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=\ngithub.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=\ngithub.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=\ngithub.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=\ngithub.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=\ngithub.com/sashabaranov/go-openai v1.36.0 h1:fcSrn8uGuorzPWCBp8L0aCR95Zjb/Dd+ZSML0YZy9EI=\ngithub.com/sashabaranov/go-openai v1.36.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=\ngithub.com/secure-systems-lab/go-securesystemslib v0.6.0 h1:T65atpAVCJQK14UA57LMdZGpHi4QYSH/9FZyNGqMYIA=\ngithub.com/secure-systems-lab/go-securesystemslib v0.6.0/go.mod h1:8Mtpo9JKks/qhPG4HGZ2LGMvrPbzuxwfz/f/zLfEWkk=\ngithub.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=\ngithub.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=\ngithub.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b h1:h+3JX2VoWTFuyQEo87pStk/a99dzIO1mM9KxIyLPGTU=\ngithub.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc=\ngithub.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI=\ngithub.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE=\ngithub.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=\ngithub.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=\ngithub.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=\ngithub.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=\ngithub.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=\ngithub.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=\ngithub.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=\ngithub.com/spdx/tools-golang v0.5.5 h1:61c0KLfAcNqAjlg6UNMdkwpMernhw3zVRwDZ2x9XOmk=\ngithub.com/spdx/tools-golang v0.5.5/go.mod h1:MVIsXx8ZZzaRWNQpUDhC4Dud34edUYJYecciXgrw5vE=\ngithub.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94 h1:JmfC365KywYwHB946TTiQWEb8kqPY+pybPLoGE9GgVk=\ngithub.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=\ngithub.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=\ngithub.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=\ngithub.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=\ngithub.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431 h1:XTHrT015sxHyJ5FnQ0AeemSspZWaDq7DoTRW0EVsDCE=\ngithub.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=\ngithub.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=\ngithub.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=\ngithub.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c h1:2EejZtjFjKJGk71ANb+wtFK5EjUzUkEM3R0xnp559xg=\ngithub.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=\ngithub.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=\ngithub.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=\ngithub.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=\ngithub.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=\ngithub.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=\ngithub.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=\ngithub.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=\ngithub.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=\ngithub.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=\ngithub.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c=\ngithub.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw=\ngithub.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 h1:QB54BJwA6x8QU9nHY3xJSZR2kX9bgpZekRKGkLTmEXA=\ngithub.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375/go.mod h1:xRroudyp5iVtxKqZCrA6n2TLFRBf8bmnjr1UD4x+z7g=\ngithub.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323 h1:r0p7fK56l8WPequOaR3i9LBqfPtEdXIQbUTzT55iqT4=\ngithub.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323/go.mod h1:3Iuxbr0P7D3zUzBMAZB+ois3h/et0shEz0qApgHYGpY=\ngithub.com/tonistiigi/fsutil v0.0.0-20250605211040-586307ad452f h1:MoxeMfHAe5Qj/ySSBfL8A7l1V+hxuluj8owsIEEZipI=\ngithub.com/tonistiigi/fsutil v0.0.0-20250605211040-586307ad452f/go.mod h1:BKdcez7BiVtBvIcef90ZPc6ebqIWr4JWD7+EvLm6J98=\ngithub.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0 h1:2f304B10LaZdB8kkVEaoXvAMVan2tl9AiK4G0odjQtE=\ngithub.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0/go.mod h1:278M4p8WsNh3n4a1eqiFcV2FGk7wE5fwUpUom9mK9lE=\ngithub.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0=\ngithub.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk=\ngithub.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab h1:H6aJ0yKQ0gF49Qb2z5hI1UHxSQt4JMyxebFR15KnApw=\ngithub.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc=\ngithub.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo=\ngithub.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=\ngithub.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=\ngithub.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=\ngithub.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=\ngithub.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=\ngithub.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=\ngithub.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=\ngithub.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=\ngithub.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=\ngithub.com/zclconf/go-cty v1.17.0 h1:seZvECve6XX4tmnvRzWtJNHdscMtYEx5R7bnnVyd/d0=\ngithub.com/zclconf/go-cty v1.17.0/go.mod h1:wqFzcImaLTI6A5HfsRwB0nj5n0MRZFwmey8YoFPPs3U=\ngo.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=\ngo.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=\ngo.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=\ngo.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=\ngo.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=\ngo.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=\ngo.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0 h1:0tY123n7CdWMem7MOVdKOt0YfshufLCwfE5Bob+hQuM=\ngo.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0/go.mod h1:CosX/aS4eHnG9D7nESYpV753l4j9q5j3SL/PUYd2lR8=\ngo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=\ngo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=\ngo.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=\ngo.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=\ngo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 h1:QcFwRrZLc82r8wODjvyCbP7Ifp3UANaBSmhDSFjnqSc=\ngo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0/go.mod h1:CXIWhUomyWBG/oY2/r/kLp6K/cmx9e/7DLpBuuGdLCA=\ngo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0 h1:0NIXxOCFx+SKbhCVxwl3ETG8ClLPAa0KuKV6p3yhxP8=\ngo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0/go.mod h1:ChZSJbbfbl/DcRZNc9Gqh6DYGlfjw4PvO1pEOZH1ZsE=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk=\ngo.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=\ngo.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=\ngo.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=\ngo.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=\ngo.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=\ngo.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=\ngo.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=\ngo.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=\ngo.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=\ngo.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=\ngo.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=\ngo.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=\ngo.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=\ngo.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=\ngo.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=\ngo.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=\ngolang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=\ngolang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=\ngolang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=\ngolang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=\ngolang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=\ngolang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=\ngolang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=\ngolang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=\ngolang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=\ngolang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=\ngolang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=\ngolang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=\ngolang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=\ngolang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=\ngolang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=\ngolang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=\ngolang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=\ngolang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=\ngolang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=\ngolang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=\ngolang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=\ngolang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=\ngolang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=\ngolang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=\ngolang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=\ngolang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=\ngolang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=\ngolang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=\ngolang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=\ngolang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=\ngolang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=\ngolang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=\ngolang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=\ngolang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=\ngolang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=\ngolang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=\ngolang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=\ngolang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=\ngolang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=\ngolang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=\ngolang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngoogle.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a h1:SGktgSolFCo75dnHJF2yMvnns6jCmHFJ0vE4Vn2JKvQ=\ngoogle.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a/go.mod h1:a77HrdMjoeKbnd2jmgcWdaS++ZLZAEq3orIOAEIKiVw=\ngoogle.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE=\ngoogle.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=\ngoogle.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=\ngoogle.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=\ngoogle.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=\ngoogle.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=\ngoogle.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=\ngopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=\ngopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=\ngopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9aII=\ngopkg.in/cenkalti/backoff.v2 v2.2.1/go.mod h1:S0QdOvT2AlerfSBkp0O+dk+bbIMaNbEmVk876gPCthU=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=\ngopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=\ngopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=\ngopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=\ngopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=\ngopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=\ngopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=\ngopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=\ngopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=\ngopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1 h1:d4KQkxAaAiRY2h5Zqis161Pv91A37uZyJOx73duwUwM=\ngopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1/go.mod h1:WbjuEoo1oadwzQ4apSDU+JTvmllEHtsNHS6y7vFc7iw=\ngopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=\ngopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=\ngopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=\ngotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=\nk8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls=\nk8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k=\nk8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=\nk8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=\nk8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU=\nk8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY=\nk8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=\nk8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=\nk8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=\nk8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=\nk8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=\nk8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=\nsigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=\nsigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=\nsigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA=\nsigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=\nsigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=\nsigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=\ntags.cncf.io/container-device-interface v1.0.1 h1:KqQDr4vIlxwfYh0Ed/uJGVgX+CHAkahrgabg6Q8GYxc=\ntags.cncf.io/container-device-interface v1.0.1/go.mod h1:JojJIOeW3hNbcnOH2q0NrWNha/JuHoDZcmYxAZwb2i0=\n"
  },
  {
    "path": "wren-launcher/main.go",
    "content": "package main\n\nimport (\n\t\"flag\"\n\t\"os\"\n\n\t\"github.com/Canner/WrenAI/wren-launcher/commands\"\n\t\"github.com/Canner/WrenAI/wren-launcher/config\"\n\t\"github.com/pterm/pterm\"\n)\n\nfunc main() {\n\tconfig.InitFlags()\n\n\t// Check if we have subcommands\n\tif len(os.Args) > 1 {\n\t\tswitch os.Args[1] {\n\t\tcase \"dbt-auto-convert\":\n\t\t\t// Remove the subcommand from args so flag.Parse() works correctly\n\t\t\tos.Args = append([]string{os.Args[0]}, os.Args[2:]...)\n\t\t\tcommands.DbtAutoConvert()\n\t\t\treturn\n\t\tcase \"help\", \"-h\", \"--help\":\n\t\t\tshowHelp()\n\t\t\treturn\n\t\t}\n\t}\n\n\t// help flag\n\thelp := flag.Bool(\"h\", false, \"Display help\")\n\tflag.Parse()\n\n\tif *help {\n\t\tshowHelp()\n\t\treturn\n\t}\n\n\tcommands.Launch()\n}\n\nfunc showHelp() {\n\tpterm.Info.Println(\"Usage of Wren launcher:\")\n\tpterm.Info.Println(\"\")\n\tpterm.Info.Println(\"Commands:\")\n\tpterm.Info.Println(\"  (default)                                        Launch Wren AI service\")\n\tpterm.Info.Println(\"  dbt-auto-convert --path --output [--profile] [--target]    Auto-convert dbt project to WrenDataSource and Wren MDL\")\n\tpterm.Info.Println(\"\")\n\tpterm.Info.Println(\"Flags:\")\n\tflag.PrintDefaults()\n\tpterm.Info.Println(\"\")\n\tpterm.Info.Println(\"Examples:\")\n\tpterm.Info.Println(\"  wren-launcher                                              # Launch Wren AI\")\n\tpterm.Info.Println(\"  wren-launcher dbt-auto-convert --path /path/to/dbt --output ./output    # Auto-convert dbt project\")\n\tpterm.Info.Println(\"  wren-launcher dbt-auto-convert --path /path/to/dbt --output ./output --profile my_profile --target dev # Convert with specific profile/target\")\n}\n"
  },
  {
    "path": "wren-launcher/utils/docker.go",
    "content": "package utils\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"path\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/Canner/WrenAI/wren-launcher/config\"\n\t\"github.com/docker/cli/cli/command\"\n\t\"github.com/docker/cli/cli/flags\"\n\tcmdCompose \"github.com/docker/compose/v2/cmd/compose\"\n\t\"github.com/docker/compose/v2/pkg/api\"\n\t\"github.com/docker/compose/v2/pkg/compose\"\n\t\"github.com/docker/docker/api/types/container\"\n\t\"github.com/google/uuid\"\n\t\"github.com/pterm/pterm\"\n)\n\nconst (\n\t// please change the version when the version is updated\n\tWREN_PRODUCT_VERSION\tstring = \"0.29.1\"\n\tDOCKER_COMPOSE_YAML_URL string = \"https://raw.githubusercontent.com/Canner/WrenAI/\" + WREN_PRODUCT_VERSION + \"/docker/docker-compose.yaml\"\n\tDOCKER_COMPOSE_ENV_URL  string = \"https://raw.githubusercontent.com/Canner/WrenAI/\" + WREN_PRODUCT_VERSION + \"/docker/.env.example\"\n\tAI_SERVICE_CONFIG_URL   string = \"https://raw.githubusercontent.com/Canner/WrenAI/\" + WREN_PRODUCT_VERSION + \"/docker/config.example.yaml\"\n)\n\nvar generationModelToModelName = map[string]string{\n\t\"gpt-4.1\":      \"gpt-4.1-2025-04-14\",\n\t\"gpt-4.1-mini\": \"gpt-4.1-mini-2025-04-14\",\n\t\"gpt-4.1-nano\": \"gpt-4.1-nano-2025-04-14\",\n\t\"gpt-5\":        \"gpt-5-2025-08-07\",\n\t\"gpt-5-mini\":   \"gpt-5-mini-2025-08-07\",\n\t\"gpt-5-nano\":   \"gpt-5-nano-2025-08-07\",\n}\n\nfunc replaceEnvFileContent(content string, projectDir string, openaiApiKey string, openAIGenerationModel string, hostPort int, aiPort int, userUUID string, telemetryEnabled bool, platform string, localStorage string) string {\n\t// replace PLATFORM\n\treg := regexp.MustCompile(`PLATFORM=(.*)`)\n\tstr := reg.ReplaceAllString(content, \"PLATFORM=\"+platform)\n\n\t// replace PROJECT_DIR\n\treg = regexp.MustCompile(`PROJECT_DIR=(.*)`)\n\tstr = reg.ReplaceAllString(str, \"PROJECT_DIR=\"+projectDir)\n\n\t// replace SHOULD_FORCE_DEPLOY\n\treg = regexp.MustCompile(`SHOULD_FORCE_DEPLOY=(.*)`)\n\tstr = reg.ReplaceAllString(str, \"SHOULD_FORCE_DEPLOY=1\")\n\n\t// replace OPENAI_API_KEY\n\treg = regexp.MustCompile(`OPENAI_API_KEY=(.*)`)\n\tstr = reg.ReplaceAllString(str, \"OPENAI_API_KEY=\"+openaiApiKey)\n\n\t// replace GENERATION_MODEL\n\t// it seems like using for telemetry to know the model, might be we can remove this in the future and provide a endpoint to get the information\n\treg = regexp.MustCompile(`GENERATION_MODEL=(.*)`)\n\tstr = reg.ReplaceAllString(str, \"GENERATION_MODEL=\"+openAIGenerationModel)\n\n\t// replace USER_UUID\n\treg = regexp.MustCompile(`USER_UUID=(.*)`)\n\tstr = reg.ReplaceAllString(str, \"USER_UUID=\"+userUUID)\n\n\t// replace PORT\n\treg = regexp.MustCompile(`HOST_PORT=(.*)`)\n\tstr = reg.ReplaceAllString(str, \"HOST_PORT=\"+fmt.Sprintf(\"%d\", hostPort))\n\n\t// replace AI_SERVICE_FORWARD_PORT\n\treg = regexp.MustCompile(`AI_SERVICE_FORWARD_PORT=(.*)`)\n\tstr = reg.ReplaceAllString(str, \"AI_SERVICE_FORWARD_PORT=\"+fmt.Sprintf(\"%d\", aiPort))\n\n\t// replace TELEMETRY_ENABLED\n\treg = regexp.MustCompile(`TELEMETRY_ENABLED=(.*)`)\n\tstr = reg.ReplaceAllString(str, \"TELEMETRY_ENABLED=\"+fmt.Sprintf(\"%t\", telemetryEnabled))\n\n\t// replace EXPERIMENTAL_ENGINE_RUST_VERSION\n\treg = regexp.MustCompile(`EXPERIMENTAL_ENGINE_RUST_VERSION=(.*)`)\n\tstr = reg.ReplaceAllString(str, \"EXPERIMENTAL_ENGINE_RUST_VERSION=\"+fmt.Sprintf(\"%t\", config.IsExperimentalEngineRustVersion()))\n\n\t// replace LOCAL_STORAGE\n\tif localStorage == \"\" {\n\t\tlocalStorage = \".\"\n\t}\n\treg = regexp.MustCompile(`LOCAL_STORAGE=(.*)`)\n\tstr = reg.ReplaceAllString(str, \"LOCAL_STORAGE=\"+localStorage)\n\n\treturn str\n}\n\nfunc downloadFile(filepath string, url string) error {\n\t// Get the data\n\tresp, err := http.Get(url) // #nosec G107 -- URL is from trusted source constants\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer func() { _ = resp.Body.Close() }()\n\n\t// Create the file\n\tout, err := os.Create(filepath) // #nosec G304 -- filepath is controlled by application\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer func() { _ = out.Close() }()\n\n\t// Write the body to file\n\t_, err = io.Copy(out, resp.Body)\n\treturn err\n}\n\nfunc CheckDockerDaemonRunning() (bool, error) {\n\tctx := context.Background()\n\tdockerCli, err := command.NewDockerCli()\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\terr = dockerCli.Initialize(flags.NewClientOptions())\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\t_, err = dockerCli.Client().Info(ctx)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\treturn true, nil\n}\n\nfunc prepareUserUUID(projectDir string) (string, error) {\n\twrenRC := WrenRC{projectDir}\n\terr := wrenRC.Set(\"USER_UUID\", uuid.New().String(), false)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tuserUUID, err := wrenRC.Read(\"USER_UUID\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn userUUID, nil\n}\n\nfunc PrepareConfigFileForOpenAI(projectDir string, generationModel string) error {\n\t// download config.yaml file\n\tconfigPath := path.Join(projectDir, \"config.yaml\")\n\tpterm.Info.Println(\"Downloading config.yaml file to\", configPath)\n\terr := downloadFile(configPath, AI_SERVICE_CONFIG_URL)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// read the config.yaml file\n\tcontent, err := os.ReadFile(configPath) // #nosec G304 -- configPath is controlled by application\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// replace the generation model in config.yaml\n\tconfig := string(content)\n\t// gpt-4.1-nano is the default model, so we don't need to replace it\n\tif generationModel != \"gpt-4.1-nano\" {\n\t\tconfig = strings.ReplaceAll(config, \"litellm_llm.default\", \"litellm_llm.\"+generationModelToModelName[generationModel])\n\t}\n\n\t// write back to config.yaml\n\terr = os.WriteFile(configPath, []byte(config), 0600)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc mergeEnvContent(newEnvFile string, envFileContent string) (string, error) {\n\t// Check if .env file does not exist\n\tif _, err := os.Stat(newEnvFile); err != nil {\n\t\treturn envFileContent, nil\n\t}\n\n\t// File exists, read existing content\n\texistingContent, err := os.ReadFile(newEnvFile) // #nosec G304 -- newEnvFile is controlled by application\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\t// Split both contents into lines\n\texistingLines := strings.Split(string(existingContent), \"\\n\")\n\tnewLines := strings.Split(envFileContent, \"\\n\")\n\n\t// Create map of existing env vars\n\texistingEnvVars := make(map[string]string)\n\t// Helper function to parse env var line\n\tparseEnvVar := func(line string) (string, string, bool) {\n\t\tline = strings.TrimSpace(line)\n\t\tif line == \"\" || strings.HasPrefix(line, \"#\") {\n\t\t\treturn \"\", \"\", false\n\t\t}\n\t\tparts := strings.SplitN(line, \"=\", 2)\n\t\tif len(parts) != 2 {\n\t\t\treturn \"\", \"\", false\n\t\t}\n\t\treturn parts[0], parts[1], true\n\t}\n\n\t// Parse existing env vars\n\tfor _, line := range existingLines {\n\t\tif key, val, ok := parseEnvVar(line); ok {\n\t\t\texistingEnvVars[key] = val\n\t\t}\n\t}\n\n\t// Merge with new values\n\tfor _, line := range newLines {\n\t\tif key, val, ok := parseEnvVar(line); ok && val != \"\" {\n\t\t\texistingEnvVars[key] = val\n\t\t}\n\t}\n\n\t// Build merged content\n\tvar mergedLines []string\n\tfor _, line := range newLines {\n\t\tline = strings.TrimSpace(line)\n\t\tif line == \"\" || strings.HasPrefix(line, \"#\") {\n\t\t\tmergedLines = append(mergedLines, line)\n\t\t\tcontinue\n\t\t}\n\t\tif key, _, ok := parseEnvVar(line); ok {\n\t\t\tif val, exists := existingEnvVars[key]; exists {\n\t\t\t\tmergedLines = append(mergedLines, key+\"=\"+val)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Update envFileContent with merged content\n\tenvFileContent = strings.Join(mergedLines, \"\\n\")\n\treturn envFileContent, nil\n}\n\nfunc PrepareDockerFiles(openaiApiKey string, openaiGenerationModel string, hostPort int, aiPort int, projectDir string, telemetryEnabled bool, llmProvider string, platform string, localStorage string) error {\n\t// download docker-compose file\n\tcomposeFile := path.Join(projectDir, \"docker-compose.yaml\")\n\tpterm.Info.Println(\"Downloading docker-compose file to\", composeFile)\n\terr := downloadFile(composeFile, DOCKER_COMPOSE_YAML_URL)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif strings.ToLower(llmProvider) == \"openai\" {\n\t\tuserUUID, err := prepareUserUUID(projectDir)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// download env file\n\t\tenvExampleFile := path.Join(projectDir, \".env.example\")\n\t\tpterm.Info.Println(\"Downloading env file to\", envExampleFile)\n\t\terr = downloadFile(envExampleFile, DOCKER_COMPOSE_ENV_URL)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// read the file\n\t\tenvExampleFileContent, err := os.ReadFile(envExampleFile) // #nosec G304 -- envExampleFile is controlled by application\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// replace the content with regex\n\t\tenvFileContent := replaceEnvFileContent(\n\t\t\tstring(envExampleFileContent),\n\t\t\tprojectDir,\n\t\t\topenaiApiKey,\n\t\t\topenaiGenerationModel,\n\t\t\thostPort,\n\t\t\taiPort,\n\t\t\tuserUUID,\n\t\t\ttelemetryEnabled,\n\t\t\tplatform,\n\t\t\tlocalStorage,\n\t\t)\n\t\tnewEnvFile := getEnvFilePath(projectDir)\n\n\t\t// merge the env file content with the existing env file\n\t\tenvFileContent, err = mergeEnvContent(newEnvFile, envFileContent)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// write the file\n\t\terr = os.WriteFile(newEnvFile, []byte(envFileContent), 0600)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// remove the old env file\n\t\terr = os.Remove(envExampleFile)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else if strings.ToLower(llmProvider) == \"custom\" {\n\t\t// if .env file does not exist, return error\n\t\tif _, err := os.Stat(getEnvFilePath(projectDir)); os.IsNotExist(err) {\n\t\t\treturn fmt.Errorf(\".env file does not exist, please download the env file from %s to ~/.wrenai, rename it to .env and fill in the required information\", DOCKER_COMPOSE_ENV_URL)\n\t\t}\n\n\t\t// if config.yaml file does not exist, return error\n\t\tif _, err := os.Stat(getConfigFilePath(projectDir)); os.IsNotExist(err) {\n\t\t\treturn fmt.Errorf(\"config.yaml file does not exist, please download the config.yaml file from %s to ~/.wrenai, rename it to config.yaml and fill in the required information\", AI_SERVICE_CONFIG_URL)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc getEnvFilePath(projectDir string) string {\n\treturn path.Join(projectDir, \".env\")\n}\n\nfunc getConfigFilePath(projectDir string) string {\n\treturn path.Join(projectDir, \"config.yaml\")\n}\n\n// RunDockerCompose starts Docker services for a project using docker-compose.\n// It initializes Docker CLI, checks Docker engine availability, and runs docker-compose up.\n// For custom LLM providers, it specifically recreates the wren-ai-service container.\n//\n// Parameters:\n//   - projectName: Name of the Docker Compose project\n//   - projectDir: Directory containing docker-compose.yaml and .env files\n//   - llmProvider: Type of LLM provider (e.g., \"custom\" or default)\n//\n// Returns an error if Docker initialization, configuration, or service startup fails.\n// Supports both default and custom LLM provider configurations.\n//\n// Example:\n//\n//\terr := RunDockerCompose(\"wren\", \"/path/to/project\", \"openai\")\nfunc RunDockerCompose(projectName string, projectDir string, llmProvider string) error {\n\tctx := context.Background()\n\tcomposeFilePath := path.Join(projectDir, \"docker-compose.yaml\")\n\tenvFile := path.Join(projectDir, \".env\")\n\tenvFiles := []string{envFile}\n\tconfigPaths := []string{composeFilePath}\n\n\t// docker-compose up\n\tdockerCli, err := command.NewDockerCli()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = dockerCli.Initialize(flags.NewClientOptions())\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// check if docker engine is running\n\t_, err = dockerCli.Client().Info(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Create the compose API service instance with the Docker cli\n\tapiService := compose.NewComposeService(dockerCli)\n\n\t// Create a default project options struct\n\tprojectOptions := cmdCompose.ProjectOptions{\n\t\tProjectName: projectName,\n\t\tConfigPaths: configPaths,\n\t\tWorkDir:     projectDir,\n\t\tEnvFiles:    envFiles,\n\t}\n\n\t// Turn projectOptions into a project with default values\n\tprojectType, _, err := projectOptions.ToProject(ctx, dockerCli, []string{})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Run the up command\n\terr = apiService.Up(ctx, projectType, api.UpOptions{})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif strings.ToLower(llmProvider) == \"custom\" {\n\t\t// Create up options for force recreating only wren-ai-service\n\t\tupOptions := api.UpOptions{\n\t\t\tCreate: api.CreateOptions{\n\t\t\t\tRecreate: api.RecreateForce,\n\t\t\t\tServices: []string{\"wren-ai-service\"},\n\t\t\t},\n\t\t}\n\n\t\t// Run the up command with specific options for wren-ai-service\n\t\terr = apiService.Up(ctx, projectType, upOptions)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc listProcess() ([]container.Summary, error) {\n\tctx := context.Background()\n\tdockerCli, err := command.NewDockerCli()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\terr = dockerCli.Initialize(flags.NewClientOptions())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcontainerListOptions := container.ListOptions{\n\t\tAll: true,\n\t}\n\n\tcontainers, err := dockerCli.Client().ContainerList(ctx, containerListOptions)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn containers, nil\n}\n\nfunc findWrenUIContainer() (container.Summary, error) {\n\tcontainers, err := listProcess()\n\tif err != nil {\n\t\treturn container.Summary{}, err\n\t}\n\n\tfor _, cont := range containers {\n\t\t// return if com.docker.compose.project == wrenai && com.docker.compose.service=wren-ui\n\t\tif cont.Labels[\"com.docker.compose.project\"] == \"wrenai\" && cont.Labels[\"com.docker.compose.service\"] == \"wren-ui\" {\n\t\t\treturn cont, nil\n\t\t}\n\t}\n\n\treturn container.Summary{}, fmt.Errorf(\"WrenUI container not found\")\n}\n\nfunc findAIServiceContainer() (container.Summary, error) {\n\tcontainers, err := listProcess()\n\tif err != nil {\n\t\treturn container.Summary{}, err\n\t}\n\n\tfor _, cont := range containers {\n\t\tif cont.Labels[\"com.docker.compose.project\"] == \"wrenai\" && cont.Labels[\"com.docker.compose.service\"] == \"wren-ai-service\" {\n\t\t\treturn cont, nil\n\t\t}\n\t}\n\n\treturn container.Summary{}, fmt.Errorf(\"WrenAI service container not found\")\n}\n\nfunc IfPortUsedByWrenUI(port int) bool {\n\tcontainer, err := findWrenUIContainer()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\tfor _, containerPort := range container.Ports {\n\t\tif port >= 0 && port <= 65535 && containerPort.PublicPort == uint16(port) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc IfPortUsedByAIService(port int) bool {\n\tcontainer, err := findAIServiceContainer()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\tfor _, containerPort := range container.Ports {\n\t\tif port >= 0 && port <= 65535 && containerPort.PublicPort == uint16(port) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc CheckUIServiceStarted(url string) error {\n\t// check response from localhost:3000\n\tresp, err := http.Get(url) // #nosec G107 -- URL is validated by application logic\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer func() { _ = resp.Body.Close() }()\n\n\tif resp.StatusCode != 200 {\n\t\treturn fmt.Errorf(\"wren AI is not started yet\")\n\t}\n\treturn nil\n}\n\nfunc CheckAIServiceStarted(url string) error {\n\t// health check\n\tresp, err := http.Get(url) // #nosec G107 -- URL is validated by application logic\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer func() { _ = resp.Body.Close() }()\n\n\tif resp.StatusCode != 200 {\n\t\treturn fmt.Errorf(\"AI service is not started yet\")\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "wren-launcher/utils/docker_test.go",
    "content": "package utils\n\nimport (\n\t\"testing\"\n)\n\nfunc TestFindWrenUIContainer(t *testing.T) {\n\tcontainer, error := findWrenUIContainer()\n\tif error != nil {\n\t\tt.Errorf(\"Error: %v\", error)\n\t}\n\n\tt.Logf(\"Container ID: %s\", container.ID)\n\tt.Logf(\"Container Name: %s\", container.Names[0])\n\tfor _, port := range container.Ports {\n\t\tt.Logf(\"Container IP: %s\", port.IP)\n\t\tt.Logf(\"Container Port Type: %s\", port.Type)\n\t\tt.Logf(\"Container PublicPort: %d\", port.PublicPort)\n\t\tt.Logf(\"Container PrivatePort: %d\", port.PrivatePort)\n\t}\n}\n"
  },
  {
    "path": "wren-launcher/utils/network.go",
    "content": "package utils\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\n\t\"github.com/pterm/pterm\"\n)\n\nfunc ifPortUsed(port int) bool {\n\t// listen on port to check if it's used\n\t_, err := net.Listen(\"tcp\", fmt.Sprintf(\":%d\", port))\n\treturn err != nil\n}\n\nfunc FindAvailablePort(defaultPort int) int {\n\t// Find an available port\n\t// Start from the default port and increment by 1\n\t// until a port is found that is not in use\n\tfor port := defaultPort; port < defaultPort+100; port++ {\n\t\tpterm.Info.Printf(\"Checking if port %d is available\\n\", port)\n\n\t\tif !ifPortUsed(port) {\n\t\t\t// Return the port if it's not used\n\t\t\treturn port\n\t\t} else if IfPortUsedByWrenUI(port) || IfPortUsedByAIService(port) {\n\t\t\t// Return the port if it's used, but used by wrenAI\n\t\t\treturn port\n\t\t}\n\t}\n\n\t// If no port is available, return 0\n\treturn 0\n}\n"
  },
  {
    "path": "wren-launcher/utils/os.go",
    "content": "package utils\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"runtime\"\n)\n\ntype OS int\n\nconst (\n\t// Windows is the Windows operating system.\n\tWindows OS = iota\n\t// Darwin is the Apple operating system.\n\tDarwin\n\t// Linux is the Linux operating system.\n\tLinux\n\t// Unknown is an unknown operating system.\n\tUnknown\n)\n\nfunc DetectOS() OS {\n\tswitch runtime.GOOS {\n\tcase \"windows\":\n\t\treturn Windows\n\tcase \"darwin\":\n\t\treturn Darwin\n\tcase \"linux\":\n\t\treturn Linux\n\tdefault:\n\t\treturn Unknown\n\t}\n}\n\nfunc Openbrowser(url string) error {\n\tvar err error\n\n\tswitch DetectOS() {\n\tcase Linux:\n\t\terr = exec.Command(\"xdg-open\", url).Start()\n\tcase Windows:\n\t\terr = exec.Command(\"rundll32\", \"url.dll,FileProtocolHandler\", url).Start()\n\tcase Darwin:\n\t\terr = exec.Command(\"open\", url).Start()\n\tdefault:\n\t\terr = fmt.Errorf(\"unsupported platform\")\n\t}\n\treturn err\n}\n\nfunc OpenDockerDaemon() error {\n\tvar err error\n\n\tswitch DetectOS() {\n\tcase Linux:\n\t\t// systemctl --user start docker-desktop\n\t\terr = exec.Command(\"systemctl\", \"--user\", \"start\", \"docker-desktop\").Run()\n\tcase Windows:\n\t\t// C:\\Program Files\\Docker\\Docker\\Docker Desktop.exe\n\t\terr = exec.Command(\"C:\\\\Program Files\\\\Docker\\\\Docker\\\\Docker Desktop.exe\").Run()\n\tcase Darwin:\n\t\tcmd := exec.Command(\"open\", \"-a\", \"Docker\")\n\t\terr = cmd.Run()\n\tdefault:\n\t\terr = fmt.Errorf(\"unsupported platform\")\n\t}\n\treturn err\n}\n"
  },
  {
    "path": "wren-launcher/utils/rc.go",
    "content": "// the wrenrc.go package is responsible for writing and reading rcfile\n// the rc file should located in ~/.wrenai/.wrenrc\n// should have  public methods \"append\" and \"read\"(read by key or all)\n// the structure of the rcfile is a env like file with key value pairs,\n// eg:\n//   \"foo=bar\"\n//   \"bar=baz\"\n\npackage utils\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"os\"\n\t\"path\"\n\t\"strings\"\n)\n\ntype WrenRC struct {\n\trcFileDir string\n}\n\nfunc (w *WrenRC) getWrenRcFilePath() string {\n\treturn path.Join(w.rcFileDir, \".wrenrc\")\n}\n\nfunc (w *WrenRC) ensureRcFile() (string, error) {\n\t// ensure folder created\n\terr := os.MkdirAll(w.rcFileDir, 0750)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\t// ensure file created\n\trcFilePath := w.getWrenRcFilePath()\n\t_, err = os.Stat(rcFilePath)\n\tif os.IsNotExist(err) {\n\t\tf, err := os.Create(rcFilePath) // #nosec G304 -- rcFilePath is controlled by application\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\t_ = f.Close()\n\t}\n\treturn rcFilePath, nil\n}\n\nfunc (w *WrenRC) parseInto() (map[string]string, error) {\n\trcFilePath, err := w.ensureRcFile()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tf, err := os.Open(rcFilePath) // #nosec G304 -- rcFilePath is controlled by application\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer func() { _ = f.Close() }()\n\n\t// prepare a map to store the key value pairs\n\tm := make(map[string]string)\n\t// read the file line by line\n\tr := bufio.NewReader(f)\n\tlineno := 0\n\tfor {\n\t\t// read the line\n\t\tline, err := r.ReadString('\\n')\n\t\tif err != nil {\n\t\t\tif err.Error() != \"EOF\" {\n\t\t\t\treturn nil, err // return an error if it's not EOF\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t\tlineno++\n\t\tline = strings.Trim(line, \" \\t\\v\\r\\n\")\n\n\t\t// Skip empty lines and comments\n\t\tif line == \"\" || line[0] == '#' || line[0] == ';' {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Split the line into key and value based on the '=' character\n\t\tparts := strings.SplitN(line, \"=\", 2)\n\t\tif len(parts) != 2 {\n\t\t\treturn nil, fmt.Errorf(\"syntax error on line %d: no '=' character found\", lineno)\n\t\t}\n\n\t\t// Trim spaces around key and value\n\t\tkey := strings.TrimSpace(parts[0])\n\t\tvalue := strings.TrimSpace(parts[1])\n\n\t\t// Store the key-value pair in the map\n\t\tm[key] = value\n\t}\n\n\treturn m, nil\n}\n\n// set a key value pair to the rc file\nfunc (w *WrenRC) Set(key string, value string, override bool) error {\n\t// get the parsed key value pairs\n\tm, err := w.parseInto()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// put the new key value pair in the map\n\t_, ok := m[key]\n\tif ok && !override {\n\t\t// simply return without error\n\t\treturn nil\n\t}\n\tm[key] = value\n\n\t// open the rc file for writing\n\terr = w.write(m)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n// overrite the rc file with the given key value pairs\nfunc (w *WrenRC) write(m map[string]string) error {\n\trcFilePath := w.getWrenRcFilePath()\n\tf, err := os.Create(rcFilePath) // #nosec G304 -- rcFilePath is controlled by application\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer func() { _ = f.Close() }()\n\n\tfor k, v := range m {\n\t\t_, err = fmt.Fprintf(f, \"%s=%s\\n\", k, v)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// read the value of a key from the rc file\nfunc (w *WrenRC) Read(key string) (string, error) {\n\tm, err := w.parseInto()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tv, ok := m[key]\n\tif !ok {\n\t\treturn \"\", nil\n\t}\n\n\treturn v, nil\n}\n"
  },
  {
    "path": "wren-launcher/utils/rc_test.go",
    "content": "package utils\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestReadWriteRcFile(t *testing.T) {\n\tdir, err := os.MkdirTemp(\"\", \"wrenrc\")\n\tif err != nil {\n\t\tt.Errorf(\"Error: %v\", err)\n\t}\n\tdefer func() { _ = os.RemoveAll(dir) }()\n\n\t// create a WrenRC struct\n\tw := WrenRC{dir}\n\t// write a key value pair to the rc file\n\terr = w.Set(\"key\", \"value\", false)\n\tif err != nil {\n\t\tt.Errorf(\"Error: %v\", err)\n\t}\n\n\t// read the value of the key from the rc file\n\tv, err := w.Read(\"key\")\n\tif err != nil {\n\t\tt.Errorf(\"Error: %v\", err)\n\t}\n\tif v != \"value\" {\n\t\tt.Errorf(\"Expected value: value, got: %s\", v)\n\t}\n}\n\n// read the value of a non-existent key from the rc file\nfunc TestSet(t *testing.T) {\n\t// create a temp directory\n\tdir, err := os.MkdirTemp(\"\", \"wrenrc\")\n\tif err != nil {\n\t\tt.Errorf(\"Error: %v\", err)\n\t}\n\tdefer func() { _ = os.RemoveAll(dir) }()\n\n\t// create a WrenRC struct\n\tw := WrenRC{dir}\n\t// read the value of a non-existent key from the rc file\n\tv, err := w.Read(\"key\")\n\tif err != nil {\n\t\tt.Errorf(\"Error: %v\", err)\n\t}\n\tif v != \"\" {\n\t\tt.Errorf(\"Expected value: \\\"\\\", got: %s\", v)\n\t}\n}\n"
  },
  {
    "path": "wren-mdl/mdl.schema.json",
    "content": "{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"$id\": \"https://raw.githubusercontent.com/Canner/WrenAI/main/wren-mdl/mdl.schema.json\",\n  \"title\": \"WrenMDL Manifest Schema\",\n  \"description\": \"A schema for WrenMDL manifest file\",\n  \"$defs\": {\n    \"column\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"name\": {\n          \"description\": \"the name of the column\",\n          \"type\": \"string\",\n          \"minLength\": 1\n        },\n        \"type\": {\n          \"description\": \"the type of the column\",\n          \"type\": \"string\",\n          \"minLength\": 1\n        },\n        \"relationship\": {\n          \"description\": \"the relationship used by the column. If the type is a relationship, this field is required\",\n          \"type\": \"string\"\n        },\n        \"isCalculated\": {\n          \"description\": \"whether the column is calculated or not. If the column expression used relationship, this field is required\",\n          \"type\": \"boolean\"\n        },\n        \"notNull\": {\n          \"description\": \"whether the column is not null or not\",\n          \"type\": \"boolean\"\n        },\n        \"expression\": {\n          \"description\": \"the expression of the column. If the column is calculated, this field is required\",\n          \"type\": [\"string\", \"null\"]\n        },\n        \"isHidden\": {\n          \"description\": \"whether the column is hidden or not\",\n          \"type\": \"boolean\"\n        },\n        \"columnLevelAccessControl\": {\n          \"description\": \"the access-control rule for the column\",\n          \"type\": \"object\",\n          \"properties\": {\n            \"name\": {\n              \"description\": \"the name of the access-control rule\",\n              \"type\": \"string\"\n            },\n            \"operator\": {\n              \"description\": \"the operator of the access-control rule\",\n              \"type\": \"string\",\n              \"enum\": [\n                \"EQUALS\",\n                \"NOT_EQUALS\",\n                \"GREATER_THAN\",\n                \"LESS_THAN\",\n                \"GREATER_THAN_OR_EQUALS\",\n                \"LESS_THAN_OR_EQUALS\"\n              ]\n            },\n            \"requiredProperties\": {\n              \"description\": \"the required properties for the access-control rule\",\n              \"type\": \"array\",\n              \"items\": {\n                \"$ref\": \"#/$defs/sessionProperty\"\n              },\n              \"minItems\": 1,\n              \"maxItems\": 1\n            },\n            \"threshold\": {\n              \"description\": \"the threshold value of the access-control rule\",\n              \"type\": \"object\",\n              \"properties\": {\n                \"value\": {\n                  \"description\": \"the value of the threshold\",\n                  \"type\": \"string\"\n                },\n                \"dataType\": {\n                  \"description\": \"the data type of the threshold\",\n                  \"type\": \"string\",\n                  \"enum\": [\n                    \"NUMERIC\",\n                    \"STRING\"\n                  ]\n                }\n              },\n              \"required\": [\"value\", \"dataType\"],\n              \"additionalProperties\": false\n            }\n          },\n          \"required\": [\"name\", \"operator\", \"requiredProperties\"],\n          \"additionalProperties\": false\n        },\n        \"properties\": {\n          \"description\": \"the customize properties of the column\",\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"type\": \"string\"\n          }\n        }\n      },\n      \"required\": [\"name\", \"type\"],\n      \"additionalProperties\": false\n    },\n    \"sessionProperty\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"name\": {\n          \"description\": \"the name of the session property\",\n          \"type\": \"string\",\n          \"minLength\": 1\n        },\n        \"required\": {\n          \"description\": \"whether the session property is required or not\",\n          \"type\": \"boolean\"\n        },\n        \"defaultExpr\": {\n          \"description\": \"the default SQL expression of the session property\",\n          \"type\": [\"string\", \"null\"]\n        }\n      },\n      \"required\": [\"name\", \"required\"],\n      \"additionalProperties\": false\n    }\n  },\n  \"type\": \"object\",\n  \"properties\": {\n    \"$schema\": {\n      \"description\": \"the schema of WrenMDL\",\n      \"type\": \"string\",\n      \"const\": \"https://raw.githubusercontent.com/Canner/WrenAI/main/wren-mdl/mdl.schema.json\"\n    },\n    \"catalog\": {\n      \"description\": \"the catalog name of WrenMDL\",\n      \"type\": \"string\",\n      \"minLength\": 1\n    },\n    \"schema\": {\n      \"description\": \"the schema name of WrenMDL\",\n      \"type\": \"string\",\n      \"minLength\": 1\n    },\n    \"sampleDataFolder\": {\n      \"description\": \"the folder path for sample data\",\n      \"type\": \"string\",\n      \"minLength\": 1\n    },\n    \"dataSource\": {\n      \"description\": \"the data source type (case insensitive). Valid values are: BIGQUERY, CLICKHOUSE, CANNER, TRINO, MSSQL, MYSQL, POSTGRES, SNOWFLAKE, DUCKDB, LOCAL_FILE, S3_FILE, GCS_FILE, MINIO_FILE, ORACLE, ATHENA, REDSHIFT\",\n      \"type\": \"string\",\n      \"pattern\": \"^(?:[Bb][Ii][Gg][Qq][Uu][Ee][Rr][Yy]|[Cc][Ll][Ii][Cc][Kk][Hh][Oo][Uu][Ss][Ee]|[Cc][Aa][Nn][Nn][Ee][Rr]|[Tt][Rr][Ii][Nn][Oo]|[Mm][Ss][Ss][Qq][Ll]|[Mm][Yy][Ss][Qq][Ll]|[Pp][Oo][Ss][Tt][Gg][Rr][Ee][Ss]|[Ss][Nn][Oo][Ww][Ff][Ll][Aa][Kk][Ee]|[Dd][Uu][Cc][Kk][Dd][Bb]|[Ll][Oo][Cc][Aa][Ll]_[Ff][Ii][Ll][Ee]|[Ss]3_[Ff][Ii][Ll][Ee]|[Gg][Cc][Ss]_[Ff][Ii][Ll][Ee]|[Mm][Ii][Nn][Ii][Oo]_[Ff][Ii][Ll][Ee]|[Oo][Rr][Aa][Cc][Ll][Ee]|[Aa][Tt][Hh][Ee][Nn][Aa]|[Rr][Ee][Dd][Ss][Hh][Ii][Ff][Tt])$\",\n      \"minLength\": 1\n    },\n    \"models\": {\n      \"description\": \"the list of models\",\n      \"type\": \"array\",\n      \"unevaluatedItems\": false,\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"name\": {\n            \"description\": \"the name of the model\",\n            \"type\": \"string\",\n            \"minLength\": 1\n          },\n          \"refSql\": {\n            \"description\": \"(WIP) the sql reference of the model\",\n            \"type\": \"string\", \n            \"minLength\": 1\n          },\n          \"baseObject\": {\n            \"description\": \"(WIP) the base object of the model\",\n            \"type\": \"string\",\n            \"minLength\": 1\n          },\n          \"tableReference\": {\n            \"description\": \"the table reference of the model\",\n            \"type\": \"object\",\n            \"properties\": {\n              \"catalog\": {\n                \"type\": \"string\"\n              },\n              \"schema\": {\n                \"type\": \"string\"\n              },\n              \"table\": {\n                \"type\": \"string\",\n                \"minLength\": 1\n              }\n            },\n            \"required\": [\"table\"]\n          },\n          \"columns\": {\n            \"description\": \"the list of columns\",\n            \"type\": \"array\",\n            \"items\": {\n              \"$ref\": \"#/$defs/column\"\n            }\n          },\n          \"primaryKey\": {\n            \"description\": \"the primary key of the model. It's required if the model is the one side of any OEN_TO_MANY or MANY_TO_ONE relationship\",\n            \"type\": \"string\"\n          },\n          \"cached\": {\n            \"description\": \"(WIP) whether the model is cached or not\",\n            \"type\": \"boolean\"\n          },\n          \"refreshTime\": {\n            \"description\": \"(WIP) the cache refresh time of the model\",\n            \"type\": \"string\",\n            \"pattern\": \"^\\\\s*(\\\\d+(?:\\\\.\\\\d+)?)\\\\s*([a-zA-Z]+)\\\\s*$\"\n          },\n          \"rowLevelAccessControls\": {\n            \"type\": \"array\",\n            \"items\": {\n              \"description\": \"the row-level access-control rule for the model\",\n              \"type\": \"object\",\n              \"properties\": {\n                \"name\": {\n                  \"description\": \"the name of the access-control rule\",\n                  \"type\": \"string\"\n                },\n                \"requiredProperties\": {\n                  \"description\": \"the required properties for the access-control rule\",\n                  \"type\": \"array\",\n                  \"items\": {\n                    \"$ref\": \"#/$defs/sessionProperty\"\n                  }\n                },\n                \"condition\": {\n                  \"description\": \"The condition of the access-control rule. A condition is a SQL expression that evaluates to true or false.\",\n                  \"type\": \"string\"\n                }\n              },\n              \"required\": [\"name\", \"requiredProperties\", \"condition\"],\n              \"additionalProperties\": false\n            }\n          },\n          \"properties\": {\n            \"description\": \"the customize properties of the model\",\n            \"type\": \"object\",\n            \"additionalProperties\": {\n              \"type\": [\"string\", \"number\", \"boolean\", \"object\", \"array\", \"null\"]\n            }\n          }\n        },\n        \"required\": [\"name\"],\n        \"oneOf\": [\n          { \"required\": [\"refSql\"] },\n          { \"required\": [\"baseObject\"] },\n          { \"required\": [\"tableReference\"] }\n        ],\n        \"additionalProperties\": false\n      }\n    },\n    \"relationships\": {\n      \"description\": \"the list of relationships\",\n      \"type\": \"array\",\n      \"unevaluatedItems\": false,\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"name\": {\n            \"description\": \"the name of the relationship\",\n            \"type\": \"string\",\n            \"minLength\": 1\n          },\n          \"models\": {\n            \"description\": \"the list of models\",\n            \"type\": \"array\",\n            \"items\": {\n              \"type\": \"string\",\n              \"minLength\": 1\n            },\n            \"minItems\": 2,\n            \"maxItems\": 2\n          },\n          \"joinType\": {\n            \"description\": \"the join type of the relationship\",\n            \"type\": \"string\",\n            \"enum\": [\"ONE_TO_ONE\", \"ONE_TO_MANY\", \"MANY_TO_ONE\", \"MANY_TO_MANY\"]\n          },\n          \"condition\": {\n            \"description\": \"the condition of the relationship\",\n            \"type\": \"string\",\n            \"minLength\": 1\n          },\n          \"properties\": {\n            \"description\": \"the customize properties of the relationship\",\n            \"type\": \"object\",\n            \"additionalProperties\": {\n              \"type\": [\"string\", \"number\", \"boolean\", \"object\", \"array\", \"null\"]\n            }\n          }\n        },\n        \"required\": [\"name\", \"models\", \"joinType\", \"condition\"]\n      }\n    },\n    \"metrics\": {\n      \"description\": \"(WIP) the list of metrics\",\n      \"type\": \"array\",\n      \"unevaluatedItems\": false,\n      \"items\": {\n        \"description\": \"(WIP) the metric\",\n        \"type\": \"object\",\n        \"properties\": {\n          \"name\": {\n            \"description\": \"the name of the metric\",\n            \"type\": \"string\",\n            \"minLength\": 1\n          },\n          \"baseObject\": {\n            \"description\": \"the base object of the metric\",\n            \"type\": \"string\",\n            \"minLength\": 1\n          },\n          \"dimension\": {\n            \"description\": \"the list of dimensions\",\n            \"type\": \"array\",\n            \"items\": {\n                \"$ref\": \"#/$defs/column\"\n            }\n          },\n          \"measure\": {\n            \"description\": \"the list of measures\",\n            \"type\": \"array\",\n            \"items\": {\n                \"$ref\": \"#/$defs/column\"\n            },\n            \"minItems\": 1\n          },\n          \"timeGrain\": {\n            \"description\": \"the time grain fields of the metric\",\n            \"type\": \"array\",\n            \"unevaluatedItems\": false,\n            \"items\": {\n              \"description\": \"the time grain field. It's should belong to the dimension fields\",\n              \"type\": \"object\",\n              \"properties\": {\n                \"name\": {\n                  \"description\": \"the name of the time grain field\",\n                  \"type\": \"string\",\n                  \"minLength\": 1\n                },\n                \"refColumn\": {\n                  \"description\": \"the reference column name of the time grain field\",\n                  \"type\": \"string\",\n                  \"minLength\": 1\n                },\n                \"dateParts\": {\n                  \"description\": \"the acceptable time units of the time grain field\",\n                  \"type\": \"array\",\n                  \"items\": {\n                    \"type\": \"string\",\n                    \"enum\": [\n                      \"YEAR\",\n                      \"QUARTER\",\n                      \"MONTH\",\n                      \"WEEK\",\n                      \"DAY\",\n                      \"HOUR\",\n                      \"MINUTE\",\n                      \"SECOND\"\n                    ]\n                  }\n                }\n              },\n              \"required\": [\"name\", \"refColumn\", \"dateParts\"]\n            }\n          },\n          \"cached\": {\n            \"type\": \"boolean\"\n          },\n          \"refreshTime\": {\n            \"type\": \"string\",\n            \"description\": \"the cache refresh time of the metric\",\n            \"pattern\": \"^\\\\s*(\\\\d+(?:\\\\.\\\\d+)?)\\\\s*([a-zA-Z]+)\\\\s*$\"\n          },\n          \"properties\": {\n            \"type\": \"object\",\n            \"additionalProperties\": {\n              \"type\": [\"string\", \"number\", \"boolean\", \"object\", \"array\", \"null\"]\n            }\n          }\n        },\n        \"required\": [\"name\", \"baseObject\", \"dimension\", \"measure\"]\n      }\n    },\n    \"views\": {\n      \"description\": \"the list of views\",\n      \"type\": \"array\",\n      \"unevaluatedItems\": false,\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"name\": {\n            \"description\": \"the name of the view\",\n            \"type\": \"string\",\n            \"minLength\": 1\n          },\n          \"statement\": {\n            \"description\": \"the sql statement of the view\",\n            \"type\": \"string\",\n            \"minLength\": 1\n          },\n          \"properties\": {\n            \"description\": \"the customize properties of the view\",\n            \"type\": \"object\",\n            \"additionalProperties\": {\n              \"type\": [\"string\", \"number\", \"boolean\", \"object\", \"array\", \"null\"]\n            }\n          }\n        },\n        \"required\": [\"name\", \"statement\"]\n      }\n    },\n    \"enumDefinitions\": {\n      \"description\": \"(WIP) the list of enum definitions\",\n      \"type\": \"array\",\n      \"unevaluatedItems\": false,\n      \"items\": {\n        \"description\": \"(WIP) the enum definition\",\n        \"type\": \"object\",\n        \"properties\": {\n          \"name\": {\n            \"description\": \"the name of the enum\",\n            \"type\": \"string\",\n            \"minLength\": 1\n          },\n          \"values\": {\n            \"type\": \"array\",\n            \"unevaluatedItems\": false,\n            \"items\": {\n              \"description\": \"the member of enum\",\n              \"type\": \"object\",\n              \"properties\": {\n                \"name\": {\n                  \"description\": \"the name of the member\",\n                  \"type\": \"string\",\n                  \"minLength\": 1\n                },\n                \"value\": {\n                  \"description\": \"the value of the member. If not provided, the value is the same as the name\",\n                  \"type\": \"string\",\n                  \"minLength\": 1\n                },\n                \"properties\": {\n                  \"description\": \"the customize properties of the member\",\n                  \"type\": \"object\",\n                  \"additionalProperties\": {\n                    \"type\": [\"string\", \"number\", \"boolean\", \"object\", \"array\", \"null\"]\n                  }\n                }\n              },\n              \"required\": [\"name\"]\n            }\n          },\n          \"properties\": {\n            \"description\": \"the customize properties of the enum\",\n            \"type\": \"object\",\n            \"additionalProperties\": {\n              \"type\": [\"string\", \"number\", \"boolean\", \"object\", \"array\", \"null\"]\n            }\n          }\n        },\n        \"required\": [\"name\", \"values\"]\n      }\n    }\n  },\n  \"required\": [\"catalog\", \"schema\"],\n  \"additionalProperties\": false\n}\n"
  },
  {
    "path": "wren-ui/.dockerignore",
    "content": "Dockerfile\n.dockerignore\nnode_modules\nnpm-debug.log\nREADME.md\n.next\n.git\n*.sqlite\n*.sqlite3\n.env*.local"
  },
  {
    "path": "wren-ui/.eslintignore",
    "content": "**/node_modules"
  },
  {
    "path": "wren-ui/.eslintrc.json",
    "content": "{\n  \"root\": true,\n  \"parser\": \"@typescript-eslint/parser\",\n  \"extends\": [\"next/core-web-vitals\", \"plugin:@typescript-eslint/recommended\", \"prettier\"],\n  \"plugins\": [\"@typescript-eslint\", \"eslint-plugin-prettier\"],\n  \"ignorePatterns\": [\n    \"!**/*\",\n    \".next/**/*\",\n    \"src/apollo/client/graphql/__types__.ts\",\n    \"src/apollo/client/graphql/*.generated.ts\"\n  ],\n  \"overrides\": [\n    {\n      \"files\": [\"*.ts\", \"*.tsx\", \"*.js\", \"*.jsx\"],\n      \"rules\": {\n        \"@next/next/no-html-link-for-pages\": [\n          \"error\",\n          \"src/pages\"\n        ],\n        \"@next/next/no-img-element\": \"off\",\n        \"react-hooks/exhaustive-deps\": \"off\"\n      }\n    },\n    {\n      \"files\": [\"*.ts\", \"*.tsx\"],\n      \"rules\": {}\n    },\n    {\n      \"files\": [\"*.js\", \"*.jsx\"],\n      \"rules\": {}\n    }\n  ],\n  \"rules\": {\n    \"prettier/prettier\": \"error\",\n    \"@next/next/no-html-link-for-pages\": \"off\",\n    \"react/display-name\": 0,\n    \"react/no-unescaped-entities\": 0,\n    \"@typescript-eslint/no-explicit-any\": \"off\",\n    \"@typescript-eslint/no-non-null-assertion\": \"off\",\n    \"@typescript-eslint/no-unused-vars\": [\n      \"error\",\n      {\n        \"args\": \"all\",\n        \"argsIgnorePattern\": \"^_\",\n        \"caughtErrors\": \"all\",\n        \"caughtErrorsIgnorePattern\": \"^_\",\n        \"destructuredArrayIgnorePattern\": \"^_\",\n        \"varsIgnorePattern\": \"^_\",\n        \"ignoreRestSiblings\": true\n      }\n    ]\n  },\n  \"env\": {\n    \"jest\": true\n  }\n}\n"
  },
  {
    "path": "wren-ui/.prettierrc",
    "content": "{\n  \"singleQuote\": true\n}\n"
  },
  {
    "path": "wren-ui/.yarn/releases/yarn-4.5.3.cjs",
    "content": "#!/usr/bin/env node\n/* eslint-disable */\n//prettier-ignore\n(()=>{var j3e=Object.create;var gT=Object.defineProperty;var G3e=Object.getOwnPropertyDescriptor;var W3e=Object.getOwnPropertyNames;var Y3e=Object.getPrototypeOf,K3e=Object.prototype.hasOwnProperty;var ve=(t=>typeof require<\"u\"?require:typeof Proxy<\"u\"?new Proxy(t,{get:(e,r)=>(typeof require<\"u\"?require:e)[r]}):t)(function(t){if(typeof require<\"u\")return require.apply(this,arguments);throw Error('Dynamic require of \"'+t+'\" is not supported')});var It=(t,e)=>()=>(t&&(e=t(t=0)),e);var _=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),Kt=(t,e)=>{for(var r in e)gT(t,r,{get:e[r],enumerable:!0})},V3e=(t,e,r,o)=>{if(e&&typeof e==\"object\"||typeof e==\"function\")for(let a of W3e(e))!K3e.call(t,a)&&a!==r&&gT(t,a,{get:()=>e[a],enumerable:!(o=G3e(e,a))||o.enumerable});return t};var et=(t,e,r)=>(r=t!=null?j3e(Y3e(t)):{},V3e(e||!t||!t.__esModule?gT(r,\"default\",{value:t,enumerable:!0}):r,t));var Pi={};Kt(Pi,{SAFE_TIME:()=>cW,S_IFDIR:()=>VD,S_IFLNK:()=>zD,S_IFMT:()=>Hu,S_IFREG:()=>ow});var Hu,VD,ow,zD,cW,uW=It(()=>{Hu=61440,VD=16384,ow=32768,zD=40960,cW=456789e3});var sr={};Kt(sr,{EBADF:()=>ho,EBUSY:()=>z3e,EEXIST:()=>t_e,EINVAL:()=>X3e,EISDIR:()=>e_e,ENOENT:()=>Z3e,ENOSYS:()=>J3e,ENOTDIR:()=>$3e,ENOTEMPTY:()=>n_e,EOPNOTSUPP:()=>i_e,EROFS:()=>r_e,ERR_DIR_CLOSED:()=>dT});function Nl(t,e){return Object.assign(new Error(`${t}: ${e}`),{code:t})}function z3e(t){return Nl(\"EBUSY\",t)}function J3e(t,e){return Nl(\"ENOSYS\",`${t}, ${e}`)}function X3e(t){return Nl(\"EINVAL\",`invalid argument, ${t}`)}function ho(t){return Nl(\"EBADF\",`bad file descriptor, ${t}`)}function Z3e(t){return Nl(\"ENOENT\",`no such file or directory, ${t}`)}function $3e(t){return Nl(\"ENOTDIR\",`not a directory, ${t}`)}function e_e(t){return Nl(\"EISDIR\",`illegal operation on a directory, ${t}`)}function t_e(t){return Nl(\"EEXIST\",`file already exists, ${t}`)}function r_e(t){return Nl(\"EROFS\",`read-only filesystem, ${t}`)}function n_e(t){return Nl(\"ENOTEMPTY\",`directory not empty, ${t}`)}function i_e(t){return Nl(\"EOPNOTSUPP\",`operation not supported, ${t}`)}function dT(){return Nl(\"ERR_DIR_CLOSED\",\"Directory handle was closed\")}var JD=It(()=>{});var wa={};Kt(wa,{BigIntStatsEntry:()=>cm,DEFAULT_MODE:()=>ET,DirEntry:()=>mT,StatEntry:()=>lm,areStatsEqual:()=>CT,clearStats:()=>XD,convertToBigIntStats:()=>o_e,makeDefaultStats:()=>AW,makeEmptyStats:()=>s_e});function AW(){return new lm}function s_e(){return XD(AW())}function XD(t){for(let e in t)if(Object.hasOwn(t,e)){let r=t[e];typeof r==\"number\"?t[e]=0:typeof r==\"bigint\"?t[e]=BigInt(0):yT.types.isDate(r)&&(t[e]=new Date(0))}return t}function o_e(t){let e=new cm;for(let r in t)if(Object.hasOwn(t,r)){let o=t[r];typeof o==\"number\"?e[r]=BigInt(o):yT.types.isDate(o)&&(e[r]=new Date(o))}return e.atimeNs=e.atimeMs*BigInt(1e6),e.mtimeNs=e.mtimeMs*BigInt(1e6),e.ctimeNs=e.ctimeMs*BigInt(1e6),e.birthtimeNs=e.birthtimeMs*BigInt(1e6),e}function CT(t,e){if(t.atimeMs!==e.atimeMs||t.birthtimeMs!==e.birthtimeMs||t.blksize!==e.blksize||t.blocks!==e.blocks||t.ctimeMs!==e.ctimeMs||t.dev!==e.dev||t.gid!==e.gid||t.ino!==e.ino||t.isBlockDevice()!==e.isBlockDevice()||t.isCharacterDevice()!==e.isCharacterDevice()||t.isDirectory()!==e.isDirectory()||t.isFIFO()!==e.isFIFO()||t.isFile()!==e.isFile()||t.isSocket()!==e.isSocket()||t.isSymbolicLink()!==e.isSymbolicLink()||t.mode!==e.mode||t.mtimeMs!==e.mtimeMs||t.nlink!==e.nlink||t.rdev!==e.rdev||t.size!==e.size||t.uid!==e.uid)return!1;let r=t,o=e;return!(r.atimeNs!==o.atimeNs||r.mtimeNs!==o.mtimeNs||r.ctimeNs!==o.ctimeNs||r.birthtimeNs!==o.birthtimeNs)}var yT,ET,mT,lm,cm,IT=It(()=>{yT=et(ve(\"util\")),ET=33188,mT=class{constructor(){this.name=\"\";this.path=\"\";this.mode=0}isBlockDevice(){return!1}isCharacterDevice(){return!1}isDirectory(){return(this.mode&61440)===16384}isFIFO(){return!1}isFile(){return(this.mode&61440)===32768}isSocket(){return!1}isSymbolicLink(){return(this.mode&61440)===40960}},lm=class{constructor(){this.uid=0;this.gid=0;this.size=0;this.blksize=0;this.atimeMs=0;this.mtimeMs=0;this.ctimeMs=0;this.birthtimeMs=0;this.atime=new Date(0);this.mtime=new Date(0);this.ctime=new Date(0);this.birthtime=new Date(0);this.dev=0;this.ino=0;this.mode=ET;this.nlink=1;this.rdev=0;this.blocks=1}isBlockDevice(){return!1}isCharacterDevice(){return!1}isDirectory(){return(this.mode&61440)===16384}isFIFO(){return!1}isFile(){return(this.mode&61440)===32768}isSocket(){return!1}isSymbolicLink(){return(this.mode&61440)===40960}},cm=class{constructor(){this.uid=BigInt(0);this.gid=BigInt(0);this.size=BigInt(0);this.blksize=BigInt(0);this.atimeMs=BigInt(0);this.mtimeMs=BigInt(0);this.ctimeMs=BigInt(0);this.birthtimeMs=BigInt(0);this.atimeNs=BigInt(0);this.mtimeNs=BigInt(0);this.ctimeNs=BigInt(0);this.birthtimeNs=BigInt(0);this.atime=new Date(0);this.mtime=new Date(0);this.ctime=new Date(0);this.birthtime=new Date(0);this.dev=BigInt(0);this.ino=BigInt(0);this.mode=BigInt(ET);this.nlink=BigInt(1);this.rdev=BigInt(0);this.blocks=BigInt(1)}isBlockDevice(){return!1}isCharacterDevice(){return!1}isDirectory(){return(this.mode&BigInt(61440))===BigInt(16384)}isFIFO(){return!1}isFile(){return(this.mode&BigInt(61440))===BigInt(32768)}isSocket(){return!1}isSymbolicLink(){return(this.mode&BigInt(61440))===BigInt(40960)}}});function A_e(t){let e,r;if(e=t.match(c_e))t=e[1];else if(r=t.match(u_e))t=`\\\\\\\\${r[1]?\".\\\\\":\"\"}${r[2]}`;else return t;return t.replace(/\\//g,\"\\\\\")}function f_e(t){t=t.replace(/\\\\/g,\"/\");let e,r;return(e=t.match(a_e))?t=`/${e[1]}`:(r=t.match(l_e))&&(t=`/unc/${r[1]?\".dot/\":\"\"}${r[2]}`),t}function ZD(t,e){return t===Ae?pW(e):wT(e)}var aw,Bt,mr,Ae,K,fW,a_e,l_e,c_e,u_e,wT,pW,Ba=It(()=>{aw=et(ve(\"path\")),Bt={root:\"/\",dot:\".\",parent:\"..\"},mr={home:\"~\",nodeModules:\"node_modules\",manifest:\"package.json\",lockfile:\"yarn.lock\",virtual:\"__virtual__\",pnpJs:\".pnp.js\",pnpCjs:\".pnp.cjs\",pnpData:\".pnp.data.json\",pnpEsmLoader:\".pnp.loader.mjs\",rc:\".yarnrc.yml\",env:\".env\"},Ae=Object.create(aw.default),K=Object.create(aw.default.posix);Ae.cwd=()=>process.cwd();K.cwd=process.platform===\"win32\"?()=>wT(process.cwd()):process.cwd;process.platform===\"win32\"&&(K.resolve=(...t)=>t.length>0&&K.isAbsolute(t[0])?aw.default.posix.resolve(...t):aw.default.posix.resolve(K.cwd(),...t));fW=function(t,e,r){return e=t.normalize(e),r=t.normalize(r),e===r?\".\":(e.endsWith(t.sep)||(e=e+t.sep),r.startsWith(e)?r.slice(e.length):null)};Ae.contains=(t,e)=>fW(Ae,t,e);K.contains=(t,e)=>fW(K,t,e);a_e=/^([a-zA-Z]:.*)$/,l_e=/^\\/\\/(\\.\\/)?(.*)$/,c_e=/^\\/([a-zA-Z]:.*)$/,u_e=/^\\/unc\\/(\\.dot\\/)?(.*)$/;wT=process.platform===\"win32\"?f_e:t=>t,pW=process.platform===\"win32\"?A_e:t=>t;Ae.fromPortablePath=pW;Ae.toPortablePath=wT});async function $D(t,e){let r=\"0123456789abcdef\";await t.mkdirPromise(e.indexPath,{recursive:!0});let o=[];for(let a of r)for(let n of r)o.push(t.mkdirPromise(t.pathUtils.join(e.indexPath,`${a}${n}`),{recursive:!0}));return await Promise.all(o),e.indexPath}async function hW(t,e,r,o,a){let n=t.pathUtils.normalize(e),u=r.pathUtils.normalize(o),A=[],p=[],{atime:h,mtime:E}=a.stableTime?{atime:H0,mtime:H0}:await r.lstatPromise(u);await t.mkdirpPromise(t.pathUtils.dirname(e),{utimes:[h,E]}),await BT(A,p,t,n,r,u,{...a,didParentExist:!0});for(let w of A)await w();await Promise.all(p.map(w=>w()))}async function BT(t,e,r,o,a,n,u){let A=u.didParentExist?await gW(r,o):null,p=await a.lstatPromise(n),{atime:h,mtime:E}=u.stableTime?{atime:H0,mtime:H0}:p,w;switch(!0){case p.isDirectory():w=await h_e(t,e,r,o,A,a,n,p,u);break;case p.isFile():w=await m_e(t,e,r,o,A,a,n,p,u);break;case p.isSymbolicLink():w=await y_e(t,e,r,o,A,a,n,p,u);break;default:throw new Error(`Unsupported file type (${p.mode})`)}return(u.linkStrategy?.type!==\"HardlinkFromIndex\"||!p.isFile())&&((w||A?.mtime?.getTime()!==E.getTime()||A?.atime?.getTime()!==h.getTime())&&(e.push(()=>r.lutimesPromise(o,h,E)),w=!0),(A===null||(A.mode&511)!==(p.mode&511))&&(e.push(()=>r.chmodPromise(o,p.mode&511)),w=!0)),w}async function gW(t,e){try{return await t.lstatPromise(e)}catch{return null}}async function h_e(t,e,r,o,a,n,u,A,p){if(a!==null&&!a.isDirectory())if(p.overwrite)t.push(async()=>r.removePromise(o)),a=null;else return!1;let h=!1;a===null&&(t.push(async()=>{try{await r.mkdirPromise(o,{mode:A.mode})}catch(D){if(D.code!==\"EEXIST\")throw D}}),h=!0);let E=await n.readdirPromise(u),w=p.didParentExist&&!a?{...p,didParentExist:!1}:p;if(p.stableSort)for(let D of E.sort())await BT(t,e,r,r.pathUtils.join(o,D),n,n.pathUtils.join(u,D),w)&&(h=!0);else(await Promise.all(E.map(async b=>{await BT(t,e,r,r.pathUtils.join(o,b),n,n.pathUtils.join(u,b),w)}))).some(b=>b)&&(h=!0);return h}async function g_e(t,e,r,o,a,n,u,A,p,h){let E=await n.checksumFilePromise(u,{algorithm:\"sha1\"}),w=420,D=A.mode&511,b=`${E}${D!==w?D.toString(8):\"\"}`,C=r.pathUtils.join(h.indexPath,E.slice(0,2),`${b}.dat`),T;(ue=>(ue[ue.Lock=0]=\"Lock\",ue[ue.Rename=1]=\"Rename\"))(T||={});let N=1,U=await gW(r,C);if(a){let le=U&&a.dev===U.dev&&a.ino===U.ino,ce=U?.mtimeMs!==p_e;if(le&&ce&&h.autoRepair&&(N=0,U=null),!le)if(p.overwrite)t.push(async()=>r.removePromise(o)),a=null;else return!1}let z=!U&&N===1?`${C}.${Math.floor(Math.random()*4294967296).toString(16).padStart(8,\"0\")}`:null,te=!1;return t.push(async()=>{if(!U&&(N===0&&await r.lockPromise(C,async()=>{let le=await n.readFilePromise(u);await r.writeFilePromise(C,le)}),N===1&&z)){let le=await n.readFilePromise(u);await r.writeFilePromise(z,le);try{await r.linkPromise(z,C)}catch(ce){if(ce.code===\"EEXIST\")te=!0,await r.unlinkPromise(z);else throw ce}}a||await r.linkPromise(C,o)}),e.push(async()=>{U||(await r.lutimesPromise(C,H0,H0),D!==w&&await r.chmodPromise(C,D)),z&&!te&&await r.unlinkPromise(z)}),!1}async function d_e(t,e,r,o,a,n,u,A,p){if(a!==null)if(p.overwrite)t.push(async()=>r.removePromise(o)),a=null;else return!1;return t.push(async()=>{let h=await n.readFilePromise(u);await r.writeFilePromise(o,h)}),!0}async function m_e(t,e,r,o,a,n,u,A,p){return p.linkStrategy?.type===\"HardlinkFromIndex\"?g_e(t,e,r,o,a,n,u,A,p,p.linkStrategy):d_e(t,e,r,o,a,n,u,A,p)}async function y_e(t,e,r,o,a,n,u,A,p){if(a!==null)if(p.overwrite)t.push(async()=>r.removePromise(o)),a=null;else return!1;return t.push(async()=>{await r.symlinkPromise(ZD(r.pathUtils,await n.readlinkPromise(u)),o)}),!0}var H0,p_e,vT=It(()=>{Ba();H0=new Date(456789e3*1e3),p_e=H0.getTime()});function eP(t,e,r,o){let a=()=>{let n=r.shift();if(typeof n>\"u\")return null;let u=t.pathUtils.join(e,n);return Object.assign(t.statSync(u),{name:n,path:void 0})};return new lw(e,a,o)}var lw,dW=It(()=>{JD();lw=class{constructor(e,r,o={}){this.path=e;this.nextDirent=r;this.opts=o;this.closed=!1}throwIfClosed(){if(this.closed)throw dT()}async*[Symbol.asyncIterator](){try{let e;for(;(e=await this.read())!==null;)yield e}finally{await this.close()}}read(e){let r=this.readSync();return typeof e<\"u\"?e(null,r):Promise.resolve(r)}readSync(){return this.throwIfClosed(),this.nextDirent()}close(e){return this.closeSync(),typeof e<\"u\"?e(null):Promise.resolve()}closeSync(){this.throwIfClosed(),this.opts.onClose?.(),this.closed=!0}}});function mW(t,e){if(t!==e)throw new Error(`Invalid StatWatcher status: expected '${e}', got '${t}'`)}var yW,tP,EW=It(()=>{yW=ve(\"events\");IT();tP=class t extends yW.EventEmitter{constructor(r,o,{bigint:a=!1}={}){super();this.status=\"ready\";this.changeListeners=new Map;this.startTimeout=null;this.fakeFs=r,this.path=o,this.bigint=a,this.lastStats=this.stat()}static create(r,o,a){let n=new t(r,o,a);return n.start(),n}start(){mW(this.status,\"ready\"),this.status=\"running\",this.startTimeout=setTimeout(()=>{this.startTimeout=null,this.fakeFs.existsSync(this.path)||this.emit(\"change\",this.lastStats,this.lastStats)},3)}stop(){mW(this.status,\"running\"),this.status=\"stopped\",this.startTimeout!==null&&(clearTimeout(this.startTimeout),this.startTimeout=null),this.emit(\"stop\")}stat(){try{return this.fakeFs.statSync(this.path,{bigint:this.bigint})}catch{let o=this.bigint?new cm:new lm;return XD(o)}}makeInterval(r){let o=setInterval(()=>{let a=this.stat(),n=this.lastStats;CT(a,n)||(this.lastStats=a,this.emit(\"change\",a,n))},r.interval);return r.persistent?o:o.unref()}registerChangeListener(r,o){this.addListener(\"change\",r),this.changeListeners.set(r,this.makeInterval(o))}unregisterChangeListener(r){this.removeListener(\"change\",r);let o=this.changeListeners.get(r);typeof o<\"u\"&&clearInterval(o),this.changeListeners.delete(r)}unregisterAllChangeListeners(){for(let r of this.changeListeners.keys())this.unregisterChangeListener(r)}hasChangeListeners(){return this.changeListeners.size>0}ref(){for(let r of this.changeListeners.values())r.ref();return this}unref(){for(let r of this.changeListeners.values())r.unref();return this}}});function um(t,e,r,o){let a,n,u,A;switch(typeof r){case\"function\":a=!1,n=!0,u=5007,A=r;break;default:({bigint:a=!1,persistent:n=!0,interval:u=5007}=r),A=o;break}let p=rP.get(t);typeof p>\"u\"&&rP.set(t,p=new Map);let h=p.get(e);return typeof h>\"u\"&&(h=tP.create(t,e,{bigint:a}),p.set(e,h)),h.registerChangeListener(A,{persistent:n,interval:u}),h}function q0(t,e,r){let o=rP.get(t);if(typeof o>\"u\")return;let a=o.get(e);typeof a>\"u\"||(typeof r>\"u\"?a.unregisterAllChangeListeners():a.unregisterChangeListener(r),a.hasChangeListeners()||(a.stop(),o.delete(e)))}function j0(t){let e=rP.get(t);if(!(typeof e>\"u\"))for(let r of e.keys())q0(t,r)}var rP,DT=It(()=>{EW();rP=new WeakMap});function E_e(t){let e=t.match(/\\r?\\n/g);if(e===null)return IW.EOL;let r=e.filter(a=>a===`\\r\n`).length,o=e.length-r;return r>o?`\\r\n`:`\n`}function G0(t,e){return e.replace(/\\r?\\n/g,E_e(t))}var CW,IW,hf,qu,W0=It(()=>{CW=ve(\"crypto\"),IW=ve(\"os\");vT();Ba();hf=class{constructor(e){this.pathUtils=e}async*genTraversePromise(e,{stableSort:r=!1}={}){let o=[e];for(;o.length>0;){let a=o.shift();if((await this.lstatPromise(a)).isDirectory()){let u=await this.readdirPromise(a);if(r)for(let A of u.sort())o.push(this.pathUtils.join(a,A));else throw new Error(\"Not supported\")}else yield a}}async checksumFilePromise(e,{algorithm:r=\"sha512\"}={}){let o=await this.openPromise(e,\"r\");try{let n=Buffer.allocUnsafeSlow(65536),u=(0,CW.createHash)(r),A=0;for(;(A=await this.readPromise(o,n,0,65536))!==0;)u.update(A===65536?n:n.slice(0,A));return u.digest(\"hex\")}finally{await this.closePromise(o)}}async removePromise(e,{recursive:r=!0,maxRetries:o=5}={}){let a;try{a=await this.lstatPromise(e)}catch(n){if(n.code===\"ENOENT\")return;throw n}if(a.isDirectory()){if(r){let n=await this.readdirPromise(e);await Promise.all(n.map(u=>this.removePromise(this.pathUtils.resolve(e,u))))}for(let n=0;n<=o;n++)try{await this.rmdirPromise(e);break}catch(u){if(u.code!==\"EBUSY\"&&u.code!==\"ENOTEMPTY\")throw u;n<o&&await new Promise(A=>setTimeout(A,n*100))}}else await this.unlinkPromise(e)}removeSync(e,{recursive:r=!0}={}){let o;try{o=this.lstatSync(e)}catch(a){if(a.code===\"ENOENT\")return;throw a}if(o.isDirectory()){if(r)for(let a of this.readdirSync(e))this.removeSync(this.pathUtils.resolve(e,a));this.rmdirSync(e)}else this.unlinkSync(e)}async mkdirpPromise(e,{chmod:r,utimes:o}={}){if(e=this.resolve(e),e===this.pathUtils.dirname(e))return;let a=e.split(this.pathUtils.sep),n;for(let u=2;u<=a.length;++u){let A=a.slice(0,u).join(this.pathUtils.sep);if(!this.existsSync(A)){try{await this.mkdirPromise(A)}catch(p){if(p.code===\"EEXIST\")continue;throw p}if(n??=A,r!=null&&await this.chmodPromise(A,r),o!=null)await this.utimesPromise(A,o[0],o[1]);else{let p=await this.statPromise(this.pathUtils.dirname(A));await this.utimesPromise(A,p.atime,p.mtime)}}}return n}mkdirpSync(e,{chmod:r,utimes:o}={}){if(e=this.resolve(e),e===this.pathUtils.dirname(e))return;let a=e.split(this.pathUtils.sep),n;for(let u=2;u<=a.length;++u){let A=a.slice(0,u).join(this.pathUtils.sep);if(!this.existsSync(A)){try{this.mkdirSync(A)}catch(p){if(p.code===\"EEXIST\")continue;throw p}if(n??=A,r!=null&&this.chmodSync(A,r),o!=null)this.utimesSync(A,o[0],o[1]);else{let p=this.statSync(this.pathUtils.dirname(A));this.utimesSync(A,p.atime,p.mtime)}}}return n}async copyPromise(e,r,{baseFs:o=this,overwrite:a=!0,stableSort:n=!1,stableTime:u=!1,linkStrategy:A=null}={}){return await hW(this,e,o,r,{overwrite:a,stableSort:n,stableTime:u,linkStrategy:A})}copySync(e,r,{baseFs:o=this,overwrite:a=!0}={}){let n=o.lstatSync(r),u=this.existsSync(e);if(n.isDirectory()){this.mkdirpSync(e);let p=o.readdirSync(r);for(let h of p)this.copySync(this.pathUtils.join(e,h),o.pathUtils.join(r,h),{baseFs:o,overwrite:a})}else if(n.isFile()){if(!u||a){u&&this.removeSync(e);let p=o.readFileSync(r);this.writeFileSync(e,p)}}else if(n.isSymbolicLink()){if(!u||a){u&&this.removeSync(e);let p=o.readlinkSync(r);this.symlinkSync(ZD(this.pathUtils,p),e)}}else throw new Error(`Unsupported file type (file: ${r}, mode: 0o${n.mode.toString(8).padStart(6,\"0\")})`);let A=n.mode&511;this.chmodSync(e,A)}async changeFilePromise(e,r,o={}){return Buffer.isBuffer(r)?this.changeFileBufferPromise(e,r,o):this.changeFileTextPromise(e,r,o)}async changeFileBufferPromise(e,r,{mode:o}={}){let a=Buffer.alloc(0);try{a=await this.readFilePromise(e)}catch{}Buffer.compare(a,r)!==0&&await this.writeFilePromise(e,r,{mode:o})}async changeFileTextPromise(e,r,{automaticNewlines:o,mode:a}={}){let n=\"\";try{n=await this.readFilePromise(e,\"utf8\")}catch{}let u=o?G0(n,r):r;n!==u&&await this.writeFilePromise(e,u,{mode:a})}changeFileSync(e,r,o={}){return Buffer.isBuffer(r)?this.changeFileBufferSync(e,r,o):this.changeFileTextSync(e,r,o)}changeFileBufferSync(e,r,{mode:o}={}){let a=Buffer.alloc(0);try{a=this.readFileSync(e)}catch{}Buffer.compare(a,r)!==0&&this.writeFileSync(e,r,{mode:o})}changeFileTextSync(e,r,{automaticNewlines:o=!1,mode:a}={}){let n=\"\";try{n=this.readFileSync(e,\"utf8\")}catch{}let u=o?G0(n,r):r;n!==u&&this.writeFileSync(e,u,{mode:a})}async movePromise(e,r){try{await this.renamePromise(e,r)}catch(o){if(o.code===\"EXDEV\")await this.copyPromise(r,e),await this.removePromise(e);else throw o}}moveSync(e,r){try{this.renameSync(e,r)}catch(o){if(o.code===\"EXDEV\")this.copySync(r,e),this.removeSync(e);else throw o}}async lockPromise(e,r){let o=`${e}.flock`,a=1e3/60,n=Date.now(),u=null,A=async()=>{let p;try{[p]=await this.readJsonPromise(o)}catch{return Date.now()-n<500}try{return process.kill(p,0),!0}catch{return!1}};for(;u===null;)try{u=await this.openPromise(o,\"wx\")}catch(p){if(p.code===\"EEXIST\"){if(!await A())try{await this.unlinkPromise(o);continue}catch{}if(Date.now()-n<60*1e3)await new Promise(h=>setTimeout(h,a));else throw new Error(`Couldn't acquire a lock in a reasonable time (via ${o})`)}else throw p}await this.writePromise(u,JSON.stringify([process.pid]));try{return await r()}finally{try{await this.closePromise(u),await this.unlinkPromise(o)}catch{}}}async readJsonPromise(e){let r=await this.readFilePromise(e,\"utf8\");try{return JSON.parse(r)}catch(o){throw o.message+=` (in ${e})`,o}}readJsonSync(e){let r=this.readFileSync(e,\"utf8\");try{return JSON.parse(r)}catch(o){throw o.message+=` (in ${e})`,o}}async writeJsonPromise(e,r,{compact:o=!1}={}){let a=o?0:2;return await this.writeFilePromise(e,`${JSON.stringify(r,null,a)}\n`)}writeJsonSync(e,r,{compact:o=!1}={}){let a=o?0:2;return this.writeFileSync(e,`${JSON.stringify(r,null,a)}\n`)}async preserveTimePromise(e,r){let o=await this.lstatPromise(e),a=await r();typeof a<\"u\"&&(e=a),await this.lutimesPromise(e,o.atime,o.mtime)}async preserveTimeSync(e,r){let o=this.lstatSync(e),a=r();typeof a<\"u\"&&(e=a),this.lutimesSync(e,o.atime,o.mtime)}},qu=class extends hf{constructor(){super(K)}}});var ws,gf=It(()=>{W0();ws=class extends hf{getExtractHint(e){return this.baseFs.getExtractHint(e)}resolve(e){return this.mapFromBase(this.baseFs.resolve(this.mapToBase(e)))}getRealPath(){return this.mapFromBase(this.baseFs.getRealPath())}async openPromise(e,r,o){return this.baseFs.openPromise(this.mapToBase(e),r,o)}openSync(e,r,o){return this.baseFs.openSync(this.mapToBase(e),r,o)}async opendirPromise(e,r){return Object.assign(await this.baseFs.opendirPromise(this.mapToBase(e),r),{path:e})}opendirSync(e,r){return Object.assign(this.baseFs.opendirSync(this.mapToBase(e),r),{path:e})}async readPromise(e,r,o,a,n){return await this.baseFs.readPromise(e,r,o,a,n)}readSync(e,r,o,a,n){return this.baseFs.readSync(e,r,o,a,n)}async writePromise(e,r,o,a,n){return typeof r==\"string\"?await this.baseFs.writePromise(e,r,o):await this.baseFs.writePromise(e,r,o,a,n)}writeSync(e,r,o,a,n){return typeof r==\"string\"?this.baseFs.writeSync(e,r,o):this.baseFs.writeSync(e,r,o,a,n)}async closePromise(e){return this.baseFs.closePromise(e)}closeSync(e){this.baseFs.closeSync(e)}createReadStream(e,r){return this.baseFs.createReadStream(e!==null?this.mapToBase(e):e,r)}createWriteStream(e,r){return this.baseFs.createWriteStream(e!==null?this.mapToBase(e):e,r)}async realpathPromise(e){return this.mapFromBase(await this.baseFs.realpathPromise(this.mapToBase(e)))}realpathSync(e){return this.mapFromBase(this.baseFs.realpathSync(this.mapToBase(e)))}async existsPromise(e){return this.baseFs.existsPromise(this.mapToBase(e))}existsSync(e){return this.baseFs.existsSync(this.mapToBase(e))}accessSync(e,r){return this.baseFs.accessSync(this.mapToBase(e),r)}async accessPromise(e,r){return this.baseFs.accessPromise(this.mapToBase(e),r)}async statPromise(e,r){return this.baseFs.statPromise(this.mapToBase(e),r)}statSync(e,r){return this.baseFs.statSync(this.mapToBase(e),r)}async fstatPromise(e,r){return this.baseFs.fstatPromise(e,r)}fstatSync(e,r){return this.baseFs.fstatSync(e,r)}lstatPromise(e,r){return this.baseFs.lstatPromise(this.mapToBase(e),r)}lstatSync(e,r){return this.baseFs.lstatSync(this.mapToBase(e),r)}async fchmodPromise(e,r){return this.baseFs.fchmodPromise(e,r)}fchmodSync(e,r){return this.baseFs.fchmodSync(e,r)}async chmodPromise(e,r){return this.baseFs.chmodPromise(this.mapToBase(e),r)}chmodSync(e,r){return this.baseFs.chmodSync(this.mapToBase(e),r)}async fchownPromise(e,r,o){return this.baseFs.fchownPromise(e,r,o)}fchownSync(e,r,o){return this.baseFs.fchownSync(e,r,o)}async chownPromise(e,r,o){return this.baseFs.chownPromise(this.mapToBase(e),r,o)}chownSync(e,r,o){return this.baseFs.chownSync(this.mapToBase(e),r,o)}async renamePromise(e,r){return this.baseFs.renamePromise(this.mapToBase(e),this.mapToBase(r))}renameSync(e,r){return this.baseFs.renameSync(this.mapToBase(e),this.mapToBase(r))}async copyFilePromise(e,r,o=0){return this.baseFs.copyFilePromise(this.mapToBase(e),this.mapToBase(r),o)}copyFileSync(e,r,o=0){return this.baseFs.copyFileSync(this.mapToBase(e),this.mapToBase(r),o)}async appendFilePromise(e,r,o){return this.baseFs.appendFilePromise(this.fsMapToBase(e),r,o)}appendFileSync(e,r,o){return this.baseFs.appendFileSync(this.fsMapToBase(e),r,o)}async writeFilePromise(e,r,o){return this.baseFs.writeFilePromise(this.fsMapToBase(e),r,o)}writeFileSync(e,r,o){return this.baseFs.writeFileSync(this.fsMapToBase(e),r,o)}async unlinkPromise(e){return this.baseFs.unlinkPromise(this.mapToBase(e))}unlinkSync(e){return this.baseFs.unlinkSync(this.mapToBase(e))}async utimesPromise(e,r,o){return this.baseFs.utimesPromise(this.mapToBase(e),r,o)}utimesSync(e,r,o){return this.baseFs.utimesSync(this.mapToBase(e),r,o)}async lutimesPromise(e,r,o){return this.baseFs.lutimesPromise(this.mapToBase(e),r,o)}lutimesSync(e,r,o){return this.baseFs.lutimesSync(this.mapToBase(e),r,o)}async mkdirPromise(e,r){return this.baseFs.mkdirPromise(this.mapToBase(e),r)}mkdirSync(e,r){return this.baseFs.mkdirSync(this.mapToBase(e),r)}async rmdirPromise(e,r){return this.baseFs.rmdirPromise(this.mapToBase(e),r)}rmdirSync(e,r){return this.baseFs.rmdirSync(this.mapToBase(e),r)}async rmPromise(e,r){return this.baseFs.rmPromise(this.mapToBase(e),r)}rmSync(e,r){return this.baseFs.rmSync(this.mapToBase(e),r)}async linkPromise(e,r){return this.baseFs.linkPromise(this.mapToBase(e),this.mapToBase(r))}linkSync(e,r){return this.baseFs.linkSync(this.mapToBase(e),this.mapToBase(r))}async symlinkPromise(e,r,o){let a=this.mapToBase(r);if(this.pathUtils.isAbsolute(e))return this.baseFs.symlinkPromise(this.mapToBase(e),a,o);let n=this.mapToBase(this.pathUtils.join(this.pathUtils.dirname(r),e)),u=this.baseFs.pathUtils.relative(this.baseFs.pathUtils.dirname(a),n);return this.baseFs.symlinkPromise(u,a,o)}symlinkSync(e,r,o){let a=this.mapToBase(r);if(this.pathUtils.isAbsolute(e))return this.baseFs.symlinkSync(this.mapToBase(e),a,o);let n=this.mapToBase(this.pathUtils.join(this.pathUtils.dirname(r),e)),u=this.baseFs.pathUtils.relative(this.baseFs.pathUtils.dirname(a),n);return this.baseFs.symlinkSync(u,a,o)}async readFilePromise(e,r){return this.baseFs.readFilePromise(this.fsMapToBase(e),r)}readFileSync(e,r){return this.baseFs.readFileSync(this.fsMapToBase(e),r)}readdirPromise(e,r){return this.baseFs.readdirPromise(this.mapToBase(e),r)}readdirSync(e,r){return this.baseFs.readdirSync(this.mapToBase(e),r)}async readlinkPromise(e){return this.mapFromBase(await this.baseFs.readlinkPromise(this.mapToBase(e)))}readlinkSync(e){return this.mapFromBase(this.baseFs.readlinkSync(this.mapToBase(e)))}async truncatePromise(e,r){return this.baseFs.truncatePromise(this.mapToBase(e),r)}truncateSync(e,r){return this.baseFs.truncateSync(this.mapToBase(e),r)}async ftruncatePromise(e,r){return this.baseFs.ftruncatePromise(e,r)}ftruncateSync(e,r){return this.baseFs.ftruncateSync(e,r)}watch(e,r,o){return this.baseFs.watch(this.mapToBase(e),r,o)}watchFile(e,r,o){return this.baseFs.watchFile(this.mapToBase(e),r,o)}unwatchFile(e,r){return this.baseFs.unwatchFile(this.mapToBase(e),r)}fsMapToBase(e){return typeof e==\"number\"?e:this.mapToBase(e)}}});var ju,wW=It(()=>{gf();ju=class extends ws{constructor(e,{baseFs:r,pathUtils:o}){super(o),this.target=e,this.baseFs=r}getRealPath(){return this.target}getBaseFs(){return this.baseFs}mapFromBase(e){return e}mapToBase(e){return e}}});function BW(t){let e=t;return typeof t.path==\"string\"&&(e.path=Ae.toPortablePath(t.path)),e}var vW,_n,Y0=It(()=>{vW=et(ve(\"fs\"));W0();Ba();_n=class extends qu{constructor(e=vW.default){super(),this.realFs=e}getExtractHint(){return!1}getRealPath(){return Bt.root}resolve(e){return K.resolve(e)}async openPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.open(Ae.fromPortablePath(e),r,o,this.makeCallback(a,n))})}openSync(e,r,o){return this.realFs.openSync(Ae.fromPortablePath(e),r,o)}async opendirPromise(e,r){return await new Promise((o,a)=>{typeof r<\"u\"?this.realFs.opendir(Ae.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.opendir(Ae.fromPortablePath(e),this.makeCallback(o,a))}).then(o=>{let a=o;return Object.defineProperty(a,\"path\",{value:e,configurable:!0,writable:!0}),a})}opendirSync(e,r){let a=typeof r<\"u\"?this.realFs.opendirSync(Ae.fromPortablePath(e),r):this.realFs.opendirSync(Ae.fromPortablePath(e));return Object.defineProperty(a,\"path\",{value:e,configurable:!0,writable:!0}),a}async readPromise(e,r,o=0,a=0,n=-1){return await new Promise((u,A)=>{this.realFs.read(e,r,o,a,n,(p,h)=>{p?A(p):u(h)})})}readSync(e,r,o,a,n){return this.realFs.readSync(e,r,o,a,n)}async writePromise(e,r,o,a,n){return await new Promise((u,A)=>typeof r==\"string\"?this.realFs.write(e,r,o,this.makeCallback(u,A)):this.realFs.write(e,r,o,a,n,this.makeCallback(u,A)))}writeSync(e,r,o,a,n){return typeof r==\"string\"?this.realFs.writeSync(e,r,o):this.realFs.writeSync(e,r,o,a,n)}async closePromise(e){await new Promise((r,o)=>{this.realFs.close(e,this.makeCallback(r,o))})}closeSync(e){this.realFs.closeSync(e)}createReadStream(e,r){let o=e!==null?Ae.fromPortablePath(e):e;return this.realFs.createReadStream(o,r)}createWriteStream(e,r){let o=e!==null?Ae.fromPortablePath(e):e;return this.realFs.createWriteStream(o,r)}async realpathPromise(e){return await new Promise((r,o)=>{this.realFs.realpath(Ae.fromPortablePath(e),{},this.makeCallback(r,o))}).then(r=>Ae.toPortablePath(r))}realpathSync(e){return Ae.toPortablePath(this.realFs.realpathSync(Ae.fromPortablePath(e),{}))}async existsPromise(e){return await new Promise(r=>{this.realFs.exists(Ae.fromPortablePath(e),r)})}accessSync(e,r){return this.realFs.accessSync(Ae.fromPortablePath(e),r)}async accessPromise(e,r){return await new Promise((o,a)=>{this.realFs.access(Ae.fromPortablePath(e),r,this.makeCallback(o,a))})}existsSync(e){return this.realFs.existsSync(Ae.fromPortablePath(e))}async statPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.stat(Ae.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.stat(Ae.fromPortablePath(e),this.makeCallback(o,a))})}statSync(e,r){return r?this.realFs.statSync(Ae.fromPortablePath(e),r):this.realFs.statSync(Ae.fromPortablePath(e))}async fstatPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.fstat(e,r,this.makeCallback(o,a)):this.realFs.fstat(e,this.makeCallback(o,a))})}fstatSync(e,r){return r?this.realFs.fstatSync(e,r):this.realFs.fstatSync(e)}async lstatPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.lstat(Ae.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.lstat(Ae.fromPortablePath(e),this.makeCallback(o,a))})}lstatSync(e,r){return r?this.realFs.lstatSync(Ae.fromPortablePath(e),r):this.realFs.lstatSync(Ae.fromPortablePath(e))}async fchmodPromise(e,r){return await new Promise((o,a)=>{this.realFs.fchmod(e,r,this.makeCallback(o,a))})}fchmodSync(e,r){return this.realFs.fchmodSync(e,r)}async chmodPromise(e,r){return await new Promise((o,a)=>{this.realFs.chmod(Ae.fromPortablePath(e),r,this.makeCallback(o,a))})}chmodSync(e,r){return this.realFs.chmodSync(Ae.fromPortablePath(e),r)}async fchownPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.fchown(e,r,o,this.makeCallback(a,n))})}fchownSync(e,r,o){return this.realFs.fchownSync(e,r,o)}async chownPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.chown(Ae.fromPortablePath(e),r,o,this.makeCallback(a,n))})}chownSync(e,r,o){return this.realFs.chownSync(Ae.fromPortablePath(e),r,o)}async renamePromise(e,r){return await new Promise((o,a)=>{this.realFs.rename(Ae.fromPortablePath(e),Ae.fromPortablePath(r),this.makeCallback(o,a))})}renameSync(e,r){return this.realFs.renameSync(Ae.fromPortablePath(e),Ae.fromPortablePath(r))}async copyFilePromise(e,r,o=0){return await new Promise((a,n)=>{this.realFs.copyFile(Ae.fromPortablePath(e),Ae.fromPortablePath(r),o,this.makeCallback(a,n))})}copyFileSync(e,r,o=0){return this.realFs.copyFileSync(Ae.fromPortablePath(e),Ae.fromPortablePath(r),o)}async appendFilePromise(e,r,o){return await new Promise((a,n)=>{let u=typeof e==\"string\"?Ae.fromPortablePath(e):e;o?this.realFs.appendFile(u,r,o,this.makeCallback(a,n)):this.realFs.appendFile(u,r,this.makeCallback(a,n))})}appendFileSync(e,r,o){let a=typeof e==\"string\"?Ae.fromPortablePath(e):e;o?this.realFs.appendFileSync(a,r,o):this.realFs.appendFileSync(a,r)}async writeFilePromise(e,r,o){return await new Promise((a,n)=>{let u=typeof e==\"string\"?Ae.fromPortablePath(e):e;o?this.realFs.writeFile(u,r,o,this.makeCallback(a,n)):this.realFs.writeFile(u,r,this.makeCallback(a,n))})}writeFileSync(e,r,o){let a=typeof e==\"string\"?Ae.fromPortablePath(e):e;o?this.realFs.writeFileSync(a,r,o):this.realFs.writeFileSync(a,r)}async unlinkPromise(e){return await new Promise((r,o)=>{this.realFs.unlink(Ae.fromPortablePath(e),this.makeCallback(r,o))})}unlinkSync(e){return this.realFs.unlinkSync(Ae.fromPortablePath(e))}async utimesPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.utimes(Ae.fromPortablePath(e),r,o,this.makeCallback(a,n))})}utimesSync(e,r,o){this.realFs.utimesSync(Ae.fromPortablePath(e),r,o)}async lutimesPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.lutimes(Ae.fromPortablePath(e),r,o,this.makeCallback(a,n))})}lutimesSync(e,r,o){this.realFs.lutimesSync(Ae.fromPortablePath(e),r,o)}async mkdirPromise(e,r){return await new Promise((o,a)=>{this.realFs.mkdir(Ae.fromPortablePath(e),r,this.makeCallback(o,a))})}mkdirSync(e,r){return this.realFs.mkdirSync(Ae.fromPortablePath(e),r)}async rmdirPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.rmdir(Ae.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.rmdir(Ae.fromPortablePath(e),this.makeCallback(o,a))})}rmdirSync(e,r){return this.realFs.rmdirSync(Ae.fromPortablePath(e),r)}async rmPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.rm(Ae.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.rm(Ae.fromPortablePath(e),this.makeCallback(o,a))})}rmSync(e,r){return this.realFs.rmSync(Ae.fromPortablePath(e),r)}async linkPromise(e,r){return await new Promise((o,a)=>{this.realFs.link(Ae.fromPortablePath(e),Ae.fromPortablePath(r),this.makeCallback(o,a))})}linkSync(e,r){return this.realFs.linkSync(Ae.fromPortablePath(e),Ae.fromPortablePath(r))}async symlinkPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.symlink(Ae.fromPortablePath(e.replace(/\\/+$/,\"\")),Ae.fromPortablePath(r),o,this.makeCallback(a,n))})}symlinkSync(e,r,o){return this.realFs.symlinkSync(Ae.fromPortablePath(e.replace(/\\/+$/,\"\")),Ae.fromPortablePath(r),o)}async readFilePromise(e,r){return await new Promise((o,a)=>{let n=typeof e==\"string\"?Ae.fromPortablePath(e):e;this.realFs.readFile(n,r,this.makeCallback(o,a))})}readFileSync(e,r){let o=typeof e==\"string\"?Ae.fromPortablePath(e):e;return this.realFs.readFileSync(o,r)}async readdirPromise(e,r){return await new Promise((o,a)=>{r?r.recursive&&process.platform===\"win32\"?r.withFileTypes?this.realFs.readdir(Ae.fromPortablePath(e),r,this.makeCallback(n=>o(n.map(BW)),a)):this.realFs.readdir(Ae.fromPortablePath(e),r,this.makeCallback(n=>o(n.map(Ae.toPortablePath)),a)):this.realFs.readdir(Ae.fromPortablePath(e),r,this.makeCallback(o,a)):this.realFs.readdir(Ae.fromPortablePath(e),this.makeCallback(o,a))})}readdirSync(e,r){return r?r.recursive&&process.platform===\"win32\"?r.withFileTypes?this.realFs.readdirSync(Ae.fromPortablePath(e),r).map(BW):this.realFs.readdirSync(Ae.fromPortablePath(e),r).map(Ae.toPortablePath):this.realFs.readdirSync(Ae.fromPortablePath(e),r):this.realFs.readdirSync(Ae.fromPortablePath(e))}async readlinkPromise(e){return await new Promise((r,o)=>{this.realFs.readlink(Ae.fromPortablePath(e),this.makeCallback(r,o))}).then(r=>Ae.toPortablePath(r))}readlinkSync(e){return Ae.toPortablePath(this.realFs.readlinkSync(Ae.fromPortablePath(e)))}async truncatePromise(e,r){return await new Promise((o,a)=>{this.realFs.truncate(Ae.fromPortablePath(e),r,this.makeCallback(o,a))})}truncateSync(e,r){return this.realFs.truncateSync(Ae.fromPortablePath(e),r)}async ftruncatePromise(e,r){return await new Promise((o,a)=>{this.realFs.ftruncate(e,r,this.makeCallback(o,a))})}ftruncateSync(e,r){return this.realFs.ftruncateSync(e,r)}watch(e,r,o){return this.realFs.watch(Ae.fromPortablePath(e),r,o)}watchFile(e,r,o){return this.realFs.watchFile(Ae.fromPortablePath(e),r,o)}unwatchFile(e,r){return this.realFs.unwatchFile(Ae.fromPortablePath(e),r)}makeCallback(e,r){return(o,a)=>{o?r(o):e(a)}}}});var En,DW=It(()=>{Y0();gf();Ba();En=class extends ws{constructor(e,{baseFs:r=new _n}={}){super(K),this.target=this.pathUtils.normalize(e),this.baseFs=r}getRealPath(){return this.pathUtils.resolve(this.baseFs.getRealPath(),this.target)}resolve(e){return this.pathUtils.isAbsolute(e)?K.normalize(e):this.baseFs.resolve(K.join(this.target,e))}mapFromBase(e){return e}mapToBase(e){return this.pathUtils.isAbsolute(e)?e:this.pathUtils.join(this.target,e)}}});var PW,Gu,SW=It(()=>{Y0();gf();Ba();PW=Bt.root,Gu=class extends ws{constructor(e,{baseFs:r=new _n}={}){super(K),this.target=this.pathUtils.resolve(Bt.root,e),this.baseFs=r}getRealPath(){return this.pathUtils.resolve(this.baseFs.getRealPath(),this.pathUtils.relative(Bt.root,this.target))}getTarget(){return this.target}getBaseFs(){return this.baseFs}mapToBase(e){let r=this.pathUtils.normalize(e);if(this.pathUtils.isAbsolute(e))return this.pathUtils.resolve(this.target,this.pathUtils.relative(PW,e));if(r.match(/^\\.\\.\\/?/))throw new Error(`Resolving this path (${e}) would escape the jail`);return this.pathUtils.resolve(this.target,e)}mapFromBase(e){return this.pathUtils.resolve(PW,this.pathUtils.relative(this.target,e))}}});var Am,xW=It(()=>{gf();Am=class extends ws{constructor(r,o){super(o);this.instance=null;this.factory=r}get baseFs(){return this.instance||(this.instance=this.factory()),this.instance}set baseFs(r){this.instance=r}mapFromBase(r){return r}mapToBase(r){return r}}});var K0,va,Gp,bW=It(()=>{K0=ve(\"fs\");W0();Y0();DT();JD();Ba();va=4278190080,Gp=class extends qu{constructor({baseFs:r=new _n,filter:o=null,magicByte:a=42,maxOpenFiles:n=1/0,useCache:u=!0,maxAge:A=5e3,typeCheck:p=K0.constants.S_IFREG,getMountPoint:h,factoryPromise:E,factorySync:w}){if(Math.floor(a)!==a||!(a>1&&a<=127))throw new Error(\"The magic byte must be set to a round value between 1 and 127 included\");super();this.fdMap=new Map;this.nextFd=3;this.isMount=new Set;this.notMount=new Set;this.realPaths=new Map;this.limitOpenFilesTimeout=null;this.baseFs=r,this.mountInstances=u?new Map:null,this.factoryPromise=E,this.factorySync=w,this.filter=o,this.getMountPoint=h,this.magic=a<<24,this.maxAge=A,this.maxOpenFiles=n,this.typeCheck=p}getExtractHint(r){return this.baseFs.getExtractHint(r)}getRealPath(){return this.baseFs.getRealPath()}saveAndClose(){if(j0(this),this.mountInstances)for(let[r,{childFs:o}]of this.mountInstances.entries())o.saveAndClose?.(),this.mountInstances.delete(r)}discardAndClose(){if(j0(this),this.mountInstances)for(let[r,{childFs:o}]of this.mountInstances.entries())o.discardAndClose?.(),this.mountInstances.delete(r)}resolve(r){return this.baseFs.resolve(r)}remapFd(r,o){let a=this.nextFd++|this.magic;return this.fdMap.set(a,[r,o]),a}async openPromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.openPromise(r,o,a),async(n,{subPath:u})=>this.remapFd(n,await n.openPromise(u,o,a)))}openSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.openSync(r,o,a),(n,{subPath:u})=>this.remapFd(n,n.openSync(u,o,a)))}async opendirPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.opendirPromise(r,o),async(a,{subPath:n})=>await a.opendirPromise(n,o),{requireSubpath:!1})}opendirSync(r,o){return this.makeCallSync(r,()=>this.baseFs.opendirSync(r,o),(a,{subPath:n})=>a.opendirSync(n,o),{requireSubpath:!1})}async readPromise(r,o,a,n,u){if((r&va)!==this.magic)return await this.baseFs.readPromise(r,o,a,n,u);let A=this.fdMap.get(r);if(typeof A>\"u\")throw ho(\"read\");let[p,h]=A;return await p.readPromise(h,o,a,n,u)}readSync(r,o,a,n,u){if((r&va)!==this.magic)return this.baseFs.readSync(r,o,a,n,u);let A=this.fdMap.get(r);if(typeof A>\"u\")throw ho(\"readSync\");let[p,h]=A;return p.readSync(h,o,a,n,u)}async writePromise(r,o,a,n,u){if((r&va)!==this.magic)return typeof o==\"string\"?await this.baseFs.writePromise(r,o,a):await this.baseFs.writePromise(r,o,a,n,u);let A=this.fdMap.get(r);if(typeof A>\"u\")throw ho(\"write\");let[p,h]=A;return typeof o==\"string\"?await p.writePromise(h,o,a):await p.writePromise(h,o,a,n,u)}writeSync(r,o,a,n,u){if((r&va)!==this.magic)return typeof o==\"string\"?this.baseFs.writeSync(r,o,a):this.baseFs.writeSync(r,o,a,n,u);let A=this.fdMap.get(r);if(typeof A>\"u\")throw ho(\"writeSync\");let[p,h]=A;return typeof o==\"string\"?p.writeSync(h,o,a):p.writeSync(h,o,a,n,u)}async closePromise(r){if((r&va)!==this.magic)return await this.baseFs.closePromise(r);let o=this.fdMap.get(r);if(typeof o>\"u\")throw ho(\"close\");this.fdMap.delete(r);let[a,n]=o;return await a.closePromise(n)}closeSync(r){if((r&va)!==this.magic)return this.baseFs.closeSync(r);let o=this.fdMap.get(r);if(typeof o>\"u\")throw ho(\"closeSync\");this.fdMap.delete(r);let[a,n]=o;return a.closeSync(n)}createReadStream(r,o){return r===null?this.baseFs.createReadStream(r,o):this.makeCallSync(r,()=>this.baseFs.createReadStream(r,o),(a,{archivePath:n,subPath:u})=>{let A=a.createReadStream(u,o);return A.path=Ae.fromPortablePath(this.pathUtils.join(n,u)),A})}createWriteStream(r,o){return r===null?this.baseFs.createWriteStream(r,o):this.makeCallSync(r,()=>this.baseFs.createWriteStream(r,o),(a,{subPath:n})=>a.createWriteStream(n,o))}async realpathPromise(r){return await this.makeCallPromise(r,async()=>await this.baseFs.realpathPromise(r),async(o,{archivePath:a,subPath:n})=>{let u=this.realPaths.get(a);return typeof u>\"u\"&&(u=await this.baseFs.realpathPromise(a),this.realPaths.set(a,u)),this.pathUtils.join(u,this.pathUtils.relative(Bt.root,await o.realpathPromise(n)))})}realpathSync(r){return this.makeCallSync(r,()=>this.baseFs.realpathSync(r),(o,{archivePath:a,subPath:n})=>{let u=this.realPaths.get(a);return typeof u>\"u\"&&(u=this.baseFs.realpathSync(a),this.realPaths.set(a,u)),this.pathUtils.join(u,this.pathUtils.relative(Bt.root,o.realpathSync(n)))})}async existsPromise(r){return await this.makeCallPromise(r,async()=>await this.baseFs.existsPromise(r),async(o,{subPath:a})=>await o.existsPromise(a))}existsSync(r){return this.makeCallSync(r,()=>this.baseFs.existsSync(r),(o,{subPath:a})=>o.existsSync(a))}async accessPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.accessPromise(r,o),async(a,{subPath:n})=>await a.accessPromise(n,o))}accessSync(r,o){return this.makeCallSync(r,()=>this.baseFs.accessSync(r,o),(a,{subPath:n})=>a.accessSync(n,o))}async statPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.statPromise(r,o),async(a,{subPath:n})=>await a.statPromise(n,o))}statSync(r,o){return this.makeCallSync(r,()=>this.baseFs.statSync(r,o),(a,{subPath:n})=>a.statSync(n,o))}async fstatPromise(r,o){if((r&va)!==this.magic)return this.baseFs.fstatPromise(r,o);let a=this.fdMap.get(r);if(typeof a>\"u\")throw ho(\"fstat\");let[n,u]=a;return n.fstatPromise(u,o)}fstatSync(r,o){if((r&va)!==this.magic)return this.baseFs.fstatSync(r,o);let a=this.fdMap.get(r);if(typeof a>\"u\")throw ho(\"fstatSync\");let[n,u]=a;return n.fstatSync(u,o)}async lstatPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.lstatPromise(r,o),async(a,{subPath:n})=>await a.lstatPromise(n,o))}lstatSync(r,o){return this.makeCallSync(r,()=>this.baseFs.lstatSync(r,o),(a,{subPath:n})=>a.lstatSync(n,o))}async fchmodPromise(r,o){if((r&va)!==this.magic)return this.baseFs.fchmodPromise(r,o);let a=this.fdMap.get(r);if(typeof a>\"u\")throw ho(\"fchmod\");let[n,u]=a;return n.fchmodPromise(u,o)}fchmodSync(r,o){if((r&va)!==this.magic)return this.baseFs.fchmodSync(r,o);let a=this.fdMap.get(r);if(typeof a>\"u\")throw ho(\"fchmodSync\");let[n,u]=a;return n.fchmodSync(u,o)}async chmodPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.chmodPromise(r,o),async(a,{subPath:n})=>await a.chmodPromise(n,o))}chmodSync(r,o){return this.makeCallSync(r,()=>this.baseFs.chmodSync(r,o),(a,{subPath:n})=>a.chmodSync(n,o))}async fchownPromise(r,o,a){if((r&va)!==this.magic)return this.baseFs.fchownPromise(r,o,a);let n=this.fdMap.get(r);if(typeof n>\"u\")throw ho(\"fchown\");let[u,A]=n;return u.fchownPromise(A,o,a)}fchownSync(r,o,a){if((r&va)!==this.magic)return this.baseFs.fchownSync(r,o,a);let n=this.fdMap.get(r);if(typeof n>\"u\")throw ho(\"fchownSync\");let[u,A]=n;return u.fchownSync(A,o,a)}async chownPromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.chownPromise(r,o,a),async(n,{subPath:u})=>await n.chownPromise(u,o,a))}chownSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.chownSync(r,o,a),(n,{subPath:u})=>n.chownSync(u,o,a))}async renamePromise(r,o){return await this.makeCallPromise(r,async()=>await this.makeCallPromise(o,async()=>await this.baseFs.renamePromise(r,o),async()=>{throw Object.assign(new Error(\"EEXDEV: cross-device link not permitted\"),{code:\"EEXDEV\"})}),async(a,{subPath:n})=>await this.makeCallPromise(o,async()=>{throw Object.assign(new Error(\"EEXDEV: cross-device link not permitted\"),{code:\"EEXDEV\"})},async(u,{subPath:A})=>{if(a!==u)throw Object.assign(new Error(\"EEXDEV: cross-device link not permitted\"),{code:\"EEXDEV\"});return await a.renamePromise(n,A)}))}renameSync(r,o){return this.makeCallSync(r,()=>this.makeCallSync(o,()=>this.baseFs.renameSync(r,o),()=>{throw Object.assign(new Error(\"EEXDEV: cross-device link not permitted\"),{code:\"EEXDEV\"})}),(a,{subPath:n})=>this.makeCallSync(o,()=>{throw Object.assign(new Error(\"EEXDEV: cross-device link not permitted\"),{code:\"EEXDEV\"})},(u,{subPath:A})=>{if(a!==u)throw Object.assign(new Error(\"EEXDEV: cross-device link not permitted\"),{code:\"EEXDEV\"});return a.renameSync(n,A)}))}async copyFilePromise(r,o,a=0){let n=async(u,A,p,h)=>{if(a&K0.constants.COPYFILE_FICLONE_FORCE)throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${A}' -> ${h}'`),{code:\"EXDEV\"});if(a&K0.constants.COPYFILE_EXCL&&await this.existsPromise(A))throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${A}' -> '${h}'`),{code:\"EEXIST\"});let E;try{E=await u.readFilePromise(A)}catch{throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${A}' -> '${h}'`),{code:\"EINVAL\"})}await p.writeFilePromise(h,E)};return await this.makeCallPromise(r,async()=>await this.makeCallPromise(o,async()=>await this.baseFs.copyFilePromise(r,o,a),async(u,{subPath:A})=>await n(this.baseFs,r,u,A)),async(u,{subPath:A})=>await this.makeCallPromise(o,async()=>await n(u,A,this.baseFs,o),async(p,{subPath:h})=>u!==p?await n(u,A,p,h):await u.copyFilePromise(A,h,a)))}copyFileSync(r,o,a=0){let n=(u,A,p,h)=>{if(a&K0.constants.COPYFILE_FICLONE_FORCE)throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${A}' -> ${h}'`),{code:\"EXDEV\"});if(a&K0.constants.COPYFILE_EXCL&&this.existsSync(A))throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${A}' -> '${h}'`),{code:\"EEXIST\"});let E;try{E=u.readFileSync(A)}catch{throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${A}' -> '${h}'`),{code:\"EINVAL\"})}p.writeFileSync(h,E)};return this.makeCallSync(r,()=>this.makeCallSync(o,()=>this.baseFs.copyFileSync(r,o,a),(u,{subPath:A})=>n(this.baseFs,r,u,A)),(u,{subPath:A})=>this.makeCallSync(o,()=>n(u,A,this.baseFs,o),(p,{subPath:h})=>u!==p?n(u,A,p,h):u.copyFileSync(A,h,a)))}async appendFilePromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.appendFilePromise(r,o,a),async(n,{subPath:u})=>await n.appendFilePromise(u,o,a))}appendFileSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.appendFileSync(r,o,a),(n,{subPath:u})=>n.appendFileSync(u,o,a))}async writeFilePromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.writeFilePromise(r,o,a),async(n,{subPath:u})=>await n.writeFilePromise(u,o,a))}writeFileSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.writeFileSync(r,o,a),(n,{subPath:u})=>n.writeFileSync(u,o,a))}async unlinkPromise(r){return await this.makeCallPromise(r,async()=>await this.baseFs.unlinkPromise(r),async(o,{subPath:a})=>await o.unlinkPromise(a))}unlinkSync(r){return this.makeCallSync(r,()=>this.baseFs.unlinkSync(r),(o,{subPath:a})=>o.unlinkSync(a))}async utimesPromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.utimesPromise(r,o,a),async(n,{subPath:u})=>await n.utimesPromise(u,o,a))}utimesSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.utimesSync(r,o,a),(n,{subPath:u})=>n.utimesSync(u,o,a))}async lutimesPromise(r,o,a){return await this.makeCallPromise(r,async()=>await this.baseFs.lutimesPromise(r,o,a),async(n,{subPath:u})=>await n.lutimesPromise(u,o,a))}lutimesSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.lutimesSync(r,o,a),(n,{subPath:u})=>n.lutimesSync(u,o,a))}async mkdirPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.mkdirPromise(r,o),async(a,{subPath:n})=>await a.mkdirPromise(n,o))}mkdirSync(r,o){return this.makeCallSync(r,()=>this.baseFs.mkdirSync(r,o),(a,{subPath:n})=>a.mkdirSync(n,o))}async rmdirPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.rmdirPromise(r,o),async(a,{subPath:n})=>await a.rmdirPromise(n,o))}rmdirSync(r,o){return this.makeCallSync(r,()=>this.baseFs.rmdirSync(r,o),(a,{subPath:n})=>a.rmdirSync(n,o))}async rmPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.rmPromise(r,o),async(a,{subPath:n})=>await a.rmPromise(n,o))}rmSync(r,o){return this.makeCallSync(r,()=>this.baseFs.rmSync(r,o),(a,{subPath:n})=>a.rmSync(n,o))}async linkPromise(r,o){return await this.makeCallPromise(o,async()=>await this.baseFs.linkPromise(r,o),async(a,{subPath:n})=>await a.linkPromise(r,n))}linkSync(r,o){return this.makeCallSync(o,()=>this.baseFs.linkSync(r,o),(a,{subPath:n})=>a.linkSync(r,n))}async symlinkPromise(r,o,a){return await this.makeCallPromise(o,async()=>await this.baseFs.symlinkPromise(r,o,a),async(n,{subPath:u})=>await n.symlinkPromise(r,u))}symlinkSync(r,o,a){return this.makeCallSync(o,()=>this.baseFs.symlinkSync(r,o,a),(n,{subPath:u})=>n.symlinkSync(r,u))}async readFilePromise(r,o){return this.makeCallPromise(r,async()=>await this.baseFs.readFilePromise(r,o),async(a,{subPath:n})=>await a.readFilePromise(n,o))}readFileSync(r,o){return this.makeCallSync(r,()=>this.baseFs.readFileSync(r,o),(a,{subPath:n})=>a.readFileSync(n,o))}async readdirPromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.readdirPromise(r,o),async(a,{subPath:n})=>await a.readdirPromise(n,o),{requireSubpath:!1})}readdirSync(r,o){return this.makeCallSync(r,()=>this.baseFs.readdirSync(r,o),(a,{subPath:n})=>a.readdirSync(n,o),{requireSubpath:!1})}async readlinkPromise(r){return await this.makeCallPromise(r,async()=>await this.baseFs.readlinkPromise(r),async(o,{subPath:a})=>await o.readlinkPromise(a))}readlinkSync(r){return this.makeCallSync(r,()=>this.baseFs.readlinkSync(r),(o,{subPath:a})=>o.readlinkSync(a))}async truncatePromise(r,o){return await this.makeCallPromise(r,async()=>await this.baseFs.truncatePromise(r,o),async(a,{subPath:n})=>await a.truncatePromise(n,o))}truncateSync(r,o){return this.makeCallSync(r,()=>this.baseFs.truncateSync(r,o),(a,{subPath:n})=>a.truncateSync(n,o))}async ftruncatePromise(r,o){if((r&va)!==this.magic)return this.baseFs.ftruncatePromise(r,o);let a=this.fdMap.get(r);if(typeof a>\"u\")throw ho(\"ftruncate\");let[n,u]=a;return n.ftruncatePromise(u,o)}ftruncateSync(r,o){if((r&va)!==this.magic)return this.baseFs.ftruncateSync(r,o);let a=this.fdMap.get(r);if(typeof a>\"u\")throw ho(\"ftruncateSync\");let[n,u]=a;return n.ftruncateSync(u,o)}watch(r,o,a){return this.makeCallSync(r,()=>this.baseFs.watch(r,o,a),(n,{subPath:u})=>n.watch(u,o,a))}watchFile(r,o,a){return this.makeCallSync(r,()=>this.baseFs.watchFile(r,o,a),()=>um(this,r,o,a))}unwatchFile(r,o){return this.makeCallSync(r,()=>this.baseFs.unwatchFile(r,o),()=>q0(this,r,o))}async makeCallPromise(r,o,a,{requireSubpath:n=!0}={}){if(typeof r!=\"string\")return await o();let u=this.resolve(r),A=this.findMount(u);return A?n&&A.subPath===\"/\"?await o():await this.getMountPromise(A.archivePath,async p=>await a(p,A)):await o()}makeCallSync(r,o,a,{requireSubpath:n=!0}={}){if(typeof r!=\"string\")return o();let u=this.resolve(r),A=this.findMount(u);return!A||n&&A.subPath===\"/\"?o():this.getMountSync(A.archivePath,p=>a(p,A))}findMount(r){if(this.filter&&!this.filter.test(r))return null;let o=\"\";for(;;){let a=r.substring(o.length),n=this.getMountPoint(a,o);if(!n)return null;if(o=this.pathUtils.join(o,n),!this.isMount.has(o)){if(this.notMount.has(o))continue;try{if(this.typeCheck!==null&&(this.baseFs.statSync(o).mode&K0.constants.S_IFMT)!==this.typeCheck){this.notMount.add(o);continue}}catch{return null}this.isMount.add(o)}return{archivePath:o,subPath:this.pathUtils.join(Bt.root,r.substring(o.length))}}}limitOpenFiles(r){if(this.mountInstances===null)return;let o=Date.now(),a=o+this.maxAge,n=r===null?0:this.mountInstances.size-r;for(let[u,{childFs:A,expiresAt:p,refCount:h}]of this.mountInstances.entries())if(!(h!==0||A.hasOpenFileHandles?.())){if(o>=p){A.saveAndClose?.(),this.mountInstances.delete(u),n-=1;continue}else if(r===null||n<=0){a=p;break}A.saveAndClose?.(),this.mountInstances.delete(u),n-=1}this.limitOpenFilesTimeout===null&&(r===null&&this.mountInstances.size>0||r!==null)&&isFinite(a)&&(this.limitOpenFilesTimeout=setTimeout(()=>{this.limitOpenFilesTimeout=null,this.limitOpenFiles(null)},a-o).unref())}async getMountPromise(r,o){if(this.mountInstances){let a=this.mountInstances.get(r);if(!a){let n=await this.factoryPromise(this.baseFs,r);a=this.mountInstances.get(r),a||(a={childFs:n(),expiresAt:0,refCount:0})}this.mountInstances.delete(r),this.limitOpenFiles(this.maxOpenFiles-1),this.mountInstances.set(r,a),a.expiresAt=Date.now()+this.maxAge,a.refCount+=1;try{return await o(a.childFs)}finally{a.refCount-=1}}else{let a=(await this.factoryPromise(this.baseFs,r))();try{return await o(a)}finally{a.saveAndClose?.()}}}getMountSync(r,o){if(this.mountInstances){let a=this.mountInstances.get(r);return a||(a={childFs:this.factorySync(this.baseFs,r),expiresAt:0,refCount:0}),this.mountInstances.delete(r),this.limitOpenFiles(this.maxOpenFiles-1),this.mountInstances.set(r,a),a.expiresAt=Date.now()+this.maxAge,o(a.childFs)}else{let a=this.factorySync(this.baseFs,r);try{return o(a)}finally{a.saveAndClose?.()}}}}});var $t,nP,kW=It(()=>{W0();Ba();$t=()=>Object.assign(new Error(\"ENOSYS: unsupported filesystem access\"),{code:\"ENOSYS\"}),nP=class t extends hf{static{this.instance=new t}constructor(){super(K)}getExtractHint(){throw $t()}getRealPath(){throw $t()}resolve(){throw $t()}async openPromise(){throw $t()}openSync(){throw $t()}async opendirPromise(){throw $t()}opendirSync(){throw $t()}async readPromise(){throw $t()}readSync(){throw $t()}async writePromise(){throw $t()}writeSync(){throw $t()}async closePromise(){throw $t()}closeSync(){throw $t()}createWriteStream(){throw $t()}createReadStream(){throw $t()}async realpathPromise(){throw $t()}realpathSync(){throw $t()}async readdirPromise(){throw $t()}readdirSync(){throw $t()}async existsPromise(e){throw $t()}existsSync(e){throw $t()}async accessPromise(){throw $t()}accessSync(){throw $t()}async statPromise(){throw $t()}statSync(){throw $t()}async fstatPromise(e){throw $t()}fstatSync(e){throw $t()}async lstatPromise(e){throw $t()}lstatSync(e){throw $t()}async fchmodPromise(){throw $t()}fchmodSync(){throw $t()}async chmodPromise(){throw $t()}chmodSync(){throw $t()}async fchownPromise(){throw $t()}fchownSync(){throw $t()}async chownPromise(){throw $t()}chownSync(){throw $t()}async mkdirPromise(){throw $t()}mkdirSync(){throw $t()}async rmdirPromise(){throw $t()}rmdirSync(){throw $t()}async rmPromise(){throw $t()}rmSync(){throw $t()}async linkPromise(){throw $t()}linkSync(){throw $t()}async symlinkPromise(){throw $t()}symlinkSync(){throw $t()}async renamePromise(){throw $t()}renameSync(){throw $t()}async copyFilePromise(){throw $t()}copyFileSync(){throw $t()}async appendFilePromise(){throw $t()}appendFileSync(){throw $t()}async writeFilePromise(){throw $t()}writeFileSync(){throw $t()}async unlinkPromise(){throw $t()}unlinkSync(){throw $t()}async utimesPromise(){throw $t()}utimesSync(){throw $t()}async lutimesPromise(){throw $t()}lutimesSync(){throw $t()}async readFilePromise(){throw $t()}readFileSync(){throw $t()}async readlinkPromise(){throw $t()}readlinkSync(){throw $t()}async truncatePromise(){throw $t()}truncateSync(){throw $t()}async ftruncatePromise(e,r){throw $t()}ftruncateSync(e,r){throw $t()}watch(){throw $t()}watchFile(){throw $t()}unwatchFile(){throw $t()}}});var Wp,QW=It(()=>{gf();Ba();Wp=class extends ws{constructor(e){super(Ae),this.baseFs=e}mapFromBase(e){return Ae.fromPortablePath(e)}mapToBase(e){return Ae.toPortablePath(e)}}});var C_e,PT,I_e,qs,FW=It(()=>{Y0();gf();Ba();C_e=/^[0-9]+$/,PT=/^(\\/(?:[^/]+\\/)*?(?:\\$\\$virtual|__virtual__))((?:\\/((?:[^/]+-)?[a-f0-9]+)(?:\\/([^/]+))?)?((?:\\/.*)?))$/,I_e=/^([^/]+-)?[a-f0-9]+$/,qs=class t extends ws{static makeVirtualPath(e,r,o){if(K.basename(e)!==\"__virtual__\")throw new Error('Assertion failed: Virtual folders must be named \"__virtual__\"');if(!K.basename(r).match(I_e))throw new Error(\"Assertion failed: Virtual components must be ended by an hexadecimal hash\");let n=K.relative(K.dirname(e),o).split(\"/\"),u=0;for(;u<n.length&&n[u]===\"..\";)u+=1;let A=n.slice(u);return K.join(e,r,String(u),...A)}static resolveVirtual(e){let r=e.match(PT);if(!r||!r[3]&&r[5])return e;let o=K.dirname(r[1]);if(!r[3]||!r[4])return o;if(!C_e.test(r[4]))return e;let n=Number(r[4]),u=\"../\".repeat(n),A=r[5]||\".\";return t.resolveVirtual(K.join(o,u,A))}constructor({baseFs:e=new _n}={}){super(K),this.baseFs=e}getExtractHint(e){return this.baseFs.getExtractHint(e)}getRealPath(){return this.baseFs.getRealPath()}realpathSync(e){let r=e.match(PT);if(!r)return this.baseFs.realpathSync(e);if(!r[5])return e;let o=this.baseFs.realpathSync(this.mapToBase(e));return t.makeVirtualPath(r[1],r[3],o)}async realpathPromise(e){let r=e.match(PT);if(!r)return await this.baseFs.realpathPromise(e);if(!r[5])return e;let o=await this.baseFs.realpathPromise(this.mapToBase(e));return t.makeVirtualPath(r[1],r[3],o)}mapToBase(e){if(e===\"\")return e;if(this.pathUtils.isAbsolute(e))return t.resolveVirtual(e);let r=t.resolveVirtual(this.baseFs.resolve(Bt.dot)),o=t.resolveVirtual(this.baseFs.resolve(e));return K.relative(r,o)||Bt.dot}mapFromBase(e){return e}}});function w_e(t,e){return typeof ST.default.isUtf8<\"u\"?ST.default.isUtf8(t):Buffer.byteLength(e)===t.byteLength}var ST,RW,TW,iP,LW=It(()=>{ST=et(ve(\"buffer\")),RW=ve(\"url\"),TW=ve(\"util\");gf();Ba();iP=class extends ws{constructor(e){super(Ae),this.baseFs=e}mapFromBase(e){return e}mapToBase(e){if(typeof e==\"string\")return e;if(e instanceof URL)return(0,RW.fileURLToPath)(e);if(Buffer.isBuffer(e)){let r=e.toString();if(!w_e(e,r))throw new Error(\"Non-utf8 buffers are not supported at the moment. Please upvote the following issue if you encounter this error: https://github.com/yarnpkg/berry/issues/4942\");return r}throw new Error(`Unsupported path type: ${(0,TW.inspect)(e)}`)}}});var _W,go,df,Yp,sP,oP,fm,_c,Hc,NW,OW,MW,UW,cw,HW=It(()=>{_W=ve(\"readline\"),go=Symbol(\"kBaseFs\"),df=Symbol(\"kFd\"),Yp=Symbol(\"kClosePromise\"),sP=Symbol(\"kCloseResolve\"),oP=Symbol(\"kCloseReject\"),fm=Symbol(\"kRefs\"),_c=Symbol(\"kRef\"),Hc=Symbol(\"kUnref\"),cw=class{constructor(e,r){this[UW]=1;this[MW]=void 0;this[OW]=void 0;this[NW]=void 0;this[go]=r,this[df]=e}get fd(){return this[df]}async appendFile(e,r){try{this[_c](this.appendFile);let o=(typeof r==\"string\"?r:r?.encoding)??void 0;return await this[go].appendFilePromise(this.fd,e,o?{encoding:o}:void 0)}finally{this[Hc]()}}async chown(e,r){try{return this[_c](this.chown),await this[go].fchownPromise(this.fd,e,r)}finally{this[Hc]()}}async chmod(e){try{return this[_c](this.chmod),await this[go].fchmodPromise(this.fd,e)}finally{this[Hc]()}}createReadStream(e){return this[go].createReadStream(null,{...e,fd:this.fd})}createWriteStream(e){return this[go].createWriteStream(null,{...e,fd:this.fd})}datasync(){throw new Error(\"Method not implemented.\")}sync(){throw new Error(\"Method not implemented.\")}async read(e,r,o,a){try{this[_c](this.read);let n;return Buffer.isBuffer(e)?n=e:(e??={},n=e.buffer??Buffer.alloc(16384),r=e.offset||0,o=e.length??n.byteLength,a=e.position??null),r??=0,o??=0,o===0?{bytesRead:o,buffer:n}:{bytesRead:await this[go].readPromise(this.fd,n,r,o,a),buffer:n}}finally{this[Hc]()}}async readFile(e){try{this[_c](this.readFile);let r=(typeof e==\"string\"?e:e?.encoding)??void 0;return await this[go].readFilePromise(this.fd,r)}finally{this[Hc]()}}readLines(e){return(0,_W.createInterface)({input:this.createReadStream(e),crlfDelay:1/0})}async stat(e){try{return this[_c](this.stat),await this[go].fstatPromise(this.fd,e)}finally{this[Hc]()}}async truncate(e){try{return this[_c](this.truncate),await this[go].ftruncatePromise(this.fd,e)}finally{this[Hc]()}}utimes(e,r){throw new Error(\"Method not implemented.\")}async writeFile(e,r){try{this[_c](this.writeFile);let o=(typeof r==\"string\"?r:r?.encoding)??void 0;await this[go].writeFilePromise(this.fd,e,o)}finally{this[Hc]()}}async write(...e){try{if(this[_c](this.write),ArrayBuffer.isView(e[0])){let[r,o,a,n]=e;return{bytesWritten:await this[go].writePromise(this.fd,r,o??void 0,a??void 0,n??void 0),buffer:r}}else{let[r,o,a]=e;return{bytesWritten:await this[go].writePromise(this.fd,r,o,a),buffer:r}}}finally{this[Hc]()}}async writev(e,r){try{this[_c](this.writev);let o=0;if(typeof r<\"u\")for(let a of e){let n=await this.write(a,void 0,void 0,r);o+=n.bytesWritten,r+=n.bytesWritten}else for(let a of e){let n=await this.write(a);o+=n.bytesWritten}return{buffers:e,bytesWritten:o}}finally{this[Hc]()}}readv(e,r){throw new Error(\"Method not implemented.\")}close(){if(this[df]===-1)return Promise.resolve();if(this[Yp])return this[Yp];if(this[fm]--,this[fm]===0){let e=this[df];this[df]=-1,this[Yp]=this[go].closePromise(e).finally(()=>{this[Yp]=void 0})}else this[Yp]=new Promise((e,r)=>{this[sP]=e,this[oP]=r}).finally(()=>{this[Yp]=void 0,this[oP]=void 0,this[sP]=void 0});return this[Yp]}[(go,df,UW=fm,MW=Yp,OW=sP,NW=oP,_c)](e){if(this[df]===-1){let r=new Error(\"file closed\");throw r.code=\"EBADF\",r.syscall=e.name,r}this[fm]++}[Hc](){if(this[fm]--,this[fm]===0){let e=this[df];this[df]=-1,this[go].closePromise(e).then(this[sP],this[oP])}}}});function uw(t,e){e=new iP(e);let r=(o,a,n)=>{let u=o[a];o[a]=n,typeof u?.[pm.promisify.custom]<\"u\"&&(n[pm.promisify.custom]=u[pm.promisify.custom])};{r(t,\"exists\",(o,...a)=>{let u=typeof a[a.length-1]==\"function\"?a.pop():()=>{};process.nextTick(()=>{e.existsPromise(o).then(A=>{u(A)},()=>{u(!1)})})}),r(t,\"read\",(...o)=>{let[a,n,u,A,p,h]=o;if(o.length<=3){let E={};o.length<3?h=o[1]:(E=o[1],h=o[2]),{buffer:n=Buffer.alloc(16384),offset:u=0,length:A=n.byteLength,position:p}=E}if(u==null&&(u=0),A|=0,A===0){process.nextTick(()=>{h(null,0,n)});return}p==null&&(p=-1),process.nextTick(()=>{e.readPromise(a,n,u,A,p).then(E=>{h(null,E,n)},E=>{h(E,0,n)})})});for(let o of qW){let a=o.replace(/Promise$/,\"\");if(typeof t[a]>\"u\")continue;let n=e[o];if(typeof n>\"u\")continue;r(t,a,(...A)=>{let h=typeof A[A.length-1]==\"function\"?A.pop():()=>{};process.nextTick(()=>{n.apply(e,A).then(E=>{h(null,E)},E=>{h(E)})})})}t.realpath.native=t.realpath}{r(t,\"existsSync\",o=>{try{return e.existsSync(o)}catch{return!1}}),r(t,\"readSync\",(...o)=>{let[a,n,u,A,p]=o;return o.length<=3&&({offset:u=0,length:A=n.byteLength,position:p}=o[2]||{}),u==null&&(u=0),A|=0,A===0?0:(p==null&&(p=-1),e.readSync(a,n,u,A,p))});for(let o of B_e){let a=o;if(typeof t[a]>\"u\")continue;let n=e[o];typeof n>\"u\"||r(t,a,n.bind(e))}t.realpathSync.native=t.realpathSync}{let o=t.promises;for(let a of qW){let n=a.replace(/Promise$/,\"\");if(typeof o[n]>\"u\")continue;let u=e[a];typeof u>\"u\"||a!==\"open\"&&r(o,n,(A,...p)=>A instanceof cw?A[n].apply(A,p):u.call(e,A,...p))}r(o,\"open\",async(...a)=>{let n=await e.openPromise(...a);return new cw(n,e)})}t.read[pm.promisify.custom]=async(o,a,...n)=>({bytesRead:await e.readPromise(o,a,...n),buffer:a}),t.write[pm.promisify.custom]=async(o,a,...n)=>({bytesWritten:await e.writePromise(o,a,...n),buffer:a})}function aP(t,e){let r=Object.create(t);return uw(r,e),r}var pm,B_e,qW,jW=It(()=>{pm=ve(\"util\");LW();HW();B_e=new Set([\"accessSync\",\"appendFileSync\",\"createReadStream\",\"createWriteStream\",\"chmodSync\",\"fchmodSync\",\"chownSync\",\"fchownSync\",\"closeSync\",\"copyFileSync\",\"linkSync\",\"lstatSync\",\"fstatSync\",\"lutimesSync\",\"mkdirSync\",\"openSync\",\"opendirSync\",\"readlinkSync\",\"readFileSync\",\"readdirSync\",\"readlinkSync\",\"realpathSync\",\"renameSync\",\"rmdirSync\",\"rmSync\",\"statSync\",\"symlinkSync\",\"truncateSync\",\"ftruncateSync\",\"unlinkSync\",\"unwatchFile\",\"utimesSync\",\"watch\",\"watchFile\",\"writeFileSync\",\"writeSync\"]),qW=new Set([\"accessPromise\",\"appendFilePromise\",\"fchmodPromise\",\"chmodPromise\",\"fchownPromise\",\"chownPromise\",\"closePromise\",\"copyFilePromise\",\"linkPromise\",\"fstatPromise\",\"lstatPromise\",\"lutimesPromise\",\"mkdirPromise\",\"openPromise\",\"opendirPromise\",\"readdirPromise\",\"realpathPromise\",\"readFilePromise\",\"readdirPromise\",\"readlinkPromise\",\"renamePromise\",\"rmdirPromise\",\"rmPromise\",\"statPromise\",\"symlinkPromise\",\"truncatePromise\",\"ftruncatePromise\",\"unlinkPromise\",\"utimesPromise\",\"writeFilePromise\",\"writeSync\"])});function GW(t){let e=Math.ceil(Math.random()*4294967296).toString(16).padStart(8,\"0\");return`${t}${e}`}function WW(){if(xT)return xT;let t=Ae.toPortablePath(YW.default.tmpdir()),e=ae.realpathSync(t);return process.once(\"exit\",()=>{ae.rmtempSync()}),xT={tmpdir:t,realTmpdir:e}}var YW,qc,xT,ae,KW=It(()=>{YW=et(ve(\"os\"));Y0();Ba();qc=new Set,xT=null;ae=Object.assign(new _n,{detachTemp(t){qc.delete(t)},mktempSync(t){let{tmpdir:e,realTmpdir:r}=WW();for(;;){let o=GW(\"xfs-\");try{this.mkdirSync(K.join(e,o))}catch(n){if(n.code===\"EEXIST\")continue;throw n}let a=K.join(r,o);if(qc.add(a),typeof t>\"u\")return a;try{return t(a)}finally{if(qc.has(a)){qc.delete(a);try{this.removeSync(a)}catch{}}}}},async mktempPromise(t){let{tmpdir:e,realTmpdir:r}=WW();for(;;){let o=GW(\"xfs-\");try{await this.mkdirPromise(K.join(e,o))}catch(n){if(n.code===\"EEXIST\")continue;throw n}let a=K.join(r,o);if(qc.add(a),typeof t>\"u\")return a;try{return await t(a)}finally{if(qc.has(a)){qc.delete(a);try{await this.removePromise(a)}catch{}}}}},async rmtempPromise(){await Promise.all(Array.from(qc.values()).map(async t=>{try{await ae.removePromise(t,{maxRetries:0}),qc.delete(t)}catch{}}))},rmtempSync(){for(let t of qc)try{ae.removeSync(t),qc.delete(t)}catch{}}})});var Aw={};Kt(Aw,{AliasFS:()=>ju,BasePortableFakeFS:()=>qu,CustomDir:()=>lw,CwdFS:()=>En,FakeFS:()=>hf,Filename:()=>mr,JailFS:()=>Gu,LazyFS:()=>Am,MountFS:()=>Gp,NoFS:()=>nP,NodeFS:()=>_n,PortablePath:()=>Bt,PosixFS:()=>Wp,ProxiedFS:()=>ws,VirtualFS:()=>qs,constants:()=>Pi,errors:()=>sr,extendFs:()=>aP,normalizeLineEndings:()=>G0,npath:()=>Ae,opendir:()=>eP,patchFs:()=>uw,ppath:()=>K,setupCopyIndex:()=>$D,statUtils:()=>wa,unwatchAllFiles:()=>j0,unwatchFile:()=>q0,watchFile:()=>um,xfs:()=>ae});var Pt=It(()=>{uW();JD();IT();vT();dW();DT();W0();Ba();Ba();wW();W0();DW();SW();xW();bW();kW();Y0();QW();gf();FW();jW();KW()});var ZW=_((qSt,XW)=>{XW.exports=JW;JW.sync=D_e;var VW=ve(\"fs\");function v_e(t,e){var r=e.pathExt!==void 0?e.pathExt:process.env.PATHEXT;if(!r||(r=r.split(\";\"),r.indexOf(\"\")!==-1))return!0;for(var o=0;o<r.length;o++){var a=r[o].toLowerCase();if(a&&t.substr(-a.length).toLowerCase()===a)return!0}return!1}function zW(t,e,r){return!t.isSymbolicLink()&&!t.isFile()?!1:v_e(e,r)}function JW(t,e,r){VW.stat(t,function(o,a){r(o,o?!1:zW(a,t,e))})}function D_e(t,e){return zW(VW.statSync(t),t,e)}});var nY=_((jSt,rY)=>{rY.exports=eY;eY.sync=P_e;var $W=ve(\"fs\");function eY(t,e,r){$W.stat(t,function(o,a){r(o,o?!1:tY(a,e))})}function P_e(t,e){return tY($W.statSync(t),e)}function tY(t,e){return t.isFile()&&S_e(t,e)}function S_e(t,e){var r=t.mode,o=t.uid,a=t.gid,n=e.uid!==void 0?e.uid:process.getuid&&process.getuid(),u=e.gid!==void 0?e.gid:process.getgid&&process.getgid(),A=parseInt(\"100\",8),p=parseInt(\"010\",8),h=parseInt(\"001\",8),E=A|p,w=r&h||r&p&&a===u||r&A&&o===n||r&E&&n===0;return w}});var sY=_((WSt,iY)=>{var GSt=ve(\"fs\"),lP;process.platform===\"win32\"||global.TESTING_WINDOWS?lP=ZW():lP=nY();iY.exports=bT;bT.sync=x_e;function bT(t,e,r){if(typeof e==\"function\"&&(r=e,e={}),!r){if(typeof Promise!=\"function\")throw new TypeError(\"callback not provided\");return new Promise(function(o,a){bT(t,e||{},function(n,u){n?a(n):o(u)})})}lP(t,e||{},function(o,a){o&&(o.code===\"EACCES\"||e&&e.ignoreErrors)&&(o=null,a=!1),r(o,a)})}function x_e(t,e){try{return lP.sync(t,e||{})}catch(r){if(e&&e.ignoreErrors||r.code===\"EACCES\")return!1;throw r}}});var fY=_((YSt,AY)=>{var hm=process.platform===\"win32\"||process.env.OSTYPE===\"cygwin\"||process.env.OSTYPE===\"msys\",oY=ve(\"path\"),b_e=hm?\";\":\":\",aY=sY(),lY=t=>Object.assign(new Error(`not found: ${t}`),{code:\"ENOENT\"}),cY=(t,e)=>{let r=e.colon||b_e,o=t.match(/\\//)||hm&&t.match(/\\\\/)?[\"\"]:[...hm?[process.cwd()]:[],...(e.path||process.env.PATH||\"\").split(r)],a=hm?e.pathExt||process.env.PATHEXT||\".EXE;.CMD;.BAT;.COM\":\"\",n=hm?a.split(r):[\"\"];return hm&&t.indexOf(\".\")!==-1&&n[0]!==\"\"&&n.unshift(\"\"),{pathEnv:o,pathExt:n,pathExtExe:a}},uY=(t,e,r)=>{typeof e==\"function\"&&(r=e,e={}),e||(e={});let{pathEnv:o,pathExt:a,pathExtExe:n}=cY(t,e),u=[],A=h=>new Promise((E,w)=>{if(h===o.length)return e.all&&u.length?E(u):w(lY(t));let D=o[h],b=/^\".*\"$/.test(D)?D.slice(1,-1):D,C=oY.join(b,t),T=!b&&/^\\.[\\\\\\/]/.test(t)?t.slice(0,2)+C:C;E(p(T,h,0))}),p=(h,E,w)=>new Promise((D,b)=>{if(w===a.length)return D(A(E+1));let C=a[w];aY(h+C,{pathExt:n},(T,N)=>{if(!T&&N)if(e.all)u.push(h+C);else return D(h+C);return D(p(h,E,w+1))})});return r?A(0).then(h=>r(null,h),r):A(0)},k_e=(t,e)=>{e=e||{};let{pathEnv:r,pathExt:o,pathExtExe:a}=cY(t,e),n=[];for(let u=0;u<r.length;u++){let A=r[u],p=/^\".*\"$/.test(A)?A.slice(1,-1):A,h=oY.join(p,t),E=!p&&/^\\.[\\\\\\/]/.test(t)?t.slice(0,2)+h:h;for(let w=0;w<o.length;w++){let D=E+o[w];try{if(aY.sync(D,{pathExt:a}))if(e.all)n.push(D);else return D}catch{}}}if(e.all&&n.length)return n;if(e.nothrow)return null;throw lY(t)};AY.exports=uY;uY.sync=k_e});var hY=_((KSt,kT)=>{\"use strict\";var pY=(t={})=>{let e=t.env||process.env;return(t.platform||process.platform)!==\"win32\"?\"PATH\":Object.keys(e).reverse().find(o=>o.toUpperCase()===\"PATH\")||\"Path\"};kT.exports=pY;kT.exports.default=pY});var yY=_((VSt,mY)=>{\"use strict\";var gY=ve(\"path\"),Q_e=fY(),F_e=hY();function dY(t,e){let r=t.options.env||process.env,o=process.cwd(),a=t.options.cwd!=null,n=a&&process.chdir!==void 0&&!process.chdir.disabled;if(n)try{process.chdir(t.options.cwd)}catch{}let u;try{u=Q_e.sync(t.command,{path:r[F_e({env:r})],pathExt:e?gY.delimiter:void 0})}catch{}finally{n&&process.chdir(o)}return u&&(u=gY.resolve(a?t.options.cwd:\"\",u)),u}function R_e(t){return dY(t)||dY(t,!0)}mY.exports=R_e});var EY=_((zSt,FT)=>{\"use strict\";var QT=/([()\\][%!^\"`<>&|;, *?])/g;function T_e(t){return t=t.replace(QT,\"^$1\"),t}function L_e(t,e){return t=`${t}`,t=t.replace(/(\\\\*)\"/g,'$1$1\\\\\"'),t=t.replace(/(\\\\*)$/,\"$1$1\"),t=`\"${t}\"`,t=t.replace(QT,\"^$1\"),e&&(t=t.replace(QT,\"^$1\")),t}FT.exports.command=T_e;FT.exports.argument=L_e});var IY=_((JSt,CY)=>{\"use strict\";CY.exports=/^#!(.*)/});var BY=_((XSt,wY)=>{\"use strict\";var N_e=IY();wY.exports=(t=\"\")=>{let e=t.match(N_e);if(!e)return null;let[r,o]=e[0].replace(/#! ?/,\"\").split(\" \"),a=r.split(\"/\").pop();return a===\"env\"?o:o?`${a} ${o}`:a}});var DY=_((ZSt,vY)=>{\"use strict\";var RT=ve(\"fs\"),O_e=BY();function M_e(t){let r=Buffer.alloc(150),o;try{o=RT.openSync(t,\"r\"),RT.readSync(o,r,0,150,0),RT.closeSync(o)}catch{}return O_e(r.toString())}vY.exports=M_e});var bY=_(($St,xY)=>{\"use strict\";var U_e=ve(\"path\"),PY=yY(),SY=EY(),__e=DY(),H_e=process.platform===\"win32\",q_e=/\\.(?:com|exe)$/i,j_e=/node_modules[\\\\/].bin[\\\\/][^\\\\/]+\\.cmd$/i;function G_e(t){t.file=PY(t);let e=t.file&&__e(t.file);return e?(t.args.unshift(t.file),t.command=e,PY(t)):t.file}function W_e(t){if(!H_e)return t;let e=G_e(t),r=!q_e.test(e);if(t.options.forceShell||r){let o=j_e.test(e);t.command=U_e.normalize(t.command),t.command=SY.command(t.command),t.args=t.args.map(n=>SY.argument(n,o));let a=[t.command].concat(t.args).join(\" \");t.args=[\"/d\",\"/s\",\"/c\",`\"${a}\"`],t.command=process.env.comspec||\"cmd.exe\",t.options.windowsVerbatimArguments=!0}return t}function Y_e(t,e,r){e&&!Array.isArray(e)&&(r=e,e=null),e=e?e.slice(0):[],r=Object.assign({},r);let o={command:t,args:e,options:r,file:void 0,original:{command:t,args:e}};return r.shell?o:W_e(o)}xY.exports=Y_e});var FY=_((ext,QY)=>{\"use strict\";var TT=process.platform===\"win32\";function LT(t,e){return Object.assign(new Error(`${e} ${t.command} ENOENT`),{code:\"ENOENT\",errno:\"ENOENT\",syscall:`${e} ${t.command}`,path:t.command,spawnargs:t.args})}function K_e(t,e){if(!TT)return;let r=t.emit;t.emit=function(o,a){if(o===\"exit\"){let n=kY(a,e,\"spawn\");if(n)return r.call(t,\"error\",n)}return r.apply(t,arguments)}}function kY(t,e){return TT&&t===1&&!e.file?LT(e.original,\"spawn\"):null}function V_e(t,e){return TT&&t===1&&!e.file?LT(e.original,\"spawnSync\"):null}QY.exports={hookChildProcess:K_e,verifyENOENT:kY,verifyENOENTSync:V_e,notFoundError:LT}});var MT=_((txt,gm)=>{\"use strict\";var RY=ve(\"child_process\"),NT=bY(),OT=FY();function TY(t,e,r){let o=NT(t,e,r),a=RY.spawn(o.command,o.args,o.options);return OT.hookChildProcess(a,o),a}function z_e(t,e,r){let o=NT(t,e,r),a=RY.spawnSync(o.command,o.args,o.options);return a.error=a.error||OT.verifyENOENTSync(a.status,o),a}gm.exports=TY;gm.exports.spawn=TY;gm.exports.sync=z_e;gm.exports._parse=NT;gm.exports._enoent=OT});var NY=_((rxt,LY)=>{\"use strict\";function J_e(t,e){function r(){this.constructor=t}r.prototype=e.prototype,t.prototype=new r}function V0(t,e,r,o){this.message=t,this.expected=e,this.found=r,this.location=o,this.name=\"SyntaxError\",typeof Error.captureStackTrace==\"function\"&&Error.captureStackTrace(this,V0)}J_e(V0,Error);V0.buildMessage=function(t,e){var r={literal:function(h){return'\"'+a(h.text)+'\"'},class:function(h){var E=\"\",w;for(w=0;w<h.parts.length;w++)E+=h.parts[w]instanceof Array?n(h.parts[w][0])+\"-\"+n(h.parts[w][1]):n(h.parts[w]);return\"[\"+(h.inverted?\"^\":\"\")+E+\"]\"},any:function(h){return\"any character\"},end:function(h){return\"end of input\"},other:function(h){return h.description}};function o(h){return h.charCodeAt(0).toString(16).toUpperCase()}function a(h){return h.replace(/\\\\/g,\"\\\\\\\\\").replace(/\"/g,'\\\\\"').replace(/\\0/g,\"\\\\0\").replace(/\\t/g,\"\\\\t\").replace(/\\n/g,\"\\\\n\").replace(/\\r/g,\"\\\\r\").replace(/[\\x00-\\x0F]/g,function(E){return\"\\\\x0\"+o(E)}).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g,function(E){return\"\\\\x\"+o(E)})}function n(h){return h.replace(/\\\\/g,\"\\\\\\\\\").replace(/\\]/g,\"\\\\]\").replace(/\\^/g,\"\\\\^\").replace(/-/g,\"\\\\-\").replace(/\\0/g,\"\\\\0\").replace(/\\t/g,\"\\\\t\").replace(/\\n/g,\"\\\\n\").replace(/\\r/g,\"\\\\r\").replace(/[\\x00-\\x0F]/g,function(E){return\"\\\\x0\"+o(E)}).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g,function(E){return\"\\\\x\"+o(E)})}function u(h){return r[h.type](h)}function A(h){var E=new Array(h.length),w,D;for(w=0;w<h.length;w++)E[w]=u(h[w]);if(E.sort(),E.length>0){for(w=1,D=1;w<E.length;w++)E[w-1]!==E[w]&&(E[D]=E[w],D++);E.length=D}switch(E.length){case 1:return E[0];case 2:return E[0]+\" or \"+E[1];default:return E.slice(0,-1).join(\", \")+\", or \"+E[E.length-1]}}function p(h){return h?'\"'+a(h)+'\"':\"end of input\"}return\"Expected \"+A(t)+\" but \"+p(e)+\" found.\"};function X_e(t,e){e=e!==void 0?e:{};var r={},o={Start:ha},a=ha,n=function(L){return L||[]},u=function(L,V,re){return[{command:L,type:V}].concat(re||[])},A=function(L,V){return[{command:L,type:V||\";\"}]},p=function(L){return L},h=\";\",E=cr(\";\",!1),w=\"&\",D=cr(\"&\",!1),b=function(L,V){return V?{chain:L,then:V}:{chain:L}},C=function(L,V){return{type:L,line:V}},T=\"&&\",N=cr(\"&&\",!1),U=\"||\",z=cr(\"||\",!1),te=function(L,V){return V?{...L,then:V}:L},le=function(L,V){return{type:L,chain:V}},ce=\"|&\",ue=cr(\"|&\",!1),Ie=\"|\",he=cr(\"|\",!1),De=\"=\",Ee=cr(\"=\",!1),g=function(L,V){return{name:L,args:[V]}},me=function(L){return{name:L,args:[]}},Ce=\"(\",fe=cr(\"(\",!1),ie=\")\",Z=cr(\")\",!1),Pe=function(L,V){return{type:\"subshell\",subshell:L,args:V}},Re=\"{\",ht=cr(\"{\",!1),q=\"}\",nt=cr(\"}\",!1),Le=function(L,V){return{type:\"group\",group:L,args:V}},Te=function(L,V){return{type:\"command\",args:V,envs:L}},ke=function(L){return{type:\"envs\",envs:L}},Ve=function(L){return L},xe=function(L){return L},tt=/^[0-9]/,He=Ni([[\"0\",\"9\"]],!1,!1),x=function(L,V,re){return{type:\"redirection\",subtype:V,fd:L!==null?parseInt(L):null,args:[re]}},I=\">>\",S=cr(\">>\",!1),y=\">&\",R=cr(\">&\",!1),J=\">\",X=cr(\">\",!1),$=\"<<<\",se=cr(\"<<<\",!1),be=\"<&\",Fe=cr(\"<&\",!1),lt=\"<\",Et=cr(\"<\",!1),qt=function(L){return{type:\"argument\",segments:[].concat(...L)}},nr=function(L){return L},St=\"$'\",cn=cr(\"$'\",!1),Pr=\"'\",yr=cr(\"'\",!1),Rr=function(L){return[{type:\"text\",text:L}]},Xr='\"\"',$n=cr('\"\"',!1),Xs=function(){return{type:\"text\",text:\"\"}},Hi='\"',Qs=cr('\"',!1),Zs=function(L){return L},bi=function(L){return{type:\"arithmetic\",arithmetic:L,quoted:!0}},Fs=function(L){return{type:\"shell\",shell:L,quoted:!0}},$s=function(L){return{type:\"variable\",...L,quoted:!0}},SA=function(L){return{type:\"text\",text:L}},gu=function(L){return{type:\"arithmetic\",arithmetic:L,quoted:!1}},op=function(L){return{type:\"shell\",shell:L,quoted:!1}},ap=function(L){return{type:\"variable\",...L,quoted:!1}},Rs=function(L){return{type:\"glob\",pattern:L}},Nn=/^[^']/,hs=Ni([\"'\"],!0,!1),Ts=function(L){return L.join(\"\")},pc=/^[^$\"]/,hc=Ni([\"$\",'\"'],!0,!1),gc=`\\\\\n`,xA=cr(`\\\\\n`,!1),bA=function(){return\"\"},Ro=\"\\\\\",To=cr(\"\\\\\",!1),kA=/^[\\\\$\"`]/,pr=Ni([\"\\\\\",\"$\",'\"',\"`\"],!1,!1),Me=function(L){return L},ia=\"\\\\a\",dc=cr(\"\\\\a\",!1),Er=function(){return\"a\"},du=\"\\\\b\",QA=cr(\"\\\\b\",!1),FA=function(){return\"\\b\"},mc=/^[Ee]/,yc=Ni([\"E\",\"e\"],!1,!1),Il=function(){return\"\\x1B\"},we=\"\\\\f\",Tt=cr(\"\\\\f\",!1),wl=function(){return\"\\f\"},Bi=\"\\\\n\",Ls=cr(\"\\\\n\",!1),Ft=function(){return`\n`},Bn=\"\\\\r\",Lo=cr(\"\\\\r\",!1),ki=function(){return\"\\r\"},vi=\"\\\\t\",sa=cr(\"\\\\t\",!1),un=function(){return\"\t\"},qn=\"\\\\v\",Ec=cr(\"\\\\v\",!1),lp=function(){return\"\\v\"},oa=/^[\\\\'\"?]/,aa=Ni([\"\\\\\",\"'\",'\"',\"?\"],!1,!1),la=function(L){return String.fromCharCode(parseInt(L,16))},Ze=\"\\\\x\",ca=cr(\"\\\\x\",!1),mu=\"\\\\u\",Bl=cr(\"\\\\u\",!1),dn=\"\\\\U\",No=cr(\"\\\\U\",!1),RA=function(L){return String.fromCodePoint(parseInt(L,16))},TA=/^[0-7]/,Oo=Ni([[\"0\",\"7\"]],!1,!1),qa=/^[0-9a-fA-f]/,Ot=Ni([[\"0\",\"9\"],[\"a\",\"f\"],[\"A\",\"f\"]],!1,!1),vn=Iu(),Mo=\"{}\",ua=cr(\"{}\",!1),qi=function(){return\"{}\"},vl=\"-\",Cc=cr(\"-\",!1),Dl=\"+\",Aa=cr(\"+\",!1),Di=\".\",rs=cr(\".\",!1),ja=function(L,V,re){return{type:\"number\",value:(L===\"-\"?-1:1)*parseFloat(V.join(\"\")+\".\"+re.join(\"\"))}},yu=function(L,V){return{type:\"number\",value:(L===\"-\"?-1:1)*parseInt(V.join(\"\"))}},Pl=function(L){return{type:\"variable\",...L}},pi=function(L){return{type:\"variable\",name:L}},Dn=function(L){return L},Sl=\"*\",ze=cr(\"*\",!1),it=\"/\",vt=cr(\"/\",!1),ar=function(L,V,re){return{type:V===\"*\"?\"multiplication\":\"division\",right:re}},ee=function(L,V){return V.reduce((re,ge)=>({left:re,...ge}),L)},ye=function(L,V,re){return{type:V===\"+\"?\"addition\":\"subtraction\",right:re}},Ne=\"$((\",gt=cr(\"$((\",!1),mt=\"))\",Dt=cr(\"))\",!1),er=function(L){return L},sn=\"$(\",ei=cr(\"$(\",!1),Qi=function(L){return L},Pn=\"${\",fa=cr(\"${\",!1),wd=\":-\",BI=cr(\":-\",!1),eo=function(L,V){return{name:L,defaultValue:V}},Bd=\":-}\",cp=cr(\":-}\",!1),vI=function(L){return{name:L,defaultValue:[]}},to=\":+\",up=cr(\":+\",!1),Ap=function(L,V){return{name:L,alternativeValue:V}},Ic=\":+}\",fp=cr(\":+}\",!1),s0=function(L){return{name:L,alternativeValue:[]}},o0=function(L){return{name:L}},a0=\"$\",vd=cr(\"$\",!1),Eu=function(L){return e.isGlobPattern(L)},ro=function(L){return L},Ga=/^[a-zA-Z0-9_]/,pp=Ni([[\"a\",\"z\"],[\"A\",\"Z\"],[\"0\",\"9\"],\"_\"],!1,!1),l0=function(){return xd()},Wa=/^[$@*?#a-zA-Z0-9_\\-]/,Ya=Ni([\"$\",\"@\",\"*\",\"?\",\"#\",[\"a\",\"z\"],[\"A\",\"Z\"],[\"0\",\"9\"],\"_\",\"-\"],!1,!1),Dd=/^[()}<>$|&; \\t\"']/,LA=Ni([\"(\",\")\",\"}\",\"<\",\">\",\"$\",\"|\",\"&\",\";\",\" \",\"\t\",'\"',\"'\"],!1,!1),Pd=/^[<>&; \\t\"']/,Sd=Ni([\"<\",\">\",\"&\",\";\",\" \",\"\t\",'\"',\"'\"],!1,!1),NA=/^[ \\t]/,OA=Ni([\" \",\"\t\"],!1,!1),W=0,xt=0,MA=[{line:1,column:1}],no=0,Cu=[],dt=0,wc;if(\"startRule\"in e){if(!(e.startRule in o))throw new Error(`Can't start parsing from rule \"`+e.startRule+'\".');a=o[e.startRule]}function xd(){return t.substring(xt,W)}function c0(){return wu(xt,W)}function DI(L,V){throw V=V!==void 0?V:wu(xt,W),UA([u0(L)],t.substring(xt,W),V)}function hp(L,V){throw V=V!==void 0?V:wu(xt,W),oi(L,V)}function cr(L,V){return{type:\"literal\",text:L,ignoreCase:V}}function Ni(L,V,re){return{type:\"class\",parts:L,inverted:V,ignoreCase:re}}function Iu(){return{type:\"any\"}}function pa(){return{type:\"end\"}}function u0(L){return{type:\"other\",description:L}}function Bc(L){var V=MA[L],re;if(V)return V;for(re=L-1;!MA[re];)re--;for(V=MA[re],V={line:V.line,column:V.column};re<L;)t.charCodeAt(re)===10?(V.line++,V.column=1):V.column++,re++;return MA[L]=V,V}function wu(L,V){var re=Bc(L),ge=Bc(V);return{start:{offset:L,line:re.line,column:re.column},end:{offset:V,line:ge.line,column:ge.column}}}function wt(L){W<no||(W>no&&(no=W,Cu=[]),Cu.push(L))}function oi(L,V){return new V0(L,null,null,V)}function UA(L,V,re){return new V0(V0.buildMessage(L,V),L,V,re)}function ha(){var L,V,re;for(L=W,V=[],re=bt();re!==r;)V.push(re),re=bt();return V!==r?(re=Uo(),re===r&&(re=null),re!==r?(xt=L,V=n(re),L=V):(W=L,L=r)):(W=L,L=r),L}function Uo(){var L,V,re,ge,Ye;if(L=W,V=gp(),V!==r){for(re=[],ge=bt();ge!==r;)re.push(ge),ge=bt();re!==r?(ge=A0(),ge!==r?(Ye=ga(),Ye===r&&(Ye=null),Ye!==r?(xt=L,V=u(V,ge,Ye),L=V):(W=L,L=r)):(W=L,L=r)):(W=L,L=r)}else W=L,L=r;if(L===r)if(L=W,V=gp(),V!==r){for(re=[],ge=bt();ge!==r;)re.push(ge),ge=bt();re!==r?(ge=A0(),ge===r&&(ge=null),ge!==r?(xt=L,V=A(V,ge),L=V):(W=L,L=r)):(W=L,L=r)}else W=L,L=r;return L}function ga(){var L,V,re,ge,Ye;for(L=W,V=[],re=bt();re!==r;)V.push(re),re=bt();if(V!==r)if(re=Uo(),re!==r){for(ge=[],Ye=bt();Ye!==r;)ge.push(Ye),Ye=bt();ge!==r?(xt=L,V=p(re),L=V):(W=L,L=r)}else W=L,L=r;else W=L,L=r;return L}function A0(){var L;return t.charCodeAt(W)===59?(L=h,W++):(L=r,dt===0&&wt(E)),L===r&&(t.charCodeAt(W)===38?(L=w,W++):(L=r,dt===0&&wt(D))),L}function gp(){var L,V,re;return L=W,V=_A(),V!==r?(re=f0(),re===r&&(re=null),re!==r?(xt=L,V=b(V,re),L=V):(W=L,L=r)):(W=L,L=r),L}function f0(){var L,V,re,ge,Ye,At,hr;for(L=W,V=[],re=bt();re!==r;)V.push(re),re=bt();if(V!==r)if(re=bd(),re!==r){for(ge=[],Ye=bt();Ye!==r;)ge.push(Ye),Ye=bt();if(ge!==r)if(Ye=gp(),Ye!==r){for(At=[],hr=bt();hr!==r;)At.push(hr),hr=bt();At!==r?(xt=L,V=C(re,Ye),L=V):(W=L,L=r)}else W=L,L=r;else W=L,L=r}else W=L,L=r;else W=L,L=r;return L}function bd(){var L;return t.substr(W,2)===T?(L=T,W+=2):(L=r,dt===0&&wt(N)),L===r&&(t.substr(W,2)===U?(L=U,W+=2):(L=r,dt===0&&wt(z))),L}function _A(){var L,V,re;return L=W,V=Bu(),V!==r?(re=p0(),re===r&&(re=null),re!==r?(xt=L,V=te(V,re),L=V):(W=L,L=r)):(W=L,L=r),L}function p0(){var L,V,re,ge,Ye,At,hr;for(L=W,V=[],re=bt();re!==r;)V.push(re),re=bt();if(V!==r)if(re=vc(),re!==r){for(ge=[],Ye=bt();Ye!==r;)ge.push(Ye),Ye=bt();if(ge!==r)if(Ye=_A(),Ye!==r){for(At=[],hr=bt();hr!==r;)At.push(hr),hr=bt();At!==r?(xt=L,V=le(re,Ye),L=V):(W=L,L=r)}else W=L,L=r;else W=L,L=r}else W=L,L=r;else W=L,L=r;return L}function vc(){var L;return t.substr(W,2)===ce?(L=ce,W+=2):(L=r,dt===0&&wt(ue)),L===r&&(t.charCodeAt(W)===124?(L=Ie,W++):(L=r,dt===0&&wt(he))),L}function Dc(){var L,V,re,ge,Ye,At;if(L=W,V=yp(),V!==r)if(t.charCodeAt(W)===61?(re=De,W++):(re=r,dt===0&&wt(Ee)),re!==r)if(ge=HA(),ge!==r){for(Ye=[],At=bt();At!==r;)Ye.push(At),At=bt();Ye!==r?(xt=L,V=g(V,ge),L=V):(W=L,L=r)}else W=L,L=r;else W=L,L=r;else W=L,L=r;if(L===r)if(L=W,V=yp(),V!==r)if(t.charCodeAt(W)===61?(re=De,W++):(re=r,dt===0&&wt(Ee)),re!==r){for(ge=[],Ye=bt();Ye!==r;)ge.push(Ye),Ye=bt();ge!==r?(xt=L,V=me(V),L=V):(W=L,L=r)}else W=L,L=r;else W=L,L=r;return L}function Bu(){var L,V,re,ge,Ye,At,hr,Ir,Rn,ai,ns;for(L=W,V=[],re=bt();re!==r;)V.push(re),re=bt();if(V!==r)if(t.charCodeAt(W)===40?(re=Ce,W++):(re=r,dt===0&&wt(fe)),re!==r){for(ge=[],Ye=bt();Ye!==r;)ge.push(Ye),Ye=bt();if(ge!==r)if(Ye=Uo(),Ye!==r){for(At=[],hr=bt();hr!==r;)At.push(hr),hr=bt();if(At!==r)if(t.charCodeAt(W)===41?(hr=ie,W++):(hr=r,dt===0&&wt(Z)),hr!==r){for(Ir=[],Rn=bt();Rn!==r;)Ir.push(Rn),Rn=bt();if(Ir!==r){for(Rn=[],ai=On();ai!==r;)Rn.push(ai),ai=On();if(Rn!==r){for(ai=[],ns=bt();ns!==r;)ai.push(ns),ns=bt();ai!==r?(xt=L,V=Pe(Ye,Rn),L=V):(W=L,L=r)}else W=L,L=r}else W=L,L=r}else W=L,L=r;else W=L,L=r}else W=L,L=r;else W=L,L=r}else W=L,L=r;else W=L,L=r;if(L===r){for(L=W,V=[],re=bt();re!==r;)V.push(re),re=bt();if(V!==r)if(t.charCodeAt(W)===123?(re=Re,W++):(re=r,dt===0&&wt(ht)),re!==r){for(ge=[],Ye=bt();Ye!==r;)ge.push(Ye),Ye=bt();if(ge!==r)if(Ye=Uo(),Ye!==r){for(At=[],hr=bt();hr!==r;)At.push(hr),hr=bt();if(At!==r)if(t.charCodeAt(W)===125?(hr=q,W++):(hr=r,dt===0&&wt(nt)),hr!==r){for(Ir=[],Rn=bt();Rn!==r;)Ir.push(Rn),Rn=bt();if(Ir!==r){for(Rn=[],ai=On();ai!==r;)Rn.push(ai),ai=On();if(Rn!==r){for(ai=[],ns=bt();ns!==r;)ai.push(ns),ns=bt();ai!==r?(xt=L,V=Le(Ye,Rn),L=V):(W=L,L=r)}else W=L,L=r}else W=L,L=r}else W=L,L=r;else W=L,L=r}else W=L,L=r;else W=L,L=r}else W=L,L=r;else W=L,L=r;if(L===r){for(L=W,V=[],re=bt();re!==r;)V.push(re),re=bt();if(V!==r){for(re=[],ge=Dc();ge!==r;)re.push(ge),ge=Dc();if(re!==r){for(ge=[],Ye=bt();Ye!==r;)ge.push(Ye),Ye=bt();if(ge!==r){if(Ye=[],At=Pc(),At!==r)for(;At!==r;)Ye.push(At),At=Pc();else Ye=r;if(Ye!==r){for(At=[],hr=bt();hr!==r;)At.push(hr),hr=bt();At!==r?(xt=L,V=Te(re,Ye),L=V):(W=L,L=r)}else W=L,L=r}else W=L,L=r}else W=L,L=r}else W=L,L=r;if(L===r){for(L=W,V=[],re=bt();re!==r;)V.push(re),re=bt();if(V!==r){if(re=[],ge=Dc(),ge!==r)for(;ge!==r;)re.push(ge),ge=Dc();else re=r;if(re!==r){for(ge=[],Ye=bt();Ye!==r;)ge.push(Ye),Ye=bt();ge!==r?(xt=L,V=ke(re),L=V):(W=L,L=r)}else W=L,L=r}else W=L,L=r}}}return L}function gs(){var L,V,re,ge,Ye;for(L=W,V=[],re=bt();re!==r;)V.push(re),re=bt();if(V!==r){if(re=[],ge=Ci(),ge!==r)for(;ge!==r;)re.push(ge),ge=Ci();else re=r;if(re!==r){for(ge=[],Ye=bt();Ye!==r;)ge.push(Ye),Ye=bt();ge!==r?(xt=L,V=Ve(re),L=V):(W=L,L=r)}else W=L,L=r}else W=L,L=r;return L}function Pc(){var L,V,re;for(L=W,V=[],re=bt();re!==r;)V.push(re),re=bt();if(V!==r?(re=On(),re!==r?(xt=L,V=xe(re),L=V):(W=L,L=r)):(W=L,L=r),L===r){for(L=W,V=[],re=bt();re!==r;)V.push(re),re=bt();V!==r?(re=Ci(),re!==r?(xt=L,V=xe(re),L=V):(W=L,L=r)):(W=L,L=r)}return L}function On(){var L,V,re,ge,Ye;for(L=W,V=[],re=bt();re!==r;)V.push(re),re=bt();return V!==r?(tt.test(t.charAt(W))?(re=t.charAt(W),W++):(re=r,dt===0&&wt(He)),re===r&&(re=null),re!==r?(ge=ji(),ge!==r?(Ye=Ci(),Ye!==r?(xt=L,V=x(re,ge,Ye),L=V):(W=L,L=r)):(W=L,L=r)):(W=L,L=r)):(W=L,L=r),L}function ji(){var L;return t.substr(W,2)===I?(L=I,W+=2):(L=r,dt===0&&wt(S)),L===r&&(t.substr(W,2)===y?(L=y,W+=2):(L=r,dt===0&&wt(R)),L===r&&(t.charCodeAt(W)===62?(L=J,W++):(L=r,dt===0&&wt(X)),L===r&&(t.substr(W,3)===$?(L=$,W+=3):(L=r,dt===0&&wt(se)),L===r&&(t.substr(W,2)===be?(L=be,W+=2):(L=r,dt===0&&wt(Fe)),L===r&&(t.charCodeAt(W)===60?(L=lt,W++):(L=r,dt===0&&wt(Et))))))),L}function Ci(){var L,V,re;for(L=W,V=[],re=bt();re!==r;)V.push(re),re=bt();return V!==r?(re=HA(),re!==r?(xt=L,V=xe(re),L=V):(W=L,L=r)):(W=L,L=r),L}function HA(){var L,V,re;if(L=W,V=[],re=vu(),re!==r)for(;re!==r;)V.push(re),re=vu();else V=r;return V!==r&&(xt=L,V=qt(V)),L=V,L}function vu(){var L,V;return L=W,V=An(),V!==r&&(xt=L,V=nr(V)),L=V,L===r&&(L=W,V=h0(),V!==r&&(xt=L,V=nr(V)),L=V,L===r&&(L=W,V=g0(),V!==r&&(xt=L,V=nr(V)),L=V,L===r&&(L=W,V=Gi(),V!==r&&(xt=L,V=nr(V)),L=V))),L}function An(){var L,V,re,ge;return L=W,t.substr(W,2)===St?(V=St,W+=2):(V=r,dt===0&&wt(cn)),V!==r?(re=fn(),re!==r?(t.charCodeAt(W)===39?(ge=Pr,W++):(ge=r,dt===0&&wt(yr)),ge!==r?(xt=L,V=Rr(re),L=V):(W=L,L=r)):(W=L,L=r)):(W=L,L=r),L}function h0(){var L,V,re,ge;return L=W,t.charCodeAt(W)===39?(V=Pr,W++):(V=r,dt===0&&wt(yr)),V!==r?(re=Du(),re!==r?(t.charCodeAt(W)===39?(ge=Pr,W++):(ge=r,dt===0&&wt(yr)),ge!==r?(xt=L,V=Rr(re),L=V):(W=L,L=r)):(W=L,L=r)):(W=L,L=r),L}function g0(){var L,V,re,ge;if(L=W,t.substr(W,2)===Xr?(V=Xr,W+=2):(V=r,dt===0&&wt($n)),V!==r&&(xt=L,V=Xs()),L=V,L===r)if(L=W,t.charCodeAt(W)===34?(V=Hi,W++):(V=r,dt===0&&wt(Qs)),V!==r){for(re=[],ge=Ka();ge!==r;)re.push(ge),ge=Ka();re!==r?(t.charCodeAt(W)===34?(ge=Hi,W++):(ge=r,dt===0&&wt(Qs)),ge!==r?(xt=L,V=Zs(re),L=V):(W=L,L=r)):(W=L,L=r)}else W=L,L=r;return L}function Gi(){var L,V,re;if(L=W,V=[],re=io(),re!==r)for(;re!==r;)V.push(re),re=io();else V=r;return V!==r&&(xt=L,V=Zs(V)),L=V,L}function Ka(){var L,V;return L=W,V=Kr(),V!==r&&(xt=L,V=bi(V)),L=V,L===r&&(L=W,V=mp(),V!==r&&(xt=L,V=Fs(V)),L=V,L===r&&(L=W,V=jA(),V!==r&&(xt=L,V=$s(V)),L=V,L===r&&(L=W,V=Pu(),V!==r&&(xt=L,V=SA(V)),L=V))),L}function io(){var L,V;return L=W,V=Kr(),V!==r&&(xt=L,V=gu(V)),L=V,L===r&&(L=W,V=mp(),V!==r&&(xt=L,V=op(V)),L=V,L===r&&(L=W,V=jA(),V!==r&&(xt=L,V=ap(V)),L=V,L===r&&(L=W,V=kd(),V!==r&&(xt=L,V=Rs(V)),L=V,L===r&&(L=W,V=dp(),V!==r&&(xt=L,V=SA(V)),L=V)))),L}function Du(){var L,V,re;for(L=W,V=[],Nn.test(t.charAt(W))?(re=t.charAt(W),W++):(re=r,dt===0&&wt(hs));re!==r;)V.push(re),Nn.test(t.charAt(W))?(re=t.charAt(W),W++):(re=r,dt===0&&wt(hs));return V!==r&&(xt=L,V=Ts(V)),L=V,L}function Pu(){var L,V,re;if(L=W,V=[],re=Va(),re===r&&(pc.test(t.charAt(W))?(re=t.charAt(W),W++):(re=r,dt===0&&wt(hc))),re!==r)for(;re!==r;)V.push(re),re=Va(),re===r&&(pc.test(t.charAt(W))?(re=t.charAt(W),W++):(re=r,dt===0&&wt(hc)));else V=r;return V!==r&&(xt=L,V=Ts(V)),L=V,L}function Va(){var L,V,re;return L=W,t.substr(W,2)===gc?(V=gc,W+=2):(V=r,dt===0&&wt(xA)),V!==r&&(xt=L,V=bA()),L=V,L===r&&(L=W,t.charCodeAt(W)===92?(V=Ro,W++):(V=r,dt===0&&wt(To)),V!==r?(kA.test(t.charAt(W))?(re=t.charAt(W),W++):(re=r,dt===0&&wt(pr)),re!==r?(xt=L,V=Me(re),L=V):(W=L,L=r)):(W=L,L=r)),L}function fn(){var L,V,re;for(L=W,V=[],re=so(),re===r&&(Nn.test(t.charAt(W))?(re=t.charAt(W),W++):(re=r,dt===0&&wt(hs)));re!==r;)V.push(re),re=so(),re===r&&(Nn.test(t.charAt(W))?(re=t.charAt(W),W++):(re=r,dt===0&&wt(hs)));return V!==r&&(xt=L,V=Ts(V)),L=V,L}function so(){var L,V,re;return L=W,t.substr(W,2)===ia?(V=ia,W+=2):(V=r,dt===0&&wt(dc)),V!==r&&(xt=L,V=Er()),L=V,L===r&&(L=W,t.substr(W,2)===du?(V=du,W+=2):(V=r,dt===0&&wt(QA)),V!==r&&(xt=L,V=FA()),L=V,L===r&&(L=W,t.charCodeAt(W)===92?(V=Ro,W++):(V=r,dt===0&&wt(To)),V!==r?(mc.test(t.charAt(W))?(re=t.charAt(W),W++):(re=r,dt===0&&wt(yc)),re!==r?(xt=L,V=Il(),L=V):(W=L,L=r)):(W=L,L=r),L===r&&(L=W,t.substr(W,2)===we?(V=we,W+=2):(V=r,dt===0&&wt(Tt)),V!==r&&(xt=L,V=wl()),L=V,L===r&&(L=W,t.substr(W,2)===Bi?(V=Bi,W+=2):(V=r,dt===0&&wt(Ls)),V!==r&&(xt=L,V=Ft()),L=V,L===r&&(L=W,t.substr(W,2)===Bn?(V=Bn,W+=2):(V=r,dt===0&&wt(Lo)),V!==r&&(xt=L,V=ki()),L=V,L===r&&(L=W,t.substr(W,2)===vi?(V=vi,W+=2):(V=r,dt===0&&wt(sa)),V!==r&&(xt=L,V=un()),L=V,L===r&&(L=W,t.substr(W,2)===qn?(V=qn,W+=2):(V=r,dt===0&&wt(Ec)),V!==r&&(xt=L,V=lp()),L=V,L===r&&(L=W,t.charCodeAt(W)===92?(V=Ro,W++):(V=r,dt===0&&wt(To)),V!==r?(oa.test(t.charAt(W))?(re=t.charAt(W),W++):(re=r,dt===0&&wt(aa)),re!==r?(xt=L,V=Me(re),L=V):(W=L,L=r)):(W=L,L=r),L===r&&(L=Sc()))))))))),L}function Sc(){var L,V,re,ge,Ye,At,hr,Ir,Rn,ai,ns,GA;return L=W,t.charCodeAt(W)===92?(V=Ro,W++):(V=r,dt===0&&wt(To)),V!==r?(re=_o(),re!==r?(xt=L,V=la(re),L=V):(W=L,L=r)):(W=L,L=r),L===r&&(L=W,t.substr(W,2)===Ze?(V=Ze,W+=2):(V=r,dt===0&&wt(ca)),V!==r?(re=W,ge=W,Ye=_o(),Ye!==r?(At=ds(),At!==r?(Ye=[Ye,At],ge=Ye):(W=ge,ge=r)):(W=ge,ge=r),ge===r&&(ge=_o()),ge!==r?re=t.substring(re,W):re=ge,re!==r?(xt=L,V=la(re),L=V):(W=L,L=r)):(W=L,L=r),L===r&&(L=W,t.substr(W,2)===mu?(V=mu,W+=2):(V=r,dt===0&&wt(Bl)),V!==r?(re=W,ge=W,Ye=ds(),Ye!==r?(At=ds(),At!==r?(hr=ds(),hr!==r?(Ir=ds(),Ir!==r?(Ye=[Ye,At,hr,Ir],ge=Ye):(W=ge,ge=r)):(W=ge,ge=r)):(W=ge,ge=r)):(W=ge,ge=r),ge!==r?re=t.substring(re,W):re=ge,re!==r?(xt=L,V=la(re),L=V):(W=L,L=r)):(W=L,L=r),L===r&&(L=W,t.substr(W,2)===dn?(V=dn,W+=2):(V=r,dt===0&&wt(No)),V!==r?(re=W,ge=W,Ye=ds(),Ye!==r?(At=ds(),At!==r?(hr=ds(),hr!==r?(Ir=ds(),Ir!==r?(Rn=ds(),Rn!==r?(ai=ds(),ai!==r?(ns=ds(),ns!==r?(GA=ds(),GA!==r?(Ye=[Ye,At,hr,Ir,Rn,ai,ns,GA],ge=Ye):(W=ge,ge=r)):(W=ge,ge=r)):(W=ge,ge=r)):(W=ge,ge=r)):(W=ge,ge=r)):(W=ge,ge=r)):(W=ge,ge=r)):(W=ge,ge=r),ge!==r?re=t.substring(re,W):re=ge,re!==r?(xt=L,V=RA(re),L=V):(W=L,L=r)):(W=L,L=r)))),L}function _o(){var L;return TA.test(t.charAt(W))?(L=t.charAt(W),W++):(L=r,dt===0&&wt(Oo)),L}function ds(){var L;return qa.test(t.charAt(W))?(L=t.charAt(W),W++):(L=r,dt===0&&wt(Ot)),L}function dp(){var L,V,re,ge,Ye;if(L=W,V=[],re=W,t.charCodeAt(W)===92?(ge=Ro,W++):(ge=r,dt===0&&wt(To)),ge!==r?(t.length>W?(Ye=t.charAt(W),W++):(Ye=r,dt===0&&wt(vn)),Ye!==r?(xt=re,ge=Me(Ye),re=ge):(W=re,re=r)):(W=re,re=r),re===r&&(re=W,t.substr(W,2)===Mo?(ge=Mo,W+=2):(ge=r,dt===0&&wt(ua)),ge!==r&&(xt=re,ge=qi()),re=ge,re===r&&(re=W,ge=W,dt++,Ye=Qd(),dt--,Ye===r?ge=void 0:(W=ge,ge=r),ge!==r?(t.length>W?(Ye=t.charAt(W),W++):(Ye=r,dt===0&&wt(vn)),Ye!==r?(xt=re,ge=Me(Ye),re=ge):(W=re,re=r)):(W=re,re=r))),re!==r)for(;re!==r;)V.push(re),re=W,t.charCodeAt(W)===92?(ge=Ro,W++):(ge=r,dt===0&&wt(To)),ge!==r?(t.length>W?(Ye=t.charAt(W),W++):(Ye=r,dt===0&&wt(vn)),Ye!==r?(xt=re,ge=Me(Ye),re=ge):(W=re,re=r)):(W=re,re=r),re===r&&(re=W,t.substr(W,2)===Mo?(ge=Mo,W+=2):(ge=r,dt===0&&wt(ua)),ge!==r&&(xt=re,ge=qi()),re=ge,re===r&&(re=W,ge=W,dt++,Ye=Qd(),dt--,Ye===r?ge=void 0:(W=ge,ge=r),ge!==r?(t.length>W?(Ye=t.charAt(W),W++):(Ye=r,dt===0&&wt(vn)),Ye!==r?(xt=re,ge=Me(Ye),re=ge):(W=re,re=r)):(W=re,re=r)));else V=r;return V!==r&&(xt=L,V=Ts(V)),L=V,L}function qA(){var L,V,re,ge,Ye,At;if(L=W,t.charCodeAt(W)===45?(V=vl,W++):(V=r,dt===0&&wt(Cc)),V===r&&(t.charCodeAt(W)===43?(V=Dl,W++):(V=r,dt===0&&wt(Aa))),V===r&&(V=null),V!==r){if(re=[],tt.test(t.charAt(W))?(ge=t.charAt(W),W++):(ge=r,dt===0&&wt(He)),ge!==r)for(;ge!==r;)re.push(ge),tt.test(t.charAt(W))?(ge=t.charAt(W),W++):(ge=r,dt===0&&wt(He));else re=r;if(re!==r)if(t.charCodeAt(W)===46?(ge=Di,W++):(ge=r,dt===0&&wt(rs)),ge!==r){if(Ye=[],tt.test(t.charAt(W))?(At=t.charAt(W),W++):(At=r,dt===0&&wt(He)),At!==r)for(;At!==r;)Ye.push(At),tt.test(t.charAt(W))?(At=t.charAt(W),W++):(At=r,dt===0&&wt(He));else Ye=r;Ye!==r?(xt=L,V=ja(V,re,Ye),L=V):(W=L,L=r)}else W=L,L=r;else W=L,L=r}else W=L,L=r;if(L===r){if(L=W,t.charCodeAt(W)===45?(V=vl,W++):(V=r,dt===0&&wt(Cc)),V===r&&(t.charCodeAt(W)===43?(V=Dl,W++):(V=r,dt===0&&wt(Aa))),V===r&&(V=null),V!==r){if(re=[],tt.test(t.charAt(W))?(ge=t.charAt(W),W++):(ge=r,dt===0&&wt(He)),ge!==r)for(;ge!==r;)re.push(ge),tt.test(t.charAt(W))?(ge=t.charAt(W),W++):(ge=r,dt===0&&wt(He));else re=r;re!==r?(xt=L,V=yu(V,re),L=V):(W=L,L=r)}else W=L,L=r;if(L===r&&(L=W,V=jA(),V!==r&&(xt=L,V=Pl(V)),L=V,L===r&&(L=W,V=xl(),V!==r&&(xt=L,V=pi(V)),L=V,L===r)))if(L=W,t.charCodeAt(W)===40?(V=Ce,W++):(V=r,dt===0&&wt(fe)),V!==r){for(re=[],ge=bt();ge!==r;)re.push(ge),ge=bt();if(re!==r)if(ge=Ns(),ge!==r){for(Ye=[],At=bt();At!==r;)Ye.push(At),At=bt();Ye!==r?(t.charCodeAt(W)===41?(At=ie,W++):(At=r,dt===0&&wt(Z)),At!==r?(xt=L,V=Dn(ge),L=V):(W=L,L=r)):(W=L,L=r)}else W=L,L=r;else W=L,L=r}else W=L,L=r}return L}function Su(){var L,V,re,ge,Ye,At,hr,Ir;if(L=W,V=qA(),V!==r){for(re=[],ge=W,Ye=[],At=bt();At!==r;)Ye.push(At),At=bt();if(Ye!==r)if(t.charCodeAt(W)===42?(At=Sl,W++):(At=r,dt===0&&wt(ze)),At===r&&(t.charCodeAt(W)===47?(At=it,W++):(At=r,dt===0&&wt(vt))),At!==r){for(hr=[],Ir=bt();Ir!==r;)hr.push(Ir),Ir=bt();hr!==r?(Ir=qA(),Ir!==r?(xt=ge,Ye=ar(V,At,Ir),ge=Ye):(W=ge,ge=r)):(W=ge,ge=r)}else W=ge,ge=r;else W=ge,ge=r;for(;ge!==r;){for(re.push(ge),ge=W,Ye=[],At=bt();At!==r;)Ye.push(At),At=bt();if(Ye!==r)if(t.charCodeAt(W)===42?(At=Sl,W++):(At=r,dt===0&&wt(ze)),At===r&&(t.charCodeAt(W)===47?(At=it,W++):(At=r,dt===0&&wt(vt))),At!==r){for(hr=[],Ir=bt();Ir!==r;)hr.push(Ir),Ir=bt();hr!==r?(Ir=qA(),Ir!==r?(xt=ge,Ye=ar(V,At,Ir),ge=Ye):(W=ge,ge=r)):(W=ge,ge=r)}else W=ge,ge=r;else W=ge,ge=r}re!==r?(xt=L,V=ee(V,re),L=V):(W=L,L=r)}else W=L,L=r;return L}function Ns(){var L,V,re,ge,Ye,At,hr,Ir;if(L=W,V=Su(),V!==r){for(re=[],ge=W,Ye=[],At=bt();At!==r;)Ye.push(At),At=bt();if(Ye!==r)if(t.charCodeAt(W)===43?(At=Dl,W++):(At=r,dt===0&&wt(Aa)),At===r&&(t.charCodeAt(W)===45?(At=vl,W++):(At=r,dt===0&&wt(Cc))),At!==r){for(hr=[],Ir=bt();Ir!==r;)hr.push(Ir),Ir=bt();hr!==r?(Ir=Su(),Ir!==r?(xt=ge,Ye=ye(V,At,Ir),ge=Ye):(W=ge,ge=r)):(W=ge,ge=r)}else W=ge,ge=r;else W=ge,ge=r;for(;ge!==r;){for(re.push(ge),ge=W,Ye=[],At=bt();At!==r;)Ye.push(At),At=bt();if(Ye!==r)if(t.charCodeAt(W)===43?(At=Dl,W++):(At=r,dt===0&&wt(Aa)),At===r&&(t.charCodeAt(W)===45?(At=vl,W++):(At=r,dt===0&&wt(Cc))),At!==r){for(hr=[],Ir=bt();Ir!==r;)hr.push(Ir),Ir=bt();hr!==r?(Ir=Su(),Ir!==r?(xt=ge,Ye=ye(V,At,Ir),ge=Ye):(W=ge,ge=r)):(W=ge,ge=r)}else W=ge,ge=r;else W=ge,ge=r}re!==r?(xt=L,V=ee(V,re),L=V):(W=L,L=r)}else W=L,L=r;return L}function Kr(){var L,V,re,ge,Ye,At;if(L=W,t.substr(W,3)===Ne?(V=Ne,W+=3):(V=r,dt===0&&wt(gt)),V!==r){for(re=[],ge=bt();ge!==r;)re.push(ge),ge=bt();if(re!==r)if(ge=Ns(),ge!==r){for(Ye=[],At=bt();At!==r;)Ye.push(At),At=bt();Ye!==r?(t.substr(W,2)===mt?(At=mt,W+=2):(At=r,dt===0&&wt(Dt)),At!==r?(xt=L,V=er(ge),L=V):(W=L,L=r)):(W=L,L=r)}else W=L,L=r;else W=L,L=r}else W=L,L=r;return L}function mp(){var L,V,re,ge;return L=W,t.substr(W,2)===sn?(V=sn,W+=2):(V=r,dt===0&&wt(ei)),V!==r?(re=Uo(),re!==r?(t.charCodeAt(W)===41?(ge=ie,W++):(ge=r,dt===0&&wt(Z)),ge!==r?(xt=L,V=Qi(re),L=V):(W=L,L=r)):(W=L,L=r)):(W=L,L=r),L}function jA(){var L,V,re,ge,Ye,At;return L=W,t.substr(W,2)===Pn?(V=Pn,W+=2):(V=r,dt===0&&wt(fa)),V!==r?(re=xl(),re!==r?(t.substr(W,2)===wd?(ge=wd,W+=2):(ge=r,dt===0&&wt(BI)),ge!==r?(Ye=gs(),Ye!==r?(t.charCodeAt(W)===125?(At=q,W++):(At=r,dt===0&&wt(nt)),At!==r?(xt=L,V=eo(re,Ye),L=V):(W=L,L=r)):(W=L,L=r)):(W=L,L=r)):(W=L,L=r)):(W=L,L=r),L===r&&(L=W,t.substr(W,2)===Pn?(V=Pn,W+=2):(V=r,dt===0&&wt(fa)),V!==r?(re=xl(),re!==r?(t.substr(W,3)===Bd?(ge=Bd,W+=3):(ge=r,dt===0&&wt(cp)),ge!==r?(xt=L,V=vI(re),L=V):(W=L,L=r)):(W=L,L=r)):(W=L,L=r),L===r&&(L=W,t.substr(W,2)===Pn?(V=Pn,W+=2):(V=r,dt===0&&wt(fa)),V!==r?(re=xl(),re!==r?(t.substr(W,2)===to?(ge=to,W+=2):(ge=r,dt===0&&wt(up)),ge!==r?(Ye=gs(),Ye!==r?(t.charCodeAt(W)===125?(At=q,W++):(At=r,dt===0&&wt(nt)),At!==r?(xt=L,V=Ap(re,Ye),L=V):(W=L,L=r)):(W=L,L=r)):(W=L,L=r)):(W=L,L=r)):(W=L,L=r),L===r&&(L=W,t.substr(W,2)===Pn?(V=Pn,W+=2):(V=r,dt===0&&wt(fa)),V!==r?(re=xl(),re!==r?(t.substr(W,3)===Ic?(ge=Ic,W+=3):(ge=r,dt===0&&wt(fp)),ge!==r?(xt=L,V=s0(re),L=V):(W=L,L=r)):(W=L,L=r)):(W=L,L=r),L===r&&(L=W,t.substr(W,2)===Pn?(V=Pn,W+=2):(V=r,dt===0&&wt(fa)),V!==r?(re=xl(),re!==r?(t.charCodeAt(W)===125?(ge=q,W++):(ge=r,dt===0&&wt(nt)),ge!==r?(xt=L,V=o0(re),L=V):(W=L,L=r)):(W=L,L=r)):(W=L,L=r),L===r&&(L=W,t.charCodeAt(W)===36?(V=a0,W++):(V=r,dt===0&&wt(vd)),V!==r?(re=xl(),re!==r?(xt=L,V=o0(re),L=V):(W=L,L=r)):(W=L,L=r)))))),L}function kd(){var L,V,re;return L=W,V=d0(),V!==r?(xt=W,re=Eu(V),re?re=void 0:re=r,re!==r?(xt=L,V=ro(V),L=V):(W=L,L=r)):(W=L,L=r),L}function d0(){var L,V,re,ge,Ye;if(L=W,V=[],re=W,ge=W,dt++,Ye=Ep(),dt--,Ye===r?ge=void 0:(W=ge,ge=r),ge!==r?(t.length>W?(Ye=t.charAt(W),W++):(Ye=r,dt===0&&wt(vn)),Ye!==r?(xt=re,ge=Me(Ye),re=ge):(W=re,re=r)):(W=re,re=r),re!==r)for(;re!==r;)V.push(re),re=W,ge=W,dt++,Ye=Ep(),dt--,Ye===r?ge=void 0:(W=ge,ge=r),ge!==r?(t.length>W?(Ye=t.charAt(W),W++):(Ye=r,dt===0&&wt(vn)),Ye!==r?(xt=re,ge=Me(Ye),re=ge):(W=re,re=r)):(W=re,re=r);else V=r;return V!==r&&(xt=L,V=Ts(V)),L=V,L}function yp(){var L,V,re;if(L=W,V=[],Ga.test(t.charAt(W))?(re=t.charAt(W),W++):(re=r,dt===0&&wt(pp)),re!==r)for(;re!==r;)V.push(re),Ga.test(t.charAt(W))?(re=t.charAt(W),W++):(re=r,dt===0&&wt(pp));else V=r;return V!==r&&(xt=L,V=l0()),L=V,L}function xl(){var L,V,re;if(L=W,V=[],Wa.test(t.charAt(W))?(re=t.charAt(W),W++):(re=r,dt===0&&wt(Ya)),re!==r)for(;re!==r;)V.push(re),Wa.test(t.charAt(W))?(re=t.charAt(W),W++):(re=r,dt===0&&wt(Ya));else V=r;return V!==r&&(xt=L,V=l0()),L=V,L}function Qd(){var L;return Dd.test(t.charAt(W))?(L=t.charAt(W),W++):(L=r,dt===0&&wt(LA)),L}function Ep(){var L;return Pd.test(t.charAt(W))?(L=t.charAt(W),W++):(L=r,dt===0&&wt(Sd)),L}function bt(){var L,V;if(L=[],NA.test(t.charAt(W))?(V=t.charAt(W),W++):(V=r,dt===0&&wt(OA)),V!==r)for(;V!==r;)L.push(V),NA.test(t.charAt(W))?(V=t.charAt(W),W++):(V=r,dt===0&&wt(OA));else L=r;return L}if(wc=a(),wc!==r&&W===t.length)return wc;throw wc!==r&&W<t.length&&wt(pa()),UA(Cu,no<t.length?t.charAt(no):null,no<t.length?wu(no,no+1):wu(no,no))}LY.exports={SyntaxError:V0,parse:X_e}});function uP(t,e={isGlobPattern:()=>!1}){try{return(0,OY.parse)(t,e)}catch(r){throw r.location&&(r.message=r.message.replace(/(\\.)?$/,` (line ${r.location.start.line}, column ${r.location.start.column})$1`)),r}}function dm(t,{endSemicolon:e=!1}={}){return t.map(({command:r,type:o},a)=>`${AP(r)}${o===\";\"?a!==t.length-1||e?\";\":\"\":\" &\"}`).join(\" \")}function AP(t){return`${mm(t.chain)}${t.then?` ${UT(t.then)}`:\"\"}`}function UT(t){return`${t.type} ${AP(t.line)}`}function mm(t){return`${HT(t)}${t.then?` ${_T(t.then)}`:\"\"}`}function _T(t){return`${t.type} ${mm(t.chain)}`}function HT(t){switch(t.type){case\"command\":return`${t.envs.length>0?`${t.envs.map(e=>cP(e)).join(\" \")} `:\"\"}${t.args.map(e=>qT(e)).join(\" \")}`;case\"subshell\":return`(${dm(t.subshell)})${t.args.length>0?` ${t.args.map(e=>fw(e)).join(\" \")}`:\"\"}`;case\"group\":return`{ ${dm(t.group,{endSemicolon:!0})} }${t.args.length>0?` ${t.args.map(e=>fw(e)).join(\" \")}`:\"\"}`;case\"envs\":return t.envs.map(e=>cP(e)).join(\" \");default:throw new Error(`Unsupported command type:  \"${t.type}\"`)}}function cP(t){return`${t.name}=${t.args[0]?z0(t.args[0]):\"\"}`}function qT(t){switch(t.type){case\"redirection\":return fw(t);case\"argument\":return z0(t);default:throw new Error(`Unsupported argument type: \"${t.type}\"`)}}function fw(t){return`${t.subtype} ${t.args.map(e=>z0(e)).join(\" \")}`}function z0(t){return t.segments.map(e=>jT(e)).join(\"\")}function jT(t){let e=(o,a)=>a?`\"${o}\"`:o,r=o=>o===\"\"?\"''\":o.match(/[()}<>$|&;\"'\\n\\t ]/)?o.match(/['\\t\\p{C}]/u)?o.match(/'/)?`\"${o.replace(/[\"$\\t\\p{C}]/u,$_e)}\"`:`$'${o.replace(/[\\t\\p{C}]/u,UY)}'`:`'${o}'`:o;switch(t.type){case\"text\":return r(t.text);case\"glob\":return t.pattern;case\"shell\":return e(`$(${dm(t.shell)})`,t.quoted);case\"variable\":return e(typeof t.defaultValue>\"u\"?typeof t.alternativeValue>\"u\"?`\\${${t.name}}`:t.alternativeValue.length===0?`\\${${t.name}:+}`:`\\${${t.name}:+${t.alternativeValue.map(o=>z0(o)).join(\" \")}}`:t.defaultValue.length===0?`\\${${t.name}:-}`:`\\${${t.name}:-${t.defaultValue.map(o=>z0(o)).join(\" \")}}`,t.quoted);case\"arithmetic\":return`$(( ${fP(t.arithmetic)} ))`;default:throw new Error(`Unsupported argument segment type: \"${t.type}\"`)}}function fP(t){let e=a=>{switch(a){case\"addition\":return\"+\";case\"subtraction\":return\"-\";case\"multiplication\":return\"*\";case\"division\":return\"/\";default:throw new Error(`Can't extract operator from arithmetic expression of type \"${a}\"`)}},r=(a,n)=>n?`( ${a} )`:a,o=a=>r(fP(a),![\"number\",\"variable\"].includes(a.type));switch(t.type){case\"number\":return String(t.value);case\"variable\":return t.name;default:return`${o(t.left)} ${e(t.type)} ${o(t.right)}`}}var OY,MY,Z_e,UY,$_e,_Y=It(()=>{OY=et(NY());MY=new Map([[\"\\f\",\"\\\\f\"],[`\n`,\"\\\\n\"],[\"\\r\",\"\\\\r\"],[\"\t\",\"\\\\t\"],[\"\\v\",\"\\\\v\"],[\"\\0\",\"\\\\0\"]]),Z_e=new Map([[\"\\\\\",\"\\\\\\\\\"],[\"$\",\"\\\\$\"],['\"','\\\\\"'],...Array.from(MY,([t,e])=>[t,`\"$'${e}'\"`])]),UY=t=>MY.get(t)??`\\\\x${t.charCodeAt(0).toString(16).padStart(2,\"0\")}`,$_e=t=>Z_e.get(t)??`\"$'${UY(t)}'\"`});var qY=_((dxt,HY)=>{\"use strict\";function e8e(t,e){function r(){this.constructor=t}r.prototype=e.prototype,t.prototype=new r}function J0(t,e,r,o){this.message=t,this.expected=e,this.found=r,this.location=o,this.name=\"SyntaxError\",typeof Error.captureStackTrace==\"function\"&&Error.captureStackTrace(this,J0)}e8e(J0,Error);J0.buildMessage=function(t,e){var r={literal:function(h){return'\"'+a(h.text)+'\"'},class:function(h){var E=\"\",w;for(w=0;w<h.parts.length;w++)E+=h.parts[w]instanceof Array?n(h.parts[w][0])+\"-\"+n(h.parts[w][1]):n(h.parts[w]);return\"[\"+(h.inverted?\"^\":\"\")+E+\"]\"},any:function(h){return\"any character\"},end:function(h){return\"end of input\"},other:function(h){return h.description}};function o(h){return h.charCodeAt(0).toString(16).toUpperCase()}function a(h){return h.replace(/\\\\/g,\"\\\\\\\\\").replace(/\"/g,'\\\\\"').replace(/\\0/g,\"\\\\0\").replace(/\\t/g,\"\\\\t\").replace(/\\n/g,\"\\\\n\").replace(/\\r/g,\"\\\\r\").replace(/[\\x00-\\x0F]/g,function(E){return\"\\\\x0\"+o(E)}).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g,function(E){return\"\\\\x\"+o(E)})}function n(h){return h.replace(/\\\\/g,\"\\\\\\\\\").replace(/\\]/g,\"\\\\]\").replace(/\\^/g,\"\\\\^\").replace(/-/g,\"\\\\-\").replace(/\\0/g,\"\\\\0\").replace(/\\t/g,\"\\\\t\").replace(/\\n/g,\"\\\\n\").replace(/\\r/g,\"\\\\r\").replace(/[\\x00-\\x0F]/g,function(E){return\"\\\\x0\"+o(E)}).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g,function(E){return\"\\\\x\"+o(E)})}function u(h){return r[h.type](h)}function A(h){var E=new Array(h.length),w,D;for(w=0;w<h.length;w++)E[w]=u(h[w]);if(E.sort(),E.length>0){for(w=1,D=1;w<E.length;w++)E[w-1]!==E[w]&&(E[D]=E[w],D++);E.length=D}switch(E.length){case 1:return E[0];case 2:return E[0]+\" or \"+E[1];default:return E.slice(0,-1).join(\", \")+\", or \"+E[E.length-1]}}function p(h){return h?'\"'+a(h)+'\"':\"end of input\"}return\"Expected \"+A(t)+\" but \"+p(e)+\" found.\"};function t8e(t,e){e=e!==void 0?e:{};var r={},o={resolution:Te},a=Te,n=\"/\",u=Ce(\"/\",!1),A=function(He,x){return{from:He,descriptor:x}},p=function(He){return{descriptor:He}},h=\"@\",E=Ce(\"@\",!1),w=function(He,x){return{fullName:He,description:x}},D=function(He){return{fullName:He}},b=function(){return De()},C=/^[^\\/@]/,T=fe([\"/\",\"@\"],!0,!1),N=/^[^\\/]/,U=fe([\"/\"],!0,!1),z=0,te=0,le=[{line:1,column:1}],ce=0,ue=[],Ie=0,he;if(\"startRule\"in e){if(!(e.startRule in o))throw new Error(`Can't start parsing from rule \"`+e.startRule+'\".');a=o[e.startRule]}function De(){return t.substring(te,z)}function Ee(){return ht(te,z)}function g(He,x){throw x=x!==void 0?x:ht(te,z),Le([Pe(He)],t.substring(te,z),x)}function me(He,x){throw x=x!==void 0?x:ht(te,z),nt(He,x)}function Ce(He,x){return{type:\"literal\",text:He,ignoreCase:x}}function fe(He,x,I){return{type:\"class\",parts:He,inverted:x,ignoreCase:I}}function ie(){return{type:\"any\"}}function Z(){return{type:\"end\"}}function Pe(He){return{type:\"other\",description:He}}function Re(He){var x=le[He],I;if(x)return x;for(I=He-1;!le[I];)I--;for(x=le[I],x={line:x.line,column:x.column};I<He;)t.charCodeAt(I)===10?(x.line++,x.column=1):x.column++,I++;return le[He]=x,x}function ht(He,x){var I=Re(He),S=Re(x);return{start:{offset:He,line:I.line,column:I.column},end:{offset:x,line:S.line,column:S.column}}}function q(He){z<ce||(z>ce&&(ce=z,ue=[]),ue.push(He))}function nt(He,x){return new J0(He,null,null,x)}function Le(He,x,I){return new J0(J0.buildMessage(He,x),He,x,I)}function Te(){var He,x,I,S;return He=z,x=ke(),x!==r?(t.charCodeAt(z)===47?(I=n,z++):(I=r,Ie===0&&q(u)),I!==r?(S=ke(),S!==r?(te=He,x=A(x,S),He=x):(z=He,He=r)):(z=He,He=r)):(z=He,He=r),He===r&&(He=z,x=ke(),x!==r&&(te=He,x=p(x)),He=x),He}function ke(){var He,x,I,S;return He=z,x=Ve(),x!==r?(t.charCodeAt(z)===64?(I=h,z++):(I=r,Ie===0&&q(E)),I!==r?(S=tt(),S!==r?(te=He,x=w(x,S),He=x):(z=He,He=r)):(z=He,He=r)):(z=He,He=r),He===r&&(He=z,x=Ve(),x!==r&&(te=He,x=D(x)),He=x),He}function Ve(){var He,x,I,S,y;return He=z,t.charCodeAt(z)===64?(x=h,z++):(x=r,Ie===0&&q(E)),x!==r?(I=xe(),I!==r?(t.charCodeAt(z)===47?(S=n,z++):(S=r,Ie===0&&q(u)),S!==r?(y=xe(),y!==r?(te=He,x=b(),He=x):(z=He,He=r)):(z=He,He=r)):(z=He,He=r)):(z=He,He=r),He===r&&(He=z,x=xe(),x!==r&&(te=He,x=b()),He=x),He}function xe(){var He,x,I;if(He=z,x=[],C.test(t.charAt(z))?(I=t.charAt(z),z++):(I=r,Ie===0&&q(T)),I!==r)for(;I!==r;)x.push(I),C.test(t.charAt(z))?(I=t.charAt(z),z++):(I=r,Ie===0&&q(T));else x=r;return x!==r&&(te=He,x=b()),He=x,He}function tt(){var He,x,I;if(He=z,x=[],N.test(t.charAt(z))?(I=t.charAt(z),z++):(I=r,Ie===0&&q(U)),I!==r)for(;I!==r;)x.push(I),N.test(t.charAt(z))?(I=t.charAt(z),z++):(I=r,Ie===0&&q(U));else x=r;return x!==r&&(te=He,x=b()),He=x,He}if(he=a(),he!==r&&z===t.length)return he;throw he!==r&&z<t.length&&q(Z()),Le(ue,ce<t.length?t.charAt(ce):null,ce<t.length?ht(ce,ce+1):ht(ce,ce))}HY.exports={SyntaxError:J0,parse:t8e}});function pP(t){let e=t.match(/^\\*{1,2}\\/(.*)/);if(e)throw new Error(`The override for '${t}' includes a glob pattern. Glob patterns have been removed since their behaviours don't match what you'd expect. Set the override to '${e[1]}' instead.`);try{return(0,jY.parse)(t)}catch(r){throw r.location&&(r.message=r.message.replace(/(\\.)?$/,` (line ${r.location.start.line}, column ${r.location.start.column})$1`)),r}}function hP(t){let e=\"\";return t.from&&(e+=t.from.fullName,t.from.description&&(e+=`@${t.from.description}`),e+=\"/\"),e+=t.descriptor.fullName,t.descriptor.description&&(e+=`@${t.descriptor.description}`),e}var jY,GY=It(()=>{jY=et(qY())});var Z0=_((yxt,X0)=>{\"use strict\";function WY(t){return typeof t>\"u\"||t===null}function r8e(t){return typeof t==\"object\"&&t!==null}function n8e(t){return Array.isArray(t)?t:WY(t)?[]:[t]}function i8e(t,e){var r,o,a,n;if(e)for(n=Object.keys(e),r=0,o=n.length;r<o;r+=1)a=n[r],t[a]=e[a];return t}function s8e(t,e){var r=\"\",o;for(o=0;o<e;o+=1)r+=t;return r}function o8e(t){return t===0&&Number.NEGATIVE_INFINITY===1/t}X0.exports.isNothing=WY;X0.exports.isObject=r8e;X0.exports.toArray=n8e;X0.exports.repeat=s8e;X0.exports.isNegativeZero=o8e;X0.exports.extend=i8e});var ym=_((Ext,YY)=>{\"use strict\";function pw(t,e){Error.call(this),this.name=\"YAMLException\",this.reason=t,this.mark=e,this.message=(this.reason||\"(unknown reason)\")+(this.mark?\" \"+this.mark.toString():\"\"),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=new Error().stack||\"\"}pw.prototype=Object.create(Error.prototype);pw.prototype.constructor=pw;pw.prototype.toString=function(e){var r=this.name+\": \";return r+=this.reason||\"(unknown reason)\",!e&&this.mark&&(r+=\" \"+this.mark.toString()),r};YY.exports=pw});var zY=_((Cxt,VY)=>{\"use strict\";var KY=Z0();function GT(t,e,r,o,a){this.name=t,this.buffer=e,this.position=r,this.line=o,this.column=a}GT.prototype.getSnippet=function(e,r){var o,a,n,u,A;if(!this.buffer)return null;for(e=e||4,r=r||75,o=\"\",a=this.position;a>0&&`\\0\\r\n\\x85\\u2028\\u2029`.indexOf(this.buffer.charAt(a-1))===-1;)if(a-=1,this.position-a>r/2-1){o=\" ... \",a+=5;break}for(n=\"\",u=this.position;u<this.buffer.length&&`\\0\\r\n\\x85\\u2028\\u2029`.indexOf(this.buffer.charAt(u))===-1;)if(u+=1,u-this.position>r/2-1){n=\" ... \",u-=5;break}return A=this.buffer.slice(a,u),KY.repeat(\" \",e)+o+A+n+`\n`+KY.repeat(\" \",e+this.position-a+o.length)+\"^\"};GT.prototype.toString=function(e){var r,o=\"\";return this.name&&(o+='in \"'+this.name+'\" '),o+=\"at line \"+(this.line+1)+\", column \"+(this.column+1),e||(r=this.getSnippet(),r&&(o+=`:\n`+r)),o};VY.exports=GT});var as=_((Ixt,XY)=>{\"use strict\";var JY=ym(),a8e=[\"kind\",\"resolve\",\"construct\",\"instanceOf\",\"predicate\",\"represent\",\"defaultStyle\",\"styleAliases\"],l8e=[\"scalar\",\"sequence\",\"mapping\"];function c8e(t){var e={};return t!==null&&Object.keys(t).forEach(function(r){t[r].forEach(function(o){e[String(o)]=r})}),e}function u8e(t,e){if(e=e||{},Object.keys(e).forEach(function(r){if(a8e.indexOf(r)===-1)throw new JY('Unknown option \"'+r+'\" is met in definition of \"'+t+'\" YAML type.')}),this.tag=t,this.kind=e.kind||null,this.resolve=e.resolve||function(){return!0},this.construct=e.construct||function(r){return r},this.instanceOf=e.instanceOf||null,this.predicate=e.predicate||null,this.represent=e.represent||null,this.defaultStyle=e.defaultStyle||null,this.styleAliases=c8e(e.styleAliases||null),l8e.indexOf(this.kind)===-1)throw new JY('Unknown kind \"'+this.kind+'\" is specified for \"'+t+'\" YAML type.')}XY.exports=u8e});var $0=_((wxt,$Y)=>{\"use strict\";var ZY=Z0(),gP=ym(),A8e=as();function WT(t,e,r){var o=[];return t.include.forEach(function(a){r=WT(a,e,r)}),t[e].forEach(function(a){r.forEach(function(n,u){n.tag===a.tag&&n.kind===a.kind&&o.push(u)}),r.push(a)}),r.filter(function(a,n){return o.indexOf(n)===-1})}function f8e(){var t={scalar:{},sequence:{},mapping:{},fallback:{}},e,r;function o(a){t[a.kind][a.tag]=t.fallback[a.tag]=a}for(e=0,r=arguments.length;e<r;e+=1)arguments[e].forEach(o);return t}function Em(t){this.include=t.include||[],this.implicit=t.implicit||[],this.explicit=t.explicit||[],this.implicit.forEach(function(e){if(e.loadKind&&e.loadKind!==\"scalar\")throw new gP(\"There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.\")}),this.compiledImplicit=WT(this,\"implicit\",[]),this.compiledExplicit=WT(this,\"explicit\",[]),this.compiledTypeMap=f8e(this.compiledImplicit,this.compiledExplicit)}Em.DEFAULT=null;Em.create=function(){var e,r;switch(arguments.length){case 1:e=Em.DEFAULT,r=arguments[0];break;case 2:e=arguments[0],r=arguments[1];break;default:throw new gP(\"Wrong number of arguments for Schema.create function\")}if(e=ZY.toArray(e),r=ZY.toArray(r),!e.every(function(o){return o instanceof Em}))throw new gP(\"Specified list of super schemas (or a single Schema object) contains a non-Schema object.\");if(!r.every(function(o){return o instanceof A8e}))throw new gP(\"Specified list of YAML types (or a single Type object) contains a non-Type object.\");return new Em({include:e,explicit:r})};$Y.exports=Em});var tK=_((Bxt,eK)=>{\"use strict\";var p8e=as();eK.exports=new p8e(\"tag:yaml.org,2002:str\",{kind:\"scalar\",construct:function(t){return t!==null?t:\"\"}})});var nK=_((vxt,rK)=>{\"use strict\";var h8e=as();rK.exports=new h8e(\"tag:yaml.org,2002:seq\",{kind:\"sequence\",construct:function(t){return t!==null?t:[]}})});var sK=_((Dxt,iK)=>{\"use strict\";var g8e=as();iK.exports=new g8e(\"tag:yaml.org,2002:map\",{kind:\"mapping\",construct:function(t){return t!==null?t:{}}})});var dP=_((Pxt,oK)=>{\"use strict\";var d8e=$0();oK.exports=new d8e({explicit:[tK(),nK(),sK()]})});var lK=_((Sxt,aK)=>{\"use strict\";var m8e=as();function y8e(t){if(t===null)return!0;var e=t.length;return e===1&&t===\"~\"||e===4&&(t===\"null\"||t===\"Null\"||t===\"NULL\")}function E8e(){return null}function C8e(t){return t===null}aK.exports=new m8e(\"tag:yaml.org,2002:null\",{kind:\"scalar\",resolve:y8e,construct:E8e,predicate:C8e,represent:{canonical:function(){return\"~\"},lowercase:function(){return\"null\"},uppercase:function(){return\"NULL\"},camelcase:function(){return\"Null\"}},defaultStyle:\"lowercase\"})});var uK=_((xxt,cK)=>{\"use strict\";var I8e=as();function w8e(t){if(t===null)return!1;var e=t.length;return e===4&&(t===\"true\"||t===\"True\"||t===\"TRUE\")||e===5&&(t===\"false\"||t===\"False\"||t===\"FALSE\")}function B8e(t){return t===\"true\"||t===\"True\"||t===\"TRUE\"}function v8e(t){return Object.prototype.toString.call(t)===\"[object Boolean]\"}cK.exports=new I8e(\"tag:yaml.org,2002:bool\",{kind:\"scalar\",resolve:w8e,construct:B8e,predicate:v8e,represent:{lowercase:function(t){return t?\"true\":\"false\"},uppercase:function(t){return t?\"TRUE\":\"FALSE\"},camelcase:function(t){return t?\"True\":\"False\"}},defaultStyle:\"lowercase\"})});var fK=_((bxt,AK)=>{\"use strict\";var D8e=Z0(),P8e=as();function S8e(t){return 48<=t&&t<=57||65<=t&&t<=70||97<=t&&t<=102}function x8e(t){return 48<=t&&t<=55}function b8e(t){return 48<=t&&t<=57}function k8e(t){if(t===null)return!1;var e=t.length,r=0,o=!1,a;if(!e)return!1;if(a=t[r],(a===\"-\"||a===\"+\")&&(a=t[++r]),a===\"0\"){if(r+1===e)return!0;if(a=t[++r],a===\"b\"){for(r++;r<e;r++)if(a=t[r],a!==\"_\"){if(a!==\"0\"&&a!==\"1\")return!1;o=!0}return o&&a!==\"_\"}if(a===\"x\"){for(r++;r<e;r++)if(a=t[r],a!==\"_\"){if(!S8e(t.charCodeAt(r)))return!1;o=!0}return o&&a!==\"_\"}for(;r<e;r++)if(a=t[r],a!==\"_\"){if(!x8e(t.charCodeAt(r)))return!1;o=!0}return o&&a!==\"_\"}if(a===\"_\")return!1;for(;r<e;r++)if(a=t[r],a!==\"_\"){if(a===\":\")break;if(!b8e(t.charCodeAt(r)))return!1;o=!0}return!o||a===\"_\"?!1:a!==\":\"?!0:/^(:[0-5]?[0-9])+$/.test(t.slice(r))}function Q8e(t){var e=t,r=1,o,a,n=[];return e.indexOf(\"_\")!==-1&&(e=e.replace(/_/g,\"\")),o=e[0],(o===\"-\"||o===\"+\")&&(o===\"-\"&&(r=-1),e=e.slice(1),o=e[0]),e===\"0\"?0:o===\"0\"?e[1]===\"b\"?r*parseInt(e.slice(2),2):e[1]===\"x\"?r*parseInt(e,16):r*parseInt(e,8):e.indexOf(\":\")!==-1?(e.split(\":\").forEach(function(u){n.unshift(parseInt(u,10))}),e=0,a=1,n.forEach(function(u){e+=u*a,a*=60}),r*e):r*parseInt(e,10)}function F8e(t){return Object.prototype.toString.call(t)===\"[object Number]\"&&t%1===0&&!D8e.isNegativeZero(t)}AK.exports=new P8e(\"tag:yaml.org,2002:int\",{kind:\"scalar\",resolve:k8e,construct:Q8e,predicate:F8e,represent:{binary:function(t){return t>=0?\"0b\"+t.toString(2):\"-0b\"+t.toString(2).slice(1)},octal:function(t){return t>=0?\"0\"+t.toString(8):\"-0\"+t.toString(8).slice(1)},decimal:function(t){return t.toString(10)},hexadecimal:function(t){return t>=0?\"0x\"+t.toString(16).toUpperCase():\"-0x\"+t.toString(16).toUpperCase().slice(1)}},defaultStyle:\"decimal\",styleAliases:{binary:[2,\"bin\"],octal:[8,\"oct\"],decimal:[10,\"dec\"],hexadecimal:[16,\"hex\"]}})});var gK=_((kxt,hK)=>{\"use strict\";var pK=Z0(),R8e=as(),T8e=new RegExp(\"^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\\\.[0-9_]*|[-+]?\\\\.(?:inf|Inf|INF)|\\\\.(?:nan|NaN|NAN))$\");function L8e(t){return!(t===null||!T8e.test(t)||t[t.length-1]===\"_\")}function N8e(t){var e,r,o,a;return e=t.replace(/_/g,\"\").toLowerCase(),r=e[0]===\"-\"?-1:1,a=[],\"+-\".indexOf(e[0])>=0&&(e=e.slice(1)),e===\".inf\"?r===1?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:e===\".nan\"?NaN:e.indexOf(\":\")>=0?(e.split(\":\").forEach(function(n){a.unshift(parseFloat(n,10))}),e=0,o=1,a.forEach(function(n){e+=n*o,o*=60}),r*e):r*parseFloat(e,10)}var O8e=/^[-+]?[0-9]+e/;function M8e(t,e){var r;if(isNaN(t))switch(e){case\"lowercase\":return\".nan\";case\"uppercase\":return\".NAN\";case\"camelcase\":return\".NaN\"}else if(Number.POSITIVE_INFINITY===t)switch(e){case\"lowercase\":return\".inf\";case\"uppercase\":return\".INF\";case\"camelcase\":return\".Inf\"}else if(Number.NEGATIVE_INFINITY===t)switch(e){case\"lowercase\":return\"-.inf\";case\"uppercase\":return\"-.INF\";case\"camelcase\":return\"-.Inf\"}else if(pK.isNegativeZero(t))return\"-0.0\";return r=t.toString(10),O8e.test(r)?r.replace(\"e\",\".e\"):r}function U8e(t){return Object.prototype.toString.call(t)===\"[object Number]\"&&(t%1!==0||pK.isNegativeZero(t))}hK.exports=new R8e(\"tag:yaml.org,2002:float\",{kind:\"scalar\",resolve:L8e,construct:N8e,predicate:U8e,represent:M8e,defaultStyle:\"lowercase\"})});var YT=_((Qxt,dK)=>{\"use strict\";var _8e=$0();dK.exports=new _8e({include:[dP()],implicit:[lK(),uK(),fK(),gK()]})});var KT=_((Fxt,mK)=>{\"use strict\";var H8e=$0();mK.exports=new H8e({include:[YT()]})});var IK=_((Rxt,CK)=>{\"use strict\";var q8e=as(),yK=new RegExp(\"^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$\"),EK=new RegExp(\"^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\\\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\\\.([0-9]*))?(?:[ \\\\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$\");function j8e(t){return t===null?!1:yK.exec(t)!==null||EK.exec(t)!==null}function G8e(t){var e,r,o,a,n,u,A,p=0,h=null,E,w,D;if(e=yK.exec(t),e===null&&(e=EK.exec(t)),e===null)throw new Error(\"Date resolve error\");if(r=+e[1],o=+e[2]-1,a=+e[3],!e[4])return new Date(Date.UTC(r,o,a));if(n=+e[4],u=+e[5],A=+e[6],e[7]){for(p=e[7].slice(0,3);p.length<3;)p+=\"0\";p=+p}return e[9]&&(E=+e[10],w=+(e[11]||0),h=(E*60+w)*6e4,e[9]===\"-\"&&(h=-h)),D=new Date(Date.UTC(r,o,a,n,u,A,p)),h&&D.setTime(D.getTime()-h),D}function W8e(t){return t.toISOString()}CK.exports=new q8e(\"tag:yaml.org,2002:timestamp\",{kind:\"scalar\",resolve:j8e,construct:G8e,instanceOf:Date,represent:W8e})});var BK=_((Txt,wK)=>{\"use strict\";var Y8e=as();function K8e(t){return t===\"<<\"||t===null}wK.exports=new Y8e(\"tag:yaml.org,2002:merge\",{kind:\"scalar\",resolve:K8e})});var PK=_((Lxt,DK)=>{\"use strict\";var eg;try{vK=ve,eg=vK(\"buffer\").Buffer}catch{}var vK,V8e=as(),VT=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\\r`;function z8e(t){if(t===null)return!1;var e,r,o=0,a=t.length,n=VT;for(r=0;r<a;r++)if(e=n.indexOf(t.charAt(r)),!(e>64)){if(e<0)return!1;o+=6}return o%8===0}function J8e(t){var e,r,o=t.replace(/[\\r\\n=]/g,\"\"),a=o.length,n=VT,u=0,A=[];for(e=0;e<a;e++)e%4===0&&e&&(A.push(u>>16&255),A.push(u>>8&255),A.push(u&255)),u=u<<6|n.indexOf(o.charAt(e));return r=a%4*6,r===0?(A.push(u>>16&255),A.push(u>>8&255),A.push(u&255)):r===18?(A.push(u>>10&255),A.push(u>>2&255)):r===12&&A.push(u>>4&255),eg?eg.from?eg.from(A):new eg(A):A}function X8e(t){var e=\"\",r=0,o,a,n=t.length,u=VT;for(o=0;o<n;o++)o%3===0&&o&&(e+=u[r>>18&63],e+=u[r>>12&63],e+=u[r>>6&63],e+=u[r&63]),r=(r<<8)+t[o];return a=n%3,a===0?(e+=u[r>>18&63],e+=u[r>>12&63],e+=u[r>>6&63],e+=u[r&63]):a===2?(e+=u[r>>10&63],e+=u[r>>4&63],e+=u[r<<2&63],e+=u[64]):a===1&&(e+=u[r>>2&63],e+=u[r<<4&63],e+=u[64],e+=u[64]),e}function Z8e(t){return eg&&eg.isBuffer(t)}DK.exports=new V8e(\"tag:yaml.org,2002:binary\",{kind:\"scalar\",resolve:z8e,construct:J8e,predicate:Z8e,represent:X8e})});var xK=_((Oxt,SK)=>{\"use strict\";var $8e=as(),eHe=Object.prototype.hasOwnProperty,tHe=Object.prototype.toString;function rHe(t){if(t===null)return!0;var e=[],r,o,a,n,u,A=t;for(r=0,o=A.length;r<o;r+=1){if(a=A[r],u=!1,tHe.call(a)!==\"[object Object]\")return!1;for(n in a)if(eHe.call(a,n))if(!u)u=!0;else return!1;if(!u)return!1;if(e.indexOf(n)===-1)e.push(n);else return!1}return!0}function nHe(t){return t!==null?t:[]}SK.exports=new $8e(\"tag:yaml.org,2002:omap\",{kind:\"sequence\",resolve:rHe,construct:nHe})});var kK=_((Mxt,bK)=>{\"use strict\";var iHe=as(),sHe=Object.prototype.toString;function oHe(t){if(t===null)return!0;var e,r,o,a,n,u=t;for(n=new Array(u.length),e=0,r=u.length;e<r;e+=1){if(o=u[e],sHe.call(o)!==\"[object Object]\"||(a=Object.keys(o),a.length!==1))return!1;n[e]=[a[0],o[a[0]]]}return!0}function aHe(t){if(t===null)return[];var e,r,o,a,n,u=t;for(n=new Array(u.length),e=0,r=u.length;e<r;e+=1)o=u[e],a=Object.keys(o),n[e]=[a[0],o[a[0]]];return n}bK.exports=new iHe(\"tag:yaml.org,2002:pairs\",{kind:\"sequence\",resolve:oHe,construct:aHe})});var FK=_((Uxt,QK)=>{\"use strict\";var lHe=as(),cHe=Object.prototype.hasOwnProperty;function uHe(t){if(t===null)return!0;var e,r=t;for(e in r)if(cHe.call(r,e)&&r[e]!==null)return!1;return!0}function AHe(t){return t!==null?t:{}}QK.exports=new lHe(\"tag:yaml.org,2002:set\",{kind:\"mapping\",resolve:uHe,construct:AHe})});var Cm=_((_xt,RK)=>{\"use strict\";var fHe=$0();RK.exports=new fHe({include:[KT()],implicit:[IK(),BK()],explicit:[PK(),xK(),kK(),FK()]})});var LK=_((Hxt,TK)=>{\"use strict\";var pHe=as();function hHe(){return!0}function gHe(){}function dHe(){return\"\"}function mHe(t){return typeof t>\"u\"}TK.exports=new pHe(\"tag:yaml.org,2002:js/undefined\",{kind:\"scalar\",resolve:hHe,construct:gHe,predicate:mHe,represent:dHe})});var OK=_((qxt,NK)=>{\"use strict\";var yHe=as();function EHe(t){if(t===null||t.length===0)return!1;var e=t,r=/\\/([gim]*)$/.exec(t),o=\"\";return!(e[0]===\"/\"&&(r&&(o=r[1]),o.length>3||e[e.length-o.length-1]!==\"/\"))}function CHe(t){var e=t,r=/\\/([gim]*)$/.exec(t),o=\"\";return e[0]===\"/\"&&(r&&(o=r[1]),e=e.slice(1,e.length-o.length-1)),new RegExp(e,o)}function IHe(t){var e=\"/\"+t.source+\"/\";return t.global&&(e+=\"g\"),t.multiline&&(e+=\"m\"),t.ignoreCase&&(e+=\"i\"),e}function wHe(t){return Object.prototype.toString.call(t)===\"[object RegExp]\"}NK.exports=new yHe(\"tag:yaml.org,2002:js/regexp\",{kind:\"scalar\",resolve:EHe,construct:CHe,predicate:wHe,represent:IHe})});var _K=_((jxt,UK)=>{\"use strict\";var mP;try{MK=ve,mP=MK(\"esprima\")}catch{typeof window<\"u\"&&(mP=window.esprima)}var MK,BHe=as();function vHe(t){if(t===null)return!1;try{var e=\"(\"+t+\")\",r=mP.parse(e,{range:!0});return!(r.type!==\"Program\"||r.body.length!==1||r.body[0].type!==\"ExpressionStatement\"||r.body[0].expression.type!==\"ArrowFunctionExpression\"&&r.body[0].expression.type!==\"FunctionExpression\")}catch{return!1}}function DHe(t){var e=\"(\"+t+\")\",r=mP.parse(e,{range:!0}),o=[],a;if(r.type!==\"Program\"||r.body.length!==1||r.body[0].type!==\"ExpressionStatement\"||r.body[0].expression.type!==\"ArrowFunctionExpression\"&&r.body[0].expression.type!==\"FunctionExpression\")throw new Error(\"Failed to resolve function\");return r.body[0].expression.params.forEach(function(n){o.push(n.name)}),a=r.body[0].expression.body.range,r.body[0].expression.body.type===\"BlockStatement\"?new Function(o,e.slice(a[0]+1,a[1]-1)):new Function(o,\"return \"+e.slice(a[0],a[1]))}function PHe(t){return t.toString()}function SHe(t){return Object.prototype.toString.call(t)===\"[object Function]\"}UK.exports=new BHe(\"tag:yaml.org,2002:js/function\",{kind:\"scalar\",resolve:vHe,construct:DHe,predicate:SHe,represent:PHe})});var hw=_((Wxt,qK)=>{\"use strict\";var HK=$0();qK.exports=HK.DEFAULT=new HK({include:[Cm()],explicit:[LK(),OK(),_K()]})});var aV=_((Yxt,gw)=>{\"use strict\";var mf=Z0(),zK=ym(),xHe=zY(),JK=Cm(),bHe=hw(),Vp=Object.prototype.hasOwnProperty,yP=1,XK=2,ZK=3,EP=4,zT=1,kHe=2,jK=3,QHe=/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F-\\x84\\x86-\\x9F\\uFFFE\\uFFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]/,FHe=/[\\x85\\u2028\\u2029]/,RHe=/[,\\[\\]\\{\\}]/,$K=/^(?:!|!!|![a-z\\-]+!)$/i,eV=/^(?:!|[^,\\[\\]\\{\\}])(?:%[0-9a-f]{2}|[0-9a-z\\-#;\\/\\?:@&=\\+\\$,_\\.!~\\*'\\(\\)\\[\\]])*$/i;function GK(t){return Object.prototype.toString.call(t)}function Wu(t){return t===10||t===13}function rg(t){return t===9||t===32}function Da(t){return t===9||t===32||t===10||t===13}function Im(t){return t===44||t===91||t===93||t===123||t===125}function THe(t){var e;return 48<=t&&t<=57?t-48:(e=t|32,97<=e&&e<=102?e-97+10:-1)}function LHe(t){return t===120?2:t===117?4:t===85?8:0}function NHe(t){return 48<=t&&t<=57?t-48:-1}function WK(t){return t===48?\"\\0\":t===97?\"\\x07\":t===98?\"\\b\":t===116||t===9?\"\t\":t===110?`\n`:t===118?\"\\v\":t===102?\"\\f\":t===114?\"\\r\":t===101?\"\\x1B\":t===32?\" \":t===34?'\"':t===47?\"/\":t===92?\"\\\\\":t===78?\"\\x85\":t===95?\"\\xA0\":t===76?\"\\u2028\":t===80?\"\\u2029\":\"\"}function OHe(t){return t<=65535?String.fromCharCode(t):String.fromCharCode((t-65536>>10)+55296,(t-65536&1023)+56320)}var tV=new Array(256),rV=new Array(256);for(tg=0;tg<256;tg++)tV[tg]=WK(tg)?1:0,rV[tg]=WK(tg);var tg;function MHe(t,e){this.input=t,this.filename=e.filename||null,this.schema=e.schema||bHe,this.onWarning=e.onWarning||null,this.legacy=e.legacy||!1,this.json=e.json||!1,this.listener=e.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=t.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.documents=[]}function nV(t,e){return new zK(e,new xHe(t.filename,t.input,t.position,t.line,t.position-t.lineStart))}function Qr(t,e){throw nV(t,e)}function CP(t,e){t.onWarning&&t.onWarning.call(null,nV(t,e))}var YK={YAML:function(e,r,o){var a,n,u;e.version!==null&&Qr(e,\"duplication of %YAML directive\"),o.length!==1&&Qr(e,\"YAML directive accepts exactly one argument\"),a=/^([0-9]+)\\.([0-9]+)$/.exec(o[0]),a===null&&Qr(e,\"ill-formed argument of the YAML directive\"),n=parseInt(a[1],10),u=parseInt(a[2],10),n!==1&&Qr(e,\"unacceptable YAML version of the document\"),e.version=o[0],e.checkLineBreaks=u<2,u!==1&&u!==2&&CP(e,\"unsupported YAML version of the document\")},TAG:function(e,r,o){var a,n;o.length!==2&&Qr(e,\"TAG directive accepts exactly two arguments\"),a=o[0],n=o[1],$K.test(a)||Qr(e,\"ill-formed tag handle (first argument) of the TAG directive\"),Vp.call(e.tagMap,a)&&Qr(e,'there is a previously declared suffix for \"'+a+'\" tag handle'),eV.test(n)||Qr(e,\"ill-formed tag prefix (second argument) of the TAG directive\"),e.tagMap[a]=n}};function Kp(t,e,r,o){var a,n,u,A;if(e<r){if(A=t.input.slice(e,r),o)for(a=0,n=A.length;a<n;a+=1)u=A.charCodeAt(a),u===9||32<=u&&u<=1114111||Qr(t,\"expected valid JSON character\");else QHe.test(A)&&Qr(t,\"the stream contains non-printable characters\");t.result+=A}}function KK(t,e,r,o){var a,n,u,A;for(mf.isObject(r)||Qr(t,\"cannot merge mappings; the provided source object is unacceptable\"),a=Object.keys(r),u=0,A=a.length;u<A;u+=1)n=a[u],Vp.call(e,n)||(e[n]=r[n],o[n]=!0)}function wm(t,e,r,o,a,n,u,A){var p,h;if(Array.isArray(a))for(a=Array.prototype.slice.call(a),p=0,h=a.length;p<h;p+=1)Array.isArray(a[p])&&Qr(t,\"nested arrays are not supported inside keys\"),typeof a==\"object\"&&GK(a[p])===\"[object Object]\"&&(a[p]=\"[object Object]\");if(typeof a==\"object\"&&GK(a)===\"[object Object]\"&&(a=\"[object Object]\"),a=String(a),e===null&&(e={}),o===\"tag:yaml.org,2002:merge\")if(Array.isArray(n))for(p=0,h=n.length;p<h;p+=1)KK(t,e,n[p],r);else KK(t,e,n,r);else!t.json&&!Vp.call(r,a)&&Vp.call(e,a)&&(t.line=u||t.line,t.position=A||t.position,Qr(t,\"duplicated mapping key\")),e[a]=n,delete r[a];return e}function JT(t){var e;e=t.input.charCodeAt(t.position),e===10?t.position++:e===13?(t.position++,t.input.charCodeAt(t.position)===10&&t.position++):Qr(t,\"a line break is expected\"),t.line+=1,t.lineStart=t.position}function Yi(t,e,r){for(var o=0,a=t.input.charCodeAt(t.position);a!==0;){for(;rg(a);)a=t.input.charCodeAt(++t.position);if(e&&a===35)do a=t.input.charCodeAt(++t.position);while(a!==10&&a!==13&&a!==0);if(Wu(a))for(JT(t),a=t.input.charCodeAt(t.position),o++,t.lineIndent=0;a===32;)t.lineIndent++,a=t.input.charCodeAt(++t.position);else break}return r!==-1&&o!==0&&t.lineIndent<r&&CP(t,\"deficient indentation\"),o}function IP(t){var e=t.position,r;return r=t.input.charCodeAt(e),!!((r===45||r===46)&&r===t.input.charCodeAt(e+1)&&r===t.input.charCodeAt(e+2)&&(e+=3,r=t.input.charCodeAt(e),r===0||Da(r)))}function XT(t,e){e===1?t.result+=\" \":e>1&&(t.result+=mf.repeat(`\n`,e-1))}function UHe(t,e,r){var o,a,n,u,A,p,h,E,w=t.kind,D=t.result,b;if(b=t.input.charCodeAt(t.position),Da(b)||Im(b)||b===35||b===38||b===42||b===33||b===124||b===62||b===39||b===34||b===37||b===64||b===96||(b===63||b===45)&&(a=t.input.charCodeAt(t.position+1),Da(a)||r&&Im(a)))return!1;for(t.kind=\"scalar\",t.result=\"\",n=u=t.position,A=!1;b!==0;){if(b===58){if(a=t.input.charCodeAt(t.position+1),Da(a)||r&&Im(a))break}else if(b===35){if(o=t.input.charCodeAt(t.position-1),Da(o))break}else{if(t.position===t.lineStart&&IP(t)||r&&Im(b))break;if(Wu(b))if(p=t.line,h=t.lineStart,E=t.lineIndent,Yi(t,!1,-1),t.lineIndent>=e){A=!0,b=t.input.charCodeAt(t.position);continue}else{t.position=u,t.line=p,t.lineStart=h,t.lineIndent=E;break}}A&&(Kp(t,n,u,!1),XT(t,t.line-p),n=u=t.position,A=!1),rg(b)||(u=t.position+1),b=t.input.charCodeAt(++t.position)}return Kp(t,n,u,!1),t.result?!0:(t.kind=w,t.result=D,!1)}function _He(t,e){var r,o,a;if(r=t.input.charCodeAt(t.position),r!==39)return!1;for(t.kind=\"scalar\",t.result=\"\",t.position++,o=a=t.position;(r=t.input.charCodeAt(t.position))!==0;)if(r===39)if(Kp(t,o,t.position,!0),r=t.input.charCodeAt(++t.position),r===39)o=t.position,t.position++,a=t.position;else return!0;else Wu(r)?(Kp(t,o,a,!0),XT(t,Yi(t,!1,e)),o=a=t.position):t.position===t.lineStart&&IP(t)?Qr(t,\"unexpected end of the document within a single quoted scalar\"):(t.position++,a=t.position);Qr(t,\"unexpected end of the stream within a single quoted scalar\")}function HHe(t,e){var r,o,a,n,u,A;if(A=t.input.charCodeAt(t.position),A!==34)return!1;for(t.kind=\"scalar\",t.result=\"\",t.position++,r=o=t.position;(A=t.input.charCodeAt(t.position))!==0;){if(A===34)return Kp(t,r,t.position,!0),t.position++,!0;if(A===92){if(Kp(t,r,t.position,!0),A=t.input.charCodeAt(++t.position),Wu(A))Yi(t,!1,e);else if(A<256&&tV[A])t.result+=rV[A],t.position++;else if((u=LHe(A))>0){for(a=u,n=0;a>0;a--)A=t.input.charCodeAt(++t.position),(u=THe(A))>=0?n=(n<<4)+u:Qr(t,\"expected hexadecimal character\");t.result+=OHe(n),t.position++}else Qr(t,\"unknown escape sequence\");r=o=t.position}else Wu(A)?(Kp(t,r,o,!0),XT(t,Yi(t,!1,e)),r=o=t.position):t.position===t.lineStart&&IP(t)?Qr(t,\"unexpected end of the document within a double quoted scalar\"):(t.position++,o=t.position)}Qr(t,\"unexpected end of the stream within a double quoted scalar\")}function qHe(t,e){var r=!0,o,a=t.tag,n,u=t.anchor,A,p,h,E,w,D={},b,C,T,N;if(N=t.input.charCodeAt(t.position),N===91)p=93,w=!1,n=[];else if(N===123)p=125,w=!0,n={};else return!1;for(t.anchor!==null&&(t.anchorMap[t.anchor]=n),N=t.input.charCodeAt(++t.position);N!==0;){if(Yi(t,!0,e),N=t.input.charCodeAt(t.position),N===p)return t.position++,t.tag=a,t.anchor=u,t.kind=w?\"mapping\":\"sequence\",t.result=n,!0;r||Qr(t,\"missed comma between flow collection entries\"),C=b=T=null,h=E=!1,N===63&&(A=t.input.charCodeAt(t.position+1),Da(A)&&(h=E=!0,t.position++,Yi(t,!0,e))),o=t.line,Bm(t,e,yP,!1,!0),C=t.tag,b=t.result,Yi(t,!0,e),N=t.input.charCodeAt(t.position),(E||t.line===o)&&N===58&&(h=!0,N=t.input.charCodeAt(++t.position),Yi(t,!0,e),Bm(t,e,yP,!1,!0),T=t.result),w?wm(t,n,D,C,b,T):h?n.push(wm(t,null,D,C,b,T)):n.push(b),Yi(t,!0,e),N=t.input.charCodeAt(t.position),N===44?(r=!0,N=t.input.charCodeAt(++t.position)):r=!1}Qr(t,\"unexpected end of the stream within a flow collection\")}function jHe(t,e){var r,o,a=zT,n=!1,u=!1,A=e,p=0,h=!1,E,w;if(w=t.input.charCodeAt(t.position),w===124)o=!1;else if(w===62)o=!0;else return!1;for(t.kind=\"scalar\",t.result=\"\";w!==0;)if(w=t.input.charCodeAt(++t.position),w===43||w===45)zT===a?a=w===43?jK:kHe:Qr(t,\"repeat of a chomping mode identifier\");else if((E=NHe(w))>=0)E===0?Qr(t,\"bad explicit indentation width of a block scalar; it cannot be less than one\"):u?Qr(t,\"repeat of an indentation width identifier\"):(A=e+E-1,u=!0);else break;if(rg(w)){do w=t.input.charCodeAt(++t.position);while(rg(w));if(w===35)do w=t.input.charCodeAt(++t.position);while(!Wu(w)&&w!==0)}for(;w!==0;){for(JT(t),t.lineIndent=0,w=t.input.charCodeAt(t.position);(!u||t.lineIndent<A)&&w===32;)t.lineIndent++,w=t.input.charCodeAt(++t.position);if(!u&&t.lineIndent>A&&(A=t.lineIndent),Wu(w)){p++;continue}if(t.lineIndent<A){a===jK?t.result+=mf.repeat(`\n`,n?1+p:p):a===zT&&n&&(t.result+=`\n`);break}for(o?rg(w)?(h=!0,t.result+=mf.repeat(`\n`,n?1+p:p)):h?(h=!1,t.result+=mf.repeat(`\n`,p+1)):p===0?n&&(t.result+=\" \"):t.result+=mf.repeat(`\n`,p):t.result+=mf.repeat(`\n`,n?1+p:p),n=!0,u=!0,p=0,r=t.position;!Wu(w)&&w!==0;)w=t.input.charCodeAt(++t.position);Kp(t,r,t.position,!1)}return!0}function VK(t,e){var r,o=t.tag,a=t.anchor,n=[],u,A=!1,p;for(t.anchor!==null&&(t.anchorMap[t.anchor]=n),p=t.input.charCodeAt(t.position);p!==0&&!(p!==45||(u=t.input.charCodeAt(t.position+1),!Da(u)));){if(A=!0,t.position++,Yi(t,!0,-1)&&t.lineIndent<=e){n.push(null),p=t.input.charCodeAt(t.position);continue}if(r=t.line,Bm(t,e,ZK,!1,!0),n.push(t.result),Yi(t,!0,-1),p=t.input.charCodeAt(t.position),(t.line===r||t.lineIndent>e)&&p!==0)Qr(t,\"bad indentation of a sequence entry\");else if(t.lineIndent<e)break}return A?(t.tag=o,t.anchor=a,t.kind=\"sequence\",t.result=n,!0):!1}function GHe(t,e,r){var o,a,n,u,A=t.tag,p=t.anchor,h={},E={},w=null,D=null,b=null,C=!1,T=!1,N;for(t.anchor!==null&&(t.anchorMap[t.anchor]=h),N=t.input.charCodeAt(t.position);N!==0;){if(o=t.input.charCodeAt(t.position+1),n=t.line,u=t.position,(N===63||N===58)&&Da(o))N===63?(C&&(wm(t,h,E,w,D,null),w=D=b=null),T=!0,C=!0,a=!0):C?(C=!1,a=!0):Qr(t,\"incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line\"),t.position+=1,N=o;else if(Bm(t,r,XK,!1,!0))if(t.line===n){for(N=t.input.charCodeAt(t.position);rg(N);)N=t.input.charCodeAt(++t.position);if(N===58)N=t.input.charCodeAt(++t.position),Da(N)||Qr(t,\"a whitespace character is expected after the key-value separator within a block mapping\"),C&&(wm(t,h,E,w,D,null),w=D=b=null),T=!0,C=!1,a=!1,w=t.tag,D=t.result;else if(T)Qr(t,\"can not read an implicit mapping pair; a colon is missed\");else return t.tag=A,t.anchor=p,!0}else if(T)Qr(t,\"can not read a block mapping entry; a multiline key may not be an implicit key\");else return t.tag=A,t.anchor=p,!0;else break;if((t.line===n||t.lineIndent>e)&&(Bm(t,e,EP,!0,a)&&(C?D=t.result:b=t.result),C||(wm(t,h,E,w,D,b,n,u),w=D=b=null),Yi(t,!0,-1),N=t.input.charCodeAt(t.position)),t.lineIndent>e&&N!==0)Qr(t,\"bad indentation of a mapping entry\");else if(t.lineIndent<e)break}return C&&wm(t,h,E,w,D,null),T&&(t.tag=A,t.anchor=p,t.kind=\"mapping\",t.result=h),T}function WHe(t){var e,r=!1,o=!1,a,n,u;if(u=t.input.charCodeAt(t.position),u!==33)return!1;if(t.tag!==null&&Qr(t,\"duplication of a tag property\"),u=t.input.charCodeAt(++t.position),u===60?(r=!0,u=t.input.charCodeAt(++t.position)):u===33?(o=!0,a=\"!!\",u=t.input.charCodeAt(++t.position)):a=\"!\",e=t.position,r){do u=t.input.charCodeAt(++t.position);while(u!==0&&u!==62);t.position<t.length?(n=t.input.slice(e,t.position),u=t.input.charCodeAt(++t.position)):Qr(t,\"unexpected end of the stream within a verbatim tag\")}else{for(;u!==0&&!Da(u);)u===33&&(o?Qr(t,\"tag suffix cannot contain exclamation marks\"):(a=t.input.slice(e-1,t.position+1),$K.test(a)||Qr(t,\"named tag handle cannot contain such characters\"),o=!0,e=t.position+1)),u=t.input.charCodeAt(++t.position);n=t.input.slice(e,t.position),RHe.test(n)&&Qr(t,\"tag suffix cannot contain flow indicator characters\")}return n&&!eV.test(n)&&Qr(t,\"tag name cannot contain such characters: \"+n),r?t.tag=n:Vp.call(t.tagMap,a)?t.tag=t.tagMap[a]+n:a===\"!\"?t.tag=\"!\"+n:a===\"!!\"?t.tag=\"tag:yaml.org,2002:\"+n:Qr(t,'undeclared tag handle \"'+a+'\"'),!0}function YHe(t){var e,r;if(r=t.input.charCodeAt(t.position),r!==38)return!1;for(t.anchor!==null&&Qr(t,\"duplication of an anchor property\"),r=t.input.charCodeAt(++t.position),e=t.position;r!==0&&!Da(r)&&!Im(r);)r=t.input.charCodeAt(++t.position);return t.position===e&&Qr(t,\"name of an anchor node must contain at least one character\"),t.anchor=t.input.slice(e,t.position),!0}function KHe(t){var e,r,o;if(o=t.input.charCodeAt(t.position),o!==42)return!1;for(o=t.input.charCodeAt(++t.position),e=t.position;o!==0&&!Da(o)&&!Im(o);)o=t.input.charCodeAt(++t.position);return t.position===e&&Qr(t,\"name of an alias node must contain at least one character\"),r=t.input.slice(e,t.position),Vp.call(t.anchorMap,r)||Qr(t,'unidentified alias \"'+r+'\"'),t.result=t.anchorMap[r],Yi(t,!0,-1),!0}function Bm(t,e,r,o,a){var n,u,A,p=1,h=!1,E=!1,w,D,b,C,T;if(t.listener!==null&&t.listener(\"open\",t),t.tag=null,t.anchor=null,t.kind=null,t.result=null,n=u=A=EP===r||ZK===r,o&&Yi(t,!0,-1)&&(h=!0,t.lineIndent>e?p=1:t.lineIndent===e?p=0:t.lineIndent<e&&(p=-1)),p===1)for(;WHe(t)||YHe(t);)Yi(t,!0,-1)?(h=!0,A=n,t.lineIndent>e?p=1:t.lineIndent===e?p=0:t.lineIndent<e&&(p=-1)):A=!1;if(A&&(A=h||a),(p===1||EP===r)&&(yP===r||XK===r?C=e:C=e+1,T=t.position-t.lineStart,p===1?A&&(VK(t,T)||GHe(t,T,C))||qHe(t,C)?E=!0:(u&&jHe(t,C)||_He(t,C)||HHe(t,C)?E=!0:KHe(t)?(E=!0,(t.tag!==null||t.anchor!==null)&&Qr(t,\"alias node should not have any properties\")):UHe(t,C,yP===r)&&(E=!0,t.tag===null&&(t.tag=\"?\")),t.anchor!==null&&(t.anchorMap[t.anchor]=t.result)):p===0&&(E=A&&VK(t,T))),t.tag!==null&&t.tag!==\"!\")if(t.tag===\"?\"){for(t.result!==null&&t.kind!==\"scalar\"&&Qr(t,'unacceptable node kind for !<?> tag; it should be \"scalar\", not \"'+t.kind+'\"'),w=0,D=t.implicitTypes.length;w<D;w+=1)if(b=t.implicitTypes[w],b.resolve(t.result)){t.result=b.construct(t.result),t.tag=b.tag,t.anchor!==null&&(t.anchorMap[t.anchor]=t.result);break}}else Vp.call(t.typeMap[t.kind||\"fallback\"],t.tag)?(b=t.typeMap[t.kind||\"fallback\"][t.tag],t.result!==null&&b.kind!==t.kind&&Qr(t,\"unacceptable node kind for !<\"+t.tag+'> tag; it should be \"'+b.kind+'\", not \"'+t.kind+'\"'),b.resolve(t.result)?(t.result=b.construct(t.result),t.anchor!==null&&(t.anchorMap[t.anchor]=t.result)):Qr(t,\"cannot resolve a node with !<\"+t.tag+\"> explicit tag\")):Qr(t,\"unknown tag !<\"+t.tag+\">\");return t.listener!==null&&t.listener(\"close\",t),t.tag!==null||t.anchor!==null||E}function VHe(t){var e=t.position,r,o,a,n=!1,u;for(t.version=null,t.checkLineBreaks=t.legacy,t.tagMap={},t.anchorMap={};(u=t.input.charCodeAt(t.position))!==0&&(Yi(t,!0,-1),u=t.input.charCodeAt(t.position),!(t.lineIndent>0||u!==37));){for(n=!0,u=t.input.charCodeAt(++t.position),r=t.position;u!==0&&!Da(u);)u=t.input.charCodeAt(++t.position);for(o=t.input.slice(r,t.position),a=[],o.length<1&&Qr(t,\"directive name must not be less than one character in length\");u!==0;){for(;rg(u);)u=t.input.charCodeAt(++t.position);if(u===35){do u=t.input.charCodeAt(++t.position);while(u!==0&&!Wu(u));break}if(Wu(u))break;for(r=t.position;u!==0&&!Da(u);)u=t.input.charCodeAt(++t.position);a.push(t.input.slice(r,t.position))}u!==0&&JT(t),Vp.call(YK,o)?YK[o](t,o,a):CP(t,'unknown document directive \"'+o+'\"')}if(Yi(t,!0,-1),t.lineIndent===0&&t.input.charCodeAt(t.position)===45&&t.input.charCodeAt(t.position+1)===45&&t.input.charCodeAt(t.position+2)===45?(t.position+=3,Yi(t,!0,-1)):n&&Qr(t,\"directives end mark is expected\"),Bm(t,t.lineIndent-1,EP,!1,!0),Yi(t,!0,-1),t.checkLineBreaks&&FHe.test(t.input.slice(e,t.position))&&CP(t,\"non-ASCII line breaks are interpreted as content\"),t.documents.push(t.result),t.position===t.lineStart&&IP(t)){t.input.charCodeAt(t.position)===46&&(t.position+=3,Yi(t,!0,-1));return}if(t.position<t.length-1)Qr(t,\"end of the stream or a document separator is expected\");else return}function iV(t,e){t=String(t),e=e||{},t.length!==0&&(t.charCodeAt(t.length-1)!==10&&t.charCodeAt(t.length-1)!==13&&(t+=`\n`),t.charCodeAt(0)===65279&&(t=t.slice(1)));var r=new MHe(t,e),o=t.indexOf(\"\\0\");for(o!==-1&&(r.position=o,Qr(r,\"null byte is not allowed in input\")),r.input+=\"\\0\";r.input.charCodeAt(r.position)===32;)r.lineIndent+=1,r.position+=1;for(;r.position<r.length-1;)VHe(r);return r.documents}function sV(t,e,r){e!==null&&typeof e==\"object\"&&typeof r>\"u\"&&(r=e,e=null);var o=iV(t,r);if(typeof e!=\"function\")return o;for(var a=0,n=o.length;a<n;a+=1)e(o[a])}function oV(t,e){var r=iV(t,e);if(r.length!==0){if(r.length===1)return r[0];throw new zK(\"expected a single document in the stream, but found more\")}}function zHe(t,e,r){return typeof e==\"object\"&&e!==null&&typeof r>\"u\"&&(r=e,e=null),sV(t,e,mf.extend({schema:JK},r))}function JHe(t,e){return oV(t,mf.extend({schema:JK},e))}gw.exports.loadAll=sV;gw.exports.load=oV;gw.exports.safeLoadAll=zHe;gw.exports.safeLoad=JHe});var kV=_((Kxt,tL)=>{\"use strict\";var mw=Z0(),yw=ym(),XHe=hw(),ZHe=Cm(),gV=Object.prototype.toString,dV=Object.prototype.hasOwnProperty,$He=9,dw=10,e6e=13,t6e=32,r6e=33,n6e=34,mV=35,i6e=37,s6e=38,o6e=39,a6e=42,yV=44,l6e=45,EV=58,c6e=61,u6e=62,A6e=63,f6e=64,CV=91,IV=93,p6e=96,wV=123,h6e=124,BV=125,mo={};mo[0]=\"\\\\0\";mo[7]=\"\\\\a\";mo[8]=\"\\\\b\";mo[9]=\"\\\\t\";mo[10]=\"\\\\n\";mo[11]=\"\\\\v\";mo[12]=\"\\\\f\";mo[13]=\"\\\\r\";mo[27]=\"\\\\e\";mo[34]='\\\\\"';mo[92]=\"\\\\\\\\\";mo[133]=\"\\\\N\";mo[160]=\"\\\\_\";mo[8232]=\"\\\\L\";mo[8233]=\"\\\\P\";var g6e=[\"y\",\"Y\",\"yes\",\"Yes\",\"YES\",\"on\",\"On\",\"ON\",\"n\",\"N\",\"no\",\"No\",\"NO\",\"off\",\"Off\",\"OFF\"];function d6e(t,e){var r,o,a,n,u,A,p;if(e===null)return{};for(r={},o=Object.keys(e),a=0,n=o.length;a<n;a+=1)u=o[a],A=String(e[u]),u.slice(0,2)===\"!!\"&&(u=\"tag:yaml.org,2002:\"+u.slice(2)),p=t.compiledTypeMap.fallback[u],p&&dV.call(p.styleAliases,A)&&(A=p.styleAliases[A]),r[u]=A;return r}function lV(t){var e,r,o;if(e=t.toString(16).toUpperCase(),t<=255)r=\"x\",o=2;else if(t<=65535)r=\"u\",o=4;else if(t<=4294967295)r=\"U\",o=8;else throw new yw(\"code point within a string may not be greater than 0xFFFFFFFF\");return\"\\\\\"+r+mw.repeat(\"0\",o-e.length)+e}function m6e(t){this.schema=t.schema||XHe,this.indent=Math.max(1,t.indent||2),this.noArrayIndent=t.noArrayIndent||!1,this.skipInvalid=t.skipInvalid||!1,this.flowLevel=mw.isNothing(t.flowLevel)?-1:t.flowLevel,this.styleMap=d6e(this.schema,t.styles||null),this.sortKeys=t.sortKeys||!1,this.lineWidth=t.lineWidth||80,this.noRefs=t.noRefs||!1,this.noCompatMode=t.noCompatMode||!1,this.condenseFlow=t.condenseFlow||!1,this.implicitTypes=this.schema.compiledImplicit,this.explicitTypes=this.schema.compiledExplicit,this.tag=null,this.result=\"\",this.duplicates=[],this.usedDuplicates=null}function cV(t,e){for(var r=mw.repeat(\" \",e),o=0,a=-1,n=\"\",u,A=t.length;o<A;)a=t.indexOf(`\n`,o),a===-1?(u=t.slice(o),o=A):(u=t.slice(o,a+1),o=a+1),u.length&&u!==`\n`&&(n+=r),n+=u;return n}function ZT(t,e){return`\n`+mw.repeat(\" \",t.indent*e)}function y6e(t,e){var r,o,a;for(r=0,o=t.implicitTypes.length;r<o;r+=1)if(a=t.implicitTypes[r],a.resolve(e))return!0;return!1}function eL(t){return t===t6e||t===$He}function vm(t){return 32<=t&&t<=126||161<=t&&t<=55295&&t!==8232&&t!==8233||57344<=t&&t<=65533&&t!==65279||65536<=t&&t<=1114111}function E6e(t){return vm(t)&&!eL(t)&&t!==65279&&t!==e6e&&t!==dw}function uV(t,e){return vm(t)&&t!==65279&&t!==yV&&t!==CV&&t!==IV&&t!==wV&&t!==BV&&t!==EV&&(t!==mV||e&&E6e(e))}function C6e(t){return vm(t)&&t!==65279&&!eL(t)&&t!==l6e&&t!==A6e&&t!==EV&&t!==yV&&t!==CV&&t!==IV&&t!==wV&&t!==BV&&t!==mV&&t!==s6e&&t!==a6e&&t!==r6e&&t!==h6e&&t!==c6e&&t!==u6e&&t!==o6e&&t!==n6e&&t!==i6e&&t!==f6e&&t!==p6e}function vV(t){var e=/^\\n* /;return e.test(t)}var DV=1,PV=2,SV=3,xV=4,wP=5;function I6e(t,e,r,o,a){var n,u,A,p=!1,h=!1,E=o!==-1,w=-1,D=C6e(t.charCodeAt(0))&&!eL(t.charCodeAt(t.length-1));if(e)for(n=0;n<t.length;n++){if(u=t.charCodeAt(n),!vm(u))return wP;A=n>0?t.charCodeAt(n-1):null,D=D&&uV(u,A)}else{for(n=0;n<t.length;n++){if(u=t.charCodeAt(n),u===dw)p=!0,E&&(h=h||n-w-1>o&&t[w+1]!==\" \",w=n);else if(!vm(u))return wP;A=n>0?t.charCodeAt(n-1):null,D=D&&uV(u,A)}h=h||E&&n-w-1>o&&t[w+1]!==\" \"}return!p&&!h?D&&!a(t)?DV:PV:r>9&&vV(t)?wP:h?xV:SV}function w6e(t,e,r,o){t.dump=function(){if(e.length===0)return\"''\";if(!t.noCompatMode&&g6e.indexOf(e)!==-1)return\"'\"+e+\"'\";var a=t.indent*Math.max(1,r),n=t.lineWidth===-1?-1:Math.max(Math.min(t.lineWidth,40),t.lineWidth-a),u=o||t.flowLevel>-1&&r>=t.flowLevel;function A(p){return y6e(t,p)}switch(I6e(e,u,t.indent,n,A)){case DV:return e;case PV:return\"'\"+e.replace(/'/g,\"''\")+\"'\";case SV:return\"|\"+AV(e,t.indent)+fV(cV(e,a));case xV:return\">\"+AV(e,t.indent)+fV(cV(B6e(e,n),a));case wP:return'\"'+v6e(e,n)+'\"';default:throw new yw(\"impossible error: invalid scalar style\")}}()}function AV(t,e){var r=vV(t)?String(e):\"\",o=t[t.length-1]===`\n`,a=o&&(t[t.length-2]===`\n`||t===`\n`),n=a?\"+\":o?\"\":\"-\";return r+n+`\n`}function fV(t){return t[t.length-1]===`\n`?t.slice(0,-1):t}function B6e(t,e){for(var r=/(\\n+)([^\\n]*)/g,o=function(){var h=t.indexOf(`\n`);return h=h!==-1?h:t.length,r.lastIndex=h,pV(t.slice(0,h),e)}(),a=t[0]===`\n`||t[0]===\" \",n,u;u=r.exec(t);){var A=u[1],p=u[2];n=p[0]===\" \",o+=A+(!a&&!n&&p!==\"\"?`\n`:\"\")+pV(p,e),a=n}return o}function pV(t,e){if(t===\"\"||t[0]===\" \")return t;for(var r=/ [^ ]/g,o,a=0,n,u=0,A=0,p=\"\";o=r.exec(t);)A=o.index,A-a>e&&(n=u>a?u:A,p+=`\n`+t.slice(a,n),a=n+1),u=A;return p+=`\n`,t.length-a>e&&u>a?p+=t.slice(a,u)+`\n`+t.slice(u+1):p+=t.slice(a),p.slice(1)}function v6e(t){for(var e=\"\",r,o,a,n=0;n<t.length;n++){if(r=t.charCodeAt(n),r>=55296&&r<=56319&&(o=t.charCodeAt(n+1),o>=56320&&o<=57343)){e+=lV((r-55296)*1024+o-56320+65536),n++;continue}a=mo[r],e+=!a&&vm(r)?t[n]:a||lV(r)}return e}function D6e(t,e,r){var o=\"\",a=t.tag,n,u;for(n=0,u=r.length;n<u;n+=1)ng(t,e,r[n],!1,!1)&&(n!==0&&(o+=\",\"+(t.condenseFlow?\"\":\" \")),o+=t.dump);t.tag=a,t.dump=\"[\"+o+\"]\"}function P6e(t,e,r,o){var a=\"\",n=t.tag,u,A;for(u=0,A=r.length;u<A;u+=1)ng(t,e+1,r[u],!0,!0)&&((!o||u!==0)&&(a+=ZT(t,e)),t.dump&&dw===t.dump.charCodeAt(0)?a+=\"-\":a+=\"- \",a+=t.dump);t.tag=n,t.dump=a||\"[]\"}function S6e(t,e,r){var o=\"\",a=t.tag,n=Object.keys(r),u,A,p,h,E;for(u=0,A=n.length;u<A;u+=1)E=\"\",u!==0&&(E+=\", \"),t.condenseFlow&&(E+='\"'),p=n[u],h=r[p],ng(t,e,p,!1,!1)&&(t.dump.length>1024&&(E+=\"? \"),E+=t.dump+(t.condenseFlow?'\"':\"\")+\":\"+(t.condenseFlow?\"\":\" \"),ng(t,e,h,!1,!1)&&(E+=t.dump,o+=E));t.tag=a,t.dump=\"{\"+o+\"}\"}function x6e(t,e,r,o){var a=\"\",n=t.tag,u=Object.keys(r),A,p,h,E,w,D;if(t.sortKeys===!0)u.sort();else if(typeof t.sortKeys==\"function\")u.sort(t.sortKeys);else if(t.sortKeys)throw new yw(\"sortKeys must be a boolean or a function\");for(A=0,p=u.length;A<p;A+=1)D=\"\",(!o||A!==0)&&(D+=ZT(t,e)),h=u[A],E=r[h],ng(t,e+1,h,!0,!0,!0)&&(w=t.tag!==null&&t.tag!==\"?\"||t.dump&&t.dump.length>1024,w&&(t.dump&&dw===t.dump.charCodeAt(0)?D+=\"?\":D+=\"? \"),D+=t.dump,w&&(D+=ZT(t,e)),ng(t,e+1,E,!0,w)&&(t.dump&&dw===t.dump.charCodeAt(0)?D+=\":\":D+=\": \",D+=t.dump,a+=D));t.tag=n,t.dump=a||\"{}\"}function hV(t,e,r){var o,a,n,u,A,p;for(a=r?t.explicitTypes:t.implicitTypes,n=0,u=a.length;n<u;n+=1)if(A=a[n],(A.instanceOf||A.predicate)&&(!A.instanceOf||typeof e==\"object\"&&e instanceof A.instanceOf)&&(!A.predicate||A.predicate(e))){if(t.tag=r?A.tag:\"?\",A.represent){if(p=t.styleMap[A.tag]||A.defaultStyle,gV.call(A.represent)===\"[object Function]\")o=A.represent(e,p);else if(dV.call(A.represent,p))o=A.represent[p](e,p);else throw new yw(\"!<\"+A.tag+'> tag resolver accepts not \"'+p+'\" style');t.dump=o}return!0}return!1}function ng(t,e,r,o,a,n){t.tag=null,t.dump=r,hV(t,r,!1)||hV(t,r,!0);var u=gV.call(t.dump);o&&(o=t.flowLevel<0||t.flowLevel>e);var A=u===\"[object Object]\"||u===\"[object Array]\",p,h;if(A&&(p=t.duplicates.indexOf(r),h=p!==-1),(t.tag!==null&&t.tag!==\"?\"||h||t.indent!==2&&e>0)&&(a=!1),h&&t.usedDuplicates[p])t.dump=\"*ref_\"+p;else{if(A&&h&&!t.usedDuplicates[p]&&(t.usedDuplicates[p]=!0),u===\"[object Object]\")o&&Object.keys(t.dump).length!==0?(x6e(t,e,t.dump,a),h&&(t.dump=\"&ref_\"+p+t.dump)):(S6e(t,e,t.dump),h&&(t.dump=\"&ref_\"+p+\" \"+t.dump));else if(u===\"[object Array]\"){var E=t.noArrayIndent&&e>0?e-1:e;o&&t.dump.length!==0?(P6e(t,E,t.dump,a),h&&(t.dump=\"&ref_\"+p+t.dump)):(D6e(t,E,t.dump),h&&(t.dump=\"&ref_\"+p+\" \"+t.dump))}else if(u===\"[object String]\")t.tag!==\"?\"&&w6e(t,t.dump,e,n);else{if(t.skipInvalid)return!1;throw new yw(\"unacceptable kind of an object to dump \"+u)}t.tag!==null&&t.tag!==\"?\"&&(t.dump=\"!<\"+t.tag+\"> \"+t.dump)}return!0}function b6e(t,e){var r=[],o=[],a,n;for($T(t,r,o),a=0,n=o.length;a<n;a+=1)e.duplicates.push(r[o[a]]);e.usedDuplicates=new Array(n)}function $T(t,e,r){var o,a,n;if(t!==null&&typeof t==\"object\")if(a=e.indexOf(t),a!==-1)r.indexOf(a)===-1&&r.push(a);else if(e.push(t),Array.isArray(t))for(a=0,n=t.length;a<n;a+=1)$T(t[a],e,r);else for(o=Object.keys(t),a=0,n=o.length;a<n;a+=1)$T(t[o[a]],e,r)}function bV(t,e){e=e||{};var r=new m6e(e);return r.noRefs||b6e(t,r),ng(r,0,t,!0,!0)?r.dump+`\n`:\"\"}function k6e(t,e){return bV(t,mw.extend({schema:ZHe},e))}tL.exports.dump=bV;tL.exports.safeDump=k6e});var FV=_((Vxt,Fi)=>{\"use strict\";var BP=aV(),QV=kV();function vP(t){return function(){throw new Error(\"Function \"+t+\" is deprecated and cannot be used.\")}}Fi.exports.Type=as();Fi.exports.Schema=$0();Fi.exports.FAILSAFE_SCHEMA=dP();Fi.exports.JSON_SCHEMA=YT();Fi.exports.CORE_SCHEMA=KT();Fi.exports.DEFAULT_SAFE_SCHEMA=Cm();Fi.exports.DEFAULT_FULL_SCHEMA=hw();Fi.exports.load=BP.load;Fi.exports.loadAll=BP.loadAll;Fi.exports.safeLoad=BP.safeLoad;Fi.exports.safeLoadAll=BP.safeLoadAll;Fi.exports.dump=QV.dump;Fi.exports.safeDump=QV.safeDump;Fi.exports.YAMLException=ym();Fi.exports.MINIMAL_SCHEMA=dP();Fi.exports.SAFE_SCHEMA=Cm();Fi.exports.DEFAULT_SCHEMA=hw();Fi.exports.scan=vP(\"scan\");Fi.exports.parse=vP(\"parse\");Fi.exports.compose=vP(\"compose\");Fi.exports.addConstructor=vP(\"addConstructor\")});var TV=_((zxt,RV)=>{\"use strict\";var Q6e=FV();RV.exports=Q6e});var NV=_((Jxt,LV)=>{\"use strict\";function F6e(t,e){function r(){this.constructor=t}r.prototype=e.prototype,t.prototype=new r}function ig(t,e,r,o){this.message=t,this.expected=e,this.found=r,this.location=o,this.name=\"SyntaxError\",typeof Error.captureStackTrace==\"function\"&&Error.captureStackTrace(this,ig)}F6e(ig,Error);ig.buildMessage=function(t,e){var r={literal:function(h){return'\"'+a(h.text)+'\"'},class:function(h){var E=\"\",w;for(w=0;w<h.parts.length;w++)E+=h.parts[w]instanceof Array?n(h.parts[w][0])+\"-\"+n(h.parts[w][1]):n(h.parts[w]);return\"[\"+(h.inverted?\"^\":\"\")+E+\"]\"},any:function(h){return\"any character\"},end:function(h){return\"end of input\"},other:function(h){return h.description}};function o(h){return h.charCodeAt(0).toString(16).toUpperCase()}function a(h){return h.replace(/\\\\/g,\"\\\\\\\\\").replace(/\"/g,'\\\\\"').replace(/\\0/g,\"\\\\0\").replace(/\\t/g,\"\\\\t\").replace(/\\n/g,\"\\\\n\").replace(/\\r/g,\"\\\\r\").replace(/[\\x00-\\x0F]/g,function(E){return\"\\\\x0\"+o(E)}).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g,function(E){return\"\\\\x\"+o(E)})}function n(h){return h.replace(/\\\\/g,\"\\\\\\\\\").replace(/\\]/g,\"\\\\]\").replace(/\\^/g,\"\\\\^\").replace(/-/g,\"\\\\-\").replace(/\\0/g,\"\\\\0\").replace(/\\t/g,\"\\\\t\").replace(/\\n/g,\"\\\\n\").replace(/\\r/g,\"\\\\r\").replace(/[\\x00-\\x0F]/g,function(E){return\"\\\\x0\"+o(E)}).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g,function(E){return\"\\\\x\"+o(E)})}function u(h){return r[h.type](h)}function A(h){var E=new Array(h.length),w,D;for(w=0;w<h.length;w++)E[w]=u(h[w]);if(E.sort(),E.length>0){for(w=1,D=1;w<E.length;w++)E[w-1]!==E[w]&&(E[D]=E[w],D++);E.length=D}switch(E.length){case 1:return E[0];case 2:return E[0]+\" or \"+E[1];default:return E.slice(0,-1).join(\", \")+\", or \"+E[E.length-1]}}function p(h){return h?'\"'+a(h)+'\"':\"end of input\"}return\"Expected \"+A(t)+\" but \"+p(e)+\" found.\"};function R6e(t,e){e=e!==void 0?e:{};var r={},o={Start:Bl},a=Bl,n=function(ee){return[].concat(...ee)},u=\"-\",A=un(\"-\",!1),p=function(ee){return ee},h=function(ee){return Object.assign({},...ee)},E=\"#\",w=un(\"#\",!1),D=Ec(),b=function(){return{}},C=\":\",T=un(\":\",!1),N=function(ee,ye){return{[ee]:ye}},U=\",\",z=un(\",\",!1),te=function(ee,ye){return ye},le=function(ee,ye,Ne){return Object.assign({},...[ee].concat(ye).map(gt=>({[gt]:Ne})))},ce=function(ee){return ee},ue=function(ee){return ee},Ie=oa(\"correct indentation\"),he=\" \",De=un(\" \",!1),Ee=function(ee){return ee.length===ar*vt},g=function(ee){return ee.length===(ar+1)*vt},me=function(){return ar++,!0},Ce=function(){return ar--,!0},fe=function(){return Lo()},ie=oa(\"pseudostring\"),Z=/^[^\\r\\n\\t ?:,\\][{}#&*!|>'\"%@`\\-]/,Pe=qn([\"\\r\",`\n`,\"\t\",\" \",\"?\",\":\",\",\",\"]\",\"[\",\"{\",\"}\",\"#\",\"&\",\"*\",\"!\",\"|\",\">\",\"'\",'\"',\"%\",\"@\",\"`\",\"-\"],!0,!1),Re=/^[^\\r\\n\\t ,\\][{}:#\"']/,ht=qn([\"\\r\",`\n`,\"\t\",\" \",\",\",\"]\",\"[\",\"{\",\"}\",\":\",\"#\",'\"',\"'\"],!0,!1),q=function(){return Lo().replace(/^ *| *$/g,\"\")},nt=\"--\",Le=un(\"--\",!1),Te=/^[a-zA-Z\\/0-9]/,ke=qn([[\"a\",\"z\"],[\"A\",\"Z\"],\"/\",[\"0\",\"9\"]],!1,!1),Ve=/^[^\\r\\n\\t :,]/,xe=qn([\"\\r\",`\n`,\"\t\",\" \",\":\",\",\"],!0,!1),tt=\"null\",He=un(\"null\",!1),x=function(){return null},I=\"true\",S=un(\"true\",!1),y=function(){return!0},R=\"false\",J=un(\"false\",!1),X=function(){return!1},$=oa(\"string\"),se='\"',be=un('\"',!1),Fe=function(){return\"\"},lt=function(ee){return ee},Et=function(ee){return ee.join(\"\")},qt=/^[^\"\\\\\\0-\\x1F\\x7F]/,nr=qn(['\"',\"\\\\\",[\"\\0\",\"\u001f\"],\"\\x7F\"],!0,!1),St='\\\\\"',cn=un('\\\\\"',!1),Pr=function(){return'\"'},yr=\"\\\\\\\\\",Rr=un(\"\\\\\\\\\",!1),Xr=function(){return\"\\\\\"},$n=\"\\\\/\",Xs=un(\"\\\\/\",!1),Hi=function(){return\"/\"},Qs=\"\\\\b\",Zs=un(\"\\\\b\",!1),bi=function(){return\"\\b\"},Fs=\"\\\\f\",$s=un(\"\\\\f\",!1),SA=function(){return\"\\f\"},gu=\"\\\\n\",op=un(\"\\\\n\",!1),ap=function(){return`\n`},Rs=\"\\\\r\",Nn=un(\"\\\\r\",!1),hs=function(){return\"\\r\"},Ts=\"\\\\t\",pc=un(\"\\\\t\",!1),hc=function(){return\"\t\"},gc=\"\\\\u\",xA=un(\"\\\\u\",!1),bA=function(ee,ye,Ne,gt){return String.fromCharCode(parseInt(`0x${ee}${ye}${Ne}${gt}`))},Ro=/^[0-9a-fA-F]/,To=qn([[\"0\",\"9\"],[\"a\",\"f\"],[\"A\",\"F\"]],!1,!1),kA=oa(\"blank space\"),pr=/^[ \\t]/,Me=qn([\" \",\"\t\"],!1,!1),ia=oa(\"white space\"),dc=/^[ \\t\\n\\r]/,Er=qn([\" \",\"\t\",`\n`,\"\\r\"],!1,!1),du=`\\r\n`,QA=un(`\\r\n`,!1),FA=`\n`,mc=un(`\n`,!1),yc=\"\\r\",Il=un(\"\\r\",!1),we=0,Tt=0,wl=[{line:1,column:1}],Bi=0,Ls=[],Ft=0,Bn;if(\"startRule\"in e){if(!(e.startRule in o))throw new Error(`Can't start parsing from rule \"`+e.startRule+'\".');a=o[e.startRule]}function Lo(){return t.substring(Tt,we)}function ki(){return la(Tt,we)}function vi(ee,ye){throw ye=ye!==void 0?ye:la(Tt,we),mu([oa(ee)],t.substring(Tt,we),ye)}function sa(ee,ye){throw ye=ye!==void 0?ye:la(Tt,we),ca(ee,ye)}function un(ee,ye){return{type:\"literal\",text:ee,ignoreCase:ye}}function qn(ee,ye,Ne){return{type:\"class\",parts:ee,inverted:ye,ignoreCase:Ne}}function Ec(){return{type:\"any\"}}function lp(){return{type:\"end\"}}function oa(ee){return{type:\"other\",description:ee}}function aa(ee){var ye=wl[ee],Ne;if(ye)return ye;for(Ne=ee-1;!wl[Ne];)Ne--;for(ye=wl[Ne],ye={line:ye.line,column:ye.column};Ne<ee;)t.charCodeAt(Ne)===10?(ye.line++,ye.column=1):ye.column++,Ne++;return wl[ee]=ye,ye}function la(ee,ye){var Ne=aa(ee),gt=aa(ye);return{start:{offset:ee,line:Ne.line,column:Ne.column},end:{offset:ye,line:gt.line,column:gt.column}}}function Ze(ee){we<Bi||(we>Bi&&(Bi=we,Ls=[]),Ls.push(ee))}function ca(ee,ye){return new ig(ee,null,null,ye)}function mu(ee,ye,Ne){return new ig(ig.buildMessage(ee,ye),ee,ye,Ne)}function Bl(){var ee;return ee=RA(),ee}function dn(){var ee,ye,Ne;for(ee=we,ye=[],Ne=No();Ne!==r;)ye.push(Ne),Ne=No();return ye!==r&&(Tt=ee,ye=n(ye)),ee=ye,ee}function No(){var ee,ye,Ne,gt,mt;return ee=we,ye=qa(),ye!==r?(t.charCodeAt(we)===45?(Ne=u,we++):(Ne=r,Ft===0&&Ze(A)),Ne!==r?(gt=Dn(),gt!==r?(mt=Oo(),mt!==r?(Tt=ee,ye=p(mt),ee=ye):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r),ee}function RA(){var ee,ye,Ne;for(ee=we,ye=[],Ne=TA();Ne!==r;)ye.push(Ne),Ne=TA();return ye!==r&&(Tt=ee,ye=h(ye)),ee=ye,ee}function TA(){var ee,ye,Ne,gt,mt,Dt,er,sn,ei;if(ee=we,ye=Dn(),ye===r&&(ye=null),ye!==r){if(Ne=we,t.charCodeAt(we)===35?(gt=E,we++):(gt=r,Ft===0&&Ze(w)),gt!==r){if(mt=[],Dt=we,er=we,Ft++,sn=it(),Ft--,sn===r?er=void 0:(we=er,er=r),er!==r?(t.length>we?(sn=t.charAt(we),we++):(sn=r,Ft===0&&Ze(D)),sn!==r?(er=[er,sn],Dt=er):(we=Dt,Dt=r)):(we=Dt,Dt=r),Dt!==r)for(;Dt!==r;)mt.push(Dt),Dt=we,er=we,Ft++,sn=it(),Ft--,sn===r?er=void 0:(we=er,er=r),er!==r?(t.length>we?(sn=t.charAt(we),we++):(sn=r,Ft===0&&Ze(D)),sn!==r?(er=[er,sn],Dt=er):(we=Dt,Dt=r)):(we=Dt,Dt=r);else mt=r;mt!==r?(gt=[gt,mt],Ne=gt):(we=Ne,Ne=r)}else we=Ne,Ne=r;if(Ne===r&&(Ne=null),Ne!==r){if(gt=[],mt=ze(),mt!==r)for(;mt!==r;)gt.push(mt),mt=ze();else gt=r;gt!==r?(Tt=ee,ye=b(),ee=ye):(we=ee,ee=r)}else we=ee,ee=r}else we=ee,ee=r;if(ee===r&&(ee=we,ye=qa(),ye!==r?(Ne=ua(),Ne!==r?(gt=Dn(),gt===r&&(gt=null),gt!==r?(t.charCodeAt(we)===58?(mt=C,we++):(mt=r,Ft===0&&Ze(T)),mt!==r?(Dt=Dn(),Dt===r&&(Dt=null),Dt!==r?(er=Oo(),er!==r?(Tt=ee,ye=N(Ne,er),ee=ye):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r),ee===r&&(ee=we,ye=qa(),ye!==r?(Ne=qi(),Ne!==r?(gt=Dn(),gt===r&&(gt=null),gt!==r?(t.charCodeAt(we)===58?(mt=C,we++):(mt=r,Ft===0&&Ze(T)),mt!==r?(Dt=Dn(),Dt===r&&(Dt=null),Dt!==r?(er=Oo(),er!==r?(Tt=ee,ye=N(Ne,er),ee=ye):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r),ee===r))){if(ee=we,ye=qa(),ye!==r)if(Ne=qi(),Ne!==r)if(gt=Dn(),gt!==r)if(mt=Cc(),mt!==r){if(Dt=[],er=ze(),er!==r)for(;er!==r;)Dt.push(er),er=ze();else Dt=r;Dt!==r?(Tt=ee,ye=N(Ne,mt),ee=ye):(we=ee,ee=r)}else we=ee,ee=r;else we=ee,ee=r;else we=ee,ee=r;else we=ee,ee=r;if(ee===r)if(ee=we,ye=qa(),ye!==r)if(Ne=qi(),Ne!==r){if(gt=[],mt=we,Dt=Dn(),Dt===r&&(Dt=null),Dt!==r?(t.charCodeAt(we)===44?(er=U,we++):(er=r,Ft===0&&Ze(z)),er!==r?(sn=Dn(),sn===r&&(sn=null),sn!==r?(ei=qi(),ei!==r?(Tt=mt,Dt=te(Ne,ei),mt=Dt):(we=mt,mt=r)):(we=mt,mt=r)):(we=mt,mt=r)):(we=mt,mt=r),mt!==r)for(;mt!==r;)gt.push(mt),mt=we,Dt=Dn(),Dt===r&&(Dt=null),Dt!==r?(t.charCodeAt(we)===44?(er=U,we++):(er=r,Ft===0&&Ze(z)),er!==r?(sn=Dn(),sn===r&&(sn=null),sn!==r?(ei=qi(),ei!==r?(Tt=mt,Dt=te(Ne,ei),mt=Dt):(we=mt,mt=r)):(we=mt,mt=r)):(we=mt,mt=r)):(we=mt,mt=r);else gt=r;gt!==r?(mt=Dn(),mt===r&&(mt=null),mt!==r?(t.charCodeAt(we)===58?(Dt=C,we++):(Dt=r,Ft===0&&Ze(T)),Dt!==r?(er=Dn(),er===r&&(er=null),er!==r?(sn=Oo(),sn!==r?(Tt=ee,ye=le(Ne,gt,sn),ee=ye):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)}else we=ee,ee=r;else we=ee,ee=r}return ee}function Oo(){var ee,ye,Ne,gt,mt,Dt,er;if(ee=we,ye=we,Ft++,Ne=we,gt=it(),gt!==r?(mt=Ot(),mt!==r?(t.charCodeAt(we)===45?(Dt=u,we++):(Dt=r,Ft===0&&Ze(A)),Dt!==r?(er=Dn(),er!==r?(gt=[gt,mt,Dt,er],Ne=gt):(we=Ne,Ne=r)):(we=Ne,Ne=r)):(we=Ne,Ne=r)):(we=Ne,Ne=r),Ft--,Ne!==r?(we=ye,ye=void 0):ye=r,ye!==r?(Ne=ze(),Ne!==r?(gt=vn(),gt!==r?(mt=dn(),mt!==r?(Dt=Mo(),Dt!==r?(Tt=ee,ye=ce(mt),ee=ye):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r),ee===r&&(ee=we,ye=it(),ye!==r?(Ne=vn(),Ne!==r?(gt=RA(),gt!==r?(mt=Mo(),mt!==r?(Tt=ee,ye=ce(gt),ee=ye):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r),ee===r))if(ee=we,ye=vl(),ye!==r){if(Ne=[],gt=ze(),gt!==r)for(;gt!==r;)Ne.push(gt),gt=ze();else Ne=r;Ne!==r?(Tt=ee,ye=ue(ye),ee=ye):(we=ee,ee=r)}else we=ee,ee=r;return ee}function qa(){var ee,ye,Ne;for(Ft++,ee=we,ye=[],t.charCodeAt(we)===32?(Ne=he,we++):(Ne=r,Ft===0&&Ze(De));Ne!==r;)ye.push(Ne),t.charCodeAt(we)===32?(Ne=he,we++):(Ne=r,Ft===0&&Ze(De));return ye!==r?(Tt=we,Ne=Ee(ye),Ne?Ne=void 0:Ne=r,Ne!==r?(ye=[ye,Ne],ee=ye):(we=ee,ee=r)):(we=ee,ee=r),Ft--,ee===r&&(ye=r,Ft===0&&Ze(Ie)),ee}function Ot(){var ee,ye,Ne;for(ee=we,ye=[],t.charCodeAt(we)===32?(Ne=he,we++):(Ne=r,Ft===0&&Ze(De));Ne!==r;)ye.push(Ne),t.charCodeAt(we)===32?(Ne=he,we++):(Ne=r,Ft===0&&Ze(De));return ye!==r?(Tt=we,Ne=g(ye),Ne?Ne=void 0:Ne=r,Ne!==r?(ye=[ye,Ne],ee=ye):(we=ee,ee=r)):(we=ee,ee=r),ee}function vn(){var ee;return Tt=we,ee=me(),ee?ee=void 0:ee=r,ee}function Mo(){var ee;return Tt=we,ee=Ce(),ee?ee=void 0:ee=r,ee}function ua(){var ee;return ee=ja(),ee===r&&(ee=Dl()),ee}function qi(){var ee,ye,Ne;if(ee=ja(),ee===r){if(ee=we,ye=[],Ne=Aa(),Ne!==r)for(;Ne!==r;)ye.push(Ne),Ne=Aa();else ye=r;ye!==r&&(Tt=ee,ye=fe()),ee=ye}return ee}function vl(){var ee;return ee=Di(),ee===r&&(ee=rs(),ee===r&&(ee=ja(),ee===r&&(ee=Dl()))),ee}function Cc(){var ee;return ee=Di(),ee===r&&(ee=ja(),ee===r&&(ee=Aa())),ee}function Dl(){var ee,ye,Ne,gt,mt,Dt;if(Ft++,ee=we,Z.test(t.charAt(we))?(ye=t.charAt(we),we++):(ye=r,Ft===0&&Ze(Pe)),ye!==r){for(Ne=[],gt=we,mt=Dn(),mt===r&&(mt=null),mt!==r?(Re.test(t.charAt(we))?(Dt=t.charAt(we),we++):(Dt=r,Ft===0&&Ze(ht)),Dt!==r?(mt=[mt,Dt],gt=mt):(we=gt,gt=r)):(we=gt,gt=r);gt!==r;)Ne.push(gt),gt=we,mt=Dn(),mt===r&&(mt=null),mt!==r?(Re.test(t.charAt(we))?(Dt=t.charAt(we),we++):(Dt=r,Ft===0&&Ze(ht)),Dt!==r?(mt=[mt,Dt],gt=mt):(we=gt,gt=r)):(we=gt,gt=r);Ne!==r?(Tt=ee,ye=q(),ee=ye):(we=ee,ee=r)}else we=ee,ee=r;return Ft--,ee===r&&(ye=r,Ft===0&&Ze(ie)),ee}function Aa(){var ee,ye,Ne,gt,mt;if(ee=we,t.substr(we,2)===nt?(ye=nt,we+=2):(ye=r,Ft===0&&Ze(Le)),ye===r&&(ye=null),ye!==r)if(Te.test(t.charAt(we))?(Ne=t.charAt(we),we++):(Ne=r,Ft===0&&Ze(ke)),Ne!==r){for(gt=[],Ve.test(t.charAt(we))?(mt=t.charAt(we),we++):(mt=r,Ft===0&&Ze(xe));mt!==r;)gt.push(mt),Ve.test(t.charAt(we))?(mt=t.charAt(we),we++):(mt=r,Ft===0&&Ze(xe));gt!==r?(Tt=ee,ye=q(),ee=ye):(we=ee,ee=r)}else we=ee,ee=r;else we=ee,ee=r;return ee}function Di(){var ee,ye;return ee=we,t.substr(we,4)===tt?(ye=tt,we+=4):(ye=r,Ft===0&&Ze(He)),ye!==r&&(Tt=ee,ye=x()),ee=ye,ee}function rs(){var ee,ye;return ee=we,t.substr(we,4)===I?(ye=I,we+=4):(ye=r,Ft===0&&Ze(S)),ye!==r&&(Tt=ee,ye=y()),ee=ye,ee===r&&(ee=we,t.substr(we,5)===R?(ye=R,we+=5):(ye=r,Ft===0&&Ze(J)),ye!==r&&(Tt=ee,ye=X()),ee=ye),ee}function ja(){var ee,ye,Ne,gt;return Ft++,ee=we,t.charCodeAt(we)===34?(ye=se,we++):(ye=r,Ft===0&&Ze(be)),ye!==r?(t.charCodeAt(we)===34?(Ne=se,we++):(Ne=r,Ft===0&&Ze(be)),Ne!==r?(Tt=ee,ye=Fe(),ee=ye):(we=ee,ee=r)):(we=ee,ee=r),ee===r&&(ee=we,t.charCodeAt(we)===34?(ye=se,we++):(ye=r,Ft===0&&Ze(be)),ye!==r?(Ne=yu(),Ne!==r?(t.charCodeAt(we)===34?(gt=se,we++):(gt=r,Ft===0&&Ze(be)),gt!==r?(Tt=ee,ye=lt(Ne),ee=ye):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)),Ft--,ee===r&&(ye=r,Ft===0&&Ze($)),ee}function yu(){var ee,ye,Ne;if(ee=we,ye=[],Ne=Pl(),Ne!==r)for(;Ne!==r;)ye.push(Ne),Ne=Pl();else ye=r;return ye!==r&&(Tt=ee,ye=Et(ye)),ee=ye,ee}function Pl(){var ee,ye,Ne,gt,mt,Dt;return qt.test(t.charAt(we))?(ee=t.charAt(we),we++):(ee=r,Ft===0&&Ze(nr)),ee===r&&(ee=we,t.substr(we,2)===St?(ye=St,we+=2):(ye=r,Ft===0&&Ze(cn)),ye!==r&&(Tt=ee,ye=Pr()),ee=ye,ee===r&&(ee=we,t.substr(we,2)===yr?(ye=yr,we+=2):(ye=r,Ft===0&&Ze(Rr)),ye!==r&&(Tt=ee,ye=Xr()),ee=ye,ee===r&&(ee=we,t.substr(we,2)===$n?(ye=$n,we+=2):(ye=r,Ft===0&&Ze(Xs)),ye!==r&&(Tt=ee,ye=Hi()),ee=ye,ee===r&&(ee=we,t.substr(we,2)===Qs?(ye=Qs,we+=2):(ye=r,Ft===0&&Ze(Zs)),ye!==r&&(Tt=ee,ye=bi()),ee=ye,ee===r&&(ee=we,t.substr(we,2)===Fs?(ye=Fs,we+=2):(ye=r,Ft===0&&Ze($s)),ye!==r&&(Tt=ee,ye=SA()),ee=ye,ee===r&&(ee=we,t.substr(we,2)===gu?(ye=gu,we+=2):(ye=r,Ft===0&&Ze(op)),ye!==r&&(Tt=ee,ye=ap()),ee=ye,ee===r&&(ee=we,t.substr(we,2)===Rs?(ye=Rs,we+=2):(ye=r,Ft===0&&Ze(Nn)),ye!==r&&(Tt=ee,ye=hs()),ee=ye,ee===r&&(ee=we,t.substr(we,2)===Ts?(ye=Ts,we+=2):(ye=r,Ft===0&&Ze(pc)),ye!==r&&(Tt=ee,ye=hc()),ee=ye,ee===r&&(ee=we,t.substr(we,2)===gc?(ye=gc,we+=2):(ye=r,Ft===0&&Ze(xA)),ye!==r?(Ne=pi(),Ne!==r?(gt=pi(),gt!==r?(mt=pi(),mt!==r?(Dt=pi(),Dt!==r?(Tt=ee,ye=bA(Ne,gt,mt,Dt),ee=ye):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)):(we=ee,ee=r)))))))))),ee}function pi(){var ee;return Ro.test(t.charAt(we))?(ee=t.charAt(we),we++):(ee=r,Ft===0&&Ze(To)),ee}function Dn(){var ee,ye;if(Ft++,ee=[],pr.test(t.charAt(we))?(ye=t.charAt(we),we++):(ye=r,Ft===0&&Ze(Me)),ye!==r)for(;ye!==r;)ee.push(ye),pr.test(t.charAt(we))?(ye=t.charAt(we),we++):(ye=r,Ft===0&&Ze(Me));else ee=r;return Ft--,ee===r&&(ye=r,Ft===0&&Ze(kA)),ee}function Sl(){var ee,ye;if(Ft++,ee=[],dc.test(t.charAt(we))?(ye=t.charAt(we),we++):(ye=r,Ft===0&&Ze(Er)),ye!==r)for(;ye!==r;)ee.push(ye),dc.test(t.charAt(we))?(ye=t.charAt(we),we++):(ye=r,Ft===0&&Ze(Er));else ee=r;return Ft--,ee===r&&(ye=r,Ft===0&&Ze(ia)),ee}function ze(){var ee,ye,Ne,gt,mt,Dt;if(ee=we,ye=it(),ye!==r){for(Ne=[],gt=we,mt=Dn(),mt===r&&(mt=null),mt!==r?(Dt=it(),Dt!==r?(mt=[mt,Dt],gt=mt):(we=gt,gt=r)):(we=gt,gt=r);gt!==r;)Ne.push(gt),gt=we,mt=Dn(),mt===r&&(mt=null),mt!==r?(Dt=it(),Dt!==r?(mt=[mt,Dt],gt=mt):(we=gt,gt=r)):(we=gt,gt=r);Ne!==r?(ye=[ye,Ne],ee=ye):(we=ee,ee=r)}else we=ee,ee=r;return ee}function it(){var ee;return t.substr(we,2)===du?(ee=du,we+=2):(ee=r,Ft===0&&Ze(QA)),ee===r&&(t.charCodeAt(we)===10?(ee=FA,we++):(ee=r,Ft===0&&Ze(mc)),ee===r&&(t.charCodeAt(we)===13?(ee=yc,we++):(ee=r,Ft===0&&Ze(Il)))),ee}let vt=2,ar=0;if(Bn=a(),Bn!==r&&we===t.length)return Bn;throw Bn!==r&&we<t.length&&Ze(lp()),mu(Ls,Bi<t.length?t.charAt(Bi):null,Bi<t.length?la(Bi,Bi+1):la(Bi,Bi))}LV.exports={SyntaxError:ig,parse:R6e}});function MV(t){return t.match(T6e)?t:JSON.stringify(t)}function _V(t){return typeof t>\"u\"?!0:typeof t==\"object\"&&t!==null&&!Array.isArray(t)?Object.keys(t).every(e=>_V(t[e])):!1}function rL(t,e,r){if(t===null)return`null\n`;if(typeof t==\"number\"||typeof t==\"boolean\")return`${t.toString()}\n`;if(typeof t==\"string\")return`${MV(t)}\n`;if(Array.isArray(t)){if(t.length===0)return`[]\n`;let o=\"  \".repeat(e);return`\n${t.map(n=>`${o}- ${rL(n,e+1,!1)}`).join(\"\")}`}if(typeof t==\"object\"&&t){let[o,a]=t instanceof DP?[t.data,!1]:[t,!0],n=\"  \".repeat(e),u=Object.keys(o);a&&u.sort((p,h)=>{let E=OV.indexOf(p),w=OV.indexOf(h);return E===-1&&w===-1?p<h?-1:p>h?1:0:E!==-1&&w===-1?-1:E===-1&&w!==-1?1:E-w});let A=u.filter(p=>!_V(o[p])).map((p,h)=>{let E=o[p],w=MV(p),D=rL(E,e+1,!0),b=h>0||r?n:\"\",C=w.length>1024?`? ${w}\n${b}:`:`${w}:`,T=D.startsWith(`\n`)?D:` ${D}`;return`${b}${C}${T}`}).join(e===0?`\n`:\"\")||`\n`;return r?`\n${A}`:`${A}`}throw new Error(`Unsupported value type (${t})`)}function Pa(t){try{let e=rL(t,0,!1);return e!==`\n`?e:\"\"}catch(e){throw e.location&&(e.message=e.message.replace(/(\\.)?$/,` (line ${e.location.start.line}, column ${e.location.start.column})$1`)),e}}function L6e(t){return t.endsWith(`\n`)||(t+=`\n`),(0,UV.parse)(t)}function O6e(t){if(N6e.test(t))return L6e(t);let e=(0,PP.safeLoad)(t,{schema:PP.FAILSAFE_SCHEMA,json:!0});if(e==null)return{};if(typeof e!=\"object\")throw new Error(`Expected an indexed object, got a ${typeof e} instead. Does your file follow Yaml's rules?`);if(Array.isArray(e))throw new Error(\"Expected an indexed object, got an array instead. Does your file follow Yaml's rules?\");return e}function Ki(t){return O6e(t)}var PP,UV,T6e,OV,DP,N6e,HV=It(()=>{PP=et(TV()),UV=et(NV()),T6e=/^(?![-?:,\\][{}#&*!|>'\"%@` \\t\\r\\n]).([ \\t]*(?![,\\][{}:# \\t\\r\\n]).)*$/,OV=[\"__metadata\",\"version\",\"resolution\",\"dependencies\",\"peerDependencies\",\"dependenciesMeta\",\"peerDependenciesMeta\",\"binaries\"],DP=class{constructor(e){this.data=e}};Pa.PreserveOrdering=DP;N6e=/^(#.*(\\r?\\n))*?#\\s+yarn\\s+lockfile\\s+v1\\r?\\n/i});var Ew={};Kt(Ew,{parseResolution:()=>pP,parseShell:()=>uP,parseSyml:()=>Ki,stringifyArgument:()=>qT,stringifyArgumentSegment:()=>jT,stringifyArithmeticExpression:()=>fP,stringifyCommand:()=>HT,stringifyCommandChain:()=>mm,stringifyCommandChainThen:()=>_T,stringifyCommandLine:()=>AP,stringifyCommandLineThen:()=>UT,stringifyEnvSegment:()=>cP,stringifyRedirectArgument:()=>fw,stringifyResolution:()=>hP,stringifyShell:()=>dm,stringifyShellLine:()=>dm,stringifySyml:()=>Pa,stringifyValueArgument:()=>z0});var Ol=It(()=>{_Y();GY();HV()});var jV=_((tbt,nL)=>{\"use strict\";var M6e=t=>{let e=!1,r=!1,o=!1;for(let a=0;a<t.length;a++){let n=t[a];e&&/[a-zA-Z]/.test(n)&&n.toUpperCase()===n?(t=t.slice(0,a)+\"-\"+t.slice(a),e=!1,o=r,r=!0,a++):r&&o&&/[a-zA-Z]/.test(n)&&n.toLowerCase()===n?(t=t.slice(0,a-1)+\"-\"+t.slice(a-1),o=r,r=!1,e=!0):(e=n.toLowerCase()===n&&n.toUpperCase()!==n,o=r,r=n.toUpperCase()===n&&n.toLowerCase()!==n)}return t},qV=(t,e)=>{if(!(typeof t==\"string\"||Array.isArray(t)))throw new TypeError(\"Expected the input to be `string | string[]`\");e=Object.assign({pascalCase:!1},e);let r=a=>e.pascalCase?a.charAt(0).toUpperCase()+a.slice(1):a;return Array.isArray(t)?t=t.map(a=>a.trim()).filter(a=>a.length).join(\"-\"):t=t.trim(),t.length===0?\"\":t.length===1?e.pascalCase?t.toUpperCase():t.toLowerCase():(t!==t.toLowerCase()&&(t=M6e(t)),t=t.replace(/^[_.\\- ]+/,\"\").toLowerCase().replace(/[_.\\- ]+(\\w|$)/g,(a,n)=>n.toUpperCase()).replace(/\\d+(\\w|$)/g,a=>a.toUpperCase()),r(t))};nL.exports=qV;nL.exports.default=qV});var GV=_((rbt,U6e)=>{U6e.exports=[{name:\"Agola CI\",constant:\"AGOLA\",env:\"AGOLA_GIT_REF\",pr:\"AGOLA_PULL_REQUEST_ID\"},{name:\"Appcircle\",constant:\"APPCIRCLE\",env:\"AC_APPCIRCLE\"},{name:\"AppVeyor\",constant:\"APPVEYOR\",env:\"APPVEYOR\",pr:\"APPVEYOR_PULL_REQUEST_NUMBER\"},{name:\"AWS CodeBuild\",constant:\"CODEBUILD\",env:\"CODEBUILD_BUILD_ARN\"},{name:\"Azure Pipelines\",constant:\"AZURE_PIPELINES\",env:\"TF_BUILD\",pr:{BUILD_REASON:\"PullRequest\"}},{name:\"Bamboo\",constant:\"BAMBOO\",env:\"bamboo_planKey\"},{name:\"Bitbucket Pipelines\",constant:\"BITBUCKET\",env:\"BITBUCKET_COMMIT\",pr:\"BITBUCKET_PR_ID\"},{name:\"Bitrise\",constant:\"BITRISE\",env:\"BITRISE_IO\",pr:\"BITRISE_PULL_REQUEST\"},{name:\"Buddy\",constant:\"BUDDY\",env:\"BUDDY_WORKSPACE_ID\",pr:\"BUDDY_EXECUTION_PULL_REQUEST_ID\"},{name:\"Buildkite\",constant:\"BUILDKITE\",env:\"BUILDKITE\",pr:{env:\"BUILDKITE_PULL_REQUEST\",ne:\"false\"}},{name:\"CircleCI\",constant:\"CIRCLE\",env:\"CIRCLECI\",pr:\"CIRCLE_PULL_REQUEST\"},{name:\"Cirrus CI\",constant:\"CIRRUS\",env:\"CIRRUS_CI\",pr:\"CIRRUS_PR\"},{name:\"Codefresh\",constant:\"CODEFRESH\",env:\"CF_BUILD_ID\",pr:{any:[\"CF_PULL_REQUEST_NUMBER\",\"CF_PULL_REQUEST_ID\"]}},{name:\"Codemagic\",constant:\"CODEMAGIC\",env:\"CM_BUILD_ID\",pr:\"CM_PULL_REQUEST\"},{name:\"Codeship\",constant:\"CODESHIP\",env:{CI_NAME:\"codeship\"}},{name:\"Drone\",constant:\"DRONE\",env:\"DRONE\",pr:{DRONE_BUILD_EVENT:\"pull_request\"}},{name:\"dsari\",constant:\"DSARI\",env:\"DSARI\"},{name:\"Earthly\",constant:\"EARTHLY\",env:\"EARTHLY_CI\"},{name:\"Expo Application Services\",constant:\"EAS\",env:\"EAS_BUILD\"},{name:\"Gerrit\",constant:\"GERRIT\",env:\"GERRIT_PROJECT\"},{name:\"Gitea Actions\",constant:\"GITEA_ACTIONS\",env:\"GITEA_ACTIONS\"},{name:\"GitHub Actions\",constant:\"GITHUB_ACTIONS\",env:\"GITHUB_ACTIONS\",pr:{GITHUB_EVENT_NAME:\"pull_request\"}},{name:\"GitLab CI\",constant:\"GITLAB\",env:\"GITLAB_CI\",pr:\"CI_MERGE_REQUEST_ID\"},{name:\"GoCD\",constant:\"GOCD\",env:\"GO_PIPELINE_LABEL\"},{name:\"Google Cloud Build\",constant:\"GOOGLE_CLOUD_BUILD\",env:\"BUILDER_OUTPUT\"},{name:\"Harness CI\",constant:\"HARNESS\",env:\"HARNESS_BUILD_ID\"},{name:\"Heroku\",constant:\"HEROKU\",env:{env:\"NODE\",includes:\"/app/.heroku/node/bin/node\"}},{name:\"Hudson\",constant:\"HUDSON\",env:\"HUDSON_URL\"},{name:\"Jenkins\",constant:\"JENKINS\",env:[\"JENKINS_URL\",\"BUILD_ID\"],pr:{any:[\"ghprbPullId\",\"CHANGE_ID\"]}},{name:\"LayerCI\",constant:\"LAYERCI\",env:\"LAYERCI\",pr:\"LAYERCI_PULL_REQUEST\"},{name:\"Magnum CI\",constant:\"MAGNUM\",env:\"MAGNUM\"},{name:\"Netlify CI\",constant:\"NETLIFY\",env:\"NETLIFY\",pr:{env:\"PULL_REQUEST\",ne:\"false\"}},{name:\"Nevercode\",constant:\"NEVERCODE\",env:\"NEVERCODE\",pr:{env:\"NEVERCODE_PULL_REQUEST\",ne:\"false\"}},{name:\"Prow\",constant:\"PROW\",env:\"PROW_JOB_ID\"},{name:\"ReleaseHub\",constant:\"RELEASEHUB\",env:\"RELEASE_BUILD_ID\"},{name:\"Render\",constant:\"RENDER\",env:\"RENDER\",pr:{IS_PULL_REQUEST:\"true\"}},{name:\"Sail CI\",constant:\"SAIL\",env:\"SAILCI\",pr:\"SAIL_PULL_REQUEST_NUMBER\"},{name:\"Screwdriver\",constant:\"SCREWDRIVER\",env:\"SCREWDRIVER\",pr:{env:\"SD_PULL_REQUEST\",ne:\"false\"}},{name:\"Semaphore\",constant:\"SEMAPHORE\",env:\"SEMAPHORE\",pr:\"PULL_REQUEST_NUMBER\"},{name:\"Sourcehut\",constant:\"SOURCEHUT\",env:{CI_NAME:\"sourcehut\"}},{name:\"Strider CD\",constant:\"STRIDER\",env:\"STRIDER\"},{name:\"TaskCluster\",constant:\"TASKCLUSTER\",env:[\"TASK_ID\",\"RUN_ID\"]},{name:\"TeamCity\",constant:\"TEAMCITY\",env:\"TEAMCITY_VERSION\"},{name:\"Travis CI\",constant:\"TRAVIS\",env:\"TRAVIS\",pr:{env:\"TRAVIS_PULL_REQUEST\",ne:\"false\"}},{name:\"Vela\",constant:\"VELA\",env:\"VELA\",pr:{VELA_PULL_REQUEST:\"1\"}},{name:\"Vercel\",constant:\"VERCEL\",env:{any:[\"NOW_BUILDER\",\"VERCEL\"]},pr:\"VERCEL_GIT_PULL_REQUEST_ID\"},{name:\"Visual Studio App Center\",constant:\"APPCENTER\",env:\"APPCENTER_BUILD_ID\"},{name:\"Woodpecker\",constant:\"WOODPECKER\",env:{CI:\"woodpecker\"},pr:{CI_BUILD_EVENT:\"pull_request\"}},{name:\"Xcode Cloud\",constant:\"XCODE_CLOUD\",env:\"CI_XCODE_PROJECT\",pr:\"CI_PULL_REQUEST_NUMBER\"},{name:\"Xcode Server\",constant:\"XCODE_SERVER\",env:\"XCS\"}]});var sg=_(nl=>{\"use strict\";var YV=GV(),ls=process.env;Object.defineProperty(nl,\"_vendors\",{value:YV.map(function(t){return t.constant})});nl.name=null;nl.isPR=null;YV.forEach(function(t){let r=(Array.isArray(t.env)?t.env:[t.env]).every(function(o){return WV(o)});if(nl[t.constant]=r,!!r)switch(nl.name=t.name,typeof t.pr){case\"string\":nl.isPR=!!ls[t.pr];break;case\"object\":\"env\"in t.pr?nl.isPR=t.pr.env in ls&&ls[t.pr.env]!==t.pr.ne:\"any\"in t.pr?nl.isPR=t.pr.any.some(function(o){return!!ls[o]}):nl.isPR=WV(t.pr);break;default:nl.isPR=null}});nl.isCI=!!(ls.CI!==\"false\"&&(ls.BUILD_ID||ls.BUILD_NUMBER||ls.CI||ls.CI_APP_ID||ls.CI_BUILD_ID||ls.CI_BUILD_NUMBER||ls.CI_NAME||ls.CONTINUOUS_INTEGRATION||ls.RUN_ID||nl.name));function WV(t){return typeof t==\"string\"?!!ls[t]:\"env\"in t?ls[t.env]&&ls[t.env].includes(t.includes):\"any\"in t?t.any.some(function(e){return!!ls[e]}):Object.keys(t).every(function(e){return ls[e]===t[e]})}});var Kn,pn,og,iL,SP,KV,sL,oL,xP=It(()=>{(function(t){t.StartOfInput=\"\\0\",t.EndOfInput=\"\u0001\",t.EndOfPartialInput=\"\u0002\"})(Kn||(Kn={}));(function(t){t[t.InitialNode=0]=\"InitialNode\",t[t.SuccessNode=1]=\"SuccessNode\",t[t.ErrorNode=2]=\"ErrorNode\",t[t.CustomNode=3]=\"CustomNode\"})(pn||(pn={}));og=-1,iL=/^(-h|--help)(?:=([0-9]+))?$/,SP=/^(--[a-z]+(?:-[a-z]+)*|-[a-zA-Z]+)$/,KV=/^-[a-zA-Z]{2,}$/,sL=/^([^=]+)=([\\s\\S]*)$/,oL=process.env.DEBUG_CLI===\"1\"});var ot,Dm,bP,aL,kP=It(()=>{xP();ot=class extends Error{constructor(e){super(e),this.clipanion={type:\"usage\"},this.name=\"UsageError\"}},Dm=class extends Error{constructor(e,r){if(super(),this.input=e,this.candidates=r,this.clipanion={type:\"none\"},this.name=\"UnknownSyntaxError\",this.candidates.length===0)this.message=\"Command not found, but we're not sure what's the alternative.\";else if(this.candidates.every(o=>o.reason!==null&&o.reason===r[0].reason)){let[{reason:o}]=this.candidates;this.message=`${o}\n\n${this.candidates.map(({usage:a})=>`$ ${a}`).join(`\n`)}`}else if(this.candidates.length===1){let[{usage:o}]=this.candidates;this.message=`Command not found; did you mean:\n\n$ ${o}\n${aL(e)}`}else this.message=`Command not found; did you mean one of:\n\n${this.candidates.map(({usage:o},a)=>`${`${a}.`.padStart(4)} ${o}`).join(`\n`)}\n\n${aL(e)}`}},bP=class extends Error{constructor(e,r){super(),this.input=e,this.usages=r,this.clipanion={type:\"none\"},this.name=\"AmbiguousSyntaxError\",this.message=`Cannot find which to pick amongst the following alternatives:\n\n${this.usages.map((o,a)=>`${`${a}.`.padStart(4)} ${o}`).join(`\n`)}\n\n${aL(e)}`}},aL=t=>`While running ${t.filter(e=>e!==Kn.EndOfInput&&e!==Kn.EndOfPartialInput).map(e=>{let r=JSON.stringify(e);return e.match(/\\s/)||e.length===0||r!==`\"${e}\"`?r:e}).join(\" \")}`});function _6e(t){let e=t.split(`\n`),r=e.filter(a=>a.match(/\\S/)),o=r.length>0?r.reduce((a,n)=>Math.min(a,n.length-n.trimStart().length),Number.MAX_VALUE):0;return e.map(a=>a.slice(o).trimRight()).join(`\n`)}function yo(t,{format:e,paragraphs:r}){return t=t.replace(/\\r\\n?/g,`\n`),t=_6e(t),t=t.replace(/^\\n+|\\n+$/g,\"\"),t=t.replace(/^(\\s*)-([^\\n]*?)\\n+/gm,`$1-$2\n\n`),t=t.replace(/\\n(\\n)?\\n*/g,(o,a)=>a||\" \"),r&&(t=t.split(/\\n/).map(o=>{let a=o.match(/^\\s*[*-][\\t ]+(.*)/);if(!a)return o.match(/(.{1,80})(?: |$)/g).join(`\n`);let n=o.length-o.trimStart().length;return a[1].match(new RegExp(`(.{1,${78-n}})(?: |$)`,\"g\")).map((u,A)=>\" \".repeat(n)+(A===0?\"- \":\"  \")+u).join(`\n`)}).join(`\n\n`)),t=t.replace(/(`+)((?:.|[\\n])*?)\\1/g,(o,a,n)=>e.code(a+n+a)),t=t.replace(/(\\*\\*)((?:.|[\\n])*?)\\1/g,(o,a,n)=>e.bold(a+n+a)),t?`${t}\n`:\"\"}var lL,VV,zV,cL=It(()=>{lL=Array(80).fill(\"\\u2501\");for(let t=0;t<=24;++t)lL[lL.length-t]=`\\x1B[38;5;${232+t}m\\u2501`;VV={header:t=>`\\x1B[1m\\u2501\\u2501\\u2501 ${t}${t.length<75?` ${lL.slice(t.length+5).join(\"\")}`:\":\"}\\x1B[0m`,bold:t=>`\\x1B[1m${t}\\x1B[22m`,error:t=>`\\x1B[31m\\x1B[1m${t}\\x1B[22m\\x1B[39m`,code:t=>`\\x1B[36m${t}\\x1B[39m`},zV={header:t=>t,bold:t=>t,error:t=>t,code:t=>t}});function Wo(t){return{...t,[Cw]:!0}}function Yu(t,e){return typeof t>\"u\"?[t,e]:typeof t==\"object\"&&t!==null&&!Array.isArray(t)?[void 0,t]:[t,e]}function QP(t,{mergeName:e=!1}={}){let r=t.match(/^([^:]+): (.*)$/m);if(!r)return\"validation failed\";let[,o,a]=r;return e&&(a=a[0].toLowerCase()+a.slice(1)),a=o!==\".\"||!e?`${o.replace(/^\\.(\\[|$)/,\"$1\")}: ${a}`:`: ${a}`,a}function Iw(t,e){return e.length===1?new ot(`${t}${QP(e[0],{mergeName:!0})}`):new ot(`${t}:\n${e.map(r=>`\n- ${QP(r)}`).join(\"\")}`)}function ag(t,e,r){if(typeof r>\"u\")return e;let o=[],a=[],n=A=>{let p=e;return e=A,n.bind(null,p)};if(!r(e,{errors:o,coercions:a,coercion:n}))throw Iw(`Invalid value for ${t}`,o);for(let[,A]of a)A();return e}var Cw,yf=It(()=>{kP();Cw=Symbol(\"clipanion/isOption\")});var Yo={};Kt(Yo,{KeyRelationship:()=>Ku,TypeAssertionError:()=>Jp,applyCascade:()=>vw,as:()=>sqe,assert:()=>rqe,assertWithErrors:()=>nqe,cascade:()=>LP,fn:()=>oqe,hasAtLeastOneKey:()=>dL,hasExactLength:()=>ez,hasForbiddenKeys:()=>Dqe,hasKeyRelationship:()=>Pw,hasMaxLength:()=>lqe,hasMinLength:()=>aqe,hasMutuallyExclusiveKeys:()=>Pqe,hasRequiredKeys:()=>vqe,hasUniqueItems:()=>cqe,isArray:()=>FP,isAtLeast:()=>hL,isAtMost:()=>fqe,isBase64:()=>Cqe,isBoolean:()=>V6e,isDate:()=>J6e,isDict:()=>$6e,isEnum:()=>js,isHexColor:()=>Eqe,isISO8601:()=>yqe,isInExclusiveRange:()=>hqe,isInInclusiveRange:()=>pqe,isInstanceOf:()=>tqe,isInteger:()=>gL,isJSON:()=>Iqe,isLiteral:()=>XV,isLowerCase:()=>gqe,isMap:()=>Z6e,isNegative:()=>uqe,isNullable:()=>Bqe,isNumber:()=>fL,isObject:()=>ZV,isOneOf:()=>pL,isOptional:()=>wqe,isPartial:()=>eqe,isPayload:()=>z6e,isPositive:()=>Aqe,isRecord:()=>TP,isSet:()=>X6e,isString:()=>Sm,isTuple:()=>RP,isUUID4:()=>mqe,isUnknown:()=>AL,isUpperCase:()=>dqe,makeTrait:()=>$V,makeValidator:()=>qr,matchesRegExp:()=>Bw,softAssert:()=>iqe});function Vn(t){return t===null?\"null\":t===void 0?\"undefined\":t===\"\"?\"an empty string\":typeof t==\"symbol\"?`<${t.toString()}>`:Array.isArray(t)?\"an array\":JSON.stringify(t)}function Pm(t,e){if(t.length===0)return\"nothing\";if(t.length===1)return Vn(t[0]);let r=t.slice(0,-1),o=t[t.length-1],a=t.length>2?`, ${e} `:` ${e} `;return`${r.map(n=>Vn(n)).join(\", \")}${a}${Vn(o)}`}function zp(t,e){var r,o,a;return typeof e==\"number\"?`${(r=t?.p)!==null&&r!==void 0?r:\".\"}[${e}]`:H6e.test(e)?`${(o=t?.p)!==null&&o!==void 0?o:\"\"}.${e}`:`${(a=t?.p)!==null&&a!==void 0?a:\".\"}[${JSON.stringify(e)}]`}function uL(t,e,r){return t===1?e:r}function gr({errors:t,p:e}={},r){return t?.push(`${e??\".\"}: ${r}`),!1}function Y6e(t,e){return r=>{t[e]=r}}function Vu(t,e){return r=>{let o=t[e];return t[e]=r,Vu(t,e).bind(null,o)}}function ww(t,e,r){let o=()=>(t(r()),a),a=()=>(t(e),o);return o}function AL(){return qr({test:(t,e)=>!0})}function XV(t){return qr({test:(e,r)=>e!==t?gr(r,`Expected ${Vn(t)} (got ${Vn(e)})`):!0})}function Sm(){return qr({test:(t,e)=>typeof t!=\"string\"?gr(e,`Expected a string (got ${Vn(t)})`):!0})}function js(t){let e=Array.isArray(t)?t:Object.values(t),r=e.every(a=>typeof a==\"string\"||typeof a==\"number\"),o=new Set(e);return o.size===1?XV([...o][0]):qr({test:(a,n)=>o.has(a)?!0:r?gr(n,`Expected one of ${Pm(e,\"or\")} (got ${Vn(a)})`):gr(n,`Expected a valid enumeration value (got ${Vn(a)})`)})}function V6e(){return qr({test:(t,e)=>{var r;if(typeof t!=\"boolean\"){if(typeof e?.coercions<\"u\"){if(typeof e?.coercion>\"u\")return gr(e,\"Unbound coercion result\");let o=K6e.get(t);if(typeof o<\"u\")return e.coercions.push([(r=e.p)!==null&&r!==void 0?r:\".\",e.coercion.bind(null,o)]),!0}return gr(e,`Expected a boolean (got ${Vn(t)})`)}return!0}})}function fL(){return qr({test:(t,e)=>{var r;if(typeof t!=\"number\"){if(typeof e?.coercions<\"u\"){if(typeof e?.coercion>\"u\")return gr(e,\"Unbound coercion result\");let o;if(typeof t==\"string\"){let a;try{a=JSON.parse(t)}catch{}if(typeof a==\"number\")if(JSON.stringify(a)===t)o=a;else return gr(e,`Received a number that can't be safely represented by the runtime (${t})`)}if(typeof o<\"u\")return e.coercions.push([(r=e.p)!==null&&r!==void 0?r:\".\",e.coercion.bind(null,o)]),!0}return gr(e,`Expected a number (got ${Vn(t)})`)}return!0}})}function z6e(t){return qr({test:(e,r)=>{var o;if(typeof r?.coercions>\"u\")return gr(r,\"The isPayload predicate can only be used with coercion enabled\");if(typeof r.coercion>\"u\")return gr(r,\"Unbound coercion result\");if(typeof e!=\"string\")return gr(r,`Expected a string (got ${Vn(e)})`);let a;try{a=JSON.parse(e)}catch{return gr(r,`Expected a JSON string (got ${Vn(e)})`)}let n={value:a};return t(a,Object.assign(Object.assign({},r),{coercion:Vu(n,\"value\")}))?(r.coercions.push([(o=r.p)!==null&&o!==void 0?o:\".\",r.coercion.bind(null,n.value)]),!0):!1}})}function J6e(){return qr({test:(t,e)=>{var r;if(!(t instanceof Date)){if(typeof e?.coercions<\"u\"){if(typeof e?.coercion>\"u\")return gr(e,\"Unbound coercion result\");let o;if(typeof t==\"string\"&&JV.test(t))o=new Date(t);else{let a;if(typeof t==\"string\"){let n;try{n=JSON.parse(t)}catch{}typeof n==\"number\"&&(a=n)}else typeof t==\"number\"&&(a=t);if(typeof a<\"u\")if(Number.isSafeInteger(a)||!Number.isSafeInteger(a*1e3))o=new Date(a*1e3);else return gr(e,`Received a timestamp that can't be safely represented by the runtime (${t})`)}if(typeof o<\"u\")return e.coercions.push([(r=e.p)!==null&&r!==void 0?r:\".\",e.coercion.bind(null,o)]),!0}return gr(e,`Expected a date (got ${Vn(t)})`)}return!0}})}function FP(t,{delimiter:e}={}){return qr({test:(r,o)=>{var a;let n=r;if(typeof r==\"string\"&&typeof e<\"u\"&&typeof o?.coercions<\"u\"){if(typeof o?.coercion>\"u\")return gr(o,\"Unbound coercion result\");r=r.split(e)}if(!Array.isArray(r))return gr(o,`Expected an array (got ${Vn(r)})`);let u=!0;for(let A=0,p=r.length;A<p&&(u=t(r[A],Object.assign(Object.assign({},o),{p:zp(o,A),coercion:Vu(r,A)}))&&u,!(!u&&o?.errors==null));++A);return r!==n&&o.coercions.push([(a=o.p)!==null&&a!==void 0?a:\".\",o.coercion.bind(null,r)]),u}})}function X6e(t,{delimiter:e}={}){let r=FP(t,{delimiter:e});return qr({test:(o,a)=>{var n,u;if(Object.getPrototypeOf(o).toString()===\"[object Set]\")if(typeof a?.coercions<\"u\"){if(typeof a?.coercion>\"u\")return gr(a,\"Unbound coercion result\");let A=[...o],p=[...o];if(!r(p,Object.assign(Object.assign({},a),{coercion:void 0})))return!1;let h=()=>p.some((E,w)=>E!==A[w])?new Set(p):o;return a.coercions.push([(n=a.p)!==null&&n!==void 0?n:\".\",ww(a.coercion,o,h)]),!0}else{let A=!0;for(let p of o)if(A=t(p,Object.assign({},a))&&A,!A&&a?.errors==null)break;return A}if(typeof a?.coercions<\"u\"){if(typeof a?.coercion>\"u\")return gr(a,\"Unbound coercion result\");let A={value:o};return r(o,Object.assign(Object.assign({},a),{coercion:Vu(A,\"value\")}))?(a.coercions.push([(u=a.p)!==null&&u!==void 0?u:\".\",ww(a.coercion,o,()=>new Set(A.value))]),!0):!1}return gr(a,`Expected a set (got ${Vn(o)})`)}})}function Z6e(t,e){let r=FP(RP([t,e])),o=TP(e,{keys:t});return qr({test:(a,n)=>{var u,A,p;if(Object.getPrototypeOf(a).toString()===\"[object Map]\")if(typeof n?.coercions<\"u\"){if(typeof n?.coercion>\"u\")return gr(n,\"Unbound coercion result\");let h=[...a],E=[...a];if(!r(E,Object.assign(Object.assign({},n),{coercion:void 0})))return!1;let w=()=>E.some((D,b)=>D[0]!==h[b][0]||D[1]!==h[b][1])?new Map(E):a;return n.coercions.push([(u=n.p)!==null&&u!==void 0?u:\".\",ww(n.coercion,a,w)]),!0}else{let h=!0;for(let[E,w]of a)if(h=t(E,Object.assign({},n))&&h,!h&&n?.errors==null||(h=e(w,Object.assign(Object.assign({},n),{p:zp(n,E)}))&&h,!h&&n?.errors==null))break;return h}if(typeof n?.coercions<\"u\"){if(typeof n?.coercion>\"u\")return gr(n,\"Unbound coercion result\");let h={value:a};return Array.isArray(a)?r(a,Object.assign(Object.assign({},n),{coercion:void 0}))?(n.coercions.push([(A=n.p)!==null&&A!==void 0?A:\".\",ww(n.coercion,a,()=>new Map(h.value))]),!0):!1:o(a,Object.assign(Object.assign({},n),{coercion:Vu(h,\"value\")}))?(n.coercions.push([(p=n.p)!==null&&p!==void 0?p:\".\",ww(n.coercion,a,()=>new Map(Object.entries(h.value)))]),!0):!1}return gr(n,`Expected a map (got ${Vn(a)})`)}})}function RP(t,{delimiter:e}={}){let r=ez(t.length);return qr({test:(o,a)=>{var n;if(typeof o==\"string\"&&typeof e<\"u\"&&typeof a?.coercions<\"u\"){if(typeof a?.coercion>\"u\")return gr(a,\"Unbound coercion result\");o=o.split(e),a.coercions.push([(n=a.p)!==null&&n!==void 0?n:\".\",a.coercion.bind(null,o)])}if(!Array.isArray(o))return gr(a,`Expected a tuple (got ${Vn(o)})`);let u=r(o,Object.assign({},a));for(let A=0,p=o.length;A<p&&A<t.length&&(u=t[A](o[A],Object.assign(Object.assign({},a),{p:zp(a,A),coercion:Vu(o,A)}))&&u,!(!u&&a?.errors==null));++A);return u}})}function TP(t,{keys:e=null}={}){let r=FP(RP([e??Sm(),t]));return qr({test:(o,a)=>{var n;if(Array.isArray(o)&&typeof a?.coercions<\"u\")return typeof a?.coercion>\"u\"?gr(a,\"Unbound coercion result\"):r(o,Object.assign(Object.assign({},a),{coercion:void 0}))?(o=Object.fromEntries(o),a.coercions.push([(n=a.p)!==null&&n!==void 0?n:\".\",a.coercion.bind(null,o)]),!0):!1;if(typeof o!=\"object\"||o===null)return gr(a,`Expected an object (got ${Vn(o)})`);let u=Object.keys(o),A=!0;for(let p=0,h=u.length;p<h&&(A||a?.errors!=null);++p){let E=u[p],w=o[E];if(E===\"__proto__\"||E===\"constructor\"){A=gr(Object.assign(Object.assign({},a),{p:zp(a,E)}),\"Unsafe property name\");continue}if(e!==null&&!e(E,a)){A=!1;continue}if(!t(w,Object.assign(Object.assign({},a),{p:zp(a,E),coercion:Vu(o,E)}))){A=!1;continue}}return A}})}function $6e(t,e={}){return TP(t,e)}function ZV(t,{extra:e=null}={}){let r=Object.keys(t),o=qr({test:(a,n)=>{if(typeof a!=\"object\"||a===null)return gr(n,`Expected an object (got ${Vn(a)})`);let u=new Set([...r,...Object.keys(a)]),A={},p=!0;for(let h of u){if(h===\"constructor\"||h===\"__proto__\")p=gr(Object.assign(Object.assign({},n),{p:zp(n,h)}),\"Unsafe property name\");else{let E=Object.prototype.hasOwnProperty.call(t,h)?t[h]:void 0,w=Object.prototype.hasOwnProperty.call(a,h)?a[h]:void 0;typeof E<\"u\"?p=E(w,Object.assign(Object.assign({},n),{p:zp(n,h),coercion:Vu(a,h)}))&&p:e===null?p=gr(Object.assign(Object.assign({},n),{p:zp(n,h)}),`Extraneous property (got ${Vn(w)})`):Object.defineProperty(A,h,{enumerable:!0,get:()=>w,set:Y6e(a,h)})}if(!p&&n?.errors==null)break}return e!==null&&(p||n?.errors!=null)&&(p=e(A,n)&&p),p}});return Object.assign(o,{properties:t})}function eqe(t){return ZV(t,{extra:TP(AL())})}function $V(t){return()=>t}function qr({test:t}){return $V(t)()}function rqe(t,e){if(!e(t))throw new Jp}function nqe(t,e){let r=[];if(!e(t,{errors:r}))throw new Jp({errors:r})}function iqe(t,e){}function sqe(t,e,{coerce:r=!1,errors:o,throw:a}={}){let n=o?[]:void 0;if(!r){if(e(t,{errors:n}))return a?t:{value:t,errors:void 0};if(a)throw new Jp({errors:n});return{value:void 0,errors:n??!0}}let u={value:t},A=Vu(u,\"value\"),p=[];if(!e(t,{errors:n,coercion:A,coercions:p})){if(a)throw new Jp({errors:n});return{value:void 0,errors:n??!0}}for(let[,h]of p)h();return a?u.value:{value:u.value,errors:void 0}}function oqe(t,e){let r=RP(t);return(...o)=>{if(!r(o))throw new Jp;return e(...o)}}function aqe(t){return qr({test:(e,r)=>e.length>=t?!0:gr(r,`Expected to have a length of at least ${t} elements (got ${e.length})`)})}function lqe(t){return qr({test:(e,r)=>e.length<=t?!0:gr(r,`Expected to have a length of at most ${t} elements (got ${e.length})`)})}function ez(t){return qr({test:(e,r)=>e.length!==t?gr(r,`Expected to have a length of exactly ${t} elements (got ${e.length})`):!0})}function cqe({map:t}={}){return qr({test:(e,r)=>{let o=new Set,a=new Set;for(let n=0,u=e.length;n<u;++n){let A=e[n],p=typeof t<\"u\"?t(A):A;if(o.has(p)){if(a.has(p))continue;gr(r,`Expected to contain unique elements; got a duplicate with ${Vn(e)}`),a.add(p)}else o.add(p)}return a.size===0}})}function uqe(){return qr({test:(t,e)=>t<=0?!0:gr(e,`Expected to be negative (got ${t})`)})}function Aqe(){return qr({test:(t,e)=>t>=0?!0:gr(e,`Expected to be positive (got ${t})`)})}function hL(t){return qr({test:(e,r)=>e>=t?!0:gr(r,`Expected to be at least ${t} (got ${e})`)})}function fqe(t){return qr({test:(e,r)=>e<=t?!0:gr(r,`Expected to be at most ${t} (got ${e})`)})}function pqe(t,e){return qr({test:(r,o)=>r>=t&&r<=e?!0:gr(o,`Expected to be in the [${t}; ${e}] range (got ${r})`)})}function hqe(t,e){return qr({test:(r,o)=>r>=t&&r<e?!0:gr(o,`Expected to be in the [${t}; ${e}[ range (got ${r})`)})}function gL({unsafe:t=!1}={}){return qr({test:(e,r)=>e!==Math.round(e)?gr(r,`Expected to be an integer (got ${e})`):!t&&!Number.isSafeInteger(e)?gr(r,`Expected to be a safe integer (got ${e})`):!0})}function Bw(t){return qr({test:(e,r)=>t.test(e)?!0:gr(r,`Expected to match the pattern ${t.toString()} (got ${Vn(e)})`)})}function gqe(){return qr({test:(t,e)=>t!==t.toLowerCase()?gr(e,`Expected to be all-lowercase (got ${t})`):!0})}function dqe(){return qr({test:(t,e)=>t!==t.toUpperCase()?gr(e,`Expected to be all-uppercase (got ${t})`):!0})}function mqe(){return qr({test:(t,e)=>W6e.test(t)?!0:gr(e,`Expected to be a valid UUID v4 (got ${Vn(t)})`)})}function yqe(){return qr({test:(t,e)=>JV.test(t)?!0:gr(e,`Expected to be a valid ISO 8601 date string (got ${Vn(t)})`)})}function Eqe({alpha:t=!1}){return qr({test:(e,r)=>(t?q6e.test(e):j6e.test(e))?!0:gr(r,`Expected to be a valid hexadecimal color string (got ${Vn(e)})`)})}function Cqe(){return qr({test:(t,e)=>G6e.test(t)?!0:gr(e,`Expected to be a valid base 64 string (got ${Vn(t)})`)})}function Iqe(t=AL()){return qr({test:(e,r)=>{let o;try{o=JSON.parse(e)}catch{return gr(r,`Expected to be a valid JSON string (got ${Vn(e)})`)}return t(o,r)}})}function LP(t,...e){let r=Array.isArray(e[0])?e[0]:e;return qr({test:(o,a)=>{var n,u;let A={value:o},p=typeof a?.coercions<\"u\"?Vu(A,\"value\"):void 0,h=typeof a?.coercions<\"u\"?[]:void 0;if(!t(o,Object.assign(Object.assign({},a),{coercion:p,coercions:h})))return!1;let E=[];if(typeof h<\"u\")for(let[,w]of h)E.push(w());try{if(typeof a?.coercions<\"u\"){if(A.value!==o){if(typeof a?.coercion>\"u\")return gr(a,\"Unbound coercion result\");a.coercions.push([(n=a.p)!==null&&n!==void 0?n:\".\",a.coercion.bind(null,A.value)])}(u=a?.coercions)===null||u===void 0||u.push(...h)}return r.every(w=>w(A.value,a))}finally{for(let w of E)w()}}})}function vw(t,...e){let r=Array.isArray(e[0])?e[0]:e;return LP(t,r)}function wqe(t){return qr({test:(e,r)=>typeof e>\"u\"?!0:t(e,r)})}function Bqe(t){return qr({test:(e,r)=>e===null?!0:t(e,r)})}function vqe(t,e){var r;let o=new Set(t),a=Dw[(r=e?.missingIf)!==null&&r!==void 0?r:\"missing\"];return qr({test:(n,u)=>{let A=new Set(Object.keys(n)),p=[];for(let h of o)a(A,h,n)||p.push(h);return p.length>0?gr(u,`Missing required ${uL(p.length,\"property\",\"properties\")} ${Pm(p,\"and\")}`):!0}})}function dL(t,e){var r;let o=new Set(t),a=Dw[(r=e?.missingIf)!==null&&r!==void 0?r:\"missing\"];return qr({test:(n,u)=>Object.keys(n).some(h=>a(o,h,n))?!0:gr(u,`Missing at least one property from ${Pm(Array.from(o),\"or\")}`)})}function Dqe(t,e){var r;let o=new Set(t),a=Dw[(r=e?.missingIf)!==null&&r!==void 0?r:\"missing\"];return qr({test:(n,u)=>{let A=new Set(Object.keys(n)),p=[];for(let h of o)a(A,h,n)&&p.push(h);return p.length>0?gr(u,`Forbidden ${uL(p.length,\"property\",\"properties\")} ${Pm(p,\"and\")}`):!0}})}function Pqe(t,e){var r;let o=new Set(t),a=Dw[(r=e?.missingIf)!==null&&r!==void 0?r:\"missing\"];return qr({test:(n,u)=>{let A=new Set(Object.keys(n)),p=[];for(let h of o)a(A,h,n)&&p.push(h);return p.length>1?gr(u,`Mutually exclusive properties ${Pm(p,\"and\")}`):!0}})}function Pw(t,e,r,o){var a,n;let u=new Set((a=o?.ignore)!==null&&a!==void 0?a:[]),A=Dw[(n=o?.missingIf)!==null&&n!==void 0?n:\"missing\"],p=new Set(r),h=Sqe[e],E=e===Ku.Forbids?\"or\":\"and\";return qr({test:(w,D)=>{let b=new Set(Object.keys(w));if(!A(b,t,w)||u.has(w[t]))return!0;let C=[];for(let T of p)(A(b,T,w)&&!u.has(w[T]))!==h.expect&&C.push(T);return C.length>=1?gr(D,`Property \"${t}\" ${h.message} ${uL(C.length,\"property\",\"properties\")} ${Pm(C,E)}`):!0}})}var H6e,q6e,j6e,G6e,W6e,JV,K6e,tqe,pL,Jp,Dw,Ku,Sqe,il=It(()=>{H6e=/^[a-zA-Z_][a-zA-Z0-9_]*$/;q6e=/^#[0-9a-f]{6}$/i,j6e=/^#[0-9a-f]{6}([0-9a-f]{2})?$/i,G6e=/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/,W6e=/^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}$/i,JV=/^(?:[1-9]\\d{3}(-?)(?:(?:0[1-9]|1[0-2])\\1(?:0[1-9]|1\\d|2[0-8])|(?:0[13-9]|1[0-2])\\1(?:29|30)|(?:0[13578]|1[02])(?:\\1)31|00[1-9]|0[1-9]\\d|[12]\\d{2}|3(?:[0-5]\\d|6[0-5]))|(?:[1-9]\\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)(?:(-?)02(?:\\2)29|-?366))T(?:[01]\\d|2[0-3])(:?)[0-5]\\d(?:\\3[0-5]\\d)?(?:Z|[+-][01]\\d(?:\\3[0-5]\\d)?)$/;K6e=new Map([[\"true\",!0],[\"True\",!0],[\"1\",!0],[1,!0],[\"false\",!1],[\"False\",!1],[\"0\",!1],[0,!1]]);tqe=t=>qr({test:(e,r)=>e instanceof t?!0:gr(r,`Expected an instance of ${t.name} (got ${Vn(e)})`)}),pL=(t,{exclusive:e=!1}={})=>qr({test:(r,o)=>{var a,n,u;let A=[],p=typeof o?.errors<\"u\"?[]:void 0;for(let h=0,E=t.length;h<E;++h){let w=typeof o?.errors<\"u\"?[]:void 0,D=typeof o?.coercions<\"u\"?[]:void 0;if(t[h](r,Object.assign(Object.assign({},o),{errors:w,coercions:D,p:`${(a=o?.p)!==null&&a!==void 0?a:\".\"}#${h+1}`}))){if(A.push([`#${h+1}`,D]),!e)break}else p?.push(w[0])}if(A.length===1){let[,h]=A[0];return typeof h<\"u\"&&((n=o?.coercions)===null||n===void 0||n.push(...h)),!0}return A.length>1?gr(o,`Expected to match exactly a single predicate (matched ${A.join(\", \")})`):(u=o?.errors)===null||u===void 0||u.push(...p),!1}});Jp=class extends Error{constructor({errors:e}={}){let r=\"Type mismatch\";if(e&&e.length>0){r+=`\n`;for(let o of e)r+=`\n- ${o}`}super(r)}};Dw={missing:(t,e)=>t.has(e),undefined:(t,e,r)=>t.has(e)&&typeof r[e]<\"u\",nil:(t,e,r)=>t.has(e)&&r[e]!=null,falsy:(t,e,r)=>t.has(e)&&!!r[e]};(function(t){t.Forbids=\"Forbids\",t.Requires=\"Requires\"})(Ku||(Ku={}));Sqe={[Ku.Forbids]:{expect:!1,message:\"forbids using\"},[Ku.Requires]:{expect:!0,message:\"requires using\"}}});var st,Xp=It(()=>{yf();st=class{constructor(){this.help=!1}static Usage(e){return e}async catch(e){throw e}async validateAndExecute(){let r=this.constructor.schema;if(Array.isArray(r)){let{isDict:a,isUnknown:n,applyCascade:u}=await Promise.resolve().then(()=>(il(),Yo)),A=u(a(n()),r),p=[],h=[];if(!A(this,{errors:p,coercions:h}))throw Iw(\"Invalid option schema\",p);for(let[,w]of h)w()}else if(r!=null)throw new Error(\"Invalid command schema\");let o=await this.execute();return typeof o<\"u\"?o:0}};st.isOption=Cw;st.Default=[]});function Sa(t){oL&&console.log(t)}function rz(){let t={nodes:[]};for(let e=0;e<pn.CustomNode;++e)t.nodes.push(sl());return t}function xqe(t){let e=rz(),r=[],o=e.nodes.length;for(let a of t){r.push(o);for(let n=0;n<a.nodes.length;++n)iz(n)||e.nodes.push(Nqe(a.nodes[n],o));o+=a.nodes.length-pn.CustomNode+1}for(let a of r)xm(e,pn.InitialNode,a);return e}function jc(t,e){return t.nodes.push(e),t.nodes.length-1}function bqe(t){let e=new Set,r=o=>{if(e.has(o))return;e.add(o);let a=t.nodes[o];for(let u of Object.values(a.statics))for(let{to:A}of u)r(A);for(let[,{to:u}]of a.dynamics)r(u);for(let{to:u}of a.shortcuts)r(u);let n=new Set(a.shortcuts.map(({to:u})=>u));for(;a.shortcuts.length>0;){let{to:u}=a.shortcuts.shift(),A=t.nodes[u];for(let[p,h]of Object.entries(A.statics)){let E=Object.prototype.hasOwnProperty.call(a.statics,p)?a.statics[p]:a.statics[p]=[];for(let w of h)E.some(({to:D})=>w.to===D)||E.push(w)}for(let[p,h]of A.dynamics)a.dynamics.some(([E,{to:w}])=>p===E&&h.to===w)||a.dynamics.push([p,h]);for(let p of A.shortcuts)n.has(p.to)||(a.shortcuts.push(p),n.add(p.to))}};r(pn.InitialNode)}function kqe(t,{prefix:e=\"\"}={}){if(oL){Sa(`${e}Nodes are:`);for(let r=0;r<t.nodes.length;++r)Sa(`${e}  ${r}: ${JSON.stringify(t.nodes[r])}`)}}function Qqe(t,e,r=!1){Sa(`Running a vm on ${JSON.stringify(e)}`);let o=[{node:pn.InitialNode,state:{candidateUsage:null,requiredOptions:[],errorMessage:null,ignoreOptions:!1,options:[],path:[],positionals:[],remainder:null,selectedIndex:null,partial:!1,tokens:[]}}];kqe(t,{prefix:\"  \"});let a=[Kn.StartOfInput,...e];for(let n=0;n<a.length;++n){let u=a[n],A=u===Kn.EndOfInput||u===Kn.EndOfPartialInput,p=n-1;Sa(`  Processing ${JSON.stringify(u)}`);let h=[];for(let{node:E,state:w}of o){Sa(`    Current node is ${E}`);let D=t.nodes[E];if(E===pn.ErrorNode){h.push({node:E,state:w});continue}console.assert(D.shortcuts.length===0,\"Shortcuts should have been eliminated by now\");let b=Object.prototype.hasOwnProperty.call(D.statics,u);if(!r||n<a.length-1||b)if(b){let C=D.statics[u];for(let{to:T,reducer:N}of C)h.push({node:T,state:typeof N<\"u\"?NP(yL,N,w,u,p):w}),Sa(`      Static transition to ${T} found`)}else Sa(\"      No static transition found\");else{let C=!1;for(let T of Object.keys(D.statics))if(T.startsWith(u)){if(u===T)for(let{to:N,reducer:U}of D.statics[T])h.push({node:N,state:typeof U<\"u\"?NP(yL,U,w,u,p):w}),Sa(`      Static transition to ${N} found`);else for(let{to:N}of D.statics[T])h.push({node:N,state:{...w,remainder:T.slice(u.length)}}),Sa(`      Static transition to ${N} found (partial match)`);C=!0}C||Sa(\"      No partial static transition found\")}if(!A)for(let[C,{to:T,reducer:N}]of D.dynamics)NP(Oqe,C,w,u,p)&&(h.push({node:T,state:typeof N<\"u\"?NP(yL,N,w,u,p):w}),Sa(`      Dynamic transition to ${T} found (via ${C})`))}if(h.length===0&&A&&e.length===1)return[{node:pn.InitialNode,state:tz}];if(h.length===0)throw new Dm(e,o.filter(({node:E})=>E!==pn.ErrorNode).map(({state:E})=>({usage:E.candidateUsage,reason:null})));if(h.every(({node:E})=>E===pn.ErrorNode))throw new Dm(e,h.map(({state:E})=>({usage:E.candidateUsage,reason:E.errorMessage})));o=Rqe(h)}if(o.length>0){Sa(\"  Results:\");for(let n of o)Sa(`    - ${n.node} -> ${JSON.stringify(n.state)}`)}else Sa(\"  No results\");return o}function Fqe(t,e,{endToken:r=Kn.EndOfInput}={}){let o=Qqe(t,[...e,r]);return Tqe(e,o.map(({state:a})=>a))}function Rqe(t){let e=0;for(let{state:r}of t)r.path.length>e&&(e=r.path.length);return t.filter(({state:r})=>r.path.length===e)}function Tqe(t,e){let r=e.filter(D=>D.selectedIndex!==null),o=r.filter(D=>!D.partial);if(o.length>0&&(r=o),r.length===0)throw new Error;let a=r.filter(D=>D.selectedIndex===og||D.requiredOptions.every(b=>b.some(C=>D.options.find(T=>T.name===C))));if(a.length===0)throw new Dm(t,r.map(D=>({usage:D.candidateUsage,reason:null})));let n=0;for(let D of a)D.path.length>n&&(n=D.path.length);let u=a.filter(D=>D.path.length===n),A=D=>D.positionals.filter(({extra:b})=>!b).length+D.options.length,p=u.map(D=>({state:D,positionalCount:A(D)})),h=0;for(let{positionalCount:D}of p)D>h&&(h=D);let E=p.filter(({positionalCount:D})=>D===h).map(({state:D})=>D),w=Lqe(E);if(w.length>1)throw new bP(t,w.map(D=>D.candidateUsage));return w[0]}function Lqe(t){let e=[],r=[];for(let o of t)o.selectedIndex===og?r.push(o):e.push(o);return r.length>0&&e.push({...tz,path:nz(...r.map(o=>o.path)),options:r.reduce((o,a)=>o.concat(a.options),[])}),e}function nz(t,e,...r){return e===void 0?Array.from(t):nz(t.filter((o,a)=>o===e[a]),...r)}function sl(){return{dynamics:[],shortcuts:[],statics:{}}}function iz(t){return t===pn.SuccessNode||t===pn.ErrorNode}function mL(t,e=0){return{to:iz(t.to)?t.to:t.to>=pn.CustomNode?t.to+e-pn.CustomNode+1:t.to+e,reducer:t.reducer}}function Nqe(t,e=0){let r=sl();for(let[o,a]of t.dynamics)r.dynamics.push([o,mL(a,e)]);for(let o of t.shortcuts)r.shortcuts.push(mL(o,e));for(let[o,a]of Object.entries(t.statics))r.statics[o]=a.map(n=>mL(n,e));return r}function Bs(t,e,r,o,a){t.nodes[e].dynamics.push([r,{to:o,reducer:a}])}function xm(t,e,r,o){t.nodes[e].shortcuts.push({to:r,reducer:o})}function Ko(t,e,r,o,a){(Object.prototype.hasOwnProperty.call(t.nodes[e].statics,r)?t.nodes[e].statics[r]:t.nodes[e].statics[r]=[]).push({to:o,reducer:a})}function NP(t,e,r,o,a){if(Array.isArray(e)){let[n,...u]=e;return t[n](r,o,a,...u)}else return t[e](r,o,a)}var tz,Oqe,yL,ol,EL,OP,MP=It(()=>{xP();kP();tz={candidateUsage:null,requiredOptions:[],errorMessage:null,ignoreOptions:!1,path:[],positionals:[],options:[],remainder:null,selectedIndex:og,partial:!1,tokens:[]};Oqe={always:()=>!0,isOptionLike:(t,e)=>!t.ignoreOptions&&e!==\"-\"&&e.startsWith(\"-\"),isNotOptionLike:(t,e)=>t.ignoreOptions||e===\"-\"||!e.startsWith(\"-\"),isOption:(t,e,r,o)=>!t.ignoreOptions&&e===o,isBatchOption:(t,e,r,o)=>!t.ignoreOptions&&KV.test(e)&&[...e.slice(1)].every(a=>o.has(`-${a}`)),isBoundOption:(t,e,r,o,a)=>{let n=e.match(sL);return!t.ignoreOptions&&!!n&&SP.test(n[1])&&o.has(n[1])&&a.filter(u=>u.nameSet.includes(n[1])).every(u=>u.allowBinding)},isNegatedOption:(t,e,r,o)=>!t.ignoreOptions&&e===`--no-${o.slice(2)}`,isHelp:(t,e)=>!t.ignoreOptions&&iL.test(e),isUnsupportedOption:(t,e,r,o)=>!t.ignoreOptions&&e.startsWith(\"-\")&&SP.test(e)&&!o.has(e),isInvalidOption:(t,e)=>!t.ignoreOptions&&e.startsWith(\"-\")&&!SP.test(e)},yL={setCandidateState:(t,e,r,o)=>({...t,...o}),setSelectedIndex:(t,e,r,o)=>({...t,selectedIndex:o}),setPartialIndex:(t,e,r,o)=>({...t,selectedIndex:o,partial:!0}),pushBatch:(t,e,r,o)=>{let a=t.options.slice(),n=t.tokens.slice();for(let u=1;u<e.length;++u){let A=o.get(`-${e[u]}`),p=u===1?[0,2]:[u,u+1];a.push({name:A,value:!0}),n.push({segmentIndex:r,type:\"option\",option:A,slice:p})}return{...t,options:a,tokens:n}},pushBound:(t,e,r)=>{let[,o,a]=e.match(sL),n=t.options.concat({name:o,value:a}),u=t.tokens.concat([{segmentIndex:r,type:\"option\",slice:[0,o.length],option:o},{segmentIndex:r,type:\"assign\",slice:[o.length,o.length+1]},{segmentIndex:r,type:\"value\",slice:[o.length+1,o.length+a.length+1]}]);return{...t,options:n,tokens:u}},pushPath:(t,e,r)=>{let o=t.path.concat(e),a=t.tokens.concat({segmentIndex:r,type:\"path\"});return{...t,path:o,tokens:a}},pushPositional:(t,e,r)=>{let o=t.positionals.concat({value:e,extra:!1}),a=t.tokens.concat({segmentIndex:r,type:\"positional\"});return{...t,positionals:o,tokens:a}},pushExtra:(t,e,r)=>{let o=t.positionals.concat({value:e,extra:!0}),a=t.tokens.concat({segmentIndex:r,type:\"positional\"});return{...t,positionals:o,tokens:a}},pushExtraNoLimits:(t,e,r)=>{let o=t.positionals.concat({value:e,extra:ol}),a=t.tokens.concat({segmentIndex:r,type:\"positional\"});return{...t,positionals:o,tokens:a}},pushTrue:(t,e,r,o)=>{let a=t.options.concat({name:o,value:!0}),n=t.tokens.concat({segmentIndex:r,type:\"option\",option:o});return{...t,options:a,tokens:n}},pushFalse:(t,e,r,o)=>{let a=t.options.concat({name:o,value:!1}),n=t.tokens.concat({segmentIndex:r,type:\"option\",option:o});return{...t,options:a,tokens:n}},pushUndefined:(t,e,r,o)=>{let a=t.options.concat({name:e,value:void 0}),n=t.tokens.concat({segmentIndex:r,type:\"option\",option:e});return{...t,options:a,tokens:n}},pushStringValue:(t,e,r)=>{var o;let a=t.options[t.options.length-1],n=t.options.slice(),u=t.tokens.concat({segmentIndex:r,type:\"value\"});return a.value=((o=a.value)!==null&&o!==void 0?o:[]).concat([e]),{...t,options:n,tokens:u}},setStringValue:(t,e,r)=>{let o=t.options[t.options.length-1],a=t.options.slice(),n=t.tokens.concat({segmentIndex:r,type:\"value\"});return o.value=e,{...t,options:a,tokens:n}},inhibateOptions:t=>({...t,ignoreOptions:!0}),useHelp:(t,e,r,o)=>{let[,,a]=e.match(iL);return typeof a<\"u\"?{...t,options:[{name:\"-c\",value:String(o)},{name:\"-i\",value:a}]}:{...t,options:[{name:\"-c\",value:String(o)}]}},setError:(t,e,r,o)=>e===Kn.EndOfInput||e===Kn.EndOfPartialInput?{...t,errorMessage:`${o}.`}:{...t,errorMessage:`${o} (\"${e}\").`},setOptionArityError:(t,e)=>{let r=t.options[t.options.length-1];return{...t,errorMessage:`Not enough arguments to option ${r.name}.`}}},ol=Symbol(),EL=class{constructor(e,r){this.allOptionNames=new Map,this.arity={leading:[],trailing:[],extra:[],proxy:!1},this.options=[],this.paths=[],this.cliIndex=e,this.cliOpts=r}addPath(e){this.paths.push(e)}setArity({leading:e=this.arity.leading,trailing:r=this.arity.trailing,extra:o=this.arity.extra,proxy:a=this.arity.proxy}){Object.assign(this.arity,{leading:e,trailing:r,extra:o,proxy:a})}addPositional({name:e=\"arg\",required:r=!0}={}){if(!r&&this.arity.extra===ol)throw new Error(\"Optional parameters cannot be declared when using .rest() or .proxy()\");if(!r&&this.arity.trailing.length>0)throw new Error(\"Optional parameters cannot be declared after the required trailing positional arguments\");!r&&this.arity.extra!==ol?this.arity.extra.push(e):this.arity.extra!==ol&&this.arity.extra.length===0?this.arity.leading.push(e):this.arity.trailing.push(e)}addRest({name:e=\"arg\",required:r=0}={}){if(this.arity.extra===ol)throw new Error(\"Infinite lists cannot be declared multiple times in the same command\");if(this.arity.trailing.length>0)throw new Error(\"Infinite lists cannot be declared after the required trailing positional arguments\");for(let o=0;o<r;++o)this.addPositional({name:e});this.arity.extra=ol}addProxy({required:e=0}={}){this.addRest({required:e}),this.arity.proxy=!0}addOption({names:e,description:r,arity:o=0,hidden:a=!1,required:n=!1,allowBinding:u=!0}){if(!u&&o>1)throw new Error(\"The arity cannot be higher than 1 when the option only supports the --arg=value syntax\");if(!Number.isInteger(o))throw new Error(`The arity must be an integer, got ${o}`);if(o<0)throw new Error(`The arity must be positive, got ${o}`);let A=e.reduce((p,h)=>h.length>p.length?h:p,\"\");for(let p of e)this.allOptionNames.set(p,A);this.options.push({preferredName:A,nameSet:e,description:r,arity:o,hidden:a,required:n,allowBinding:u})}setContext(e){this.context=e}usage({detailed:e=!0,inlineOptions:r=!0}={}){let o=[this.cliOpts.binaryName],a=[];if(this.paths.length>0&&o.push(...this.paths[0]),e){for(let{preferredName:u,nameSet:A,arity:p,hidden:h,description:E,required:w}of this.options){if(h)continue;let D=[];for(let C=0;C<p;++C)D.push(` #${C}`);let b=`${A.join(\",\")}${D.join(\"\")}`;!r&&E?a.push({preferredName:u,nameSet:A,definition:b,description:E,required:w}):o.push(w?`<${b}>`:`[${b}]`)}o.push(...this.arity.leading.map(u=>`<${u}>`)),this.arity.extra===ol?o.push(\"...\"):o.push(...this.arity.extra.map(u=>`[${u}]`)),o.push(...this.arity.trailing.map(u=>`<${u}>`))}return{usage:o.join(\" \"),options:a}}compile(){if(typeof this.context>\"u\")throw new Error(\"Assertion failed: No context attached\");let e=rz(),r=pn.InitialNode,o=this.usage().usage,a=this.options.filter(A=>A.required).map(A=>A.nameSet);r=jc(e,sl()),Ko(e,pn.InitialNode,Kn.StartOfInput,r,[\"setCandidateState\",{candidateUsage:o,requiredOptions:a}]);let n=this.arity.proxy?\"always\":\"isNotOptionLike\",u=this.paths.length>0?this.paths:[[]];for(let A of u){let p=r;if(A.length>0){let D=jc(e,sl());xm(e,p,D),this.registerOptions(e,D),p=D}for(let D=0;D<A.length;++D){let b=jc(e,sl());Ko(e,p,A[D],b,\"pushPath\"),p=b}if(this.arity.leading.length>0||!this.arity.proxy){let D=jc(e,sl());Bs(e,p,\"isHelp\",D,[\"useHelp\",this.cliIndex]),Bs(e,D,\"always\",D,\"pushExtra\"),Ko(e,D,Kn.EndOfInput,pn.SuccessNode,[\"setSelectedIndex\",og]),this.registerOptions(e,p)}this.arity.leading.length>0&&(Ko(e,p,Kn.EndOfInput,pn.ErrorNode,[\"setError\",\"Not enough positional arguments\"]),Ko(e,p,Kn.EndOfPartialInput,pn.SuccessNode,[\"setPartialIndex\",this.cliIndex]));let h=p;for(let D=0;D<this.arity.leading.length;++D){let b=jc(e,sl());(!this.arity.proxy||D+1!==this.arity.leading.length)&&this.registerOptions(e,b),(this.arity.trailing.length>0||D+1!==this.arity.leading.length)&&(Ko(e,b,Kn.EndOfInput,pn.ErrorNode,[\"setError\",\"Not enough positional arguments\"]),Ko(e,b,Kn.EndOfPartialInput,pn.SuccessNode,[\"setPartialIndex\",this.cliIndex])),Bs(e,h,\"isNotOptionLike\",b,\"pushPositional\"),h=b}let E=h;if(this.arity.extra===ol||this.arity.extra.length>0){let D=jc(e,sl());if(xm(e,h,D),this.arity.extra===ol){let b=jc(e,sl());this.arity.proxy||this.registerOptions(e,b),Bs(e,h,n,b,\"pushExtraNoLimits\"),Bs(e,b,n,b,\"pushExtraNoLimits\"),xm(e,b,D)}else for(let b=0;b<this.arity.extra.length;++b){let C=jc(e,sl());(!this.arity.proxy||b>0)&&this.registerOptions(e,C),Bs(e,E,n,C,\"pushExtra\"),xm(e,C,D),E=C}E=D}this.arity.trailing.length>0&&(Ko(e,E,Kn.EndOfInput,pn.ErrorNode,[\"setError\",\"Not enough positional arguments\"]),Ko(e,E,Kn.EndOfPartialInput,pn.SuccessNode,[\"setPartialIndex\",this.cliIndex]));let w=E;for(let D=0;D<this.arity.trailing.length;++D){let b=jc(e,sl());this.arity.proxy||this.registerOptions(e,b),D+1<this.arity.trailing.length&&(Ko(e,b,Kn.EndOfInput,pn.ErrorNode,[\"setError\",\"Not enough positional arguments\"]),Ko(e,b,Kn.EndOfPartialInput,pn.SuccessNode,[\"setPartialIndex\",this.cliIndex])),Bs(e,w,\"isNotOptionLike\",b,\"pushPositional\"),w=b}Bs(e,w,n,pn.ErrorNode,[\"setError\",\"Extraneous positional argument\"]),Ko(e,w,Kn.EndOfInput,pn.SuccessNode,[\"setSelectedIndex\",this.cliIndex]),Ko(e,w,Kn.EndOfPartialInput,pn.SuccessNode,[\"setSelectedIndex\",this.cliIndex])}return{machine:e,context:this.context}}registerOptions(e,r){Bs(e,r,[\"isOption\",\"--\"],r,\"inhibateOptions\"),Bs(e,r,[\"isBatchOption\",this.allOptionNames],r,[\"pushBatch\",this.allOptionNames]),Bs(e,r,[\"isBoundOption\",this.allOptionNames,this.options],r,\"pushBound\"),Bs(e,r,[\"isUnsupportedOption\",this.allOptionNames],pn.ErrorNode,[\"setError\",\"Unsupported option name\"]),Bs(e,r,[\"isInvalidOption\"],pn.ErrorNode,[\"setError\",\"Invalid option name\"]);for(let o of this.options)if(o.arity===0)for(let a of o.nameSet)Bs(e,r,[\"isOption\",a],r,[\"pushTrue\",o.preferredName]),a.startsWith(\"--\")&&!a.startsWith(\"--no-\")&&Bs(e,r,[\"isNegatedOption\",a],r,[\"pushFalse\",o.preferredName]);else{let a=jc(e,sl());for(let n of o.nameSet)Bs(e,r,[\"isOption\",n],a,[\"pushUndefined\",o.preferredName]);for(let n=0;n<o.arity;++n){let u=jc(e,sl());Ko(e,a,Kn.EndOfInput,pn.ErrorNode,\"setOptionArityError\"),Ko(e,a,Kn.EndOfPartialInput,pn.ErrorNode,\"setOptionArityError\"),Bs(e,a,\"isOptionLike\",pn.ErrorNode,\"setOptionArityError\");let A=o.arity===1?\"setStringValue\":\"pushStringValue\";Bs(e,a,\"isNotOptionLike\",u,A),a=u}xm(e,a,r)}}},OP=class t{constructor({binaryName:e=\"...\"}={}){this.builders=[],this.opts={binaryName:e}}static build(e,r={}){return new t(r).commands(e).compile()}getBuilderByIndex(e){if(!(e>=0&&e<this.builders.length))throw new Error(`Assertion failed: Out-of-bound command index (${e})`);return this.builders[e]}commands(e){for(let r of e)r(this.command());return this}command(){let e=new EL(this.builders.length,this.opts);return this.builders.push(e),e}compile(){let e=[],r=[];for(let a of this.builders){let{machine:n,context:u}=a.compile();e.push(n),r.push(u)}let o=xqe(e);return bqe(o),{machine:o,contexts:r,process:(a,{partial:n}={})=>{let u=n?Kn.EndOfPartialInput:Kn.EndOfInput;return Fqe(o,a,{endToken:u})}}}}});function oz(){return UP.default&&\"getColorDepth\"in UP.default.WriteStream.prototype?UP.default.WriteStream.prototype.getColorDepth():process.env.FORCE_COLOR===\"0\"?1:process.env.FORCE_COLOR===\"1\"||typeof process.stdout<\"u\"&&process.stdout.isTTY?8:1}function az(t){let e=sz;if(typeof e>\"u\"){if(t.stdout===process.stdout&&t.stderr===process.stderr)return null;let{AsyncLocalStorage:r}=ve(\"async_hooks\");e=sz=new r;let o=process.stdout._write;process.stdout._write=function(n,u,A){let p=e.getStore();return typeof p>\"u\"?o.call(this,n,u,A):p.stdout.write(n,u,A)};let a=process.stderr._write;process.stderr._write=function(n,u,A){let p=e.getStore();return typeof p>\"u\"?a.call(this,n,u,A):p.stderr.write(n,u,A)}}return r=>e.run(t,r)}var UP,sz,lz=It(()=>{UP=et(ve(\"tty\"),1)});var _P,cz=It(()=>{Xp();_P=class t extends st{constructor(e){super(),this.contexts=e,this.commands=[]}static from(e,r){let o=new t(r);o.path=e.path;for(let a of e.options)switch(a.name){case\"-c\":o.commands.push(Number(a.value));break;case\"-i\":o.index=Number(a.value);break}return o}async execute(){let e=this.commands;if(typeof this.index<\"u\"&&this.index>=0&&this.index<e.length&&(e=[e[this.index]]),e.length===0)this.context.stdout.write(this.cli.usage());else if(e.length===1)this.context.stdout.write(this.cli.usage(this.contexts[e[0]].commandClass,{detailed:!0}));else if(e.length>1){this.context.stdout.write(`Multiple commands match your selection:\n`),this.context.stdout.write(`\n`);let r=0;for(let o of this.commands)this.context.stdout.write(this.cli.usage(this.contexts[o].commandClass,{prefix:`${r++}. `.padStart(5)}));this.context.stdout.write(`\n`),this.context.stdout.write(`Run again with -h=<index> to see the longer details of any of those commands.\n`)}}}});async function fz(...t){let{resolvedOptions:e,resolvedCommandClasses:r,resolvedArgv:o,resolvedContext:a}=hz(t);return Vo.from(r,e).runExit(o,a)}async function pz(...t){let{resolvedOptions:e,resolvedCommandClasses:r,resolvedArgv:o,resolvedContext:a}=hz(t);return Vo.from(r,e).run(o,a)}function hz(t){let e,r,o,a;switch(typeof process<\"u\"&&typeof process.argv<\"u\"&&(o=process.argv.slice(2)),t.length){case 1:r=t[0];break;case 2:t[0]&&t[0].prototype instanceof st||Array.isArray(t[0])?(r=t[0],Array.isArray(t[1])?o=t[1]:a=t[1]):(e=t[0],r=t[1]);break;case 3:Array.isArray(t[2])?(e=t[0],r=t[1],o=t[2]):t[0]&&t[0].prototype instanceof st||Array.isArray(t[0])?(r=t[0],o=t[1],a=t[2]):(e=t[0],r=t[1],a=t[2]);break;default:e=t[0],r=t[1],o=t[2],a=t[3];break}if(typeof o>\"u\")throw new Error(\"The argv parameter must be provided when running Clipanion outside of a Node context\");return{resolvedOptions:e,resolvedCommandClasses:r,resolvedArgv:o,resolvedContext:a}}function Az(t){return t()}var uz,Vo,gz=It(()=>{xP();MP();cL();lz();Xp();cz();uz=Symbol(\"clipanion/errorCommand\");Vo=class t{constructor({binaryLabel:e,binaryName:r=\"...\",binaryVersion:o,enableCapture:a=!1,enableColors:n}={}){this.registrations=new Map,this.builder=new OP({binaryName:r}),this.binaryLabel=e,this.binaryName=r,this.binaryVersion=o,this.enableCapture=a,this.enableColors=n}static from(e,r={}){let o=new t(r),a=Array.isArray(e)?e:[e];for(let n of a)o.register(n);return o}register(e){var r;let o=new Map,a=new e;for(let p in a){let h=a[p];typeof h==\"object\"&&h!==null&&h[st.isOption]&&o.set(p,h)}let n=this.builder.command(),u=n.cliIndex,A=(r=e.paths)!==null&&r!==void 0?r:a.paths;if(typeof A<\"u\")for(let p of A)n.addPath(p);this.registrations.set(e,{specs:o,builder:n,index:u});for(let[p,{definition:h}]of o.entries())h(n,p);n.setContext({commandClass:e})}process(e,r){let{input:o,context:a,partial:n}=typeof e==\"object\"&&Array.isArray(e)?{input:e,context:r}:e,{contexts:u,process:A}=this.builder.compile(),p=A(o,{partial:n}),h={...t.defaultContext,...a};switch(p.selectedIndex){case og:{let E=_P.from(p,u);return E.context=h,E.tokens=p.tokens,E}default:{let{commandClass:E}=u[p.selectedIndex],w=this.registrations.get(E);if(typeof w>\"u\")throw new Error(\"Assertion failed: Expected the command class to have been registered.\");let D=new E;D.context=h,D.tokens=p.tokens,D.path=p.path;try{for(let[b,{transformer:C}]of w.specs.entries())D[b]=C(w.builder,b,p,h);return D}catch(b){throw b[uz]=D,b}}break}}async run(e,r){var o,a;let n,u={...t.defaultContext,...r},A=(o=this.enableColors)!==null&&o!==void 0?o:u.colorDepth>1;if(!Array.isArray(e))n=e;else try{n=this.process(e,u)}catch(E){return u.stdout.write(this.error(E,{colored:A})),1}if(n.help)return u.stdout.write(this.usage(n,{colored:A,detailed:!0})),0;n.context=u,n.cli={binaryLabel:this.binaryLabel,binaryName:this.binaryName,binaryVersion:this.binaryVersion,enableCapture:this.enableCapture,enableColors:this.enableColors,definitions:()=>this.definitions(),definition:E=>this.definition(E),error:(E,w)=>this.error(E,w),format:E=>this.format(E),process:(E,w)=>this.process(E,{...u,...w}),run:(E,w)=>this.run(E,{...u,...w}),usage:(E,w)=>this.usage(E,w)};let p=this.enableCapture&&(a=az(u))!==null&&a!==void 0?a:Az,h;try{h=await p(()=>n.validateAndExecute().catch(E=>n.catch(E).then(()=>0)))}catch(E){return u.stdout.write(this.error(E,{colored:A,command:n})),1}return h}async runExit(e,r){process.exitCode=await this.run(e,r)}definition(e,{colored:r=!1}={}){if(!e.usage)return null;let{usage:o}=this.getUsageByRegistration(e,{detailed:!1}),{usage:a,options:n}=this.getUsageByRegistration(e,{detailed:!0,inlineOptions:!1}),u=typeof e.usage.category<\"u\"?yo(e.usage.category,{format:this.format(r),paragraphs:!1}):void 0,A=typeof e.usage.description<\"u\"?yo(e.usage.description,{format:this.format(r),paragraphs:!1}):void 0,p=typeof e.usage.details<\"u\"?yo(e.usage.details,{format:this.format(r),paragraphs:!0}):void 0,h=typeof e.usage.examples<\"u\"?e.usage.examples.map(([E,w])=>[yo(E,{format:this.format(r),paragraphs:!1}),w.replace(/\\$0/g,this.binaryName)]):void 0;return{path:o,usage:a,category:u,description:A,details:p,examples:h,options:n}}definitions({colored:e=!1}={}){let r=[];for(let o of this.registrations.keys()){let a=this.definition(o,{colored:e});a&&r.push(a)}return r}usage(e=null,{colored:r,detailed:o=!1,prefix:a=\"$ \"}={}){var n;if(e===null){for(let p of this.registrations.keys()){let h=p.paths,E=typeof p.usage<\"u\";if(!h||h.length===0||h.length===1&&h[0].length===0||((n=h?.some(b=>b.length===0))!==null&&n!==void 0?n:!1))if(e){e=null;break}else e=p;else if(E){e=null;continue}}e&&(o=!0)}let u=e!==null&&e instanceof st?e.constructor:e,A=\"\";if(u)if(o){let{description:p=\"\",details:h=\"\",examples:E=[]}=u.usage||{};p!==\"\"&&(A+=yo(p,{format:this.format(r),paragraphs:!1}).replace(/^./,b=>b.toUpperCase()),A+=`\n`),(h!==\"\"||E.length>0)&&(A+=`${this.format(r).header(\"Usage\")}\n`,A+=`\n`);let{usage:w,options:D}=this.getUsageByRegistration(u,{inlineOptions:!1});if(A+=`${this.format(r).bold(a)}${w}\n`,D.length>0){A+=`\n`,A+=`${this.format(r).header(\"Options\")}\n`;let b=D.reduce((C,T)=>Math.max(C,T.definition.length),0);A+=`\n`;for(let{definition:C,description:T}of D)A+=`  ${this.format(r).bold(C.padEnd(b))}    ${yo(T,{format:this.format(r),paragraphs:!1})}`}if(h!==\"\"&&(A+=`\n`,A+=`${this.format(r).header(\"Details\")}\n`,A+=`\n`,A+=yo(h,{format:this.format(r),paragraphs:!0})),E.length>0){A+=`\n`,A+=`${this.format(r).header(\"Examples\")}\n`;for(let[b,C]of E)A+=`\n`,A+=yo(b,{format:this.format(r),paragraphs:!1}),A+=`${C.replace(/^/m,`  ${this.format(r).bold(a)}`).replace(/\\$0/g,this.binaryName)}\n`}}else{let{usage:p}=this.getUsageByRegistration(u);A+=`${this.format(r).bold(a)}${p}\n`}else{let p=new Map;for(let[D,{index:b}]of this.registrations.entries()){if(typeof D.usage>\"u\")continue;let C=typeof D.usage.category<\"u\"?yo(D.usage.category,{format:this.format(r),paragraphs:!1}):null,T=p.get(C);typeof T>\"u\"&&p.set(C,T=[]);let{usage:N}=this.getUsageByIndex(b);T.push({commandClass:D,usage:N})}let h=Array.from(p.keys()).sort((D,b)=>D===null?-1:b===null?1:D.localeCompare(b,\"en\",{usage:\"sort\",caseFirst:\"upper\"})),E=typeof this.binaryLabel<\"u\",w=typeof this.binaryVersion<\"u\";E||w?(E&&w?A+=`${this.format(r).header(`${this.binaryLabel} - ${this.binaryVersion}`)}\n\n`:E?A+=`${this.format(r).header(`${this.binaryLabel}`)}\n`:A+=`${this.format(r).header(`${this.binaryVersion}`)}\n`,A+=`  ${this.format(r).bold(a)}${this.binaryName} <command>\n`):A+=`${this.format(r).bold(a)}${this.binaryName} <command>\n`;for(let D of h){let b=p.get(D).slice().sort((T,N)=>T.usage.localeCompare(N.usage,\"en\",{usage:\"sort\",caseFirst:\"upper\"})),C=D!==null?D.trim():\"General commands\";A+=`\n`,A+=`${this.format(r).header(`${C}`)}\n`;for(let{commandClass:T,usage:N}of b){let U=T.usage.description||\"undocumented\";A+=`\n`,A+=`  ${this.format(r).bold(N)}\n`,A+=`    ${yo(U,{format:this.format(r),paragraphs:!1})}`}}A+=`\n`,A+=yo(\"You can also print more details about any of these commands by calling them with the `-h,--help` flag right after the command name.\",{format:this.format(r),paragraphs:!0})}return A}error(e,r){var o,{colored:a,command:n=(o=e[uz])!==null&&o!==void 0?o:null}=r===void 0?{}:r;(!e||typeof e!=\"object\"||!(\"stack\"in e))&&(e=new Error(`Execution failed with a non-error rejection (rejected value: ${JSON.stringify(e)})`));let u=\"\",A=e.name.replace(/([a-z])([A-Z])/g,\"$1 $2\");A===\"Error\"&&(A=\"Internal Error\"),u+=`${this.format(a).error(A)}: ${e.message}\n`;let p=e.clipanion;return typeof p<\"u\"?p.type===\"usage\"&&(u+=`\n`,u+=this.usage(n)):e.stack&&(u+=`${e.stack.replace(/^.*\\n/,\"\")}\n`),u}format(e){var r;return((r=e??this.enableColors)!==null&&r!==void 0?r:t.defaultContext.colorDepth>1)?VV:zV}getUsageByRegistration(e,r){let o=this.registrations.get(e);if(typeof o>\"u\")throw new Error(\"Assertion failed: Unregistered command\");return this.getUsageByIndex(o.index,r)}getUsageByIndex(e,r){return this.builder.getBuilderByIndex(e).usage(r)}};Vo.defaultContext={env:process.env,stdin:process.stdin,stdout:process.stdout,stderr:process.stderr,colorDepth:oz()}});var Sw,dz=It(()=>{Xp();Sw=class extends st{async execute(){this.context.stdout.write(`${JSON.stringify(this.cli.definitions(),null,2)}\n`)}};Sw.paths=[[\"--clipanion=definitions\"]]});var xw,mz=It(()=>{Xp();xw=class extends st{async execute(){this.context.stdout.write(this.cli.usage())}};xw.paths=[[\"-h\"],[\"--help\"]]});function HP(t={}){return Wo({definition(e,r){var o;e.addProxy({name:(o=t.name)!==null&&o!==void 0?o:r,required:t.required})},transformer(e,r,o){return o.positionals.map(({value:a})=>a)}})}var CL=It(()=>{yf()});var bw,yz=It(()=>{Xp();CL();bw=class extends st{constructor(){super(...arguments),this.args=HP()}async execute(){this.context.stdout.write(`${JSON.stringify(this.cli.process(this.args).tokens,null,2)}\n`)}};bw.paths=[[\"--clipanion=tokens\"]]});var kw,Ez=It(()=>{Xp();kw=class extends st{async execute(){var e;this.context.stdout.write(`${(e=this.cli.binaryVersion)!==null&&e!==void 0?e:\"<unknown>\"}\n`)}};kw.paths=[[\"-v\"],[\"--version\"]]});var IL={};Kt(IL,{DefinitionsCommand:()=>Sw,HelpCommand:()=>xw,TokensCommand:()=>bw,VersionCommand:()=>kw});var Cz=It(()=>{dz();mz();yz();Ez()});function Iz(t,e,r){let[o,a]=Yu(e,r??{}),{arity:n=1}=a,u=t.split(\",\"),A=new Set(u);return Wo({definition(p){p.addOption({names:u,arity:n,hidden:a?.hidden,description:a?.description,required:a.required})},transformer(p,h,E){let w,D=typeof o<\"u\"?[...o]:void 0;for(let{name:b,value:C}of E.options)A.has(b)&&(w=b,D=D??[],D.push(C));return typeof D<\"u\"?ag(w??h,D,a.validator):D}})}var wz=It(()=>{yf()});function Bz(t,e,r){let[o,a]=Yu(e,r??{}),n=t.split(\",\"),u=new Set(n);return Wo({definition(A){A.addOption({names:n,allowBinding:!1,arity:0,hidden:a.hidden,description:a.description,required:a.required})},transformer(A,p,h){let E=o;for(let{name:w,value:D}of h.options)u.has(w)&&(E=D);return E}})}var vz=It(()=>{yf()});function Dz(t,e,r){let[o,a]=Yu(e,r??{}),n=t.split(\",\"),u=new Set(n);return Wo({definition(A){A.addOption({names:n,allowBinding:!1,arity:0,hidden:a.hidden,description:a.description,required:a.required})},transformer(A,p,h){let E=o;for(let{name:w,value:D}of h.options)u.has(w)&&(E??(E=0),D?E+=1:E=0);return E}})}var Pz=It(()=>{yf()});function Sz(t={}){return Wo({definition(e,r){var o;e.addRest({name:(o=t.name)!==null&&o!==void 0?o:r,required:t.required})},transformer(e,r,o){let a=u=>{let A=o.positionals[u];return A.extra===ol||A.extra===!1&&u<e.arity.leading.length},n=0;for(;n<o.positionals.length&&a(n);)n+=1;return o.positionals.splice(0,n).map(({value:u})=>u)}})}var xz=It(()=>{MP();yf()});function Mqe(t,e,r){let[o,a]=Yu(e,r??{}),{arity:n=1}=a,u=t.split(\",\"),A=new Set(u);return Wo({definition(p){p.addOption({names:u,arity:a.tolerateBoolean?0:n,hidden:a.hidden,description:a.description,required:a.required})},transformer(p,h,E,w){let D,b=o;typeof a.env<\"u\"&&w.env[a.env]&&(D=a.env,b=w.env[a.env]);for(let{name:C,value:T}of E.options)A.has(C)&&(D=C,b=T);return typeof b==\"string\"?ag(D??h,b,a.validator):b}})}function Uqe(t={}){let{required:e=!0}=t;return Wo({definition(r,o){var a;r.addPositional({name:(a=t.name)!==null&&a!==void 0?a:o,required:t.required})},transformer(r,o,a){var n;for(let u=0;u<a.positionals.length;++u){if(a.positionals[u].extra===ol||e&&a.positionals[u].extra===!0||!e&&a.positionals[u].extra===!1)continue;let[A]=a.positionals.splice(u,1);return ag((n=t.name)!==null&&n!==void 0?n:o,A.value,t.validator)}}})}function bz(t,...e){return typeof t==\"string\"?Mqe(t,...e):Uqe(t)}var kz=It(()=>{MP();yf()});var de={};Kt(de,{Array:()=>Iz,Boolean:()=>Bz,Counter:()=>Dz,Proxy:()=>HP,Rest:()=>Sz,String:()=>bz,applyValidator:()=>ag,cleanValidationError:()=>QP,formatError:()=>Iw,isOptionSymbol:()=>Cw,makeCommandOption:()=>Wo,rerouteArguments:()=>Yu});var Qz=It(()=>{yf();CL();wz();vz();Pz();xz();kz()});var Qw={};Kt(Qw,{Builtins:()=>IL,Cli:()=>Vo,Command:()=>st,Option:()=>de,UsageError:()=>ot,formatMarkdownish:()=>yo,run:()=>pz,runExit:()=>fz});var Gt=It(()=>{kP();cL();Xp();gz();Cz();Qz()});var Fz=_((ckt,_qe)=>{_qe.exports={name:\"dotenv\",version:\"16.3.1\",description:\"Loads environment variables from .env file\",main:\"lib/main.js\",types:\"lib/main.d.ts\",exports:{\".\":{types:\"./lib/main.d.ts\",require:\"./lib/main.js\",default:\"./lib/main.js\"},\"./config\":\"./config.js\",\"./config.js\":\"./config.js\",\"./lib/env-options\":\"./lib/env-options.js\",\"./lib/env-options.js\":\"./lib/env-options.js\",\"./lib/cli-options\":\"./lib/cli-options.js\",\"./lib/cli-options.js\":\"./lib/cli-options.js\",\"./package.json\":\"./package.json\"},scripts:{\"dts-check\":\"tsc --project tests/types/tsconfig.json\",lint:\"standard\",\"lint-readme\":\"standard-markdown\",pretest:\"npm run lint && npm run dts-check\",test:\"tap tests/*.js --100 -Rspec\",prerelease:\"npm test\",release:\"standard-version\"},repository:{type:\"git\",url:\"git://github.com/motdotla/dotenv.git\"},funding:\"https://github.com/motdotla/dotenv?sponsor=1\",keywords:[\"dotenv\",\"env\",\".env\",\"environment\",\"variables\",\"config\",\"settings\"],readmeFilename:\"README.md\",license:\"BSD-2-Clause\",devDependencies:{\"@definitelytyped/dtslint\":\"^0.0.133\",\"@types/node\":\"^18.11.3\",decache:\"^4.6.1\",sinon:\"^14.0.1\",standard:\"^17.0.0\",\"standard-markdown\":\"^7.1.0\",\"standard-version\":\"^9.5.0\",tap:\"^16.3.0\",tar:\"^6.1.11\",typescript:\"^4.8.4\"},engines:{node:\">=12\"},browser:{fs:!1}}});var Nz=_((ukt,Ef)=>{var Rz=ve(\"fs\"),BL=ve(\"path\"),Hqe=ve(\"os\"),qqe=ve(\"crypto\"),jqe=Fz(),vL=jqe.version,Gqe=/(?:^|^)\\s*(?:export\\s+)?([\\w.-]+)(?:\\s*=\\s*?|:\\s+?)(\\s*'(?:\\\\'|[^'])*'|\\s*\"(?:\\\\\"|[^\"])*\"|\\s*`(?:\\\\`|[^`])*`|[^#\\r\\n]+)?\\s*(?:#.*)?(?:$|$)/mg;function Wqe(t){let e={},r=t.toString();r=r.replace(/\\r\\n?/mg,`\n`);let o;for(;(o=Gqe.exec(r))!=null;){let a=o[1],n=o[2]||\"\";n=n.trim();let u=n[0];n=n.replace(/^(['\"`])([\\s\\S]*)\\1$/mg,\"$2\"),u==='\"'&&(n=n.replace(/\\\\n/g,`\n`),n=n.replace(/\\\\r/g,\"\\r\")),e[a]=n}return e}function Yqe(t){let e=Lz(t),r=vs.configDotenv({path:e});if(!r.parsed)throw new Error(`MISSING_DATA: Cannot parse ${e} for an unknown reason`);let o=Tz(t).split(\",\"),a=o.length,n;for(let u=0;u<a;u++)try{let A=o[u].trim(),p=zqe(r,A);n=vs.decrypt(p.ciphertext,p.key);break}catch(A){if(u+1>=a)throw A}return vs.parse(n)}function Kqe(t){console.log(`[dotenv@${vL}][INFO] ${t}`)}function Vqe(t){console.log(`[dotenv@${vL}][WARN] ${t}`)}function wL(t){console.log(`[dotenv@${vL}][DEBUG] ${t}`)}function Tz(t){return t&&t.DOTENV_KEY&&t.DOTENV_KEY.length>0?t.DOTENV_KEY:process.env.DOTENV_KEY&&process.env.DOTENV_KEY.length>0?process.env.DOTENV_KEY:\"\"}function zqe(t,e){let r;try{r=new URL(e)}catch(A){throw A.code===\"ERR_INVALID_URL\"?new Error(\"INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenv.org/vault/.env.vault?environment=development\"):A}let o=r.password;if(!o)throw new Error(\"INVALID_DOTENV_KEY: Missing key part\");let a=r.searchParams.get(\"environment\");if(!a)throw new Error(\"INVALID_DOTENV_KEY: Missing environment part\");let n=`DOTENV_VAULT_${a.toUpperCase()}`,u=t.parsed[n];if(!u)throw new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${n} in your .env.vault file.`);return{ciphertext:u,key:o}}function Lz(t){let e=BL.resolve(process.cwd(),\".env\");return t&&t.path&&t.path.length>0&&(e=t.path),e.endsWith(\".vault\")?e:`${e}.vault`}function Jqe(t){return t[0]===\"~\"?BL.join(Hqe.homedir(),t.slice(1)):t}function Xqe(t){Kqe(\"Loading env from encrypted .env.vault\");let e=vs._parseVault(t),r=process.env;return t&&t.processEnv!=null&&(r=t.processEnv),vs.populate(r,e,t),{parsed:e}}function Zqe(t){let e=BL.resolve(process.cwd(),\".env\"),r=\"utf8\",o=!!(t&&t.debug);t&&(t.path!=null&&(e=Jqe(t.path)),t.encoding!=null&&(r=t.encoding));try{let a=vs.parse(Rz.readFileSync(e,{encoding:r})),n=process.env;return t&&t.processEnv!=null&&(n=t.processEnv),vs.populate(n,a,t),{parsed:a}}catch(a){return o&&wL(`Failed to load ${e} ${a.message}`),{error:a}}}function $qe(t){let e=Lz(t);return Tz(t).length===0?vs.configDotenv(t):Rz.existsSync(e)?vs._configVault(t):(Vqe(`You set DOTENV_KEY but you are missing a .env.vault file at ${e}. Did you forget to build it?`),vs.configDotenv(t))}function eje(t,e){let r=Buffer.from(e.slice(-64),\"hex\"),o=Buffer.from(t,\"base64\"),a=o.slice(0,12),n=o.slice(-16);o=o.slice(12,-16);try{let u=qqe.createDecipheriv(\"aes-256-gcm\",r,a);return u.setAuthTag(n),`${u.update(o)}${u.final()}`}catch(u){let A=u instanceof RangeError,p=u.message===\"Invalid key length\",h=u.message===\"Unsupported state or unable to authenticate data\";if(A||p){let E=\"INVALID_DOTENV_KEY: It must be 64 characters long (or more)\";throw new Error(E)}else if(h){let E=\"DECRYPTION_FAILED: Please check your DOTENV_KEY\";throw new Error(E)}else throw console.error(\"Error: \",u.code),console.error(\"Error: \",u.message),u}}function tje(t,e,r={}){let o=!!(r&&r.debug),a=!!(r&&r.override);if(typeof e!=\"object\")throw new Error(\"OBJECT_REQUIRED: Please check the processEnv argument being passed to populate\");for(let n of Object.keys(e))Object.prototype.hasOwnProperty.call(t,n)?(a===!0&&(t[n]=e[n]),o&&wL(a===!0?`\"${n}\" is already defined and WAS overwritten`:`\"${n}\" is already defined and was NOT overwritten`)):t[n]=e[n]}var vs={configDotenv:Zqe,_configVault:Xqe,_parseVault:Yqe,config:$qe,decrypt:eje,parse:Wqe,populate:tje};Ef.exports.configDotenv=vs.configDotenv;Ef.exports._configVault=vs._configVault;Ef.exports._parseVault=vs._parseVault;Ef.exports.config=vs.config;Ef.exports.decrypt=vs.decrypt;Ef.exports.parse=vs.parse;Ef.exports.populate=vs.populate;Ef.exports=vs});var Mz=_((Akt,Oz)=>{\"use strict\";Oz.exports=(t,...e)=>new Promise(r=>{r(t(...e))})});var lg=_((fkt,DL)=>{\"use strict\";var rje=Mz(),Uz=t=>{if(t<1)throw new TypeError(\"Expected `concurrency` to be a number from 1 and up\");let e=[],r=0,o=()=>{r--,e.length>0&&e.shift()()},a=(A,p,...h)=>{r++;let E=rje(A,...h);p(E),E.then(o,o)},n=(A,p,...h)=>{r<t?a(A,p,...h):e.push(a.bind(null,A,p,...h))},u=(A,...p)=>new Promise(h=>n(A,h,...p));return Object.defineProperties(u,{activeCount:{get:()=>r},pendingCount:{get:()=>e.length}}),u};DL.exports=Uz;DL.exports.default=Uz});function zu(t){return`YN${t.toString(10).padStart(4,\"0\")}`}function qP(t){let e=Number(t.slice(2));if(typeof vr[e]>\"u\")throw new Error(`Unknown message name: \"${t}\"`);return e}var vr,jP=It(()=>{vr=(Me=>(Me[Me.UNNAMED=0]=\"UNNAMED\",Me[Me.EXCEPTION=1]=\"EXCEPTION\",Me[Me.MISSING_PEER_DEPENDENCY=2]=\"MISSING_PEER_DEPENDENCY\",Me[Me.CYCLIC_DEPENDENCIES=3]=\"CYCLIC_DEPENDENCIES\",Me[Me.DISABLED_BUILD_SCRIPTS=4]=\"DISABLED_BUILD_SCRIPTS\",Me[Me.BUILD_DISABLED=5]=\"BUILD_DISABLED\",Me[Me.SOFT_LINK_BUILD=6]=\"SOFT_LINK_BUILD\",Me[Me.MUST_BUILD=7]=\"MUST_BUILD\",Me[Me.MUST_REBUILD=8]=\"MUST_REBUILD\",Me[Me.BUILD_FAILED=9]=\"BUILD_FAILED\",Me[Me.RESOLVER_NOT_FOUND=10]=\"RESOLVER_NOT_FOUND\",Me[Me.FETCHER_NOT_FOUND=11]=\"FETCHER_NOT_FOUND\",Me[Me.LINKER_NOT_FOUND=12]=\"LINKER_NOT_FOUND\",Me[Me.FETCH_NOT_CACHED=13]=\"FETCH_NOT_CACHED\",Me[Me.YARN_IMPORT_FAILED=14]=\"YARN_IMPORT_FAILED\",Me[Me.REMOTE_INVALID=15]=\"REMOTE_INVALID\",Me[Me.REMOTE_NOT_FOUND=16]=\"REMOTE_NOT_FOUND\",Me[Me.RESOLUTION_PACK=17]=\"RESOLUTION_PACK\",Me[Me.CACHE_CHECKSUM_MISMATCH=18]=\"CACHE_CHECKSUM_MISMATCH\",Me[Me.UNUSED_CACHE_ENTRY=19]=\"UNUSED_CACHE_ENTRY\",Me[Me.MISSING_LOCKFILE_ENTRY=20]=\"MISSING_LOCKFILE_ENTRY\",Me[Me.WORKSPACE_NOT_FOUND=21]=\"WORKSPACE_NOT_FOUND\",Me[Me.TOO_MANY_MATCHING_WORKSPACES=22]=\"TOO_MANY_MATCHING_WORKSPACES\",Me[Me.CONSTRAINTS_MISSING_DEPENDENCY=23]=\"CONSTRAINTS_MISSING_DEPENDENCY\",Me[Me.CONSTRAINTS_INCOMPATIBLE_DEPENDENCY=24]=\"CONSTRAINTS_INCOMPATIBLE_DEPENDENCY\",Me[Me.CONSTRAINTS_EXTRANEOUS_DEPENDENCY=25]=\"CONSTRAINTS_EXTRANEOUS_DEPENDENCY\",Me[Me.CONSTRAINTS_INVALID_DEPENDENCY=26]=\"CONSTRAINTS_INVALID_DEPENDENCY\",Me[Me.CANT_SUGGEST_RESOLUTIONS=27]=\"CANT_SUGGEST_RESOLUTIONS\",Me[Me.FROZEN_LOCKFILE_EXCEPTION=28]=\"FROZEN_LOCKFILE_EXCEPTION\",Me[Me.CROSS_DRIVE_VIRTUAL_LOCAL=29]=\"CROSS_DRIVE_VIRTUAL_LOCAL\",Me[Me.FETCH_FAILED=30]=\"FETCH_FAILED\",Me[Me.DANGEROUS_NODE_MODULES=31]=\"DANGEROUS_NODE_MODULES\",Me[Me.NODE_GYP_INJECTED=32]=\"NODE_GYP_INJECTED\",Me[Me.AUTHENTICATION_NOT_FOUND=33]=\"AUTHENTICATION_NOT_FOUND\",Me[Me.INVALID_CONFIGURATION_KEY=34]=\"INVALID_CONFIGURATION_KEY\",Me[Me.NETWORK_ERROR=35]=\"NETWORK_ERROR\",Me[Me.LIFECYCLE_SCRIPT=36]=\"LIFECYCLE_SCRIPT\",Me[Me.CONSTRAINTS_MISSING_FIELD=37]=\"CONSTRAINTS_MISSING_FIELD\",Me[Me.CONSTRAINTS_INCOMPATIBLE_FIELD=38]=\"CONSTRAINTS_INCOMPATIBLE_FIELD\",Me[Me.CONSTRAINTS_EXTRANEOUS_FIELD=39]=\"CONSTRAINTS_EXTRANEOUS_FIELD\",Me[Me.CONSTRAINTS_INVALID_FIELD=40]=\"CONSTRAINTS_INVALID_FIELD\",Me[Me.AUTHENTICATION_INVALID=41]=\"AUTHENTICATION_INVALID\",Me[Me.PROLOG_UNKNOWN_ERROR=42]=\"PROLOG_UNKNOWN_ERROR\",Me[Me.PROLOG_SYNTAX_ERROR=43]=\"PROLOG_SYNTAX_ERROR\",Me[Me.PROLOG_EXISTENCE_ERROR=44]=\"PROLOG_EXISTENCE_ERROR\",Me[Me.STACK_OVERFLOW_RESOLUTION=45]=\"STACK_OVERFLOW_RESOLUTION\",Me[Me.AUTOMERGE_FAILED_TO_PARSE=46]=\"AUTOMERGE_FAILED_TO_PARSE\",Me[Me.AUTOMERGE_IMMUTABLE=47]=\"AUTOMERGE_IMMUTABLE\",Me[Me.AUTOMERGE_SUCCESS=48]=\"AUTOMERGE_SUCCESS\",Me[Me.AUTOMERGE_REQUIRED=49]=\"AUTOMERGE_REQUIRED\",Me[Me.DEPRECATED_CLI_SETTINGS=50]=\"DEPRECATED_CLI_SETTINGS\",Me[Me.PLUGIN_NAME_NOT_FOUND=51]=\"PLUGIN_NAME_NOT_FOUND\",Me[Me.INVALID_PLUGIN_REFERENCE=52]=\"INVALID_PLUGIN_REFERENCE\",Me[Me.CONSTRAINTS_AMBIGUITY=53]=\"CONSTRAINTS_AMBIGUITY\",Me[Me.CACHE_OUTSIDE_PROJECT=54]=\"CACHE_OUTSIDE_PROJECT\",Me[Me.IMMUTABLE_INSTALL=55]=\"IMMUTABLE_INSTALL\",Me[Me.IMMUTABLE_CACHE=56]=\"IMMUTABLE_CACHE\",Me[Me.INVALID_MANIFEST=57]=\"INVALID_MANIFEST\",Me[Me.PACKAGE_PREPARATION_FAILED=58]=\"PACKAGE_PREPARATION_FAILED\",Me[Me.INVALID_RANGE_PEER_DEPENDENCY=59]=\"INVALID_RANGE_PEER_DEPENDENCY\",Me[Me.INCOMPATIBLE_PEER_DEPENDENCY=60]=\"INCOMPATIBLE_PEER_DEPENDENCY\",Me[Me.DEPRECATED_PACKAGE=61]=\"DEPRECATED_PACKAGE\",Me[Me.INCOMPATIBLE_OS=62]=\"INCOMPATIBLE_OS\",Me[Me.INCOMPATIBLE_CPU=63]=\"INCOMPATIBLE_CPU\",Me[Me.FROZEN_ARTIFACT_EXCEPTION=64]=\"FROZEN_ARTIFACT_EXCEPTION\",Me[Me.TELEMETRY_NOTICE=65]=\"TELEMETRY_NOTICE\",Me[Me.PATCH_HUNK_FAILED=66]=\"PATCH_HUNK_FAILED\",Me[Me.INVALID_CONFIGURATION_VALUE=67]=\"INVALID_CONFIGURATION_VALUE\",Me[Me.UNUSED_PACKAGE_EXTENSION=68]=\"UNUSED_PACKAGE_EXTENSION\",Me[Me.REDUNDANT_PACKAGE_EXTENSION=69]=\"REDUNDANT_PACKAGE_EXTENSION\",Me[Me.AUTO_NM_SUCCESS=70]=\"AUTO_NM_SUCCESS\",Me[Me.NM_CANT_INSTALL_EXTERNAL_SOFT_LINK=71]=\"NM_CANT_INSTALL_EXTERNAL_SOFT_LINK\",Me[Me.NM_PRESERVE_SYMLINKS_REQUIRED=72]=\"NM_PRESERVE_SYMLINKS_REQUIRED\",Me[Me.UPDATE_LOCKFILE_ONLY_SKIP_LINK=73]=\"UPDATE_LOCKFILE_ONLY_SKIP_LINK\",Me[Me.NM_HARDLINKS_MODE_DOWNGRADED=74]=\"NM_HARDLINKS_MODE_DOWNGRADED\",Me[Me.PROLOG_INSTANTIATION_ERROR=75]=\"PROLOG_INSTANTIATION_ERROR\",Me[Me.INCOMPATIBLE_ARCHITECTURE=76]=\"INCOMPATIBLE_ARCHITECTURE\",Me[Me.GHOST_ARCHITECTURE=77]=\"GHOST_ARCHITECTURE\",Me[Me.RESOLUTION_MISMATCH=78]=\"RESOLUTION_MISMATCH\",Me[Me.PROLOG_LIMIT_EXCEEDED=79]=\"PROLOG_LIMIT_EXCEEDED\",Me[Me.NETWORK_DISABLED=80]=\"NETWORK_DISABLED\",Me[Me.NETWORK_UNSAFE_HTTP=81]=\"NETWORK_UNSAFE_HTTP\",Me[Me.RESOLUTION_FAILED=82]=\"RESOLUTION_FAILED\",Me[Me.AUTOMERGE_GIT_ERROR=83]=\"AUTOMERGE_GIT_ERROR\",Me[Me.CONSTRAINTS_CHECK_FAILED=84]=\"CONSTRAINTS_CHECK_FAILED\",Me[Me.UPDATED_RESOLUTION_RECORD=85]=\"UPDATED_RESOLUTION_RECORD\",Me[Me.EXPLAIN_PEER_DEPENDENCIES_CTA=86]=\"EXPLAIN_PEER_DEPENDENCIES_CTA\",Me[Me.MIGRATION_SUCCESS=87]=\"MIGRATION_SUCCESS\",Me[Me.VERSION_NOTICE=88]=\"VERSION_NOTICE\",Me[Me.TIPS_NOTICE=89]=\"TIPS_NOTICE\",Me[Me.OFFLINE_MODE_ENABLED=90]=\"OFFLINE_MODE_ENABLED\",Me))(vr||{})});var Fw=_((hkt,_z)=>{var nje=\"2.0.0\",ije=Number.MAX_SAFE_INTEGER||9007199254740991,sje=16,oje=250,aje=[\"major\",\"premajor\",\"minor\",\"preminor\",\"patch\",\"prepatch\",\"prerelease\"];_z.exports={MAX_LENGTH:256,MAX_SAFE_COMPONENT_LENGTH:sje,MAX_SAFE_BUILD_LENGTH:oje,MAX_SAFE_INTEGER:ije,RELEASE_TYPES:aje,SEMVER_SPEC_VERSION:nje,FLAG_INCLUDE_PRERELEASE:1,FLAG_LOOSE:2}});var Rw=_((gkt,Hz)=>{var lje=typeof process==\"object\"&&process.env&&process.env.NODE_DEBUG&&/\\bsemver\\b/i.test(process.env.NODE_DEBUG)?(...t)=>console.error(\"SEMVER\",...t):()=>{};Hz.exports=lje});var bm=_((Cf,qz)=>{var{MAX_SAFE_COMPONENT_LENGTH:PL,MAX_SAFE_BUILD_LENGTH:cje,MAX_LENGTH:uje}=Fw(),Aje=Rw();Cf=qz.exports={};var fje=Cf.re=[],pje=Cf.safeRe=[],tr=Cf.src=[],rr=Cf.t={},hje=0,SL=\"[a-zA-Z0-9-]\",gje=[[\"\\\\s\",1],[\"\\\\d\",uje],[SL,cje]],dje=t=>{for(let[e,r]of gje)t=t.split(`${e}*`).join(`${e}{0,${r}}`).split(`${e}+`).join(`${e}{1,${r}}`);return t},Gr=(t,e,r)=>{let o=dje(e),a=hje++;Aje(t,a,e),rr[t]=a,tr[a]=e,fje[a]=new RegExp(e,r?\"g\":void 0),pje[a]=new RegExp(o,r?\"g\":void 0)};Gr(\"NUMERICIDENTIFIER\",\"0|[1-9]\\\\d*\");Gr(\"NUMERICIDENTIFIERLOOSE\",\"\\\\d+\");Gr(\"NONNUMERICIDENTIFIER\",`\\\\d*[a-zA-Z-]${SL}*`);Gr(\"MAINVERSION\",`(${tr[rr.NUMERICIDENTIFIER]})\\\\.(${tr[rr.NUMERICIDENTIFIER]})\\\\.(${tr[rr.NUMERICIDENTIFIER]})`);Gr(\"MAINVERSIONLOOSE\",`(${tr[rr.NUMERICIDENTIFIERLOOSE]})\\\\.(${tr[rr.NUMERICIDENTIFIERLOOSE]})\\\\.(${tr[rr.NUMERICIDENTIFIERLOOSE]})`);Gr(\"PRERELEASEIDENTIFIER\",`(?:${tr[rr.NUMERICIDENTIFIER]}|${tr[rr.NONNUMERICIDENTIFIER]})`);Gr(\"PRERELEASEIDENTIFIERLOOSE\",`(?:${tr[rr.NUMERICIDENTIFIERLOOSE]}|${tr[rr.NONNUMERICIDENTIFIER]})`);Gr(\"PRERELEASE\",`(?:-(${tr[rr.PRERELEASEIDENTIFIER]}(?:\\\\.${tr[rr.PRERELEASEIDENTIFIER]})*))`);Gr(\"PRERELEASELOOSE\",`(?:-?(${tr[rr.PRERELEASEIDENTIFIERLOOSE]}(?:\\\\.${tr[rr.PRERELEASEIDENTIFIERLOOSE]})*))`);Gr(\"BUILDIDENTIFIER\",`${SL}+`);Gr(\"BUILD\",`(?:\\\\+(${tr[rr.BUILDIDENTIFIER]}(?:\\\\.${tr[rr.BUILDIDENTIFIER]})*))`);Gr(\"FULLPLAIN\",`v?${tr[rr.MAINVERSION]}${tr[rr.PRERELEASE]}?${tr[rr.BUILD]}?`);Gr(\"FULL\",`^${tr[rr.FULLPLAIN]}$`);Gr(\"LOOSEPLAIN\",`[v=\\\\s]*${tr[rr.MAINVERSIONLOOSE]}${tr[rr.PRERELEASELOOSE]}?${tr[rr.BUILD]}?`);Gr(\"LOOSE\",`^${tr[rr.LOOSEPLAIN]}$`);Gr(\"GTLT\",\"((?:<|>)?=?)\");Gr(\"XRANGEIDENTIFIERLOOSE\",`${tr[rr.NUMERICIDENTIFIERLOOSE]}|x|X|\\\\*`);Gr(\"XRANGEIDENTIFIER\",`${tr[rr.NUMERICIDENTIFIER]}|x|X|\\\\*`);Gr(\"XRANGEPLAIN\",`[v=\\\\s]*(${tr[rr.XRANGEIDENTIFIER]})(?:\\\\.(${tr[rr.XRANGEIDENTIFIER]})(?:\\\\.(${tr[rr.XRANGEIDENTIFIER]})(?:${tr[rr.PRERELEASE]})?${tr[rr.BUILD]}?)?)?`);Gr(\"XRANGEPLAINLOOSE\",`[v=\\\\s]*(${tr[rr.XRANGEIDENTIFIERLOOSE]})(?:\\\\.(${tr[rr.XRANGEIDENTIFIERLOOSE]})(?:\\\\.(${tr[rr.XRANGEIDENTIFIERLOOSE]})(?:${tr[rr.PRERELEASELOOSE]})?${tr[rr.BUILD]}?)?)?`);Gr(\"XRANGE\",`^${tr[rr.GTLT]}\\\\s*${tr[rr.XRANGEPLAIN]}$`);Gr(\"XRANGELOOSE\",`^${tr[rr.GTLT]}\\\\s*${tr[rr.XRANGEPLAINLOOSE]}$`);Gr(\"COERCEPLAIN\",`(^|[^\\\\d])(\\\\d{1,${PL}})(?:\\\\.(\\\\d{1,${PL}}))?(?:\\\\.(\\\\d{1,${PL}}))?`);Gr(\"COERCE\",`${tr[rr.COERCEPLAIN]}(?:$|[^\\\\d])`);Gr(\"COERCEFULL\",tr[rr.COERCEPLAIN]+`(?:${tr[rr.PRERELEASE]})?(?:${tr[rr.BUILD]})?(?:$|[^\\\\d])`);Gr(\"COERCERTL\",tr[rr.COERCE],!0);Gr(\"COERCERTLFULL\",tr[rr.COERCEFULL],!0);Gr(\"LONETILDE\",\"(?:~>?)\");Gr(\"TILDETRIM\",`(\\\\s*)${tr[rr.LONETILDE]}\\\\s+`,!0);Cf.tildeTrimReplace=\"$1~\";Gr(\"TILDE\",`^${tr[rr.LONETILDE]}${tr[rr.XRANGEPLAIN]}$`);Gr(\"TILDELOOSE\",`^${tr[rr.LONETILDE]}${tr[rr.XRANGEPLAINLOOSE]}$`);Gr(\"LONECARET\",\"(?:\\\\^)\");Gr(\"CARETTRIM\",`(\\\\s*)${tr[rr.LONECARET]}\\\\s+`,!0);Cf.caretTrimReplace=\"$1^\";Gr(\"CARET\",`^${tr[rr.LONECARET]}${tr[rr.XRANGEPLAIN]}$`);Gr(\"CARETLOOSE\",`^${tr[rr.LONECARET]}${tr[rr.XRANGEPLAINLOOSE]}$`);Gr(\"COMPARATORLOOSE\",`^${tr[rr.GTLT]}\\\\s*(${tr[rr.LOOSEPLAIN]})$|^$`);Gr(\"COMPARATOR\",`^${tr[rr.GTLT]}\\\\s*(${tr[rr.FULLPLAIN]})$|^$`);Gr(\"COMPARATORTRIM\",`(\\\\s*)${tr[rr.GTLT]}\\\\s*(${tr[rr.LOOSEPLAIN]}|${tr[rr.XRANGEPLAIN]})`,!0);Cf.comparatorTrimReplace=\"$1$2$3\";Gr(\"HYPHENRANGE\",`^\\\\s*(${tr[rr.XRANGEPLAIN]})\\\\s+-\\\\s+(${tr[rr.XRANGEPLAIN]})\\\\s*$`);Gr(\"HYPHENRANGELOOSE\",`^\\\\s*(${tr[rr.XRANGEPLAINLOOSE]})\\\\s+-\\\\s+(${tr[rr.XRANGEPLAINLOOSE]})\\\\s*$`);Gr(\"STAR\",\"(<|>)?=?\\\\s*\\\\*\");Gr(\"GTE0\",\"^\\\\s*>=\\\\s*0\\\\.0\\\\.0\\\\s*$\");Gr(\"GTE0PRE\",\"^\\\\s*>=\\\\s*0\\\\.0\\\\.0-0\\\\s*$\")});var GP=_((dkt,jz)=>{var mje=Object.freeze({loose:!0}),yje=Object.freeze({}),Eje=t=>t?typeof t!=\"object\"?mje:t:yje;jz.exports=Eje});var xL=_((mkt,Yz)=>{var Gz=/^[0-9]+$/,Wz=(t,e)=>{let r=Gz.test(t),o=Gz.test(e);return r&&o&&(t=+t,e=+e),t===e?0:r&&!o?-1:o&&!r?1:t<e?-1:1},Cje=(t,e)=>Wz(e,t);Yz.exports={compareIdentifiers:Wz,rcompareIdentifiers:Cje}});var Eo=_((ykt,Jz)=>{var WP=Rw(),{MAX_LENGTH:Kz,MAX_SAFE_INTEGER:YP}=Fw(),{safeRe:Vz,t:zz}=bm(),Ije=GP(),{compareIdentifiers:km}=xL(),bL=class t{constructor(e,r){if(r=Ije(r),e instanceof t){if(e.loose===!!r.loose&&e.includePrerelease===!!r.includePrerelease)return e;e=e.version}else if(typeof e!=\"string\")throw new TypeError(`Invalid version. Must be a string. Got type \"${typeof e}\".`);if(e.length>Kz)throw new TypeError(`version is longer than ${Kz} characters`);WP(\"SemVer\",e,r),this.options=r,this.loose=!!r.loose,this.includePrerelease=!!r.includePrerelease;let o=e.trim().match(r.loose?Vz[zz.LOOSE]:Vz[zz.FULL]);if(!o)throw new TypeError(`Invalid Version: ${e}`);if(this.raw=e,this.major=+o[1],this.minor=+o[2],this.patch=+o[3],this.major>YP||this.major<0)throw new TypeError(\"Invalid major version\");if(this.minor>YP||this.minor<0)throw new TypeError(\"Invalid minor version\");if(this.patch>YP||this.patch<0)throw new TypeError(\"Invalid patch version\");o[4]?this.prerelease=o[4].split(\".\").map(a=>{if(/^[0-9]+$/.test(a)){let n=+a;if(n>=0&&n<YP)return n}return a}):this.prerelease=[],this.build=o[5]?o[5].split(\".\"):[],this.format()}format(){return this.version=`${this.major}.${this.minor}.${this.patch}`,this.prerelease.length&&(this.version+=`-${this.prerelease.join(\".\")}`),this.version}toString(){return this.version}compare(e){if(WP(\"SemVer.compare\",this.version,this.options,e),!(e instanceof t)){if(typeof e==\"string\"&&e===this.version)return 0;e=new t(e,this.options)}return e.version===this.version?0:this.compareMain(e)||this.comparePre(e)}compareMain(e){return e instanceof t||(e=new t(e,this.options)),km(this.major,e.major)||km(this.minor,e.minor)||km(this.patch,e.patch)}comparePre(e){if(e instanceof t||(e=new t(e,this.options)),this.prerelease.length&&!e.prerelease.length)return-1;if(!this.prerelease.length&&e.prerelease.length)return 1;if(!this.prerelease.length&&!e.prerelease.length)return 0;let r=0;do{let o=this.prerelease[r],a=e.prerelease[r];if(WP(\"prerelease compare\",r,o,a),o===void 0&&a===void 0)return 0;if(a===void 0)return 1;if(o===void 0)return-1;if(o===a)continue;return km(o,a)}while(++r)}compareBuild(e){e instanceof t||(e=new t(e,this.options));let r=0;do{let o=this.build[r],a=e.build[r];if(WP(\"prerelease compare\",r,o,a),o===void 0&&a===void 0)return 0;if(a===void 0)return 1;if(o===void 0)return-1;if(o===a)continue;return km(o,a)}while(++r)}inc(e,r,o){switch(e){case\"premajor\":this.prerelease.length=0,this.patch=0,this.minor=0,this.major++,this.inc(\"pre\",r,o);break;case\"preminor\":this.prerelease.length=0,this.patch=0,this.minor++,this.inc(\"pre\",r,o);break;case\"prepatch\":this.prerelease.length=0,this.inc(\"patch\",r,o),this.inc(\"pre\",r,o);break;case\"prerelease\":this.prerelease.length===0&&this.inc(\"patch\",r,o),this.inc(\"pre\",r,o);break;case\"major\":(this.minor!==0||this.patch!==0||this.prerelease.length===0)&&this.major++,this.minor=0,this.patch=0,this.prerelease=[];break;case\"minor\":(this.patch!==0||this.prerelease.length===0)&&this.minor++,this.patch=0,this.prerelease=[];break;case\"patch\":this.prerelease.length===0&&this.patch++,this.prerelease=[];break;case\"pre\":{let a=Number(o)?1:0;if(!r&&o===!1)throw new Error(\"invalid increment argument: identifier is empty\");if(this.prerelease.length===0)this.prerelease=[a];else{let n=this.prerelease.length;for(;--n>=0;)typeof this.prerelease[n]==\"number\"&&(this.prerelease[n]++,n=-2);if(n===-1){if(r===this.prerelease.join(\".\")&&o===!1)throw new Error(\"invalid increment argument: identifier already exists\");this.prerelease.push(a)}}if(r){let n=[r,a];o===!1&&(n=[r]),km(this.prerelease[0],r)===0?isNaN(this.prerelease[1])&&(this.prerelease=n):this.prerelease=n}break}default:throw new Error(`invalid increment argument: ${e}`)}return this.raw=this.format(),this.build.length&&(this.raw+=`+${this.build.join(\".\")}`),this}};Jz.exports=bL});var cg=_((Ekt,Zz)=>{var Xz=Eo(),wje=(t,e,r=!1)=>{if(t instanceof Xz)return t;try{return new Xz(t,e)}catch(o){if(!r)return null;throw o}};Zz.exports=wje});var eJ=_((Ckt,$z)=>{var Bje=cg(),vje=(t,e)=>{let r=Bje(t,e);return r?r.version:null};$z.exports=vje});var rJ=_((Ikt,tJ)=>{var Dje=cg(),Pje=(t,e)=>{let r=Dje(t.trim().replace(/^[=v]+/,\"\"),e);return r?r.version:null};tJ.exports=Pje});var sJ=_((wkt,iJ)=>{var nJ=Eo(),Sje=(t,e,r,o,a)=>{typeof r==\"string\"&&(a=o,o=r,r=void 0);try{return new nJ(t instanceof nJ?t.version:t,r).inc(e,o,a).version}catch{return null}};iJ.exports=Sje});var lJ=_((Bkt,aJ)=>{var oJ=cg(),xje=(t,e)=>{let r=oJ(t,null,!0),o=oJ(e,null,!0),a=r.compare(o);if(a===0)return null;let n=a>0,u=n?r:o,A=n?o:r,p=!!u.prerelease.length;if(!!A.prerelease.length&&!p)return!A.patch&&!A.minor?\"major\":u.patch?\"patch\":u.minor?\"minor\":\"major\";let E=p?\"pre\":\"\";return r.major!==o.major?E+\"major\":r.minor!==o.minor?E+\"minor\":r.patch!==o.patch?E+\"patch\":\"prerelease\"};aJ.exports=xje});var uJ=_((vkt,cJ)=>{var bje=Eo(),kje=(t,e)=>new bje(t,e).major;cJ.exports=kje});var fJ=_((Dkt,AJ)=>{var Qje=Eo(),Fje=(t,e)=>new Qje(t,e).minor;AJ.exports=Fje});var hJ=_((Pkt,pJ)=>{var Rje=Eo(),Tje=(t,e)=>new Rje(t,e).patch;pJ.exports=Tje});var dJ=_((Skt,gJ)=>{var Lje=cg(),Nje=(t,e)=>{let r=Lje(t,e);return r&&r.prerelease.length?r.prerelease:null};gJ.exports=Nje});var Ml=_((xkt,yJ)=>{var mJ=Eo(),Oje=(t,e,r)=>new mJ(t,r).compare(new mJ(e,r));yJ.exports=Oje});var CJ=_((bkt,EJ)=>{var Mje=Ml(),Uje=(t,e,r)=>Mje(e,t,r);EJ.exports=Uje});var wJ=_((kkt,IJ)=>{var _je=Ml(),Hje=(t,e)=>_je(t,e,!0);IJ.exports=Hje});var KP=_((Qkt,vJ)=>{var BJ=Eo(),qje=(t,e,r)=>{let o=new BJ(t,r),a=new BJ(e,r);return o.compare(a)||o.compareBuild(a)};vJ.exports=qje});var PJ=_((Fkt,DJ)=>{var jje=KP(),Gje=(t,e)=>t.sort((r,o)=>jje(r,o,e));DJ.exports=Gje});var xJ=_((Rkt,SJ)=>{var Wje=KP(),Yje=(t,e)=>t.sort((r,o)=>Wje(o,r,e));SJ.exports=Yje});var Tw=_((Tkt,bJ)=>{var Kje=Ml(),Vje=(t,e,r)=>Kje(t,e,r)>0;bJ.exports=Vje});var VP=_((Lkt,kJ)=>{var zje=Ml(),Jje=(t,e,r)=>zje(t,e,r)<0;kJ.exports=Jje});var kL=_((Nkt,QJ)=>{var Xje=Ml(),Zje=(t,e,r)=>Xje(t,e,r)===0;QJ.exports=Zje});var QL=_((Okt,FJ)=>{var $je=Ml(),e9e=(t,e,r)=>$je(t,e,r)!==0;FJ.exports=e9e});var zP=_((Mkt,RJ)=>{var t9e=Ml(),r9e=(t,e,r)=>t9e(t,e,r)>=0;RJ.exports=r9e});var JP=_((Ukt,TJ)=>{var n9e=Ml(),i9e=(t,e,r)=>n9e(t,e,r)<=0;TJ.exports=i9e});var FL=_((_kt,LJ)=>{var s9e=kL(),o9e=QL(),a9e=Tw(),l9e=zP(),c9e=VP(),u9e=JP(),A9e=(t,e,r,o)=>{switch(e){case\"===\":return typeof t==\"object\"&&(t=t.version),typeof r==\"object\"&&(r=r.version),t===r;case\"!==\":return typeof t==\"object\"&&(t=t.version),typeof r==\"object\"&&(r=r.version),t!==r;case\"\":case\"=\":case\"==\":return s9e(t,r,o);case\"!=\":return o9e(t,r,o);case\">\":return a9e(t,r,o);case\">=\":return l9e(t,r,o);case\"<\":return c9e(t,r,o);case\"<=\":return u9e(t,r,o);default:throw new TypeError(`Invalid operator: ${e}`)}};LJ.exports=A9e});var OJ=_((Hkt,NJ)=>{var f9e=Eo(),p9e=cg(),{safeRe:XP,t:ZP}=bm(),h9e=(t,e)=>{if(t instanceof f9e)return t;if(typeof t==\"number\"&&(t=String(t)),typeof t!=\"string\")return null;e=e||{};let r=null;if(!e.rtl)r=t.match(e.includePrerelease?XP[ZP.COERCEFULL]:XP[ZP.COERCE]);else{let p=e.includePrerelease?XP[ZP.COERCERTLFULL]:XP[ZP.COERCERTL],h;for(;(h=p.exec(t))&&(!r||r.index+r[0].length!==t.length);)(!r||h.index+h[0].length!==r.index+r[0].length)&&(r=h),p.lastIndex=h.index+h[1].length+h[2].length;p.lastIndex=-1}if(r===null)return null;let o=r[2],a=r[3]||\"0\",n=r[4]||\"0\",u=e.includePrerelease&&r[5]?`-${r[5]}`:\"\",A=e.includePrerelease&&r[6]?`+${r[6]}`:\"\";return p9e(`${o}.${a}.${n}${u}${A}`,e)};NJ.exports=h9e});var UJ=_((qkt,MJ)=>{\"use strict\";MJ.exports=function(t){t.prototype[Symbol.iterator]=function*(){for(let e=this.head;e;e=e.next)yield e.value}}});var $P=_((jkt,_J)=>{\"use strict\";_J.exports=xn;xn.Node=ug;xn.create=xn;function xn(t){var e=this;if(e instanceof xn||(e=new xn),e.tail=null,e.head=null,e.length=0,t&&typeof t.forEach==\"function\")t.forEach(function(a){e.push(a)});else if(arguments.length>0)for(var r=0,o=arguments.length;r<o;r++)e.push(arguments[r]);return e}xn.prototype.removeNode=function(t){if(t.list!==this)throw new Error(\"removing node which does not belong to this list\");var e=t.next,r=t.prev;return e&&(e.prev=r),r&&(r.next=e),t===this.head&&(this.head=e),t===this.tail&&(this.tail=r),t.list.length--,t.next=null,t.prev=null,t.list=null,e};xn.prototype.unshiftNode=function(t){if(t!==this.head){t.list&&t.list.removeNode(t);var e=this.head;t.list=this,t.next=e,e&&(e.prev=t),this.head=t,this.tail||(this.tail=t),this.length++}};xn.prototype.pushNode=function(t){if(t!==this.tail){t.list&&t.list.removeNode(t);var e=this.tail;t.list=this,t.prev=e,e&&(e.next=t),this.tail=t,this.head||(this.head=t),this.length++}};xn.prototype.push=function(){for(var t=0,e=arguments.length;t<e;t++)d9e(this,arguments[t]);return this.length};xn.prototype.unshift=function(){for(var t=0,e=arguments.length;t<e;t++)m9e(this,arguments[t]);return this.length};xn.prototype.pop=function(){if(this.tail){var t=this.tail.value;return this.tail=this.tail.prev,this.tail?this.tail.next=null:this.head=null,this.length--,t}};xn.prototype.shift=function(){if(this.head){var t=this.head.value;return this.head=this.head.next,this.head?this.head.prev=null:this.tail=null,this.length--,t}};xn.prototype.forEach=function(t,e){e=e||this;for(var r=this.head,o=0;r!==null;o++)t.call(e,r.value,o,this),r=r.next};xn.prototype.forEachReverse=function(t,e){e=e||this;for(var r=this.tail,o=this.length-1;r!==null;o--)t.call(e,r.value,o,this),r=r.prev};xn.prototype.get=function(t){for(var e=0,r=this.head;r!==null&&e<t;e++)r=r.next;if(e===t&&r!==null)return r.value};xn.prototype.getReverse=function(t){for(var e=0,r=this.tail;r!==null&&e<t;e++)r=r.prev;if(e===t&&r!==null)return r.value};xn.prototype.map=function(t,e){e=e||this;for(var r=new xn,o=this.head;o!==null;)r.push(t.call(e,o.value,this)),o=o.next;return r};xn.prototype.mapReverse=function(t,e){e=e||this;for(var r=new xn,o=this.tail;o!==null;)r.push(t.call(e,o.value,this)),o=o.prev;return r};xn.prototype.reduce=function(t,e){var r,o=this.head;if(arguments.length>1)r=e;else if(this.head)o=this.head.next,r=this.head.value;else throw new TypeError(\"Reduce of empty list with no initial value\");for(var a=0;o!==null;a++)r=t(r,o.value,a),o=o.next;return r};xn.prototype.reduceReverse=function(t,e){var r,o=this.tail;if(arguments.length>1)r=e;else if(this.tail)o=this.tail.prev,r=this.tail.value;else throw new TypeError(\"Reduce of empty list with no initial value\");for(var a=this.length-1;o!==null;a--)r=t(r,o.value,a),o=o.prev;return r};xn.prototype.toArray=function(){for(var t=new Array(this.length),e=0,r=this.head;r!==null;e++)t[e]=r.value,r=r.next;return t};xn.prototype.toArrayReverse=function(){for(var t=new Array(this.length),e=0,r=this.tail;r!==null;e++)t[e]=r.value,r=r.prev;return t};xn.prototype.slice=function(t,e){e=e||this.length,e<0&&(e+=this.length),t=t||0,t<0&&(t+=this.length);var r=new xn;if(e<t||e<0)return r;t<0&&(t=0),e>this.length&&(e=this.length);for(var o=0,a=this.head;a!==null&&o<t;o++)a=a.next;for(;a!==null&&o<e;o++,a=a.next)r.push(a.value);return r};xn.prototype.sliceReverse=function(t,e){e=e||this.length,e<0&&(e+=this.length),t=t||0,t<0&&(t+=this.length);var r=new xn;if(e<t||e<0)return r;t<0&&(t=0),e>this.length&&(e=this.length);for(var o=this.length,a=this.tail;a!==null&&o>e;o--)a=a.prev;for(;a!==null&&o>t;o--,a=a.prev)r.push(a.value);return r};xn.prototype.splice=function(t,e,...r){t>this.length&&(t=this.length-1),t<0&&(t=this.length+t);for(var o=0,a=this.head;a!==null&&o<t;o++)a=a.next;for(var n=[],o=0;a&&o<e;o++)n.push(a.value),a=this.removeNode(a);a===null&&(a=this.tail),a!==this.head&&a!==this.tail&&(a=a.prev);for(var o=0;o<r.length;o++)a=g9e(this,a,r[o]);return n};xn.prototype.reverse=function(){for(var t=this.head,e=this.tail,r=t;r!==null;r=r.prev){var o=r.prev;r.prev=r.next,r.next=o}return this.head=e,this.tail=t,this};function g9e(t,e,r){var o=e===t.head?new ug(r,null,e,t):new ug(r,e,e.next,t);return o.next===null&&(t.tail=o),o.prev===null&&(t.head=o),t.length++,o}function d9e(t,e){t.tail=new ug(e,t.tail,null,t),t.head||(t.head=t.tail),t.length++}function m9e(t,e){t.head=new ug(e,null,t.head,t),t.tail||(t.tail=t.head),t.length++}function ug(t,e,r,o){if(!(this instanceof ug))return new ug(t,e,r,o);this.list=o,this.value=t,e?(e.next=this,this.prev=e):this.prev=null,r?(r.prev=this,this.next=r):this.next=null}try{UJ()(xn)}catch{}});var WJ=_((Gkt,GJ)=>{\"use strict\";var y9e=$P(),Ag=Symbol(\"max\"),wf=Symbol(\"length\"),Qm=Symbol(\"lengthCalculator\"),Nw=Symbol(\"allowStale\"),fg=Symbol(\"maxAge\"),If=Symbol(\"dispose\"),HJ=Symbol(\"noDisposeOnSet\"),Ds=Symbol(\"lruList\"),Gc=Symbol(\"cache\"),jJ=Symbol(\"updateAgeOnGet\"),RL=()=>1,LL=class{constructor(e){if(typeof e==\"number\"&&(e={max:e}),e||(e={}),e.max&&(typeof e.max!=\"number\"||e.max<0))throw new TypeError(\"max must be a non-negative number\");let r=this[Ag]=e.max||1/0,o=e.length||RL;if(this[Qm]=typeof o!=\"function\"?RL:o,this[Nw]=e.stale||!1,e.maxAge&&typeof e.maxAge!=\"number\")throw new TypeError(\"maxAge must be a number\");this[fg]=e.maxAge||0,this[If]=e.dispose,this[HJ]=e.noDisposeOnSet||!1,this[jJ]=e.updateAgeOnGet||!1,this.reset()}set max(e){if(typeof e!=\"number\"||e<0)throw new TypeError(\"max must be a non-negative number\");this[Ag]=e||1/0,Lw(this)}get max(){return this[Ag]}set allowStale(e){this[Nw]=!!e}get allowStale(){return this[Nw]}set maxAge(e){if(typeof e!=\"number\")throw new TypeError(\"maxAge must be a non-negative number\");this[fg]=e,Lw(this)}get maxAge(){return this[fg]}set lengthCalculator(e){typeof e!=\"function\"&&(e=RL),e!==this[Qm]&&(this[Qm]=e,this[wf]=0,this[Ds].forEach(r=>{r.length=this[Qm](r.value,r.key),this[wf]+=r.length})),Lw(this)}get lengthCalculator(){return this[Qm]}get length(){return this[wf]}get itemCount(){return this[Ds].length}rforEach(e,r){r=r||this;for(let o=this[Ds].tail;o!==null;){let a=o.prev;qJ(this,e,o,r),o=a}}forEach(e,r){r=r||this;for(let o=this[Ds].head;o!==null;){let a=o.next;qJ(this,e,o,r),o=a}}keys(){return this[Ds].toArray().map(e=>e.key)}values(){return this[Ds].toArray().map(e=>e.value)}reset(){this[If]&&this[Ds]&&this[Ds].length&&this[Ds].forEach(e=>this[If](e.key,e.value)),this[Gc]=new Map,this[Ds]=new y9e,this[wf]=0}dump(){return this[Ds].map(e=>eS(this,e)?!1:{k:e.key,v:e.value,e:e.now+(e.maxAge||0)}).toArray().filter(e=>e)}dumpLru(){return this[Ds]}set(e,r,o){if(o=o||this[fg],o&&typeof o!=\"number\")throw new TypeError(\"maxAge must be a number\");let a=o?Date.now():0,n=this[Qm](r,e);if(this[Gc].has(e)){if(n>this[Ag])return Fm(this,this[Gc].get(e)),!1;let p=this[Gc].get(e).value;return this[If]&&(this[HJ]||this[If](e,p.value)),p.now=a,p.maxAge=o,p.value=r,this[wf]+=n-p.length,p.length=n,this.get(e),Lw(this),!0}let u=new NL(e,r,n,a,o);return u.length>this[Ag]?(this[If]&&this[If](e,r),!1):(this[wf]+=u.length,this[Ds].unshift(u),this[Gc].set(e,this[Ds].head),Lw(this),!0)}has(e){if(!this[Gc].has(e))return!1;let r=this[Gc].get(e).value;return!eS(this,r)}get(e){return TL(this,e,!0)}peek(e){return TL(this,e,!1)}pop(){let e=this[Ds].tail;return e?(Fm(this,e),e.value):null}del(e){Fm(this,this[Gc].get(e))}load(e){this.reset();let r=Date.now();for(let o=e.length-1;o>=0;o--){let a=e[o],n=a.e||0;if(n===0)this.set(a.k,a.v);else{let u=n-r;u>0&&this.set(a.k,a.v,u)}}}prune(){this[Gc].forEach((e,r)=>TL(this,r,!1))}},TL=(t,e,r)=>{let o=t[Gc].get(e);if(o){let a=o.value;if(eS(t,a)){if(Fm(t,o),!t[Nw])return}else r&&(t[jJ]&&(o.value.now=Date.now()),t[Ds].unshiftNode(o));return a.value}},eS=(t,e)=>{if(!e||!e.maxAge&&!t[fg])return!1;let r=Date.now()-e.now;return e.maxAge?r>e.maxAge:t[fg]&&r>t[fg]},Lw=t=>{if(t[wf]>t[Ag])for(let e=t[Ds].tail;t[wf]>t[Ag]&&e!==null;){let r=e.prev;Fm(t,e),e=r}},Fm=(t,e)=>{if(e){let r=e.value;t[If]&&t[If](r.key,r.value),t[wf]-=r.length,t[Gc].delete(r.key),t[Ds].removeNode(e)}},NL=class{constructor(e,r,o,a,n){this.key=e,this.value=r,this.length=o,this.now=a,this.maxAge=n||0}},qJ=(t,e,r,o)=>{let a=r.value;eS(t,a)&&(Fm(t,r),t[Nw]||(a=void 0)),a&&e.call(o,a.value,a.key,t)};GJ.exports=LL});var Ul=_((Wkt,zJ)=>{var OL=class t{constructor(e,r){if(r=C9e(r),e instanceof t)return e.loose===!!r.loose&&e.includePrerelease===!!r.includePrerelease?e:new t(e.raw,r);if(e instanceof ML)return this.raw=e.value,this.set=[[e]],this.format(),this;if(this.options=r,this.loose=!!r.loose,this.includePrerelease=!!r.includePrerelease,this.raw=e.trim().split(/\\s+/).join(\" \"),this.set=this.raw.split(\"||\").map(o=>this.parseRange(o.trim())).filter(o=>o.length),!this.set.length)throw new TypeError(`Invalid SemVer Range: ${this.raw}`);if(this.set.length>1){let o=this.set[0];if(this.set=this.set.filter(a=>!KJ(a[0])),this.set.length===0)this.set=[o];else if(this.set.length>1){for(let a of this.set)if(a.length===1&&S9e(a[0])){this.set=[a];break}}}this.format()}format(){return this.range=this.set.map(e=>e.join(\" \").trim()).join(\"||\").trim(),this.range}toString(){return this.range}parseRange(e){let o=((this.options.includePrerelease&&D9e)|(this.options.loose&&P9e))+\":\"+e,a=YJ.get(o);if(a)return a;let n=this.options.loose,u=n?xa[zo.HYPHENRANGELOOSE]:xa[zo.HYPHENRANGE];e=e.replace(u,O9e(this.options.includePrerelease)),gi(\"hyphen replace\",e),e=e.replace(xa[zo.COMPARATORTRIM],w9e),gi(\"comparator trim\",e),e=e.replace(xa[zo.TILDETRIM],B9e),gi(\"tilde trim\",e),e=e.replace(xa[zo.CARETTRIM],v9e),gi(\"caret trim\",e);let A=e.split(\" \").map(w=>x9e(w,this.options)).join(\" \").split(/\\s+/).map(w=>N9e(w,this.options));n&&(A=A.filter(w=>(gi(\"loose invalid filter\",w,this.options),!!w.match(xa[zo.COMPARATORLOOSE])))),gi(\"range list\",A);let p=new Map,h=A.map(w=>new ML(w,this.options));for(let w of h){if(KJ(w))return[w];p.set(w.value,w)}p.size>1&&p.has(\"\")&&p.delete(\"\");let E=[...p.values()];return YJ.set(o,E),E}intersects(e,r){if(!(e instanceof t))throw new TypeError(\"a Range is required\");return this.set.some(o=>VJ(o,r)&&e.set.some(a=>VJ(a,r)&&o.every(n=>a.every(u=>n.intersects(u,r)))))}test(e){if(!e)return!1;if(typeof e==\"string\")try{e=new I9e(e,this.options)}catch{return!1}for(let r=0;r<this.set.length;r++)if(M9e(this.set[r],e,this.options))return!0;return!1}};zJ.exports=OL;var E9e=WJ(),YJ=new E9e({max:1e3}),C9e=GP(),ML=Ow(),gi=Rw(),I9e=Eo(),{safeRe:xa,t:zo,comparatorTrimReplace:w9e,tildeTrimReplace:B9e,caretTrimReplace:v9e}=bm(),{FLAG_INCLUDE_PRERELEASE:D9e,FLAG_LOOSE:P9e}=Fw(),KJ=t=>t.value===\"<0.0.0-0\",S9e=t=>t.value===\"\",VJ=(t,e)=>{let r=!0,o=t.slice(),a=o.pop();for(;r&&o.length;)r=o.every(n=>a.intersects(n,e)),a=o.pop();return r},x9e=(t,e)=>(gi(\"comp\",t,e),t=Q9e(t,e),gi(\"caret\",t),t=b9e(t,e),gi(\"tildes\",t),t=R9e(t,e),gi(\"xrange\",t),t=L9e(t,e),gi(\"stars\",t),t),Jo=t=>!t||t.toLowerCase()===\"x\"||t===\"*\",b9e=(t,e)=>t.trim().split(/\\s+/).map(r=>k9e(r,e)).join(\" \"),k9e=(t,e)=>{let r=e.loose?xa[zo.TILDELOOSE]:xa[zo.TILDE];return t.replace(r,(o,a,n,u,A)=>{gi(\"tilde\",t,o,a,n,u,A);let p;return Jo(a)?p=\"\":Jo(n)?p=`>=${a}.0.0 <${+a+1}.0.0-0`:Jo(u)?p=`>=${a}.${n}.0 <${a}.${+n+1}.0-0`:A?(gi(\"replaceTilde pr\",A),p=`>=${a}.${n}.${u}-${A} <${a}.${+n+1}.0-0`):p=`>=${a}.${n}.${u} <${a}.${+n+1}.0-0`,gi(\"tilde return\",p),p})},Q9e=(t,e)=>t.trim().split(/\\s+/).map(r=>F9e(r,e)).join(\" \"),F9e=(t,e)=>{gi(\"caret\",t,e);let r=e.loose?xa[zo.CARETLOOSE]:xa[zo.CARET],o=e.includePrerelease?\"-0\":\"\";return t.replace(r,(a,n,u,A,p)=>{gi(\"caret\",t,a,n,u,A,p);let h;return Jo(n)?h=\"\":Jo(u)?h=`>=${n}.0.0${o} <${+n+1}.0.0-0`:Jo(A)?n===\"0\"?h=`>=${n}.${u}.0${o} <${n}.${+u+1}.0-0`:h=`>=${n}.${u}.0${o} <${+n+1}.0.0-0`:p?(gi(\"replaceCaret pr\",p),n===\"0\"?u===\"0\"?h=`>=${n}.${u}.${A}-${p} <${n}.${u}.${+A+1}-0`:h=`>=${n}.${u}.${A}-${p} <${n}.${+u+1}.0-0`:h=`>=${n}.${u}.${A}-${p} <${+n+1}.0.0-0`):(gi(\"no pr\"),n===\"0\"?u===\"0\"?h=`>=${n}.${u}.${A}${o} <${n}.${u}.${+A+1}-0`:h=`>=${n}.${u}.${A}${o} <${n}.${+u+1}.0-0`:h=`>=${n}.${u}.${A} <${+n+1}.0.0-0`),gi(\"caret return\",h),h})},R9e=(t,e)=>(gi(\"replaceXRanges\",t,e),t.split(/\\s+/).map(r=>T9e(r,e)).join(\" \")),T9e=(t,e)=>{t=t.trim();let r=e.loose?xa[zo.XRANGELOOSE]:xa[zo.XRANGE];return t.replace(r,(o,a,n,u,A,p)=>{gi(\"xRange\",t,o,a,n,u,A,p);let h=Jo(n),E=h||Jo(u),w=E||Jo(A),D=w;return a===\"=\"&&D&&(a=\"\"),p=e.includePrerelease?\"-0\":\"\",h?a===\">\"||a===\"<\"?o=\"<0.0.0-0\":o=\"*\":a&&D?(E&&(u=0),A=0,a===\">\"?(a=\">=\",E?(n=+n+1,u=0,A=0):(u=+u+1,A=0)):a===\"<=\"&&(a=\"<\",E?n=+n+1:u=+u+1),a===\"<\"&&(p=\"-0\"),o=`${a+n}.${u}.${A}${p}`):E?o=`>=${n}.0.0${p} <${+n+1}.0.0-0`:w&&(o=`>=${n}.${u}.0${p} <${n}.${+u+1}.0-0`),gi(\"xRange return\",o),o})},L9e=(t,e)=>(gi(\"replaceStars\",t,e),t.trim().replace(xa[zo.STAR],\"\")),N9e=(t,e)=>(gi(\"replaceGTE0\",t,e),t.trim().replace(xa[e.includePrerelease?zo.GTE0PRE:zo.GTE0],\"\")),O9e=t=>(e,r,o,a,n,u,A,p,h,E,w,D,b)=>(Jo(o)?r=\"\":Jo(a)?r=`>=${o}.0.0${t?\"-0\":\"\"}`:Jo(n)?r=`>=${o}.${a}.0${t?\"-0\":\"\"}`:u?r=`>=${r}`:r=`>=${r}${t?\"-0\":\"\"}`,Jo(h)?p=\"\":Jo(E)?p=`<${+h+1}.0.0-0`:Jo(w)?p=`<${h}.${+E+1}.0-0`:D?p=`<=${h}.${E}.${w}-${D}`:t?p=`<${h}.${E}.${+w+1}-0`:p=`<=${p}`,`${r} ${p}`.trim()),M9e=(t,e,r)=>{for(let o=0;o<t.length;o++)if(!t[o].test(e))return!1;if(e.prerelease.length&&!r.includePrerelease){for(let o=0;o<t.length;o++)if(gi(t[o].semver),t[o].semver!==ML.ANY&&t[o].semver.prerelease.length>0){let a=t[o].semver;if(a.major===e.major&&a.minor===e.minor&&a.patch===e.patch)return!0}return!1}return!0}});var Ow=_((Ykt,tX)=>{var Mw=Symbol(\"SemVer ANY\"),HL=class t{static get ANY(){return Mw}constructor(e,r){if(r=JJ(r),e instanceof t){if(e.loose===!!r.loose)return e;e=e.value}e=e.trim().split(/\\s+/).join(\" \"),_L(\"comparator\",e,r),this.options=r,this.loose=!!r.loose,this.parse(e),this.semver===Mw?this.value=\"\":this.value=this.operator+this.semver.version,_L(\"comp\",this)}parse(e){let r=this.options.loose?XJ[ZJ.COMPARATORLOOSE]:XJ[ZJ.COMPARATOR],o=e.match(r);if(!o)throw new TypeError(`Invalid comparator: ${e}`);this.operator=o[1]!==void 0?o[1]:\"\",this.operator===\"=\"&&(this.operator=\"\"),o[2]?this.semver=new $J(o[2],this.options.loose):this.semver=Mw}toString(){return this.value}test(e){if(_L(\"Comparator.test\",e,this.options.loose),this.semver===Mw||e===Mw)return!0;if(typeof e==\"string\")try{e=new $J(e,this.options)}catch{return!1}return UL(e,this.operator,this.semver,this.options)}intersects(e,r){if(!(e instanceof t))throw new TypeError(\"a Comparator is required\");return this.operator===\"\"?this.value===\"\"?!0:new eX(e.value,r).test(this.value):e.operator===\"\"?e.value===\"\"?!0:new eX(this.value,r).test(e.semver):(r=JJ(r),r.includePrerelease&&(this.value===\"<0.0.0-0\"||e.value===\"<0.0.0-0\")||!r.includePrerelease&&(this.value.startsWith(\"<0.0.0\")||e.value.startsWith(\"<0.0.0\"))?!1:!!(this.operator.startsWith(\">\")&&e.operator.startsWith(\">\")||this.operator.startsWith(\"<\")&&e.operator.startsWith(\"<\")||this.semver.version===e.semver.version&&this.operator.includes(\"=\")&&e.operator.includes(\"=\")||UL(this.semver,\"<\",e.semver,r)&&this.operator.startsWith(\">\")&&e.operator.startsWith(\"<\")||UL(this.semver,\">\",e.semver,r)&&this.operator.startsWith(\"<\")&&e.operator.startsWith(\">\")))}};tX.exports=HL;var JJ=GP(),{safeRe:XJ,t:ZJ}=bm(),UL=FL(),_L=Rw(),$J=Eo(),eX=Ul()});var Uw=_((Kkt,rX)=>{var U9e=Ul(),_9e=(t,e,r)=>{try{e=new U9e(e,r)}catch{return!1}return e.test(t)};rX.exports=_9e});var iX=_((Vkt,nX)=>{var H9e=Ul(),q9e=(t,e)=>new H9e(t,e).set.map(r=>r.map(o=>o.value).join(\" \").trim().split(\" \"));nX.exports=q9e});var oX=_((zkt,sX)=>{var j9e=Eo(),G9e=Ul(),W9e=(t,e,r)=>{let o=null,a=null,n=null;try{n=new G9e(e,r)}catch{return null}return t.forEach(u=>{n.test(u)&&(!o||a.compare(u)===-1)&&(o=u,a=new j9e(o,r))}),o};sX.exports=W9e});var lX=_((Jkt,aX)=>{var Y9e=Eo(),K9e=Ul(),V9e=(t,e,r)=>{let o=null,a=null,n=null;try{n=new K9e(e,r)}catch{return null}return t.forEach(u=>{n.test(u)&&(!o||a.compare(u)===1)&&(o=u,a=new Y9e(o,r))}),o};aX.exports=V9e});var AX=_((Xkt,uX)=>{var qL=Eo(),z9e=Ul(),cX=Tw(),J9e=(t,e)=>{t=new z9e(t,e);let r=new qL(\"0.0.0\");if(t.test(r)||(r=new qL(\"0.0.0-0\"),t.test(r)))return r;r=null;for(let o=0;o<t.set.length;++o){let a=t.set[o],n=null;a.forEach(u=>{let A=new qL(u.semver.version);switch(u.operator){case\">\":A.prerelease.length===0?A.patch++:A.prerelease.push(0),A.raw=A.format();case\"\":case\">=\":(!n||cX(A,n))&&(n=A);break;case\"<\":case\"<=\":break;default:throw new Error(`Unexpected operation: ${u.operator}`)}}),n&&(!r||cX(r,n))&&(r=n)}return r&&t.test(r)?r:null};uX.exports=J9e});var pX=_((Zkt,fX)=>{var X9e=Ul(),Z9e=(t,e)=>{try{return new X9e(t,e).range||\"*\"}catch{return null}};fX.exports=Z9e});var tS=_(($kt,mX)=>{var $9e=Eo(),dX=Ow(),{ANY:eGe}=dX,tGe=Ul(),rGe=Uw(),hX=Tw(),gX=VP(),nGe=JP(),iGe=zP(),sGe=(t,e,r,o)=>{t=new $9e(t,o),e=new tGe(e,o);let a,n,u,A,p;switch(r){case\">\":a=hX,n=nGe,u=gX,A=\">\",p=\">=\";break;case\"<\":a=gX,n=iGe,u=hX,A=\"<\",p=\"<=\";break;default:throw new TypeError('Must provide a hilo val of \"<\" or \">\"')}if(rGe(t,e,o))return!1;for(let h=0;h<e.set.length;++h){let E=e.set[h],w=null,D=null;if(E.forEach(b=>{b.semver===eGe&&(b=new dX(\">=0.0.0\")),w=w||b,D=D||b,a(b.semver,w.semver,o)?w=b:u(b.semver,D.semver,o)&&(D=b)}),w.operator===A||w.operator===p||(!D.operator||D.operator===A)&&n(t,D.semver))return!1;if(D.operator===p&&u(t,D.semver))return!1}return!0};mX.exports=sGe});var EX=_((eQt,yX)=>{var oGe=tS(),aGe=(t,e,r)=>oGe(t,e,\">\",r);yX.exports=aGe});var IX=_((tQt,CX)=>{var lGe=tS(),cGe=(t,e,r)=>lGe(t,e,\"<\",r);CX.exports=cGe});var vX=_((rQt,BX)=>{var wX=Ul(),uGe=(t,e,r)=>(t=new wX(t,r),e=new wX(e,r),t.intersects(e,r));BX.exports=uGe});var PX=_((nQt,DX)=>{var AGe=Uw(),fGe=Ml();DX.exports=(t,e,r)=>{let o=[],a=null,n=null,u=t.sort((E,w)=>fGe(E,w,r));for(let E of u)AGe(E,e,r)?(n=E,a||(a=E)):(n&&o.push([a,n]),n=null,a=null);a&&o.push([a,null]);let A=[];for(let[E,w]of o)E===w?A.push(E):!w&&E===u[0]?A.push(\"*\"):w?E===u[0]?A.push(`<=${w}`):A.push(`${E} - ${w}`):A.push(`>=${E}`);let p=A.join(\" || \"),h=typeof e.raw==\"string\"?e.raw:String(e);return p.length<h.length?p:e}});var FX=_((iQt,QX)=>{var SX=Ul(),WL=Ow(),{ANY:jL}=WL,_w=Uw(),YL=Ml(),pGe=(t,e,r={})=>{if(t===e)return!0;t=new SX(t,r),e=new SX(e,r);let o=!1;e:for(let a of t.set){for(let n of e.set){let u=gGe(a,n,r);if(o=o||u!==null,u)continue e}if(o)return!1}return!0},hGe=[new WL(\">=0.0.0-0\")],xX=[new WL(\">=0.0.0\")],gGe=(t,e,r)=>{if(t===e)return!0;if(t.length===1&&t[0].semver===jL){if(e.length===1&&e[0].semver===jL)return!0;r.includePrerelease?t=hGe:t=xX}if(e.length===1&&e[0].semver===jL){if(r.includePrerelease)return!0;e=xX}let o=new Set,a,n;for(let b of t)b.operator===\">\"||b.operator===\">=\"?a=bX(a,b,r):b.operator===\"<\"||b.operator===\"<=\"?n=kX(n,b,r):o.add(b.semver);if(o.size>1)return null;let u;if(a&&n){if(u=YL(a.semver,n.semver,r),u>0)return null;if(u===0&&(a.operator!==\">=\"||n.operator!==\"<=\"))return null}for(let b of o){if(a&&!_w(b,String(a),r)||n&&!_w(b,String(n),r))return null;for(let C of e)if(!_w(b,String(C),r))return!1;return!0}let A,p,h,E,w=n&&!r.includePrerelease&&n.semver.prerelease.length?n.semver:!1,D=a&&!r.includePrerelease&&a.semver.prerelease.length?a.semver:!1;w&&w.prerelease.length===1&&n.operator===\"<\"&&w.prerelease[0]===0&&(w=!1);for(let b of e){if(E=E||b.operator===\">\"||b.operator===\">=\",h=h||b.operator===\"<\"||b.operator===\"<=\",a){if(D&&b.semver.prerelease&&b.semver.prerelease.length&&b.semver.major===D.major&&b.semver.minor===D.minor&&b.semver.patch===D.patch&&(D=!1),b.operator===\">\"||b.operator===\">=\"){if(A=bX(a,b,r),A===b&&A!==a)return!1}else if(a.operator===\">=\"&&!_w(a.semver,String(b),r))return!1}if(n){if(w&&b.semver.prerelease&&b.semver.prerelease.length&&b.semver.major===w.major&&b.semver.minor===w.minor&&b.semver.patch===w.patch&&(w=!1),b.operator===\"<\"||b.operator===\"<=\"){if(p=kX(n,b,r),p===b&&p!==n)return!1}else if(n.operator===\"<=\"&&!_w(n.semver,String(b),r))return!1}if(!b.operator&&(n||a)&&u!==0)return!1}return!(a&&h&&!n&&u!==0||n&&E&&!a&&u!==0||D||w)},bX=(t,e,r)=>{if(!t)return e;let o=YL(t.semver,e.semver,r);return o>0?t:o<0||e.operator===\">\"&&t.operator===\">=\"?e:t},kX=(t,e,r)=>{if(!t)return e;let o=YL(t.semver,e.semver,r);return o<0?t:o>0||e.operator===\"<\"&&t.operator===\"<=\"?e:t};QX.exports=pGe});var ni=_((sQt,LX)=>{var KL=bm(),RX=Fw(),dGe=Eo(),TX=xL(),mGe=cg(),yGe=eJ(),EGe=rJ(),CGe=sJ(),IGe=lJ(),wGe=uJ(),BGe=fJ(),vGe=hJ(),DGe=dJ(),PGe=Ml(),SGe=CJ(),xGe=wJ(),bGe=KP(),kGe=PJ(),QGe=xJ(),FGe=Tw(),RGe=VP(),TGe=kL(),LGe=QL(),NGe=zP(),OGe=JP(),MGe=FL(),UGe=OJ(),_Ge=Ow(),HGe=Ul(),qGe=Uw(),jGe=iX(),GGe=oX(),WGe=lX(),YGe=AX(),KGe=pX(),VGe=tS(),zGe=EX(),JGe=IX(),XGe=vX(),ZGe=PX(),$Ge=FX();LX.exports={parse:mGe,valid:yGe,clean:EGe,inc:CGe,diff:IGe,major:wGe,minor:BGe,patch:vGe,prerelease:DGe,compare:PGe,rcompare:SGe,compareLoose:xGe,compareBuild:bGe,sort:kGe,rsort:QGe,gt:FGe,lt:RGe,eq:TGe,neq:LGe,gte:NGe,lte:OGe,cmp:MGe,coerce:UGe,Comparator:_Ge,Range:HGe,satisfies:qGe,toComparators:jGe,maxSatisfying:GGe,minSatisfying:WGe,minVersion:YGe,validRange:KGe,outside:VGe,gtr:zGe,ltr:JGe,intersects:XGe,simplifyRange:ZGe,subset:$Ge,SemVer:dGe,re:KL.re,src:KL.src,tokens:KL.t,SEMVER_SPEC_VERSION:RX.SEMVER_SPEC_VERSION,RELEASE_TYPES:RX.RELEASE_TYPES,compareIdentifiers:TX.compareIdentifiers,rcompareIdentifiers:TX.rcompareIdentifiers}});var OX=_((oQt,NX)=>{\"use strict\";function e5e(t,e){function r(){this.constructor=t}r.prototype=e.prototype,t.prototype=new r}function pg(t,e,r,o){this.message=t,this.expected=e,this.found=r,this.location=o,this.name=\"SyntaxError\",typeof Error.captureStackTrace==\"function\"&&Error.captureStackTrace(this,pg)}e5e(pg,Error);pg.buildMessage=function(t,e){var r={literal:function(h){return'\"'+a(h.text)+'\"'},class:function(h){var E=\"\",w;for(w=0;w<h.parts.length;w++)E+=h.parts[w]instanceof Array?n(h.parts[w][0])+\"-\"+n(h.parts[w][1]):n(h.parts[w]);return\"[\"+(h.inverted?\"^\":\"\")+E+\"]\"},any:function(h){return\"any character\"},end:function(h){return\"end of input\"},other:function(h){return h.description}};function o(h){return h.charCodeAt(0).toString(16).toUpperCase()}function a(h){return h.replace(/\\\\/g,\"\\\\\\\\\").replace(/\"/g,'\\\\\"').replace(/\\0/g,\"\\\\0\").replace(/\\t/g,\"\\\\t\").replace(/\\n/g,\"\\\\n\").replace(/\\r/g,\"\\\\r\").replace(/[\\x00-\\x0F]/g,function(E){return\"\\\\x0\"+o(E)}).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g,function(E){return\"\\\\x\"+o(E)})}function n(h){return h.replace(/\\\\/g,\"\\\\\\\\\").replace(/\\]/g,\"\\\\]\").replace(/\\^/g,\"\\\\^\").replace(/-/g,\"\\\\-\").replace(/\\0/g,\"\\\\0\").replace(/\\t/g,\"\\\\t\").replace(/\\n/g,\"\\\\n\").replace(/\\r/g,\"\\\\r\").replace(/[\\x00-\\x0F]/g,function(E){return\"\\\\x0\"+o(E)}).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g,function(E){return\"\\\\x\"+o(E)})}function u(h){return r[h.type](h)}function A(h){var E=new Array(h.length),w,D;for(w=0;w<h.length;w++)E[w]=u(h[w]);if(E.sort(),E.length>0){for(w=1,D=1;w<E.length;w++)E[w-1]!==E[w]&&(E[D]=E[w],D++);E.length=D}switch(E.length){case 1:return E[0];case 2:return E[0]+\" or \"+E[1];default:return E.slice(0,-1).join(\", \")+\", or \"+E[E.length-1]}}function p(h){return h?'\"'+a(h)+'\"':\"end of input\"}return\"Expected \"+A(t)+\" but \"+p(e)+\" found.\"};function t5e(t,e){e=e!==void 0?e:{};var r={},o={Expression:y},a=y,n=\"|\",u=Le(\"|\",!1),A=\"&\",p=Le(\"&\",!1),h=\"^\",E=Le(\"^\",!1),w=function($,se){return!!se.reduce((be,Fe)=>{switch(Fe[1]){case\"|\":return be|Fe[3];case\"&\":return be&Fe[3];case\"^\":return be^Fe[3]}},$)},D=\"!\",b=Le(\"!\",!1),C=function($){return!$},T=\"(\",N=Le(\"(\",!1),U=\")\",z=Le(\")\",!1),te=function($){return $},le=/^[^ \\t\\n\\r()!|&\\^]/,ce=Te([\" \",\"\t\",`\n`,\"\\r\",\"(\",\")\",\"!\",\"|\",\"&\",\"^\"],!0,!1),ue=function($){return e.queryPattern.test($)},Ie=function($){return e.checkFn($)},he=xe(\"whitespace\"),De=/^[ \\t\\n\\r]/,Ee=Te([\" \",\"\t\",`\n`,\"\\r\"],!1,!1),g=0,me=0,Ce=[{line:1,column:1}],fe=0,ie=[],Z=0,Pe;if(\"startRule\"in e){if(!(e.startRule in o))throw new Error(`Can't start parsing from rule \"`+e.startRule+'\".');a=o[e.startRule]}function Re(){return t.substring(me,g)}function ht(){return He(me,g)}function q($,se){throw se=se!==void 0?se:He(me,g),S([xe($)],t.substring(me,g),se)}function nt($,se){throw se=se!==void 0?se:He(me,g),I($,se)}function Le($,se){return{type:\"literal\",text:$,ignoreCase:se}}function Te($,se,be){return{type:\"class\",parts:$,inverted:se,ignoreCase:be}}function ke(){return{type:\"any\"}}function Ve(){return{type:\"end\"}}function xe($){return{type:\"other\",description:$}}function tt($){var se=Ce[$],be;if(se)return se;for(be=$-1;!Ce[be];)be--;for(se=Ce[be],se={line:se.line,column:se.column};be<$;)t.charCodeAt(be)===10?(se.line++,se.column=1):se.column++,be++;return Ce[$]=se,se}function He($,se){var be=tt($),Fe=tt(se);return{start:{offset:$,line:be.line,column:be.column},end:{offset:se,line:Fe.line,column:Fe.column}}}function x($){g<fe||(g>fe&&(fe=g,ie=[]),ie.push($))}function I($,se){return new pg($,null,null,se)}function S($,se,be){return new pg(pg.buildMessage($,se),$,se,be)}function y(){var $,se,be,Fe,lt,Et,qt,nr;if($=g,se=R(),se!==r){for(be=[],Fe=g,lt=X(),lt!==r?(t.charCodeAt(g)===124?(Et=n,g++):(Et=r,Z===0&&x(u)),Et===r&&(t.charCodeAt(g)===38?(Et=A,g++):(Et=r,Z===0&&x(p)),Et===r&&(t.charCodeAt(g)===94?(Et=h,g++):(Et=r,Z===0&&x(E)))),Et!==r?(qt=X(),qt!==r?(nr=R(),nr!==r?(lt=[lt,Et,qt,nr],Fe=lt):(g=Fe,Fe=r)):(g=Fe,Fe=r)):(g=Fe,Fe=r)):(g=Fe,Fe=r);Fe!==r;)be.push(Fe),Fe=g,lt=X(),lt!==r?(t.charCodeAt(g)===124?(Et=n,g++):(Et=r,Z===0&&x(u)),Et===r&&(t.charCodeAt(g)===38?(Et=A,g++):(Et=r,Z===0&&x(p)),Et===r&&(t.charCodeAt(g)===94?(Et=h,g++):(Et=r,Z===0&&x(E)))),Et!==r?(qt=X(),qt!==r?(nr=R(),nr!==r?(lt=[lt,Et,qt,nr],Fe=lt):(g=Fe,Fe=r)):(g=Fe,Fe=r)):(g=Fe,Fe=r)):(g=Fe,Fe=r);be!==r?(me=$,se=w(se,be),$=se):(g=$,$=r)}else g=$,$=r;return $}function R(){var $,se,be,Fe,lt,Et;return $=g,t.charCodeAt(g)===33?(se=D,g++):(se=r,Z===0&&x(b)),se!==r?(be=R(),be!==r?(me=$,se=C(be),$=se):(g=$,$=r)):(g=$,$=r),$===r&&($=g,t.charCodeAt(g)===40?(se=T,g++):(se=r,Z===0&&x(N)),se!==r?(be=X(),be!==r?(Fe=y(),Fe!==r?(lt=X(),lt!==r?(t.charCodeAt(g)===41?(Et=U,g++):(Et=r,Z===0&&x(z)),Et!==r?(me=$,se=te(Fe),$=se):(g=$,$=r)):(g=$,$=r)):(g=$,$=r)):(g=$,$=r)):(g=$,$=r),$===r&&($=J())),$}function J(){var $,se,be,Fe,lt;if($=g,se=X(),se!==r){if(be=g,Fe=[],le.test(t.charAt(g))?(lt=t.charAt(g),g++):(lt=r,Z===0&&x(ce)),lt!==r)for(;lt!==r;)Fe.push(lt),le.test(t.charAt(g))?(lt=t.charAt(g),g++):(lt=r,Z===0&&x(ce));else Fe=r;Fe!==r?be=t.substring(be,g):be=Fe,be!==r?(me=g,Fe=ue(be),Fe?Fe=void 0:Fe=r,Fe!==r?(me=$,se=Ie(be),$=se):(g=$,$=r)):(g=$,$=r)}else g=$,$=r;return $}function X(){var $,se;for(Z++,$=[],De.test(t.charAt(g))?(se=t.charAt(g),g++):(se=r,Z===0&&x(Ee));se!==r;)$.push(se),De.test(t.charAt(g))?(se=t.charAt(g),g++):(se=r,Z===0&&x(Ee));return Z--,$===r&&(se=r,Z===0&&x(he)),$}if(Pe=a(),Pe!==r&&g===t.length)return Pe;throw Pe!==r&&g<t.length&&x(Ve()),S(ie,fe<t.length?t.charAt(fe):null,fe<t.length?He(fe,fe+1):He(fe,fe))}NX.exports={SyntaxError:pg,parse:t5e}});var MX=_(rS=>{var{parse:r5e}=OX();rS.makeParser=(t=/[a-z]+/)=>(e,r)=>r5e(e,{queryPattern:t,checkFn:r});rS.parse=rS.makeParser()});var _X=_((lQt,UX)=>{\"use strict\";UX.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}});var VL=_((cQt,qX)=>{var Hw=_X(),HX={};for(let t of Object.keys(Hw))HX[Hw[t]]=t;var fr={rgb:{channels:3,labels:\"rgb\"},hsl:{channels:3,labels:\"hsl\"},hsv:{channels:3,labels:\"hsv\"},hwb:{channels:3,labels:\"hwb\"},cmyk:{channels:4,labels:\"cmyk\"},xyz:{channels:3,labels:\"xyz\"},lab:{channels:3,labels:\"lab\"},lch:{channels:3,labels:\"lch\"},hex:{channels:1,labels:[\"hex\"]},keyword:{channels:1,labels:[\"keyword\"]},ansi16:{channels:1,labels:[\"ansi16\"]},ansi256:{channels:1,labels:[\"ansi256\"]},hcg:{channels:3,labels:[\"h\",\"c\",\"g\"]},apple:{channels:3,labels:[\"r16\",\"g16\",\"b16\"]},gray:{channels:1,labels:[\"gray\"]}};qX.exports=fr;for(let t of Object.keys(fr)){if(!(\"channels\"in fr[t]))throw new Error(\"missing channels property: \"+t);if(!(\"labels\"in fr[t]))throw new Error(\"missing channel labels property: \"+t);if(fr[t].labels.length!==fr[t].channels)throw new Error(\"channel and label counts mismatch: \"+t);let{channels:e,labels:r}=fr[t];delete fr[t].channels,delete fr[t].labels,Object.defineProperty(fr[t],\"channels\",{value:e}),Object.defineProperty(fr[t],\"labels\",{value:r})}fr.rgb.hsl=function(t){let e=t[0]/255,r=t[1]/255,o=t[2]/255,a=Math.min(e,r,o),n=Math.max(e,r,o),u=n-a,A,p;n===a?A=0:e===n?A=(r-o)/u:r===n?A=2+(o-e)/u:o===n&&(A=4+(e-r)/u),A=Math.min(A*60,360),A<0&&(A+=360);let h=(a+n)/2;return n===a?p=0:h<=.5?p=u/(n+a):p=u/(2-n-a),[A,p*100,h*100]};fr.rgb.hsv=function(t){let e,r,o,a,n,u=t[0]/255,A=t[1]/255,p=t[2]/255,h=Math.max(u,A,p),E=h-Math.min(u,A,p),w=function(D){return(h-D)/6/E+1/2};return E===0?(a=0,n=0):(n=E/h,e=w(u),r=w(A),o=w(p),u===h?a=o-r:A===h?a=1/3+e-o:p===h&&(a=2/3+r-e),a<0?a+=1:a>1&&(a-=1)),[a*360,n*100,h*100]};fr.rgb.hwb=function(t){let e=t[0],r=t[1],o=t[2],a=fr.rgb.hsl(t)[0],n=1/255*Math.min(e,Math.min(r,o));return o=1-1/255*Math.max(e,Math.max(r,o)),[a,n*100,o*100]};fr.rgb.cmyk=function(t){let e=t[0]/255,r=t[1]/255,o=t[2]/255,a=Math.min(1-e,1-r,1-o),n=(1-e-a)/(1-a)||0,u=(1-r-a)/(1-a)||0,A=(1-o-a)/(1-a)||0;return[n*100,u*100,A*100,a*100]};function n5e(t,e){return(t[0]-e[0])**2+(t[1]-e[1])**2+(t[2]-e[2])**2}fr.rgb.keyword=function(t){let e=HX[t];if(e)return e;let r=1/0,o;for(let a of Object.keys(Hw)){let n=Hw[a],u=n5e(t,n);u<r&&(r=u,o=a)}return o};fr.keyword.rgb=function(t){return Hw[t]};fr.rgb.xyz=function(t){let e=t[0]/255,r=t[1]/255,o=t[2]/255;e=e>.04045?((e+.055)/1.055)**2.4:e/12.92,r=r>.04045?((r+.055)/1.055)**2.4:r/12.92,o=o>.04045?((o+.055)/1.055)**2.4:o/12.92;let a=e*.4124+r*.3576+o*.1805,n=e*.2126+r*.7152+o*.0722,u=e*.0193+r*.1192+o*.9505;return[a*100,n*100,u*100]};fr.rgb.lab=function(t){let e=fr.rgb.xyz(t),r=e[0],o=e[1],a=e[2];r/=95.047,o/=100,a/=108.883,r=r>.008856?r**(1/3):7.787*r+16/116,o=o>.008856?o**(1/3):7.787*o+16/116,a=a>.008856?a**(1/3):7.787*a+16/116;let n=116*o-16,u=500*(r-o),A=200*(o-a);return[n,u,A]};fr.hsl.rgb=function(t){let e=t[0]/360,r=t[1]/100,o=t[2]/100,a,n,u;if(r===0)return u=o*255,[u,u,u];o<.5?a=o*(1+r):a=o+r-o*r;let A=2*o-a,p=[0,0,0];for(let h=0;h<3;h++)n=e+1/3*-(h-1),n<0&&n++,n>1&&n--,6*n<1?u=A+(a-A)*6*n:2*n<1?u=a:3*n<2?u=A+(a-A)*(2/3-n)*6:u=A,p[h]=u*255;return p};fr.hsl.hsv=function(t){let e=t[0],r=t[1]/100,o=t[2]/100,a=r,n=Math.max(o,.01);o*=2,r*=o<=1?o:2-o,a*=n<=1?n:2-n;let u=(o+r)/2,A=o===0?2*a/(n+a):2*r/(o+r);return[e,A*100,u*100]};fr.hsv.rgb=function(t){let e=t[0]/60,r=t[1]/100,o=t[2]/100,a=Math.floor(e)%6,n=e-Math.floor(e),u=255*o*(1-r),A=255*o*(1-r*n),p=255*o*(1-r*(1-n));switch(o*=255,a){case 0:return[o,p,u];case 1:return[A,o,u];case 2:return[u,o,p];case 3:return[u,A,o];case 4:return[p,u,o];case 5:return[o,u,A]}};fr.hsv.hsl=function(t){let e=t[0],r=t[1]/100,o=t[2]/100,a=Math.max(o,.01),n,u;u=(2-r)*o;let A=(2-r)*a;return n=r*a,n/=A<=1?A:2-A,n=n||0,u/=2,[e,n*100,u*100]};fr.hwb.rgb=function(t){let e=t[0]/360,r=t[1]/100,o=t[2]/100,a=r+o,n;a>1&&(r/=a,o/=a);let u=Math.floor(6*e),A=1-o;n=6*e-u,u&1&&(n=1-n);let p=r+n*(A-r),h,E,w;switch(u){default:case 6:case 0:h=A,E=p,w=r;break;case 1:h=p,E=A,w=r;break;case 2:h=r,E=A,w=p;break;case 3:h=r,E=p,w=A;break;case 4:h=p,E=r,w=A;break;case 5:h=A,E=r,w=p;break}return[h*255,E*255,w*255]};fr.cmyk.rgb=function(t){let e=t[0]/100,r=t[1]/100,o=t[2]/100,a=t[3]/100,n=1-Math.min(1,e*(1-a)+a),u=1-Math.min(1,r*(1-a)+a),A=1-Math.min(1,o*(1-a)+a);return[n*255,u*255,A*255]};fr.xyz.rgb=function(t){let e=t[0]/100,r=t[1]/100,o=t[2]/100,a,n,u;return a=e*3.2406+r*-1.5372+o*-.4986,n=e*-.9689+r*1.8758+o*.0415,u=e*.0557+r*-.204+o*1.057,a=a>.0031308?1.055*a**(1/2.4)-.055:a*12.92,n=n>.0031308?1.055*n**(1/2.4)-.055:n*12.92,u=u>.0031308?1.055*u**(1/2.4)-.055:u*12.92,a=Math.min(Math.max(0,a),1),n=Math.min(Math.max(0,n),1),u=Math.min(Math.max(0,u),1),[a*255,n*255,u*255]};fr.xyz.lab=function(t){let e=t[0],r=t[1],o=t[2];e/=95.047,r/=100,o/=108.883,e=e>.008856?e**(1/3):7.787*e+16/116,r=r>.008856?r**(1/3):7.787*r+16/116,o=o>.008856?o**(1/3):7.787*o+16/116;let a=116*r-16,n=500*(e-r),u=200*(r-o);return[a,n,u]};fr.lab.xyz=function(t){let e=t[0],r=t[1],o=t[2],a,n,u;n=(e+16)/116,a=r/500+n,u=n-o/200;let A=n**3,p=a**3,h=u**3;return n=A>.008856?A:(n-16/116)/7.787,a=p>.008856?p:(a-16/116)/7.787,u=h>.008856?h:(u-16/116)/7.787,a*=95.047,n*=100,u*=108.883,[a,n,u]};fr.lab.lch=function(t){let e=t[0],r=t[1],o=t[2],a;a=Math.atan2(o,r)*360/2/Math.PI,a<0&&(a+=360);let u=Math.sqrt(r*r+o*o);return[e,u,a]};fr.lch.lab=function(t){let e=t[0],r=t[1],a=t[2]/360*2*Math.PI,n=r*Math.cos(a),u=r*Math.sin(a);return[e,n,u]};fr.rgb.ansi16=function(t,e=null){let[r,o,a]=t,n=e===null?fr.rgb.hsv(t)[2]:e;if(n=Math.round(n/50),n===0)return 30;let u=30+(Math.round(a/255)<<2|Math.round(o/255)<<1|Math.round(r/255));return n===2&&(u+=60),u};fr.hsv.ansi16=function(t){return fr.rgb.ansi16(fr.hsv.rgb(t),t[2])};fr.rgb.ansi256=function(t){let e=t[0],r=t[1],o=t[2];return e===r&&r===o?e<8?16:e>248?231:Math.round((e-8)/247*24)+232:16+36*Math.round(e/255*5)+6*Math.round(r/255*5)+Math.round(o/255*5)};fr.ansi16.rgb=function(t){let e=t%10;if(e===0||e===7)return t>50&&(e+=3.5),e=e/10.5*255,[e,e,e];let r=(~~(t>50)+1)*.5,o=(e&1)*r*255,a=(e>>1&1)*r*255,n=(e>>2&1)*r*255;return[o,a,n]};fr.ansi256.rgb=function(t){if(t>=232){let n=(t-232)*10+8;return[n,n,n]}t-=16;let e,r=Math.floor(t/36)/5*255,o=Math.floor((e=t%36)/6)/5*255,a=e%6/5*255;return[r,o,a]};fr.rgb.hex=function(t){let r=(((Math.round(t[0])&255)<<16)+((Math.round(t[1])&255)<<8)+(Math.round(t[2])&255)).toString(16).toUpperCase();return\"000000\".substring(r.length)+r};fr.hex.rgb=function(t){let e=t.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!e)return[0,0,0];let r=e[0];e[0].length===3&&(r=r.split(\"\").map(A=>A+A).join(\"\"));let o=parseInt(r,16),a=o>>16&255,n=o>>8&255,u=o&255;return[a,n,u]};fr.rgb.hcg=function(t){let e=t[0]/255,r=t[1]/255,o=t[2]/255,a=Math.max(Math.max(e,r),o),n=Math.min(Math.min(e,r),o),u=a-n,A,p;return u<1?A=n/(1-u):A=0,u<=0?p=0:a===e?p=(r-o)/u%6:a===r?p=2+(o-e)/u:p=4+(e-r)/u,p/=6,p%=1,[p*360,u*100,A*100]};fr.hsl.hcg=function(t){let e=t[1]/100,r=t[2]/100,o=r<.5?2*e*r:2*e*(1-r),a=0;return o<1&&(a=(r-.5*o)/(1-o)),[t[0],o*100,a*100]};fr.hsv.hcg=function(t){let e=t[1]/100,r=t[2]/100,o=e*r,a=0;return o<1&&(a=(r-o)/(1-o)),[t[0],o*100,a*100]};fr.hcg.rgb=function(t){let e=t[0]/360,r=t[1]/100,o=t[2]/100;if(r===0)return[o*255,o*255,o*255];let a=[0,0,0],n=e%1*6,u=n%1,A=1-u,p=0;switch(Math.floor(n)){case 0:a[0]=1,a[1]=u,a[2]=0;break;case 1:a[0]=A,a[1]=1,a[2]=0;break;case 2:a[0]=0,a[1]=1,a[2]=u;break;case 3:a[0]=0,a[1]=A,a[2]=1;break;case 4:a[0]=u,a[1]=0,a[2]=1;break;default:a[0]=1,a[1]=0,a[2]=A}return p=(1-r)*o,[(r*a[0]+p)*255,(r*a[1]+p)*255,(r*a[2]+p)*255]};fr.hcg.hsv=function(t){let e=t[1]/100,r=t[2]/100,o=e+r*(1-e),a=0;return o>0&&(a=e/o),[t[0],a*100,o*100]};fr.hcg.hsl=function(t){let e=t[1]/100,o=t[2]/100*(1-e)+.5*e,a=0;return o>0&&o<.5?a=e/(2*o):o>=.5&&o<1&&(a=e/(2*(1-o))),[t[0],a*100,o*100]};fr.hcg.hwb=function(t){let e=t[1]/100,r=t[2]/100,o=e+r*(1-e);return[t[0],(o-e)*100,(1-o)*100]};fr.hwb.hcg=function(t){let e=t[1]/100,o=1-t[2]/100,a=o-e,n=0;return a<1&&(n=(o-a)/(1-a)),[t[0],a*100,n*100]};fr.apple.rgb=function(t){return[t[0]/65535*255,t[1]/65535*255,t[2]/65535*255]};fr.rgb.apple=function(t){return[t[0]/255*65535,t[1]/255*65535,t[2]/255*65535]};fr.gray.rgb=function(t){return[t[0]/100*255,t[0]/100*255,t[0]/100*255]};fr.gray.hsl=function(t){return[0,0,t[0]]};fr.gray.hsv=fr.gray.hsl;fr.gray.hwb=function(t){return[0,100,t[0]]};fr.gray.cmyk=function(t){return[0,0,0,t[0]]};fr.gray.lab=function(t){return[t[0],0,0]};fr.gray.hex=function(t){let e=Math.round(t[0]/100*255)&255,o=((e<<16)+(e<<8)+e).toString(16).toUpperCase();return\"000000\".substring(o.length)+o};fr.rgb.gray=function(t){return[(t[0]+t[1]+t[2])/3/255*100]}});var GX=_((uQt,jX)=>{var nS=VL();function i5e(){let t={},e=Object.keys(nS);for(let r=e.length,o=0;o<r;o++)t[e[o]]={distance:-1,parent:null};return t}function s5e(t){let e=i5e(),r=[t];for(e[t].distance=0;r.length;){let o=r.pop(),a=Object.keys(nS[o]);for(let n=a.length,u=0;u<n;u++){let A=a[u],p=e[A];p.distance===-1&&(p.distance=e[o].distance+1,p.parent=o,r.unshift(A))}}return e}function o5e(t,e){return function(r){return e(t(r))}}function a5e(t,e){let r=[e[t].parent,t],o=nS[e[t].parent][t],a=e[t].parent;for(;e[a].parent;)r.unshift(e[a].parent),o=o5e(nS[e[a].parent][a],o),a=e[a].parent;return o.conversion=r,o}jX.exports=function(t){let e=s5e(t),r={},o=Object.keys(e);for(let a=o.length,n=0;n<a;n++){let u=o[n];e[u].parent!==null&&(r[u]=a5e(u,e))}return r}});var YX=_((AQt,WX)=>{var zL=VL(),l5e=GX(),Rm={},c5e=Object.keys(zL);function u5e(t){let e=function(...r){let o=r[0];return o==null?o:(o.length>1&&(r=o),t(r))};return\"conversion\"in t&&(e.conversion=t.conversion),e}function A5e(t){let e=function(...r){let o=r[0];if(o==null)return o;o.length>1&&(r=o);let a=t(r);if(typeof a==\"object\")for(let n=a.length,u=0;u<n;u++)a[u]=Math.round(a[u]);return a};return\"conversion\"in t&&(e.conversion=t.conversion),e}c5e.forEach(t=>{Rm[t]={},Object.defineProperty(Rm[t],\"channels\",{value:zL[t].channels}),Object.defineProperty(Rm[t],\"labels\",{value:zL[t].labels});let e=l5e(t);Object.keys(e).forEach(o=>{let a=e[o];Rm[t][o]=A5e(a),Rm[t][o].raw=u5e(a)})});WX.exports=Rm});var qw=_((fQt,XX)=>{\"use strict\";var KX=(t,e)=>(...r)=>`\\x1B[${t(...r)+e}m`,VX=(t,e)=>(...r)=>{let o=t(...r);return`\\x1B[${38+e};5;${o}m`},zX=(t,e)=>(...r)=>{let o=t(...r);return`\\x1B[${38+e};2;${o[0]};${o[1]};${o[2]}m`},iS=t=>t,JX=(t,e,r)=>[t,e,r],Tm=(t,e,r)=>{Object.defineProperty(t,e,{get:()=>{let o=r();return Object.defineProperty(t,e,{value:o,enumerable:!0,configurable:!0}),o},enumerable:!0,configurable:!0})},JL,Lm=(t,e,r,o)=>{JL===void 0&&(JL=YX());let a=o?10:0,n={};for(let[u,A]of Object.entries(JL)){let p=u===\"ansi16\"?\"ansi\":u;u===e?n[p]=t(r,a):typeof A==\"object\"&&(n[p]=t(A[e],a))}return n};function f5e(){let t=new Map,e={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};e.color.gray=e.color.blackBright,e.bgColor.bgGray=e.bgColor.bgBlackBright,e.color.grey=e.color.blackBright,e.bgColor.bgGrey=e.bgColor.bgBlackBright;for(let[r,o]of Object.entries(e)){for(let[a,n]of Object.entries(o))e[a]={open:`\\x1B[${n[0]}m`,close:`\\x1B[${n[1]}m`},o[a]=e[a],t.set(n[0],n[1]);Object.defineProperty(e,r,{value:o,enumerable:!1})}return Object.defineProperty(e,\"codes\",{value:t,enumerable:!1}),e.color.close=\"\\x1B[39m\",e.bgColor.close=\"\\x1B[49m\",Tm(e.color,\"ansi\",()=>Lm(KX,\"ansi16\",iS,!1)),Tm(e.color,\"ansi256\",()=>Lm(VX,\"ansi256\",iS,!1)),Tm(e.color,\"ansi16m\",()=>Lm(zX,\"rgb\",JX,!1)),Tm(e.bgColor,\"ansi\",()=>Lm(KX,\"ansi16\",iS,!0)),Tm(e.bgColor,\"ansi256\",()=>Lm(VX,\"ansi256\",iS,!0)),Tm(e.bgColor,\"ansi16m\",()=>Lm(zX,\"rgb\",JX,!0)),e}Object.defineProperty(XX,\"exports\",{enumerable:!0,get:f5e})});var $X=_((pQt,ZX)=>{\"use strict\";ZX.exports=(t,e=process.argv)=>{let r=t.startsWith(\"-\")?\"\":t.length===1?\"-\":\"--\",o=e.indexOf(r+t),a=e.indexOf(\"--\");return o!==-1&&(a===-1||o<a)}});var $L=_((hQt,tZ)=>{\"use strict\";var p5e=ve(\"os\"),eZ=ve(\"tty\"),_l=$X(),{env:cs}=process,Zp;_l(\"no-color\")||_l(\"no-colors\")||_l(\"color=false\")||_l(\"color=never\")?Zp=0:(_l(\"color\")||_l(\"colors\")||_l(\"color=true\")||_l(\"color=always\"))&&(Zp=1);\"FORCE_COLOR\"in cs&&(cs.FORCE_COLOR===\"true\"?Zp=1:cs.FORCE_COLOR===\"false\"?Zp=0:Zp=cs.FORCE_COLOR.length===0?1:Math.min(parseInt(cs.FORCE_COLOR,10),3));function XL(t){return t===0?!1:{level:t,hasBasic:!0,has256:t>=2,has16m:t>=3}}function ZL(t,e){if(Zp===0)return 0;if(_l(\"color=16m\")||_l(\"color=full\")||_l(\"color=truecolor\"))return 3;if(_l(\"color=256\"))return 2;if(t&&!e&&Zp===void 0)return 0;let r=Zp||0;if(cs.TERM===\"dumb\")return r;if(process.platform===\"win32\"){let o=p5e.release().split(\".\");return Number(o[0])>=10&&Number(o[2])>=10586?Number(o[2])>=14931?3:2:1}if(\"CI\"in cs)return[\"TRAVIS\",\"CIRCLECI\",\"APPVEYOR\",\"GITLAB_CI\"].some(o=>o in cs)||cs.CI_NAME===\"codeship\"?1:r;if(\"TEAMCITY_VERSION\"in cs)return/^(9\\.(0*[1-9]\\d*)\\.|\\d{2,}\\.)/.test(cs.TEAMCITY_VERSION)?1:0;if(\"GITHUB_ACTIONS\"in cs)return 1;if(cs.COLORTERM===\"truecolor\")return 3;if(\"TERM_PROGRAM\"in cs){let o=parseInt((cs.TERM_PROGRAM_VERSION||\"\").split(\".\")[0],10);switch(cs.TERM_PROGRAM){case\"iTerm.app\":return o>=3?3:2;case\"Apple_Terminal\":return 2}}return/-256(color)?$/i.test(cs.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(cs.TERM)||\"COLORTERM\"in cs?1:r}function h5e(t){let e=ZL(t,t&&t.isTTY);return XL(e)}tZ.exports={supportsColor:h5e,stdout:XL(ZL(!0,eZ.isatty(1))),stderr:XL(ZL(!0,eZ.isatty(2)))}});var nZ=_((gQt,rZ)=>{\"use strict\";var g5e=(t,e,r)=>{let o=t.indexOf(e);if(o===-1)return t;let a=e.length,n=0,u=\"\";do u+=t.substr(n,o-n)+e+r,n=o+a,o=t.indexOf(e,n);while(o!==-1);return u+=t.substr(n),u},d5e=(t,e,r,o)=>{let a=0,n=\"\";do{let u=t[o-1]===\"\\r\";n+=t.substr(a,(u?o-1:o)-a)+e+(u?`\\r\n`:`\n`)+r,a=o+1,o=t.indexOf(`\n`,a)}while(o!==-1);return n+=t.substr(a),n};rZ.exports={stringReplaceAll:g5e,stringEncaseCRLFWithFirstIndex:d5e}});var lZ=_((dQt,aZ)=>{\"use strict\";var m5e=/(?:\\\\(u(?:[a-f\\d]{4}|\\{[a-f\\d]{1,6}\\})|x[a-f\\d]{2}|.))|(?:\\{(~)?(\\w+(?:\\([^)]*\\))?(?:\\.\\w+(?:\\([^)]*\\))?)*)(?:[ \\t]|(?=\\r?\\n)))|(\\})|((?:.|[\\r\\n\\f])+?)/gi,iZ=/(?:^|\\.)(\\w+)(?:\\(([^)]*)\\))?/g,y5e=/^(['\"])((?:\\\\.|(?!\\1)[^\\\\])*)\\1$/,E5e=/\\\\(u(?:[a-f\\d]{4}|\\{[a-f\\d]{1,6}\\})|x[a-f\\d]{2}|.)|([^\\\\])/gi,C5e=new Map([[\"n\",`\n`],[\"r\",\"\\r\"],[\"t\",\"\t\"],[\"b\",\"\\b\"],[\"f\",\"\\f\"],[\"v\",\"\\v\"],[\"0\",\"\\0\"],[\"\\\\\",\"\\\\\"],[\"e\",\"\\x1B\"],[\"a\",\"\\x07\"]]);function oZ(t){let e=t[0]===\"u\",r=t[1]===\"{\";return e&&!r&&t.length===5||t[0]===\"x\"&&t.length===3?String.fromCharCode(parseInt(t.slice(1),16)):e&&r?String.fromCodePoint(parseInt(t.slice(2,-1),16)):C5e.get(t)||t}function I5e(t,e){let r=[],o=e.trim().split(/\\s*,\\s*/g),a;for(let n of o){let u=Number(n);if(!Number.isNaN(u))r.push(u);else if(a=n.match(y5e))r.push(a[2].replace(E5e,(A,p,h)=>p?oZ(p):h));else throw new Error(`Invalid Chalk template style argument: ${n} (in style '${t}')`)}return r}function w5e(t){iZ.lastIndex=0;let e=[],r;for(;(r=iZ.exec(t))!==null;){let o=r[1];if(r[2]){let a=I5e(o,r[2]);e.push([o].concat(a))}else e.push([o])}return e}function sZ(t,e){let r={};for(let a of e)for(let n of a.styles)r[n[0]]=a.inverse?null:n.slice(1);let o=t;for(let[a,n]of Object.entries(r))if(Array.isArray(n)){if(!(a in o))throw new Error(`Unknown Chalk style: ${a}`);o=n.length>0?o[a](...n):o[a]}return o}aZ.exports=(t,e)=>{let r=[],o=[],a=[];if(e.replace(m5e,(n,u,A,p,h,E)=>{if(u)a.push(oZ(u));else if(p){let w=a.join(\"\");a=[],o.push(r.length===0?w:sZ(t,r)(w)),r.push({inverse:A,styles:w5e(p)})}else if(h){if(r.length===0)throw new Error(\"Found extraneous } in Chalk template literal\");o.push(sZ(t,r)(a.join(\"\"))),a=[],r.pop()}else a.push(E)}),o.push(a.join(\"\")),r.length>0){let n=`Chalk template literal is missing ${r.length} closing bracket${r.length===1?\"\":\"s\"} (\\`}\\`)`;throw new Error(n)}return o.join(\"\")}});var sN=_((mQt,fZ)=>{\"use strict\";var jw=qw(),{stdout:tN,stderr:rN}=$L(),{stringReplaceAll:B5e,stringEncaseCRLFWithFirstIndex:v5e}=nZ(),cZ=[\"ansi\",\"ansi\",\"ansi256\",\"ansi16m\"],Nm=Object.create(null),D5e=(t,e={})=>{if(e.level>3||e.level<0)throw new Error(\"The `level` option should be an integer from 0 to 3\");let r=tN?tN.level:0;t.level=e.level===void 0?r:e.level},nN=class{constructor(e){return uZ(e)}},uZ=t=>{let e={};return D5e(e,t),e.template=(...r)=>x5e(e.template,...r),Object.setPrototypeOf(e,sS.prototype),Object.setPrototypeOf(e.template,e),e.template.constructor=()=>{throw new Error(\"`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.\")},e.template.Instance=nN,e.template};function sS(t){return uZ(t)}for(let[t,e]of Object.entries(jw))Nm[t]={get(){let r=oS(this,iN(e.open,e.close,this._styler),this._isEmpty);return Object.defineProperty(this,t,{value:r}),r}};Nm.visible={get(){let t=oS(this,this._styler,!0);return Object.defineProperty(this,\"visible\",{value:t}),t}};var AZ=[\"rgb\",\"hex\",\"keyword\",\"hsl\",\"hsv\",\"hwb\",\"ansi\",\"ansi256\"];for(let t of AZ)Nm[t]={get(){let{level:e}=this;return function(...r){let o=iN(jw.color[cZ[e]][t](...r),jw.color.close,this._styler);return oS(this,o,this._isEmpty)}}};for(let t of AZ){let e=\"bg\"+t[0].toUpperCase()+t.slice(1);Nm[e]={get(){let{level:r}=this;return function(...o){let a=iN(jw.bgColor[cZ[r]][t](...o),jw.bgColor.close,this._styler);return oS(this,a,this._isEmpty)}}}}var P5e=Object.defineProperties(()=>{},{...Nm,level:{enumerable:!0,get(){return this._generator.level},set(t){this._generator.level=t}}}),iN=(t,e,r)=>{let o,a;return r===void 0?(o=t,a=e):(o=r.openAll+t,a=e+r.closeAll),{open:t,close:e,openAll:o,closeAll:a,parent:r}},oS=(t,e,r)=>{let o=(...a)=>S5e(o,a.length===1?\"\"+a[0]:a.join(\" \"));return o.__proto__=P5e,o._generator=t,o._styler=e,o._isEmpty=r,o},S5e=(t,e)=>{if(t.level<=0||!e)return t._isEmpty?\"\":e;let r=t._styler;if(r===void 0)return e;let{openAll:o,closeAll:a}=r;if(e.indexOf(\"\\x1B\")!==-1)for(;r!==void 0;)e=B5e(e,r.close,r.open),r=r.parent;let n=e.indexOf(`\n`);return n!==-1&&(e=v5e(e,a,o,n)),o+e+a},eN,x5e=(t,...e)=>{let[r]=e;if(!Array.isArray(r))return e.join(\" \");let o=e.slice(1),a=[r.raw[0]];for(let n=1;n<r.length;n++)a.push(String(o[n-1]).replace(/[{}\\\\]/g,\"\\\\$&\"),String(r.raw[n]));return eN===void 0&&(eN=lZ()),eN(t,a.join(\"\"))};Object.defineProperties(sS.prototype,Nm);var Gw=sS();Gw.supportsColor=tN;Gw.stderr=sS({level:rN?rN.level:0});Gw.stderr.supportsColor=rN;Gw.Level={None:0,Basic:1,Ansi256:2,TrueColor:3,0:\"None\",1:\"Basic\",2:\"Ansi256\",3:\"TrueColor\"};fZ.exports=Gw});var aS=_(Hl=>{\"use strict\";Hl.isInteger=t=>typeof t==\"number\"?Number.isInteger(t):typeof t==\"string\"&&t.trim()!==\"\"?Number.isInteger(Number(t)):!1;Hl.find=(t,e)=>t.nodes.find(r=>r.type===e);Hl.exceedsLimit=(t,e,r=1,o)=>o===!1||!Hl.isInteger(t)||!Hl.isInteger(e)?!1:(Number(e)-Number(t))/Number(r)>=o;Hl.escapeNode=(t,e=0,r)=>{let o=t.nodes[e];o&&(r&&o.type===r||o.type===\"open\"||o.type===\"close\")&&o.escaped!==!0&&(o.value=\"\\\\\"+o.value,o.escaped=!0)};Hl.encloseBrace=t=>t.type!==\"brace\"||t.commas>>0+t.ranges>>0?!1:(t.invalid=!0,!0);Hl.isInvalidBrace=t=>t.type!==\"brace\"?!1:t.invalid===!0||t.dollar?!0:!(t.commas>>0+t.ranges>>0)||t.open!==!0||t.close!==!0?(t.invalid=!0,!0):!1;Hl.isOpenOrClose=t=>t.type===\"open\"||t.type===\"close\"?!0:t.open===!0||t.close===!0;Hl.reduce=t=>t.reduce((e,r)=>(r.type===\"text\"&&e.push(r.value),r.type===\"range\"&&(r.type=\"text\"),e),[]);Hl.flatten=(...t)=>{let e=[],r=o=>{for(let a=0;a<o.length;a++){let n=o[a];Array.isArray(n)?r(n,e):n!==void 0&&e.push(n)}return e};return r(t),e}});var lS=_((EQt,hZ)=>{\"use strict\";var pZ=aS();hZ.exports=(t,e={})=>{let r=(o,a={})=>{let n=e.escapeInvalid&&pZ.isInvalidBrace(a),u=o.invalid===!0&&e.escapeInvalid===!0,A=\"\";if(o.value)return(n||u)&&pZ.isOpenOrClose(o)?\"\\\\\"+o.value:o.value;if(o.value)return o.value;if(o.nodes)for(let p of o.nodes)A+=r(p);return A};return r(t)}});var dZ=_((CQt,gZ)=>{\"use strict\";gZ.exports=function(t){return typeof t==\"number\"?t-t===0:typeof t==\"string\"&&t.trim()!==\"\"?Number.isFinite?Number.isFinite(+t):isFinite(+t):!1}});var DZ=_((IQt,vZ)=>{\"use strict\";var mZ=dZ(),hg=(t,e,r)=>{if(mZ(t)===!1)throw new TypeError(\"toRegexRange: expected the first argument to be a number\");if(e===void 0||t===e)return String(t);if(mZ(e)===!1)throw new TypeError(\"toRegexRange: expected the second argument to be a number.\");let o={relaxZeros:!0,...r};typeof o.strictZeros==\"boolean\"&&(o.relaxZeros=o.strictZeros===!1);let a=String(o.relaxZeros),n=String(o.shorthand),u=String(o.capture),A=String(o.wrap),p=t+\":\"+e+\"=\"+a+n+u+A;if(hg.cache.hasOwnProperty(p))return hg.cache[p].result;let h=Math.min(t,e),E=Math.max(t,e);if(Math.abs(h-E)===1){let T=t+\"|\"+e;return o.capture?`(${T})`:o.wrap===!1?T:`(?:${T})`}let w=BZ(t)||BZ(e),D={min:t,max:e,a:h,b:E},b=[],C=[];if(w&&(D.isPadded=w,D.maxLen=String(D.max).length),h<0){let T=E<0?Math.abs(E):1;C=yZ(T,Math.abs(h),D,o),h=D.a=0}return E>=0&&(b=yZ(h,E,D,o)),D.negatives=C,D.positives=b,D.result=b5e(C,b,o),o.capture===!0?D.result=`(${D.result})`:o.wrap!==!1&&b.length+C.length>1&&(D.result=`(?:${D.result})`),hg.cache[p]=D,D.result};function b5e(t,e,r){let o=oN(t,e,\"-\",!1,r)||[],a=oN(e,t,\"\",!1,r)||[],n=oN(t,e,\"-?\",!0,r)||[];return o.concat(n).concat(a).join(\"|\")}function k5e(t,e){let r=1,o=1,a=CZ(t,r),n=new Set([e]);for(;t<=a&&a<=e;)n.add(a),r+=1,a=CZ(t,r);for(a=IZ(e+1,o)-1;t<a&&a<=e;)n.add(a),o+=1,a=IZ(e+1,o)-1;return n=[...n],n.sort(R5e),n}function Q5e(t,e,r){if(t===e)return{pattern:t,count:[],digits:0};let o=F5e(t,e),a=o.length,n=\"\",u=0;for(let A=0;A<a;A++){let[p,h]=o[A];p===h?n+=p:p!==\"0\"||h!==\"9\"?n+=T5e(p,h,r):u++}return u&&(n+=r.shorthand===!0?\"\\\\d\":\"[0-9]\"),{pattern:n,count:[u],digits:a}}function yZ(t,e,r,o){let a=k5e(t,e),n=[],u=t,A;for(let p=0;p<a.length;p++){let h=a[p],E=Q5e(String(u),String(h),o),w=\"\";if(!r.isPadded&&A&&A.pattern===E.pattern){A.count.length>1&&A.count.pop(),A.count.push(E.count[0]),A.string=A.pattern+wZ(A.count),u=h+1;continue}r.isPadded&&(w=L5e(h,r,o)),E.string=w+E.pattern+wZ(E.count),n.push(E),u=h+1,A=E}return n}function oN(t,e,r,o,a){let n=[];for(let u of t){let{string:A}=u;!o&&!EZ(e,\"string\",A)&&n.push(r+A),o&&EZ(e,\"string\",A)&&n.push(r+A)}return n}function F5e(t,e){let r=[];for(let o=0;o<t.length;o++)r.push([t[o],e[o]]);return r}function R5e(t,e){return t>e?1:e>t?-1:0}function EZ(t,e,r){return t.some(o=>o[e]===r)}function CZ(t,e){return Number(String(t).slice(0,-e)+\"9\".repeat(e))}function IZ(t,e){return t-t%Math.pow(10,e)}function wZ(t){let[e=0,r=\"\"]=t;return r||e>1?`{${e+(r?\",\"+r:\"\")}}`:\"\"}function T5e(t,e,r){return`[${t}${e-t===1?\"\":\"-\"}${e}]`}function BZ(t){return/^-?(0+)\\d/.test(t)}function L5e(t,e,r){if(!e.isPadded)return t;let o=Math.abs(e.maxLen-String(t).length),a=r.relaxZeros!==!1;switch(o){case 0:return\"\";case 1:return a?\"0?\":\"0\";case 2:return a?\"0{0,2}\":\"00\";default:return a?`0{0,${o}}`:`0{${o}}`}}hg.cache={};hg.clearCache=()=>hg.cache={};vZ.exports=hg});var cN=_((wQt,RZ)=>{\"use strict\";var N5e=ve(\"util\"),xZ=DZ(),PZ=t=>t!==null&&typeof t==\"object\"&&!Array.isArray(t),O5e=t=>e=>t===!0?Number(e):String(e),aN=t=>typeof t==\"number\"||typeof t==\"string\"&&t!==\"\",Ww=t=>Number.isInteger(+t),lN=t=>{let e=`${t}`,r=-1;if(e[0]===\"-\"&&(e=e.slice(1)),e===\"0\")return!1;for(;e[++r]===\"0\";);return r>0},M5e=(t,e,r)=>typeof t==\"string\"||typeof e==\"string\"?!0:r.stringify===!0,U5e=(t,e,r)=>{if(e>0){let o=t[0]===\"-\"?\"-\":\"\";o&&(t=t.slice(1)),t=o+t.padStart(o?e-1:e,\"0\")}return r===!1?String(t):t},SZ=(t,e)=>{let r=t[0]===\"-\"?\"-\":\"\";for(r&&(t=t.slice(1),e--);t.length<e;)t=\"0\"+t;return r?\"-\"+t:t},_5e=(t,e)=>{t.negatives.sort((u,A)=>u<A?-1:u>A?1:0),t.positives.sort((u,A)=>u<A?-1:u>A?1:0);let r=e.capture?\"\":\"?:\",o=\"\",a=\"\",n;return t.positives.length&&(o=t.positives.join(\"|\")),t.negatives.length&&(a=`-(${r}${t.negatives.join(\"|\")})`),o&&a?n=`${o}|${a}`:n=o||a,e.wrap?`(${r}${n})`:n},bZ=(t,e,r,o)=>{if(r)return xZ(t,e,{wrap:!1,...o});let a=String.fromCharCode(t);if(t===e)return a;let n=String.fromCharCode(e);return`[${a}-${n}]`},kZ=(t,e,r)=>{if(Array.isArray(t)){let o=r.wrap===!0,a=r.capture?\"\":\"?:\";return o?`(${a}${t.join(\"|\")})`:t.join(\"|\")}return xZ(t,e,r)},QZ=(...t)=>new RangeError(\"Invalid range arguments: \"+N5e.inspect(...t)),FZ=(t,e,r)=>{if(r.strictRanges===!0)throw QZ([t,e]);return[]},H5e=(t,e)=>{if(e.strictRanges===!0)throw new TypeError(`Expected step \"${t}\" to be a number`);return[]},q5e=(t,e,r=1,o={})=>{let a=Number(t),n=Number(e);if(!Number.isInteger(a)||!Number.isInteger(n)){if(o.strictRanges===!0)throw QZ([t,e]);return[]}a===0&&(a=0),n===0&&(n=0);let u=a>n,A=String(t),p=String(e),h=String(r);r=Math.max(Math.abs(r),1);let E=lN(A)||lN(p)||lN(h),w=E?Math.max(A.length,p.length,h.length):0,D=E===!1&&M5e(t,e,o)===!1,b=o.transform||O5e(D);if(o.toRegex&&r===1)return bZ(SZ(t,w),SZ(e,w),!0,o);let C={negatives:[],positives:[]},T=z=>C[z<0?\"negatives\":\"positives\"].push(Math.abs(z)),N=[],U=0;for(;u?a>=n:a<=n;)o.toRegex===!0&&r>1?T(a):N.push(U5e(b(a,U),w,D)),a=u?a-r:a+r,U++;return o.toRegex===!0?r>1?_5e(C,o):kZ(N,null,{wrap:!1,...o}):N},j5e=(t,e,r=1,o={})=>{if(!Ww(t)&&t.length>1||!Ww(e)&&e.length>1)return FZ(t,e,o);let a=o.transform||(D=>String.fromCharCode(D)),n=`${t}`.charCodeAt(0),u=`${e}`.charCodeAt(0),A=n>u,p=Math.min(n,u),h=Math.max(n,u);if(o.toRegex&&r===1)return bZ(p,h,!1,o);let E=[],w=0;for(;A?n>=u:n<=u;)E.push(a(n,w)),n=A?n-r:n+r,w++;return o.toRegex===!0?kZ(E,null,{wrap:!1,options:o}):E},cS=(t,e,r,o={})=>{if(e==null&&aN(t))return[t];if(!aN(t)||!aN(e))return FZ(t,e,o);if(typeof r==\"function\")return cS(t,e,1,{transform:r});if(PZ(r))return cS(t,e,0,r);let a={...o};return a.capture===!0&&(a.wrap=!0),r=r||a.step||1,Ww(r)?Ww(t)&&Ww(e)?q5e(t,e,r,a):j5e(t,e,Math.max(Math.abs(r),1),a):r!=null&&!PZ(r)?H5e(r,a):cS(t,e,1,r)};RZ.exports=cS});var NZ=_((BQt,LZ)=>{\"use strict\";var G5e=cN(),TZ=aS(),W5e=(t,e={})=>{let r=(o,a={})=>{let n=TZ.isInvalidBrace(a),u=o.invalid===!0&&e.escapeInvalid===!0,A=n===!0||u===!0,p=e.escapeInvalid===!0?\"\\\\\":\"\",h=\"\";if(o.isOpen===!0||o.isClose===!0)return p+o.value;if(o.type===\"open\")return A?p+o.value:\"(\";if(o.type===\"close\")return A?p+o.value:\")\";if(o.type===\"comma\")return o.prev.type===\"comma\"?\"\":A?o.value:\"|\";if(o.value)return o.value;if(o.nodes&&o.ranges>0){let E=TZ.reduce(o.nodes),w=G5e(...E,{...e,wrap:!1,toRegex:!0});if(w.length!==0)return E.length>1&&w.length>1?`(${w})`:w}if(o.nodes)for(let E of o.nodes)h+=r(E,o);return h};return r(t)};LZ.exports=W5e});var UZ=_((vQt,MZ)=>{\"use strict\";var Y5e=cN(),OZ=lS(),Om=aS(),gg=(t=\"\",e=\"\",r=!1)=>{let o=[];if(t=[].concat(t),e=[].concat(e),!e.length)return t;if(!t.length)return r?Om.flatten(e).map(a=>`{${a}}`):e;for(let a of t)if(Array.isArray(a))for(let n of a)o.push(gg(n,e,r));else for(let n of e)r===!0&&typeof n==\"string\"&&(n=`{${n}}`),o.push(Array.isArray(n)?gg(a,n,r):a+n);return Om.flatten(o)},K5e=(t,e={})=>{let r=e.rangeLimit===void 0?1e3:e.rangeLimit,o=(a,n={})=>{a.queue=[];let u=n,A=n.queue;for(;u.type!==\"brace\"&&u.type!==\"root\"&&u.parent;)u=u.parent,A=u.queue;if(a.invalid||a.dollar){A.push(gg(A.pop(),OZ(a,e)));return}if(a.type===\"brace\"&&a.invalid!==!0&&a.nodes.length===2){A.push(gg(A.pop(),[\"{}\"]));return}if(a.nodes&&a.ranges>0){let w=Om.reduce(a.nodes);if(Om.exceedsLimit(...w,e.step,r))throw new RangeError(\"expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.\");let D=Y5e(...w,e);D.length===0&&(D=OZ(a,e)),A.push(gg(A.pop(),D)),a.nodes=[];return}let p=Om.encloseBrace(a),h=a.queue,E=a;for(;E.type!==\"brace\"&&E.type!==\"root\"&&E.parent;)E=E.parent,h=E.queue;for(let w=0;w<a.nodes.length;w++){let D=a.nodes[w];if(D.type===\"comma\"&&a.type===\"brace\"){w===1&&h.push(\"\"),h.push(\"\");continue}if(D.type===\"close\"){A.push(gg(A.pop(),h,p));continue}if(D.value&&D.type!==\"open\"){h.push(gg(h.pop(),D.value));continue}D.nodes&&o(D,a)}return h};return Om.flatten(o(t))};MZ.exports=K5e});var HZ=_((DQt,_Z)=>{\"use strict\";_Z.exports={MAX_LENGTH:1024*64,CHAR_0:\"0\",CHAR_9:\"9\",CHAR_UPPERCASE_A:\"A\",CHAR_LOWERCASE_A:\"a\",CHAR_UPPERCASE_Z:\"Z\",CHAR_LOWERCASE_Z:\"z\",CHAR_LEFT_PARENTHESES:\"(\",CHAR_RIGHT_PARENTHESES:\")\",CHAR_ASTERISK:\"*\",CHAR_AMPERSAND:\"&\",CHAR_AT:\"@\",CHAR_BACKSLASH:\"\\\\\",CHAR_BACKTICK:\"`\",CHAR_CARRIAGE_RETURN:\"\\r\",CHAR_CIRCUMFLEX_ACCENT:\"^\",CHAR_COLON:\":\",CHAR_COMMA:\",\",CHAR_DOLLAR:\"$\",CHAR_DOT:\".\",CHAR_DOUBLE_QUOTE:'\"',CHAR_EQUAL:\"=\",CHAR_EXCLAMATION_MARK:\"!\",CHAR_FORM_FEED:\"\\f\",CHAR_FORWARD_SLASH:\"/\",CHAR_HASH:\"#\",CHAR_HYPHEN_MINUS:\"-\",CHAR_LEFT_ANGLE_BRACKET:\"<\",CHAR_LEFT_CURLY_BRACE:\"{\",CHAR_LEFT_SQUARE_BRACKET:\"[\",CHAR_LINE_FEED:`\n`,CHAR_NO_BREAK_SPACE:\"\\xA0\",CHAR_PERCENT:\"%\",CHAR_PLUS:\"+\",CHAR_QUESTION_MARK:\"?\",CHAR_RIGHT_ANGLE_BRACKET:\">\",CHAR_RIGHT_CURLY_BRACE:\"}\",CHAR_RIGHT_SQUARE_BRACKET:\"]\",CHAR_SEMICOLON:\";\",CHAR_SINGLE_QUOTE:\"'\",CHAR_SPACE:\" \",CHAR_TAB:\"\t\",CHAR_UNDERSCORE:\"_\",CHAR_VERTICAL_LINE:\"|\",CHAR_ZERO_WIDTH_NOBREAK_SPACE:\"\\uFEFF\"}});var YZ=_((PQt,WZ)=>{\"use strict\";var V5e=lS(),{MAX_LENGTH:qZ,CHAR_BACKSLASH:uN,CHAR_BACKTICK:z5e,CHAR_COMMA:J5e,CHAR_DOT:X5e,CHAR_LEFT_PARENTHESES:Z5e,CHAR_RIGHT_PARENTHESES:$5e,CHAR_LEFT_CURLY_BRACE:e7e,CHAR_RIGHT_CURLY_BRACE:t7e,CHAR_LEFT_SQUARE_BRACKET:jZ,CHAR_RIGHT_SQUARE_BRACKET:GZ,CHAR_DOUBLE_QUOTE:r7e,CHAR_SINGLE_QUOTE:n7e,CHAR_NO_BREAK_SPACE:i7e,CHAR_ZERO_WIDTH_NOBREAK_SPACE:s7e}=HZ(),o7e=(t,e={})=>{if(typeof t!=\"string\")throw new TypeError(\"Expected a string\");let r=e||{},o=typeof r.maxLength==\"number\"?Math.min(qZ,r.maxLength):qZ;if(t.length>o)throw new SyntaxError(`Input length (${t.length}), exceeds max characters (${o})`);let a={type:\"root\",input:t,nodes:[]},n=[a],u=a,A=a,p=0,h=t.length,E=0,w=0,D,b={},C=()=>t[E++],T=N=>{if(N.type===\"text\"&&A.type===\"dot\"&&(A.type=\"text\"),A&&A.type===\"text\"&&N.type===\"text\"){A.value+=N.value;return}return u.nodes.push(N),N.parent=u,N.prev=A,A=N,N};for(T({type:\"bos\"});E<h;)if(u=n[n.length-1],D=C(),!(D===s7e||D===i7e)){if(D===uN){T({type:\"text\",value:(e.keepEscaping?D:\"\")+C()});continue}if(D===GZ){T({type:\"text\",value:\"\\\\\"+D});continue}if(D===jZ){p++;let N=!0,U;for(;E<h&&(U=C());){if(D+=U,U===jZ){p++;continue}if(U===uN){D+=C();continue}if(U===GZ&&(p--,p===0))break}T({type:\"text\",value:D});continue}if(D===Z5e){u=T({type:\"paren\",nodes:[]}),n.push(u),T({type:\"text\",value:D});continue}if(D===$5e){if(u.type!==\"paren\"){T({type:\"text\",value:D});continue}u=n.pop(),T({type:\"text\",value:D}),u=n[n.length-1];continue}if(D===r7e||D===n7e||D===z5e){let N=D,U;for(e.keepQuotes!==!0&&(D=\"\");E<h&&(U=C());){if(U===uN){D+=U+C();continue}if(U===N){e.keepQuotes===!0&&(D+=U);break}D+=U}T({type:\"text\",value:D});continue}if(D===e7e){w++;let U={type:\"brace\",open:!0,close:!1,dollar:A.value&&A.value.slice(-1)===\"$\"||u.dollar===!0,depth:w,commas:0,ranges:0,nodes:[]};u=T(U),n.push(u),T({type:\"open\",value:D});continue}if(D===t7e){if(u.type!==\"brace\"){T({type:\"text\",value:D});continue}let N=\"close\";u=n.pop(),u.close=!0,T({type:N,value:D}),w--,u=n[n.length-1];continue}if(D===J5e&&w>0){if(u.ranges>0){u.ranges=0;let N=u.nodes.shift();u.nodes=[N,{type:\"text\",value:V5e(u)}]}T({type:\"comma\",value:D}),u.commas++;continue}if(D===X5e&&w>0&&u.commas===0){let N=u.nodes;if(w===0||N.length===0){T({type:\"text\",value:D});continue}if(A.type===\"dot\"){if(u.range=[],A.value+=D,A.type=\"range\",u.nodes.length!==3&&u.nodes.length!==5){u.invalid=!0,u.ranges=0,A.type=\"text\";continue}u.ranges++,u.args=[];continue}if(A.type===\"range\"){N.pop();let U=N[N.length-1];U.value+=A.value+D,A=U,u.ranges--;continue}T({type:\"dot\",value:D});continue}T({type:\"text\",value:D})}do if(u=n.pop(),u.type!==\"root\"){u.nodes.forEach(z=>{z.nodes||(z.type===\"open\"&&(z.isOpen=!0),z.type===\"close\"&&(z.isClose=!0),z.nodes||(z.type=\"text\"),z.invalid=!0)});let N=n[n.length-1],U=N.nodes.indexOf(u);N.nodes.splice(U,1,...u.nodes)}while(n.length>0);return T({type:\"eos\"}),a};WZ.exports=o7e});var zZ=_((SQt,VZ)=>{\"use strict\";var KZ=lS(),a7e=NZ(),l7e=UZ(),c7e=YZ(),al=(t,e={})=>{let r=[];if(Array.isArray(t))for(let o of t){let a=al.create(o,e);Array.isArray(a)?r.push(...a):r.push(a)}else r=[].concat(al.create(t,e));return e&&e.expand===!0&&e.nodupes===!0&&(r=[...new Set(r)]),r};al.parse=(t,e={})=>c7e(t,e);al.stringify=(t,e={})=>KZ(typeof t==\"string\"?al.parse(t,e):t,e);al.compile=(t,e={})=>(typeof t==\"string\"&&(t=al.parse(t,e)),a7e(t,e));al.expand=(t,e={})=>{typeof t==\"string\"&&(t=al.parse(t,e));let r=l7e(t,e);return e.noempty===!0&&(r=r.filter(Boolean)),e.nodupes===!0&&(r=[...new Set(r)]),r};al.create=(t,e={})=>t===\"\"||t.length<3?[t]:e.expand!==!0?al.compile(t,e):al.expand(t,e);VZ.exports=al});var Yw=_((xQt,e$)=>{\"use strict\";var u7e=ve(\"path\"),Ju=\"\\\\\\\\/\",JZ=`[^${Ju}]`,Bf=\"\\\\.\",A7e=\"\\\\+\",f7e=\"\\\\?\",uS=\"\\\\/\",p7e=\"(?=.)\",XZ=\"[^/]\",AN=`(?:${uS}|$)`,ZZ=`(?:^|${uS})`,fN=`${Bf}{1,2}${AN}`,h7e=`(?!${Bf})`,g7e=`(?!${ZZ}${fN})`,d7e=`(?!${Bf}{0,1}${AN})`,m7e=`(?!${fN})`,y7e=`[^.${uS}]`,E7e=`${XZ}*?`,$Z={DOT_LITERAL:Bf,PLUS_LITERAL:A7e,QMARK_LITERAL:f7e,SLASH_LITERAL:uS,ONE_CHAR:p7e,QMARK:XZ,END_ANCHOR:AN,DOTS_SLASH:fN,NO_DOT:h7e,NO_DOTS:g7e,NO_DOT_SLASH:d7e,NO_DOTS_SLASH:m7e,QMARK_NO_DOT:y7e,STAR:E7e,START_ANCHOR:ZZ},C7e={...$Z,SLASH_LITERAL:`[${Ju}]`,QMARK:JZ,STAR:`${JZ}*?`,DOTS_SLASH:`${Bf}{1,2}(?:[${Ju}]|$)`,NO_DOT:`(?!${Bf})`,NO_DOTS:`(?!(?:^|[${Ju}])${Bf}{1,2}(?:[${Ju}]|$))`,NO_DOT_SLASH:`(?!${Bf}{0,1}(?:[${Ju}]|$))`,NO_DOTS_SLASH:`(?!${Bf}{1,2}(?:[${Ju}]|$))`,QMARK_NO_DOT:`[^.${Ju}]`,START_ANCHOR:`(?:^|[${Ju}])`,END_ANCHOR:`(?:[${Ju}]|$)`},I7e={alnum:\"a-zA-Z0-9\",alpha:\"a-zA-Z\",ascii:\"\\\\x00-\\\\x7F\",blank:\" \\\\t\",cntrl:\"\\\\x00-\\\\x1F\\\\x7F\",digit:\"0-9\",graph:\"\\\\x21-\\\\x7E\",lower:\"a-z\",print:\"\\\\x20-\\\\x7E \",punct:\"\\\\-!\\\"#$%&'()\\\\*+,./:;<=>?@[\\\\]^_`{|}~\",space:\" \\\\t\\\\r\\\\n\\\\v\\\\f\",upper:\"A-Z\",word:\"A-Za-z0-9_\",xdigit:\"A-Fa-f0-9\"};e$.exports={MAX_LENGTH:1024*64,POSIX_REGEX_SOURCE:I7e,REGEX_BACKSLASH:/\\\\(?![*+?^${}(|)[\\]])/g,REGEX_NON_SPECIAL_CHARS:/^[^@![\\].,$*+?^{}()|\\\\/]+/,REGEX_SPECIAL_CHARS:/[-*+?.^${}(|)[\\]]/,REGEX_SPECIAL_CHARS_BACKREF:/(\\\\?)((\\W)(\\3*))/g,REGEX_SPECIAL_CHARS_GLOBAL:/([-*+?.^${}(|)[\\]])/g,REGEX_REMOVE_BACKSLASH:/(?:\\[.*?[^\\\\]\\]|\\\\(?=.))/g,REPLACEMENTS:{\"***\":\"*\",\"**/**\":\"**\",\"**/**/**\":\"**\"},CHAR_0:48,CHAR_9:57,CHAR_UPPERCASE_A:65,CHAR_LOWERCASE_A:97,CHAR_UPPERCASE_Z:90,CHAR_LOWERCASE_Z:122,CHAR_LEFT_PARENTHESES:40,CHAR_RIGHT_PARENTHESES:41,CHAR_ASTERISK:42,CHAR_AMPERSAND:38,CHAR_AT:64,CHAR_BACKWARD_SLASH:92,CHAR_CARRIAGE_RETURN:13,CHAR_CIRCUMFLEX_ACCENT:94,CHAR_COLON:58,CHAR_COMMA:44,CHAR_DOT:46,CHAR_DOUBLE_QUOTE:34,CHAR_EQUAL:61,CHAR_EXCLAMATION_MARK:33,CHAR_FORM_FEED:12,CHAR_FORWARD_SLASH:47,CHAR_GRAVE_ACCENT:96,CHAR_HASH:35,CHAR_HYPHEN_MINUS:45,CHAR_LEFT_ANGLE_BRACKET:60,CHAR_LEFT_CURLY_BRACE:123,CHAR_LEFT_SQUARE_BRACKET:91,CHAR_LINE_FEED:10,CHAR_NO_BREAK_SPACE:160,CHAR_PERCENT:37,CHAR_PLUS:43,CHAR_QUESTION_MARK:63,CHAR_RIGHT_ANGLE_BRACKET:62,CHAR_RIGHT_CURLY_BRACE:125,CHAR_RIGHT_SQUARE_BRACKET:93,CHAR_SEMICOLON:59,CHAR_SINGLE_QUOTE:39,CHAR_SPACE:32,CHAR_TAB:9,CHAR_UNDERSCORE:95,CHAR_VERTICAL_LINE:124,CHAR_ZERO_WIDTH_NOBREAK_SPACE:65279,SEP:u7e.sep,extglobChars(t){return{\"!\":{type:\"negate\",open:\"(?:(?!(?:\",close:`))${t.STAR})`},\"?\":{type:\"qmark\",open:\"(?:\",close:\")?\"},\"+\":{type:\"plus\",open:\"(?:\",close:\")+\"},\"*\":{type:\"star\",open:\"(?:\",close:\")*\"},\"@\":{type:\"at\",open:\"(?:\",close:\")\"}}},globChars(t){return t===!0?C7e:$Z}}});var Kw=_(ba=>{\"use strict\";var w7e=ve(\"path\"),B7e=process.platform===\"win32\",{REGEX_BACKSLASH:v7e,REGEX_REMOVE_BACKSLASH:D7e,REGEX_SPECIAL_CHARS:P7e,REGEX_SPECIAL_CHARS_GLOBAL:S7e}=Yw();ba.isObject=t=>t!==null&&typeof t==\"object\"&&!Array.isArray(t);ba.hasRegexChars=t=>P7e.test(t);ba.isRegexChar=t=>t.length===1&&ba.hasRegexChars(t);ba.escapeRegex=t=>t.replace(S7e,\"\\\\$1\");ba.toPosixSlashes=t=>t.replace(v7e,\"/\");ba.removeBackslashes=t=>t.replace(D7e,e=>e===\"\\\\\"?\"\":e);ba.supportsLookbehinds=()=>{let t=process.version.slice(1).split(\".\").map(Number);return t.length===3&&t[0]>=9||t[0]===8&&t[1]>=10};ba.isWindows=t=>t&&typeof t.windows==\"boolean\"?t.windows:B7e===!0||w7e.sep===\"\\\\\";ba.escapeLast=(t,e,r)=>{let o=t.lastIndexOf(e,r);return o===-1?t:t[o-1]===\"\\\\\"?ba.escapeLast(t,e,o-1):`${t.slice(0,o)}\\\\${t.slice(o)}`};ba.removePrefix=(t,e={})=>{let r=t;return r.startsWith(\"./\")&&(r=r.slice(2),e.prefix=\"./\"),r};ba.wrapOutput=(t,e={},r={})=>{let o=r.contains?\"\":\"^\",a=r.contains?\"\":\"$\",n=`${o}(?:${t})${a}`;return e.negated===!0&&(n=`(?:^(?!${n}).*$)`),n}});var l$=_((kQt,a$)=>{\"use strict\";var t$=Kw(),{CHAR_ASTERISK:pN,CHAR_AT:x7e,CHAR_BACKWARD_SLASH:Vw,CHAR_COMMA:b7e,CHAR_DOT:hN,CHAR_EXCLAMATION_MARK:gN,CHAR_FORWARD_SLASH:o$,CHAR_LEFT_CURLY_BRACE:dN,CHAR_LEFT_PARENTHESES:mN,CHAR_LEFT_SQUARE_BRACKET:k7e,CHAR_PLUS:Q7e,CHAR_QUESTION_MARK:r$,CHAR_RIGHT_CURLY_BRACE:F7e,CHAR_RIGHT_PARENTHESES:n$,CHAR_RIGHT_SQUARE_BRACKET:R7e}=Yw(),i$=t=>t===o$||t===Vw,s$=t=>{t.isPrefix!==!0&&(t.depth=t.isGlobstar?1/0:1)},T7e=(t,e)=>{let r=e||{},o=t.length-1,a=r.parts===!0||r.scanToEnd===!0,n=[],u=[],A=[],p=t,h=-1,E=0,w=0,D=!1,b=!1,C=!1,T=!1,N=!1,U=!1,z=!1,te=!1,le=!1,ce=!1,ue=0,Ie,he,De={value:\"\",depth:0,isGlob:!1},Ee=()=>h>=o,g=()=>p.charCodeAt(h+1),me=()=>(Ie=he,p.charCodeAt(++h));for(;h<o;){he=me();let Pe;if(he===Vw){z=De.backslashes=!0,he=me(),he===dN&&(U=!0);continue}if(U===!0||he===dN){for(ue++;Ee()!==!0&&(he=me());){if(he===Vw){z=De.backslashes=!0,me();continue}if(he===dN){ue++;continue}if(U!==!0&&he===hN&&(he=me())===hN){if(D=De.isBrace=!0,C=De.isGlob=!0,ce=!0,a===!0)continue;break}if(U!==!0&&he===b7e){if(D=De.isBrace=!0,C=De.isGlob=!0,ce=!0,a===!0)continue;break}if(he===F7e&&(ue--,ue===0)){U=!1,D=De.isBrace=!0,ce=!0;break}}if(a===!0)continue;break}if(he===o$){if(n.push(h),u.push(De),De={value:\"\",depth:0,isGlob:!1},ce===!0)continue;if(Ie===hN&&h===E+1){E+=2;continue}w=h+1;continue}if(r.noext!==!0&&(he===Q7e||he===x7e||he===pN||he===r$||he===gN)===!0&&g()===mN){if(C=De.isGlob=!0,T=De.isExtglob=!0,ce=!0,he===gN&&h===E&&(le=!0),a===!0){for(;Ee()!==!0&&(he=me());){if(he===Vw){z=De.backslashes=!0,he=me();continue}if(he===n$){C=De.isGlob=!0,ce=!0;break}}continue}break}if(he===pN){if(Ie===pN&&(N=De.isGlobstar=!0),C=De.isGlob=!0,ce=!0,a===!0)continue;break}if(he===r$){if(C=De.isGlob=!0,ce=!0,a===!0)continue;break}if(he===k7e){for(;Ee()!==!0&&(Pe=me());){if(Pe===Vw){z=De.backslashes=!0,me();continue}if(Pe===R7e){b=De.isBracket=!0,C=De.isGlob=!0,ce=!0;break}}if(a===!0)continue;break}if(r.nonegate!==!0&&he===gN&&h===E){te=De.negated=!0,E++;continue}if(r.noparen!==!0&&he===mN){if(C=De.isGlob=!0,a===!0){for(;Ee()!==!0&&(he=me());){if(he===mN){z=De.backslashes=!0,he=me();continue}if(he===n$){ce=!0;break}}continue}break}if(C===!0){if(ce=!0,a===!0)continue;break}}r.noext===!0&&(T=!1,C=!1);let Ce=p,fe=\"\",ie=\"\";E>0&&(fe=p.slice(0,E),p=p.slice(E),w-=E),Ce&&C===!0&&w>0?(Ce=p.slice(0,w),ie=p.slice(w)):C===!0?(Ce=\"\",ie=p):Ce=p,Ce&&Ce!==\"\"&&Ce!==\"/\"&&Ce!==p&&i$(Ce.charCodeAt(Ce.length-1))&&(Ce=Ce.slice(0,-1)),r.unescape===!0&&(ie&&(ie=t$.removeBackslashes(ie)),Ce&&z===!0&&(Ce=t$.removeBackslashes(Ce)));let Z={prefix:fe,input:t,start:E,base:Ce,glob:ie,isBrace:D,isBracket:b,isGlob:C,isExtglob:T,isGlobstar:N,negated:te,negatedExtglob:le};if(r.tokens===!0&&(Z.maxDepth=0,i$(he)||u.push(De),Z.tokens=u),r.parts===!0||r.tokens===!0){let Pe;for(let Re=0;Re<n.length;Re++){let ht=Pe?Pe+1:E,q=n[Re],nt=t.slice(ht,q);r.tokens&&(Re===0&&E!==0?(u[Re].isPrefix=!0,u[Re].value=fe):u[Re].value=nt,s$(u[Re]),Z.maxDepth+=u[Re].depth),(Re!==0||nt!==\"\")&&A.push(nt),Pe=q}if(Pe&&Pe+1<t.length){let Re=t.slice(Pe+1);A.push(Re),r.tokens&&(u[u.length-1].value=Re,s$(u[u.length-1]),Z.maxDepth+=u[u.length-1].depth)}Z.slashes=n,Z.parts=A}return Z};a$.exports=T7e});var A$=_((QQt,u$)=>{\"use strict\";var AS=Yw(),ll=Kw(),{MAX_LENGTH:fS,POSIX_REGEX_SOURCE:L7e,REGEX_NON_SPECIAL_CHARS:N7e,REGEX_SPECIAL_CHARS_BACKREF:O7e,REPLACEMENTS:c$}=AS,M7e=(t,e)=>{if(typeof e.expandRange==\"function\")return e.expandRange(...t,e);t.sort();let r=`[${t.join(\"-\")}]`;try{new RegExp(r)}catch{return t.map(a=>ll.escapeRegex(a)).join(\"..\")}return r},Mm=(t,e)=>`Missing ${t}: \"${e}\" - use \"\\\\\\\\${e}\" to match literal characters`,yN=(t,e)=>{if(typeof t!=\"string\")throw new TypeError(\"Expected a string\");t=c$[t]||t;let r={...e},o=typeof r.maxLength==\"number\"?Math.min(fS,r.maxLength):fS,a=t.length;if(a>o)throw new SyntaxError(`Input length: ${a}, exceeds maximum allowed length: ${o}`);let n={type:\"bos\",value:\"\",output:r.prepend||\"\"},u=[n],A=r.capture?\"\":\"?:\",p=ll.isWindows(e),h=AS.globChars(p),E=AS.extglobChars(h),{DOT_LITERAL:w,PLUS_LITERAL:D,SLASH_LITERAL:b,ONE_CHAR:C,DOTS_SLASH:T,NO_DOT:N,NO_DOT_SLASH:U,NO_DOTS_SLASH:z,QMARK:te,QMARK_NO_DOT:le,STAR:ce,START_ANCHOR:ue}=h,Ie=x=>`(${A}(?:(?!${ue}${x.dot?T:w}).)*?)`,he=r.dot?\"\":N,De=r.dot?te:le,Ee=r.bash===!0?Ie(r):ce;r.capture&&(Ee=`(${Ee})`),typeof r.noext==\"boolean\"&&(r.noextglob=r.noext);let g={input:t,index:-1,start:0,dot:r.dot===!0,consumed:\"\",output:\"\",prefix:\"\",backtrack:!1,negated:!1,brackets:0,braces:0,parens:0,quotes:0,globstar:!1,tokens:u};t=ll.removePrefix(t,g),a=t.length;let me=[],Ce=[],fe=[],ie=n,Z,Pe=()=>g.index===a-1,Re=g.peek=(x=1)=>t[g.index+x],ht=g.advance=()=>t[++g.index]||\"\",q=()=>t.slice(g.index+1),nt=(x=\"\",I=0)=>{g.consumed+=x,g.index+=I},Le=x=>{g.output+=x.output!=null?x.output:x.value,nt(x.value)},Te=()=>{let x=1;for(;Re()===\"!\"&&(Re(2)!==\"(\"||Re(3)===\"?\");)ht(),g.start++,x++;return x%2===0?!1:(g.negated=!0,g.start++,!0)},ke=x=>{g[x]++,fe.push(x)},Ve=x=>{g[x]--,fe.pop()},xe=x=>{if(ie.type===\"globstar\"){let I=g.braces>0&&(x.type===\"comma\"||x.type===\"brace\"),S=x.extglob===!0||me.length&&(x.type===\"pipe\"||x.type===\"paren\");x.type!==\"slash\"&&x.type!==\"paren\"&&!I&&!S&&(g.output=g.output.slice(0,-ie.output.length),ie.type=\"star\",ie.value=\"*\",ie.output=Ee,g.output+=ie.output)}if(me.length&&x.type!==\"paren\"&&(me[me.length-1].inner+=x.value),(x.value||x.output)&&Le(x),ie&&ie.type===\"text\"&&x.type===\"text\"){ie.value+=x.value,ie.output=(ie.output||\"\")+x.value;return}x.prev=ie,u.push(x),ie=x},tt=(x,I)=>{let S={...E[I],conditions:1,inner:\"\"};S.prev=ie,S.parens=g.parens,S.output=g.output;let y=(r.capture?\"(\":\"\")+S.open;ke(\"parens\"),xe({type:x,value:I,output:g.output?\"\":C}),xe({type:\"paren\",extglob:!0,value:ht(),output:y}),me.push(S)},He=x=>{let I=x.close+(r.capture?\")\":\"\"),S;if(x.type===\"negate\"){let y=Ee;if(x.inner&&x.inner.length>1&&x.inner.includes(\"/\")&&(y=Ie(r)),(y!==Ee||Pe()||/^\\)+$/.test(q()))&&(I=x.close=`)$))${y}`),x.inner.includes(\"*\")&&(S=q())&&/^\\.[^\\\\/.]+$/.test(S)){let R=yN(S,{...e,fastpaths:!1}).output;I=x.close=`)${R})${y})`}x.prev.type===\"bos\"&&(g.negatedExtglob=!0)}xe({type:\"paren\",extglob:!0,value:Z,output:I}),Ve(\"parens\")};if(r.fastpaths!==!1&&!/(^[*!]|[/()[\\]{}\"])/.test(t)){let x=!1,I=t.replace(O7e,(S,y,R,J,X,$)=>J===\"\\\\\"?(x=!0,S):J===\"?\"?y?y+J+(X?te.repeat(X.length):\"\"):$===0?De+(X?te.repeat(X.length):\"\"):te.repeat(R.length):J===\".\"?w.repeat(R.length):J===\"*\"?y?y+J+(X?Ee:\"\"):Ee:y?S:`\\\\${S}`);return x===!0&&(r.unescape===!0?I=I.replace(/\\\\/g,\"\"):I=I.replace(/\\\\+/g,S=>S.length%2===0?\"\\\\\\\\\":S?\"\\\\\":\"\")),I===t&&r.contains===!0?(g.output=t,g):(g.output=ll.wrapOutput(I,g,e),g)}for(;!Pe();){if(Z=ht(),Z===\"\\0\")continue;if(Z===\"\\\\\"){let S=Re();if(S===\"/\"&&r.bash!==!0||S===\".\"||S===\";\")continue;if(!S){Z+=\"\\\\\",xe({type:\"text\",value:Z});continue}let y=/^\\\\+/.exec(q()),R=0;if(y&&y[0].length>2&&(R=y[0].length,g.index+=R,R%2!==0&&(Z+=\"\\\\\")),r.unescape===!0?Z=ht():Z+=ht(),g.brackets===0){xe({type:\"text\",value:Z});continue}}if(g.brackets>0&&(Z!==\"]\"||ie.value===\"[\"||ie.value===\"[^\")){if(r.posix!==!1&&Z===\":\"){let S=ie.value.slice(1);if(S.includes(\"[\")&&(ie.posix=!0,S.includes(\":\"))){let y=ie.value.lastIndexOf(\"[\"),R=ie.value.slice(0,y),J=ie.value.slice(y+2),X=L7e[J];if(X){ie.value=R+X,g.backtrack=!0,ht(),!n.output&&u.indexOf(ie)===1&&(n.output=C);continue}}}(Z===\"[\"&&Re()!==\":\"||Z===\"-\"&&Re()===\"]\")&&(Z=`\\\\${Z}`),Z===\"]\"&&(ie.value===\"[\"||ie.value===\"[^\")&&(Z=`\\\\${Z}`),r.posix===!0&&Z===\"!\"&&ie.value===\"[\"&&(Z=\"^\"),ie.value+=Z,Le({value:Z});continue}if(g.quotes===1&&Z!=='\"'){Z=ll.escapeRegex(Z),ie.value+=Z,Le({value:Z});continue}if(Z==='\"'){g.quotes=g.quotes===1?0:1,r.keepQuotes===!0&&xe({type:\"text\",value:Z});continue}if(Z===\"(\"){ke(\"parens\"),xe({type:\"paren\",value:Z});continue}if(Z===\")\"){if(g.parens===0&&r.strictBrackets===!0)throw new SyntaxError(Mm(\"opening\",\"(\"));let S=me[me.length-1];if(S&&g.parens===S.parens+1){He(me.pop());continue}xe({type:\"paren\",value:Z,output:g.parens?\")\":\"\\\\)\"}),Ve(\"parens\");continue}if(Z===\"[\"){if(r.nobracket===!0||!q().includes(\"]\")){if(r.nobracket!==!0&&r.strictBrackets===!0)throw new SyntaxError(Mm(\"closing\",\"]\"));Z=`\\\\${Z}`}else ke(\"brackets\");xe({type:\"bracket\",value:Z});continue}if(Z===\"]\"){if(r.nobracket===!0||ie&&ie.type===\"bracket\"&&ie.value.length===1){xe({type:\"text\",value:Z,output:`\\\\${Z}`});continue}if(g.brackets===0){if(r.strictBrackets===!0)throw new SyntaxError(Mm(\"opening\",\"[\"));xe({type:\"text\",value:Z,output:`\\\\${Z}`});continue}Ve(\"brackets\");let S=ie.value.slice(1);if(ie.posix!==!0&&S[0]===\"^\"&&!S.includes(\"/\")&&(Z=`/${Z}`),ie.value+=Z,Le({value:Z}),r.literalBrackets===!1||ll.hasRegexChars(S))continue;let y=ll.escapeRegex(ie.value);if(g.output=g.output.slice(0,-ie.value.length),r.literalBrackets===!0){g.output+=y,ie.value=y;continue}ie.value=`(${A}${y}|${ie.value})`,g.output+=ie.value;continue}if(Z===\"{\"&&r.nobrace!==!0){ke(\"braces\");let S={type:\"brace\",value:Z,output:\"(\",outputIndex:g.output.length,tokensIndex:g.tokens.length};Ce.push(S),xe(S);continue}if(Z===\"}\"){let S=Ce[Ce.length-1];if(r.nobrace===!0||!S){xe({type:\"text\",value:Z,output:Z});continue}let y=\")\";if(S.dots===!0){let R=u.slice(),J=[];for(let X=R.length-1;X>=0&&(u.pop(),R[X].type!==\"brace\");X--)R[X].type!==\"dots\"&&J.unshift(R[X].value);y=M7e(J,r),g.backtrack=!0}if(S.comma!==!0&&S.dots!==!0){let R=g.output.slice(0,S.outputIndex),J=g.tokens.slice(S.tokensIndex);S.value=S.output=\"\\\\{\",Z=y=\"\\\\}\",g.output=R;for(let X of J)g.output+=X.output||X.value}xe({type:\"brace\",value:Z,output:y}),Ve(\"braces\"),Ce.pop();continue}if(Z===\"|\"){me.length>0&&me[me.length-1].conditions++,xe({type:\"text\",value:Z});continue}if(Z===\",\"){let S=Z,y=Ce[Ce.length-1];y&&fe[fe.length-1]===\"braces\"&&(y.comma=!0,S=\"|\"),xe({type:\"comma\",value:Z,output:S});continue}if(Z===\"/\"){if(ie.type===\"dot\"&&g.index===g.start+1){g.start=g.index+1,g.consumed=\"\",g.output=\"\",u.pop(),ie=n;continue}xe({type:\"slash\",value:Z,output:b});continue}if(Z===\".\"){if(g.braces>0&&ie.type===\"dot\"){ie.value===\".\"&&(ie.output=w);let S=Ce[Ce.length-1];ie.type=\"dots\",ie.output+=Z,ie.value+=Z,S.dots=!0;continue}if(g.braces+g.parens===0&&ie.type!==\"bos\"&&ie.type!==\"slash\"){xe({type:\"text\",value:Z,output:w});continue}xe({type:\"dot\",value:Z,output:w});continue}if(Z===\"?\"){if(!(ie&&ie.value===\"(\")&&r.noextglob!==!0&&Re()===\"(\"&&Re(2)!==\"?\"){tt(\"qmark\",Z);continue}if(ie&&ie.type===\"paren\"){let y=Re(),R=Z;if(y===\"<\"&&!ll.supportsLookbehinds())throw new Error(\"Node.js v10 or higher is required for regex lookbehinds\");(ie.value===\"(\"&&!/[!=<:]/.test(y)||y===\"<\"&&!/<([!=]|\\w+>)/.test(q()))&&(R=`\\\\${Z}`),xe({type:\"text\",value:Z,output:R});continue}if(r.dot!==!0&&(ie.type===\"slash\"||ie.type===\"bos\")){xe({type:\"qmark\",value:Z,output:le});continue}xe({type:\"qmark\",value:Z,output:te});continue}if(Z===\"!\"){if(r.noextglob!==!0&&Re()===\"(\"&&(Re(2)!==\"?\"||!/[!=<:]/.test(Re(3)))){tt(\"negate\",Z);continue}if(r.nonegate!==!0&&g.index===0){Te();continue}}if(Z===\"+\"){if(r.noextglob!==!0&&Re()===\"(\"&&Re(2)!==\"?\"){tt(\"plus\",Z);continue}if(ie&&ie.value===\"(\"||r.regex===!1){xe({type:\"plus\",value:Z,output:D});continue}if(ie&&(ie.type===\"bracket\"||ie.type===\"paren\"||ie.type===\"brace\")||g.parens>0){xe({type:\"plus\",value:Z});continue}xe({type:\"plus\",value:D});continue}if(Z===\"@\"){if(r.noextglob!==!0&&Re()===\"(\"&&Re(2)!==\"?\"){xe({type:\"at\",extglob:!0,value:Z,output:\"\"});continue}xe({type:\"text\",value:Z});continue}if(Z!==\"*\"){(Z===\"$\"||Z===\"^\")&&(Z=`\\\\${Z}`);let S=N7e.exec(q());S&&(Z+=S[0],g.index+=S[0].length),xe({type:\"text\",value:Z});continue}if(ie&&(ie.type===\"globstar\"||ie.star===!0)){ie.type=\"star\",ie.star=!0,ie.value+=Z,ie.output=Ee,g.backtrack=!0,g.globstar=!0,nt(Z);continue}let x=q();if(r.noextglob!==!0&&/^\\([^?]/.test(x)){tt(\"star\",Z);continue}if(ie.type===\"star\"){if(r.noglobstar===!0){nt(Z);continue}let S=ie.prev,y=S.prev,R=S.type===\"slash\"||S.type===\"bos\",J=y&&(y.type===\"star\"||y.type===\"globstar\");if(r.bash===!0&&(!R||x[0]&&x[0]!==\"/\")){xe({type:\"star\",value:Z,output:\"\"});continue}let X=g.braces>0&&(S.type===\"comma\"||S.type===\"brace\"),$=me.length&&(S.type===\"pipe\"||S.type===\"paren\");if(!R&&S.type!==\"paren\"&&!X&&!$){xe({type:\"star\",value:Z,output:\"\"});continue}for(;x.slice(0,3)===\"/**\";){let se=t[g.index+4];if(se&&se!==\"/\")break;x=x.slice(3),nt(\"/**\",3)}if(S.type===\"bos\"&&Pe()){ie.type=\"globstar\",ie.value+=Z,ie.output=Ie(r),g.output=ie.output,g.globstar=!0,nt(Z);continue}if(S.type===\"slash\"&&S.prev.type!==\"bos\"&&!J&&Pe()){g.output=g.output.slice(0,-(S.output+ie.output).length),S.output=`(?:${S.output}`,ie.type=\"globstar\",ie.output=Ie(r)+(r.strictSlashes?\")\":\"|$)\"),ie.value+=Z,g.globstar=!0,g.output+=S.output+ie.output,nt(Z);continue}if(S.type===\"slash\"&&S.prev.type!==\"bos\"&&x[0]===\"/\"){let se=x[1]!==void 0?\"|$\":\"\";g.output=g.output.slice(0,-(S.output+ie.output).length),S.output=`(?:${S.output}`,ie.type=\"globstar\",ie.output=`${Ie(r)}${b}|${b}${se})`,ie.value+=Z,g.output+=S.output+ie.output,g.globstar=!0,nt(Z+ht()),xe({type:\"slash\",value:\"/\",output:\"\"});continue}if(S.type===\"bos\"&&x[0]===\"/\"){ie.type=\"globstar\",ie.value+=Z,ie.output=`(?:^|${b}|${Ie(r)}${b})`,g.output=ie.output,g.globstar=!0,nt(Z+ht()),xe({type:\"slash\",value:\"/\",output:\"\"});continue}g.output=g.output.slice(0,-ie.output.length),ie.type=\"globstar\",ie.output=Ie(r),ie.value+=Z,g.output+=ie.output,g.globstar=!0,nt(Z);continue}let I={type:\"star\",value:Z,output:Ee};if(r.bash===!0){I.output=\".*?\",(ie.type===\"bos\"||ie.type===\"slash\")&&(I.output=he+I.output),xe(I);continue}if(ie&&(ie.type===\"bracket\"||ie.type===\"paren\")&&r.regex===!0){I.output=Z,xe(I);continue}(g.index===g.start||ie.type===\"slash\"||ie.type===\"dot\")&&(ie.type===\"dot\"?(g.output+=U,ie.output+=U):r.dot===!0?(g.output+=z,ie.output+=z):(g.output+=he,ie.output+=he),Re()!==\"*\"&&(g.output+=C,ie.output+=C)),xe(I)}for(;g.brackets>0;){if(r.strictBrackets===!0)throw new SyntaxError(Mm(\"closing\",\"]\"));g.output=ll.escapeLast(g.output,\"[\"),Ve(\"brackets\")}for(;g.parens>0;){if(r.strictBrackets===!0)throw new SyntaxError(Mm(\"closing\",\")\"));g.output=ll.escapeLast(g.output,\"(\"),Ve(\"parens\")}for(;g.braces>0;){if(r.strictBrackets===!0)throw new SyntaxError(Mm(\"closing\",\"}\"));g.output=ll.escapeLast(g.output,\"{\"),Ve(\"braces\")}if(r.strictSlashes!==!0&&(ie.type===\"star\"||ie.type===\"bracket\")&&xe({type:\"maybe_slash\",value:\"\",output:`${b}?`}),g.backtrack===!0){g.output=\"\";for(let x of g.tokens)g.output+=x.output!=null?x.output:x.value,x.suffix&&(g.output+=x.suffix)}return g};yN.fastpaths=(t,e)=>{let r={...e},o=typeof r.maxLength==\"number\"?Math.min(fS,r.maxLength):fS,a=t.length;if(a>o)throw new SyntaxError(`Input length: ${a}, exceeds maximum allowed length: ${o}`);t=c$[t]||t;let n=ll.isWindows(e),{DOT_LITERAL:u,SLASH_LITERAL:A,ONE_CHAR:p,DOTS_SLASH:h,NO_DOT:E,NO_DOTS:w,NO_DOTS_SLASH:D,STAR:b,START_ANCHOR:C}=AS.globChars(n),T=r.dot?w:E,N=r.dot?D:E,U=r.capture?\"\":\"?:\",z={negated:!1,prefix:\"\"},te=r.bash===!0?\".*?\":b;r.capture&&(te=`(${te})`);let le=he=>he.noglobstar===!0?te:`(${U}(?:(?!${C}${he.dot?h:u}).)*?)`,ce=he=>{switch(he){case\"*\":return`${T}${p}${te}`;case\".*\":return`${u}${p}${te}`;case\"*.*\":return`${T}${te}${u}${p}${te}`;case\"*/*\":return`${T}${te}${A}${p}${N}${te}`;case\"**\":return T+le(r);case\"**/*\":return`(?:${T}${le(r)}${A})?${N}${p}${te}`;case\"**/*.*\":return`(?:${T}${le(r)}${A})?${N}${te}${u}${p}${te}`;case\"**/.*\":return`(?:${T}${le(r)}${A})?${u}${p}${te}`;default:{let De=/^(.*?)\\.(\\w+)$/.exec(he);if(!De)return;let Ee=ce(De[1]);return Ee?Ee+u+De[2]:void 0}}},ue=ll.removePrefix(t,z),Ie=ce(ue);return Ie&&r.strictSlashes!==!0&&(Ie+=`${A}?`),Ie};u$.exports=yN});var p$=_((FQt,f$)=>{\"use strict\";var U7e=ve(\"path\"),_7e=l$(),EN=A$(),CN=Kw(),H7e=Yw(),q7e=t=>t&&typeof t==\"object\"&&!Array.isArray(t),Mi=(t,e,r=!1)=>{if(Array.isArray(t)){let E=t.map(D=>Mi(D,e,r));return D=>{for(let b of E){let C=b(D);if(C)return C}return!1}}let o=q7e(t)&&t.tokens&&t.input;if(t===\"\"||typeof t!=\"string\"&&!o)throw new TypeError(\"Expected pattern to be a non-empty string\");let a=e||{},n=CN.isWindows(e),u=o?Mi.compileRe(t,e):Mi.makeRe(t,e,!1,!0),A=u.state;delete u.state;let p=()=>!1;if(a.ignore){let E={...e,ignore:null,onMatch:null,onResult:null};p=Mi(a.ignore,E,r)}let h=(E,w=!1)=>{let{isMatch:D,match:b,output:C}=Mi.test(E,u,e,{glob:t,posix:n}),T={glob:t,state:A,regex:u,posix:n,input:E,output:C,match:b,isMatch:D};return typeof a.onResult==\"function\"&&a.onResult(T),D===!1?(T.isMatch=!1,w?T:!1):p(E)?(typeof a.onIgnore==\"function\"&&a.onIgnore(T),T.isMatch=!1,w?T:!1):(typeof a.onMatch==\"function\"&&a.onMatch(T),w?T:!0)};return r&&(h.state=A),h};Mi.test=(t,e,r,{glob:o,posix:a}={})=>{if(typeof t!=\"string\")throw new TypeError(\"Expected input to be a string\");if(t===\"\")return{isMatch:!1,output:\"\"};let n=r||{},u=n.format||(a?CN.toPosixSlashes:null),A=t===o,p=A&&u?u(t):t;return A===!1&&(p=u?u(t):t,A=p===o),(A===!1||n.capture===!0)&&(n.matchBase===!0||n.basename===!0?A=Mi.matchBase(t,e,r,a):A=e.exec(p)),{isMatch:!!A,match:A,output:p}};Mi.matchBase=(t,e,r,o=CN.isWindows(r))=>(e instanceof RegExp?e:Mi.makeRe(e,r)).test(U7e.basename(t));Mi.isMatch=(t,e,r)=>Mi(e,r)(t);Mi.parse=(t,e)=>Array.isArray(t)?t.map(r=>Mi.parse(r,e)):EN(t,{...e,fastpaths:!1});Mi.scan=(t,e)=>_7e(t,e);Mi.compileRe=(t,e,r=!1,o=!1)=>{if(r===!0)return t.output;let a=e||{},n=a.contains?\"\":\"^\",u=a.contains?\"\":\"$\",A=`${n}(?:${t.output})${u}`;t&&t.negated===!0&&(A=`^(?!${A}).*$`);let p=Mi.toRegex(A,e);return o===!0&&(p.state=t),p};Mi.makeRe=(t,e={},r=!1,o=!1)=>{if(!t||typeof t!=\"string\")throw new TypeError(\"Expected a non-empty string\");let a={negated:!1,fastpaths:!0};return e.fastpaths!==!1&&(t[0]===\".\"||t[0]===\"*\")&&(a.output=EN.fastpaths(t,e)),a.output||(a=EN(t,e)),Mi.compileRe(a,e,r,o)};Mi.toRegex=(t,e)=>{try{let r=e||{};return new RegExp(t,r.flags||(r.nocase?\"i\":\"\"))}catch(r){if(e&&e.debug===!0)throw r;return/$^/}};Mi.constants=H7e;f$.exports=Mi});var g$=_((RQt,h$)=>{\"use strict\";h$.exports=p$()});var Xo=_((TQt,E$)=>{\"use strict\";var m$=ve(\"util\"),y$=zZ(),Xu=g$(),IN=Kw(),d$=t=>t===\"\"||t===\"./\",Ii=(t,e,r)=>{e=[].concat(e),t=[].concat(t);let o=new Set,a=new Set,n=new Set,u=0,A=E=>{n.add(E.output),r&&r.onResult&&r.onResult(E)};for(let E=0;E<e.length;E++){let w=Xu(String(e[E]),{...r,onResult:A},!0),D=w.state.negated||w.state.negatedExtglob;D&&u++;for(let b of t){let C=w(b,!0);(D?!C.isMatch:C.isMatch)&&(D?o.add(C.output):(o.delete(C.output),a.add(C.output)))}}let h=(u===e.length?[...n]:[...a]).filter(E=>!o.has(E));if(r&&h.length===0){if(r.failglob===!0)throw new Error(`No matches found for \"${e.join(\", \")}\"`);if(r.nonull===!0||r.nullglob===!0)return r.unescape?e.map(E=>E.replace(/\\\\/g,\"\")):e}return h};Ii.match=Ii;Ii.matcher=(t,e)=>Xu(t,e);Ii.isMatch=(t,e,r)=>Xu(e,r)(t);Ii.any=Ii.isMatch;Ii.not=(t,e,r={})=>{e=[].concat(e).map(String);let o=new Set,a=[],n=A=>{r.onResult&&r.onResult(A),a.push(A.output)},u=new Set(Ii(t,e,{...r,onResult:n}));for(let A of a)u.has(A)||o.add(A);return[...o]};Ii.contains=(t,e,r)=>{if(typeof t!=\"string\")throw new TypeError(`Expected a string: \"${m$.inspect(t)}\"`);if(Array.isArray(e))return e.some(o=>Ii.contains(t,o,r));if(typeof e==\"string\"){if(d$(t)||d$(e))return!1;if(t.includes(e)||t.startsWith(\"./\")&&t.slice(2).includes(e))return!0}return Ii.isMatch(t,e,{...r,contains:!0})};Ii.matchKeys=(t,e,r)=>{if(!IN.isObject(t))throw new TypeError(\"Expected the first argument to be an object\");let o=Ii(Object.keys(t),e,r),a={};for(let n of o)a[n]=t[n];return a};Ii.some=(t,e,r)=>{let o=[].concat(t);for(let a of[].concat(e)){let n=Xu(String(a),r);if(o.some(u=>n(u)))return!0}return!1};Ii.every=(t,e,r)=>{let o=[].concat(t);for(let a of[].concat(e)){let n=Xu(String(a),r);if(!o.every(u=>n(u)))return!1}return!0};Ii.all=(t,e,r)=>{if(typeof t!=\"string\")throw new TypeError(`Expected a string: \"${m$.inspect(t)}\"`);return[].concat(e).every(o=>Xu(o,r)(t))};Ii.capture=(t,e,r)=>{let o=IN.isWindows(r),n=Xu.makeRe(String(t),{...r,capture:!0}).exec(o?IN.toPosixSlashes(e):e);if(n)return n.slice(1).map(u=>u===void 0?\"\":u)};Ii.makeRe=(...t)=>Xu.makeRe(...t);Ii.scan=(...t)=>Xu.scan(...t);Ii.parse=(t,e)=>{let r=[];for(let o of[].concat(t||[]))for(let a of y$(String(o),e))r.push(Xu.parse(a,e));return r};Ii.braces=(t,e)=>{if(typeof t!=\"string\")throw new TypeError(\"Expected a string\");return e&&e.nobrace===!0||!/\\{.*\\}/.test(t)?[t]:y$(t,e)};Ii.braceExpand=(t,e)=>{if(typeof t!=\"string\")throw new TypeError(\"Expected a string\");return Ii.braces(t,{...e,expand:!0})};E$.exports=Ii});var I$=_((LQt,C$)=>{\"use strict\";C$.exports=({onlyFirst:t=!1}={})=>{let e=[\"[\\\\u001B\\\\u009B][[\\\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\\\d\\\\/#&.:=?%@~_]+)*|[a-zA-Z\\\\d]+(?:;[-a-zA-Z\\\\d\\\\/#&.:=?%@~_]*)*)?\\\\u0007)\",\"(?:(?:\\\\d{1,4}(?:;\\\\d{0,4})*)?[\\\\dA-PR-TZcf-ntqry=><~]))\"].join(\"|\");return new RegExp(e,t?void 0:\"g\")}});var pS=_((NQt,w$)=>{\"use strict\";var j7e=I$();w$.exports=t=>typeof t==\"string\"?t.replace(j7e(),\"\"):t});var v$=_((OQt,B$)=>{function G7e(){this.__data__=[],this.size=0}B$.exports=G7e});var Um=_((MQt,D$)=>{function W7e(t,e){return t===e||t!==t&&e!==e}D$.exports=W7e});var zw=_((UQt,P$)=>{var Y7e=Um();function K7e(t,e){for(var r=t.length;r--;)if(Y7e(t[r][0],e))return r;return-1}P$.exports=K7e});var x$=_((_Qt,S$)=>{var V7e=zw(),z7e=Array.prototype,J7e=z7e.splice;function X7e(t){var e=this.__data__,r=V7e(e,t);if(r<0)return!1;var o=e.length-1;return r==o?e.pop():J7e.call(e,r,1),--this.size,!0}S$.exports=X7e});var k$=_((HQt,b$)=>{var Z7e=zw();function $7e(t){var e=this.__data__,r=Z7e(e,t);return r<0?void 0:e[r][1]}b$.exports=$7e});var F$=_((qQt,Q$)=>{var eWe=zw();function tWe(t){return eWe(this.__data__,t)>-1}Q$.exports=tWe});var T$=_((jQt,R$)=>{var rWe=zw();function nWe(t,e){var r=this.__data__,o=rWe(r,t);return o<0?(++this.size,r.push([t,e])):r[o][1]=e,this}R$.exports=nWe});var Jw=_((GQt,L$)=>{var iWe=v$(),sWe=x$(),oWe=k$(),aWe=F$(),lWe=T$();function _m(t){var e=-1,r=t==null?0:t.length;for(this.clear();++e<r;){var o=t[e];this.set(o[0],o[1])}}_m.prototype.clear=iWe;_m.prototype.delete=sWe;_m.prototype.get=oWe;_m.prototype.has=aWe;_m.prototype.set=lWe;L$.exports=_m});var O$=_((WQt,N$)=>{var cWe=Jw();function uWe(){this.__data__=new cWe,this.size=0}N$.exports=uWe});var U$=_((YQt,M$)=>{function AWe(t){var e=this.__data__,r=e.delete(t);return this.size=e.size,r}M$.exports=AWe});var H$=_((KQt,_$)=>{function fWe(t){return this.__data__.get(t)}_$.exports=fWe});var j$=_((VQt,q$)=>{function pWe(t){return this.__data__.has(t)}q$.exports=pWe});var wN=_((zQt,G$)=>{var hWe=typeof global==\"object\"&&global&&global.Object===Object&&global;G$.exports=hWe});var ql=_((JQt,W$)=>{var gWe=wN(),dWe=typeof self==\"object\"&&self&&self.Object===Object&&self,mWe=gWe||dWe||Function(\"return this\")();W$.exports=mWe});var dg=_((XQt,Y$)=>{var yWe=ql(),EWe=yWe.Symbol;Y$.exports=EWe});var J$=_((ZQt,z$)=>{var K$=dg(),V$=Object.prototype,CWe=V$.hasOwnProperty,IWe=V$.toString,Xw=K$?K$.toStringTag:void 0;function wWe(t){var e=CWe.call(t,Xw),r=t[Xw];try{t[Xw]=void 0;var o=!0}catch{}var a=IWe.call(t);return o&&(e?t[Xw]=r:delete t[Xw]),a}z$.exports=wWe});var Z$=_(($Qt,X$)=>{var BWe=Object.prototype,vWe=BWe.toString;function DWe(t){return vWe.call(t)}X$.exports=DWe});var mg=_((eFt,tee)=>{var $$=dg(),PWe=J$(),SWe=Z$(),xWe=\"[object Null]\",bWe=\"[object Undefined]\",eee=$$?$$.toStringTag:void 0;function kWe(t){return t==null?t===void 0?bWe:xWe:eee&&eee in Object(t)?PWe(t):SWe(t)}tee.exports=kWe});var cl=_((tFt,ree)=>{function QWe(t){var e=typeof t;return t!=null&&(e==\"object\"||e==\"function\")}ree.exports=QWe});var hS=_((rFt,nee)=>{var FWe=mg(),RWe=cl(),TWe=\"[object AsyncFunction]\",LWe=\"[object Function]\",NWe=\"[object GeneratorFunction]\",OWe=\"[object Proxy]\";function MWe(t){if(!RWe(t))return!1;var e=FWe(t);return e==LWe||e==NWe||e==TWe||e==OWe}nee.exports=MWe});var see=_((nFt,iee)=>{var UWe=ql(),_We=UWe[\"__core-js_shared__\"];iee.exports=_We});var lee=_((iFt,aee)=>{var BN=see(),oee=function(){var t=/[^.]+$/.exec(BN&&BN.keys&&BN.keys.IE_PROTO||\"\");return t?\"Symbol(src)_1.\"+t:\"\"}();function HWe(t){return!!oee&&oee in t}aee.exports=HWe});var vN=_((sFt,cee)=>{var qWe=Function.prototype,jWe=qWe.toString;function GWe(t){if(t!=null){try{return jWe.call(t)}catch{}try{return t+\"\"}catch{}}return\"\"}cee.exports=GWe});var Aee=_((oFt,uee)=>{var WWe=hS(),YWe=lee(),KWe=cl(),VWe=vN(),zWe=/[\\\\^$.*+?()[\\]{}|]/g,JWe=/^\\[object .+?Constructor\\]$/,XWe=Function.prototype,ZWe=Object.prototype,$We=XWe.toString,eYe=ZWe.hasOwnProperty,tYe=RegExp(\"^\"+$We.call(eYe).replace(zWe,\"\\\\$&\").replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g,\"$1.*?\")+\"$\");function rYe(t){if(!KWe(t)||YWe(t))return!1;var e=WWe(t)?tYe:JWe;return e.test(VWe(t))}uee.exports=rYe});var pee=_((aFt,fee)=>{function nYe(t,e){return t?.[e]}fee.exports=nYe});var $p=_((lFt,hee)=>{var iYe=Aee(),sYe=pee();function oYe(t,e){var r=sYe(t,e);return iYe(r)?r:void 0}hee.exports=oYe});var gS=_((cFt,gee)=>{var aYe=$p(),lYe=ql(),cYe=aYe(lYe,\"Map\");gee.exports=cYe});var Zw=_((uFt,dee)=>{var uYe=$p(),AYe=uYe(Object,\"create\");dee.exports=AYe});var Eee=_((AFt,yee)=>{var mee=Zw();function fYe(){this.__data__=mee?mee(null):{},this.size=0}yee.exports=fYe});var Iee=_((fFt,Cee)=>{function pYe(t){var e=this.has(t)&&delete this.__data__[t];return this.size-=e?1:0,e}Cee.exports=pYe});var Bee=_((pFt,wee)=>{var hYe=Zw(),gYe=\"__lodash_hash_undefined__\",dYe=Object.prototype,mYe=dYe.hasOwnProperty;function yYe(t){var e=this.__data__;if(hYe){var r=e[t];return r===gYe?void 0:r}return mYe.call(e,t)?e[t]:void 0}wee.exports=yYe});var Dee=_((hFt,vee)=>{var EYe=Zw(),CYe=Object.prototype,IYe=CYe.hasOwnProperty;function wYe(t){var e=this.__data__;return EYe?e[t]!==void 0:IYe.call(e,t)}vee.exports=wYe});var See=_((gFt,Pee)=>{var BYe=Zw(),vYe=\"__lodash_hash_undefined__\";function DYe(t,e){var r=this.__data__;return this.size+=this.has(t)?0:1,r[t]=BYe&&e===void 0?vYe:e,this}Pee.exports=DYe});var bee=_((dFt,xee)=>{var PYe=Eee(),SYe=Iee(),xYe=Bee(),bYe=Dee(),kYe=See();function Hm(t){var e=-1,r=t==null?0:t.length;for(this.clear();++e<r;){var o=t[e];this.set(o[0],o[1])}}Hm.prototype.clear=PYe;Hm.prototype.delete=SYe;Hm.prototype.get=xYe;Hm.prototype.has=bYe;Hm.prototype.set=kYe;xee.exports=Hm});var Fee=_((mFt,Qee)=>{var kee=bee(),QYe=Jw(),FYe=gS();function RYe(){this.size=0,this.__data__={hash:new kee,map:new(FYe||QYe),string:new kee}}Qee.exports=RYe});var Tee=_((yFt,Ree)=>{function TYe(t){var e=typeof t;return e==\"string\"||e==\"number\"||e==\"symbol\"||e==\"boolean\"?t!==\"__proto__\":t===null}Ree.exports=TYe});var $w=_((EFt,Lee)=>{var LYe=Tee();function NYe(t,e){var r=t.__data__;return LYe(e)?r[typeof e==\"string\"?\"string\":\"hash\"]:r.map}Lee.exports=NYe});var Oee=_((CFt,Nee)=>{var OYe=$w();function MYe(t){var e=OYe(this,t).delete(t);return this.size-=e?1:0,e}Nee.exports=MYe});var Uee=_((IFt,Mee)=>{var UYe=$w();function _Ye(t){return UYe(this,t).get(t)}Mee.exports=_Ye});var Hee=_((wFt,_ee)=>{var HYe=$w();function qYe(t){return HYe(this,t).has(t)}_ee.exports=qYe});var jee=_((BFt,qee)=>{var jYe=$w();function GYe(t,e){var r=jYe(this,t),o=r.size;return r.set(t,e),this.size+=r.size==o?0:1,this}qee.exports=GYe});var dS=_((vFt,Gee)=>{var WYe=Fee(),YYe=Oee(),KYe=Uee(),VYe=Hee(),zYe=jee();function qm(t){var e=-1,r=t==null?0:t.length;for(this.clear();++e<r;){var o=t[e];this.set(o[0],o[1])}}qm.prototype.clear=WYe;qm.prototype.delete=YYe;qm.prototype.get=KYe;qm.prototype.has=VYe;qm.prototype.set=zYe;Gee.exports=qm});var Yee=_((DFt,Wee)=>{var JYe=Jw(),XYe=gS(),ZYe=dS(),$Ye=200;function eKe(t,e){var r=this.__data__;if(r instanceof JYe){var o=r.__data__;if(!XYe||o.length<$Ye-1)return o.push([t,e]),this.size=++r.size,this;r=this.__data__=new ZYe(o)}return r.set(t,e),this.size=r.size,this}Wee.exports=eKe});var mS=_((PFt,Kee)=>{var tKe=Jw(),rKe=O$(),nKe=U$(),iKe=H$(),sKe=j$(),oKe=Yee();function jm(t){var e=this.__data__=new tKe(t);this.size=e.size}jm.prototype.clear=rKe;jm.prototype.delete=nKe;jm.prototype.get=iKe;jm.prototype.has=sKe;jm.prototype.set=oKe;Kee.exports=jm});var zee=_((SFt,Vee)=>{var aKe=\"__lodash_hash_undefined__\";function lKe(t){return this.__data__.set(t,aKe),this}Vee.exports=lKe});var Xee=_((xFt,Jee)=>{function cKe(t){return this.__data__.has(t)}Jee.exports=cKe});var $ee=_((bFt,Zee)=>{var uKe=dS(),AKe=zee(),fKe=Xee();function yS(t){var e=-1,r=t==null?0:t.length;for(this.__data__=new uKe;++e<r;)this.add(t[e])}yS.prototype.add=yS.prototype.push=AKe;yS.prototype.has=fKe;Zee.exports=yS});var tte=_((kFt,ete)=>{function pKe(t,e){for(var r=-1,o=t==null?0:t.length;++r<o;)if(e(t[r],r,t))return!0;return!1}ete.exports=pKe});var nte=_((QFt,rte)=>{function hKe(t,e){return t.has(e)}rte.exports=hKe});var DN=_((FFt,ite)=>{var gKe=$ee(),dKe=tte(),mKe=nte(),yKe=1,EKe=2;function CKe(t,e,r,o,a,n){var u=r&yKe,A=t.length,p=e.length;if(A!=p&&!(u&&p>A))return!1;var h=n.get(t),E=n.get(e);if(h&&E)return h==e&&E==t;var w=-1,D=!0,b=r&EKe?new gKe:void 0;for(n.set(t,e),n.set(e,t);++w<A;){var C=t[w],T=e[w];if(o)var N=u?o(T,C,w,e,t,n):o(C,T,w,t,e,n);if(N!==void 0){if(N)continue;D=!1;break}if(b){if(!dKe(e,function(U,z){if(!mKe(b,z)&&(C===U||a(C,U,r,o,n)))return b.push(z)})){D=!1;break}}else if(!(C===T||a(C,T,r,o,n))){D=!1;break}}return n.delete(t),n.delete(e),D}ite.exports=CKe});var PN=_((RFt,ste)=>{var IKe=ql(),wKe=IKe.Uint8Array;ste.exports=wKe});var ate=_((TFt,ote)=>{function BKe(t){var e=-1,r=Array(t.size);return t.forEach(function(o,a){r[++e]=[a,o]}),r}ote.exports=BKe});var cte=_((LFt,lte)=>{function vKe(t){var e=-1,r=Array(t.size);return t.forEach(function(o){r[++e]=o}),r}lte.exports=vKe});var hte=_((NFt,pte)=>{var ute=dg(),Ate=PN(),DKe=Um(),PKe=DN(),SKe=ate(),xKe=cte(),bKe=1,kKe=2,QKe=\"[object Boolean]\",FKe=\"[object Date]\",RKe=\"[object Error]\",TKe=\"[object Map]\",LKe=\"[object Number]\",NKe=\"[object RegExp]\",OKe=\"[object Set]\",MKe=\"[object String]\",UKe=\"[object Symbol]\",_Ke=\"[object ArrayBuffer]\",HKe=\"[object DataView]\",fte=ute?ute.prototype:void 0,SN=fte?fte.valueOf:void 0;function qKe(t,e,r,o,a,n,u){switch(r){case HKe:if(t.byteLength!=e.byteLength||t.byteOffset!=e.byteOffset)return!1;t=t.buffer,e=e.buffer;case _Ke:return!(t.byteLength!=e.byteLength||!n(new Ate(t),new Ate(e)));case QKe:case FKe:case LKe:return DKe(+t,+e);case RKe:return t.name==e.name&&t.message==e.message;case NKe:case MKe:return t==e+\"\";case TKe:var A=SKe;case OKe:var p=o&bKe;if(A||(A=xKe),t.size!=e.size&&!p)return!1;var h=u.get(t);if(h)return h==e;o|=kKe,u.set(t,e);var E=PKe(A(t),A(e),o,a,n,u);return u.delete(t),E;case UKe:if(SN)return SN.call(t)==SN.call(e)}return!1}pte.exports=qKe});var ES=_((OFt,gte)=>{function jKe(t,e){for(var r=-1,o=e.length,a=t.length;++r<o;)t[a+r]=e[r];return t}gte.exports=jKe});var jl=_((MFt,dte)=>{var GKe=Array.isArray;dte.exports=GKe});var xN=_((UFt,mte)=>{var WKe=ES(),YKe=jl();function KKe(t,e,r){var o=e(t);return YKe(t)?o:WKe(o,r(t))}mte.exports=KKe});var Ete=_((_Ft,yte)=>{function VKe(t,e){for(var r=-1,o=t==null?0:t.length,a=0,n=[];++r<o;){var u=t[r];e(u,r,t)&&(n[a++]=u)}return n}yte.exports=VKe});var bN=_((HFt,Cte)=>{function zKe(){return[]}Cte.exports=zKe});var CS=_((qFt,wte)=>{var JKe=Ete(),XKe=bN(),ZKe=Object.prototype,$Ke=ZKe.propertyIsEnumerable,Ite=Object.getOwnPropertySymbols,eVe=Ite?function(t){return t==null?[]:(t=Object(t),JKe(Ite(t),function(e){return $Ke.call(t,e)}))}:XKe;wte.exports=eVe});var vte=_((jFt,Bte)=>{function tVe(t,e){for(var r=-1,o=Array(t);++r<t;)o[r]=e(r);return o}Bte.exports=tVe});var Zu=_((GFt,Dte)=>{function rVe(t){return t!=null&&typeof t==\"object\"}Dte.exports=rVe});var Ste=_((WFt,Pte)=>{var nVe=mg(),iVe=Zu(),sVe=\"[object Arguments]\";function oVe(t){return iVe(t)&&nVe(t)==sVe}Pte.exports=oVe});var e1=_((YFt,kte)=>{var xte=Ste(),aVe=Zu(),bte=Object.prototype,lVe=bte.hasOwnProperty,cVe=bte.propertyIsEnumerable,uVe=xte(function(){return arguments}())?xte:function(t){return aVe(t)&&lVe.call(t,\"callee\")&&!cVe.call(t,\"callee\")};kte.exports=uVe});var Fte=_((KFt,Qte)=>{function AVe(){return!1}Qte.exports=AVe});var r1=_((t1,Gm)=>{var fVe=ql(),pVe=Fte(),Lte=typeof t1==\"object\"&&t1&&!t1.nodeType&&t1,Rte=Lte&&typeof Gm==\"object\"&&Gm&&!Gm.nodeType&&Gm,hVe=Rte&&Rte.exports===Lte,Tte=hVe?fVe.Buffer:void 0,gVe=Tte?Tte.isBuffer:void 0,dVe=gVe||pVe;Gm.exports=dVe});var n1=_((VFt,Nte)=>{var mVe=9007199254740991,yVe=/^(?:0|[1-9]\\d*)$/;function EVe(t,e){var r=typeof t;return e=e??mVe,!!e&&(r==\"number\"||r!=\"symbol\"&&yVe.test(t))&&t>-1&&t%1==0&&t<e}Nte.exports=EVe});var IS=_((zFt,Ote)=>{var CVe=9007199254740991;function IVe(t){return typeof t==\"number\"&&t>-1&&t%1==0&&t<=CVe}Ote.exports=IVe});var Ute=_((JFt,Mte)=>{var wVe=mg(),BVe=IS(),vVe=Zu(),DVe=\"[object Arguments]\",PVe=\"[object Array]\",SVe=\"[object Boolean]\",xVe=\"[object Date]\",bVe=\"[object Error]\",kVe=\"[object Function]\",QVe=\"[object Map]\",FVe=\"[object Number]\",RVe=\"[object Object]\",TVe=\"[object RegExp]\",LVe=\"[object Set]\",NVe=\"[object String]\",OVe=\"[object WeakMap]\",MVe=\"[object ArrayBuffer]\",UVe=\"[object DataView]\",_Ve=\"[object Float32Array]\",HVe=\"[object Float64Array]\",qVe=\"[object Int8Array]\",jVe=\"[object Int16Array]\",GVe=\"[object Int32Array]\",WVe=\"[object Uint8Array]\",YVe=\"[object Uint8ClampedArray]\",KVe=\"[object Uint16Array]\",VVe=\"[object Uint32Array]\",di={};di[_Ve]=di[HVe]=di[qVe]=di[jVe]=di[GVe]=di[WVe]=di[YVe]=di[KVe]=di[VVe]=!0;di[DVe]=di[PVe]=di[MVe]=di[SVe]=di[UVe]=di[xVe]=di[bVe]=di[kVe]=di[QVe]=di[FVe]=di[RVe]=di[TVe]=di[LVe]=di[NVe]=di[OVe]=!1;function zVe(t){return vVe(t)&&BVe(t.length)&&!!di[wVe(t)]}Mte.exports=zVe});var wS=_((XFt,_te)=>{function JVe(t){return function(e){return t(e)}}_te.exports=JVe});var BS=_((i1,Wm)=>{var XVe=wN(),Hte=typeof i1==\"object\"&&i1&&!i1.nodeType&&i1,s1=Hte&&typeof Wm==\"object\"&&Wm&&!Wm.nodeType&&Wm,ZVe=s1&&s1.exports===Hte,kN=ZVe&&XVe.process,$Ve=function(){try{var t=s1&&s1.require&&s1.require(\"util\").types;return t||kN&&kN.binding&&kN.binding(\"util\")}catch{}}();Wm.exports=$Ve});var vS=_((ZFt,Gte)=>{var eze=Ute(),tze=wS(),qte=BS(),jte=qte&&qte.isTypedArray,rze=jte?tze(jte):eze;Gte.exports=rze});var QN=_(($Ft,Wte)=>{var nze=vte(),ize=e1(),sze=jl(),oze=r1(),aze=n1(),lze=vS(),cze=Object.prototype,uze=cze.hasOwnProperty;function Aze(t,e){var r=sze(t),o=!r&&ize(t),a=!r&&!o&&oze(t),n=!r&&!o&&!a&&lze(t),u=r||o||a||n,A=u?nze(t.length,String):[],p=A.length;for(var h in t)(e||uze.call(t,h))&&!(u&&(h==\"length\"||a&&(h==\"offset\"||h==\"parent\")||n&&(h==\"buffer\"||h==\"byteLength\"||h==\"byteOffset\")||aze(h,p)))&&A.push(h);return A}Wte.exports=Aze});var DS=_((eRt,Yte)=>{var fze=Object.prototype;function pze(t){var e=t&&t.constructor,r=typeof e==\"function\"&&e.prototype||fze;return t===r}Yte.exports=pze});var FN=_((tRt,Kte)=>{function hze(t,e){return function(r){return t(e(r))}}Kte.exports=hze});var zte=_((rRt,Vte)=>{var gze=FN(),dze=gze(Object.keys,Object);Vte.exports=dze});var Xte=_((nRt,Jte)=>{var mze=DS(),yze=zte(),Eze=Object.prototype,Cze=Eze.hasOwnProperty;function Ize(t){if(!mze(t))return yze(t);var e=[];for(var r in Object(t))Cze.call(t,r)&&r!=\"constructor\"&&e.push(r);return e}Jte.exports=Ize});var o1=_((iRt,Zte)=>{var wze=hS(),Bze=IS();function vze(t){return t!=null&&Bze(t.length)&&!wze(t)}Zte.exports=vze});var PS=_((sRt,$te)=>{var Dze=QN(),Pze=Xte(),Sze=o1();function xze(t){return Sze(t)?Dze(t):Pze(t)}$te.exports=xze});var RN=_((oRt,ere)=>{var bze=xN(),kze=CS(),Qze=PS();function Fze(t){return bze(t,Qze,kze)}ere.exports=Fze});var nre=_((aRt,rre)=>{var tre=RN(),Rze=1,Tze=Object.prototype,Lze=Tze.hasOwnProperty;function Nze(t,e,r,o,a,n){var u=r&Rze,A=tre(t),p=A.length,h=tre(e),E=h.length;if(p!=E&&!u)return!1;for(var w=p;w--;){var D=A[w];if(!(u?D in e:Lze.call(e,D)))return!1}var b=n.get(t),C=n.get(e);if(b&&C)return b==e&&C==t;var T=!0;n.set(t,e),n.set(e,t);for(var N=u;++w<p;){D=A[w];var U=t[D],z=e[D];if(o)var te=u?o(z,U,D,e,t,n):o(U,z,D,t,e,n);if(!(te===void 0?U===z||a(U,z,r,o,n):te)){T=!1;break}N||(N=D==\"constructor\")}if(T&&!N){var le=t.constructor,ce=e.constructor;le!=ce&&\"constructor\"in t&&\"constructor\"in e&&!(typeof le==\"function\"&&le instanceof le&&typeof ce==\"function\"&&ce instanceof ce)&&(T=!1)}return n.delete(t),n.delete(e),T}rre.exports=Nze});var sre=_((lRt,ire)=>{var Oze=$p(),Mze=ql(),Uze=Oze(Mze,\"DataView\");ire.exports=Uze});var are=_((cRt,ore)=>{var _ze=$p(),Hze=ql(),qze=_ze(Hze,\"Promise\");ore.exports=qze});var cre=_((uRt,lre)=>{var jze=$p(),Gze=ql(),Wze=jze(Gze,\"Set\");lre.exports=Wze});var Are=_((ARt,ure)=>{var Yze=$p(),Kze=ql(),Vze=Yze(Kze,\"WeakMap\");ure.exports=Vze});var a1=_((fRt,yre)=>{var TN=sre(),LN=gS(),NN=are(),ON=cre(),MN=Are(),mre=mg(),Ym=vN(),fre=\"[object Map]\",zze=\"[object Object]\",pre=\"[object Promise]\",hre=\"[object Set]\",gre=\"[object WeakMap]\",dre=\"[object DataView]\",Jze=Ym(TN),Xze=Ym(LN),Zze=Ym(NN),$ze=Ym(ON),eJe=Ym(MN),yg=mre;(TN&&yg(new TN(new ArrayBuffer(1)))!=dre||LN&&yg(new LN)!=fre||NN&&yg(NN.resolve())!=pre||ON&&yg(new ON)!=hre||MN&&yg(new MN)!=gre)&&(yg=function(t){var e=mre(t),r=e==zze?t.constructor:void 0,o=r?Ym(r):\"\";if(o)switch(o){case Jze:return dre;case Xze:return fre;case Zze:return pre;case $ze:return hre;case eJe:return gre}return e});yre.exports=yg});var Pre=_((pRt,Dre)=>{var UN=mS(),tJe=DN(),rJe=hte(),nJe=nre(),Ere=a1(),Cre=jl(),Ire=r1(),iJe=vS(),sJe=1,wre=\"[object Arguments]\",Bre=\"[object Array]\",SS=\"[object Object]\",oJe=Object.prototype,vre=oJe.hasOwnProperty;function aJe(t,e,r,o,a,n){var u=Cre(t),A=Cre(e),p=u?Bre:Ere(t),h=A?Bre:Ere(e);p=p==wre?SS:p,h=h==wre?SS:h;var E=p==SS,w=h==SS,D=p==h;if(D&&Ire(t)){if(!Ire(e))return!1;u=!0,E=!1}if(D&&!E)return n||(n=new UN),u||iJe(t)?tJe(t,e,r,o,a,n):rJe(t,e,p,r,o,a,n);if(!(r&sJe)){var b=E&&vre.call(t,\"__wrapped__\"),C=w&&vre.call(e,\"__wrapped__\");if(b||C){var T=b?t.value():t,N=C?e.value():e;return n||(n=new UN),a(T,N,r,o,n)}}return D?(n||(n=new UN),nJe(t,e,r,o,a,n)):!1}Dre.exports=aJe});var kre=_((hRt,bre)=>{var lJe=Pre(),Sre=Zu();function xre(t,e,r,o,a){return t===e?!0:t==null||e==null||!Sre(t)&&!Sre(e)?t!==t&&e!==e:lJe(t,e,r,o,xre,a)}bre.exports=xre});var Fre=_((gRt,Qre)=>{var cJe=kre();function uJe(t,e){return cJe(t,e)}Qre.exports=uJe});var _N=_((dRt,Rre)=>{var AJe=$p(),fJe=function(){try{var t=AJe(Object,\"defineProperty\");return t({},\"\",{}),t}catch{}}();Rre.exports=fJe});var xS=_((mRt,Lre)=>{var Tre=_N();function pJe(t,e,r){e==\"__proto__\"&&Tre?Tre(t,e,{configurable:!0,enumerable:!0,value:r,writable:!0}):t[e]=r}Lre.exports=pJe});var HN=_((yRt,Nre)=>{var hJe=xS(),gJe=Um();function dJe(t,e,r){(r!==void 0&&!gJe(t[e],r)||r===void 0&&!(e in t))&&hJe(t,e,r)}Nre.exports=dJe});var Mre=_((ERt,Ore)=>{function mJe(t){return function(e,r,o){for(var a=-1,n=Object(e),u=o(e),A=u.length;A--;){var p=u[t?A:++a];if(r(n[p],p,n)===!1)break}return e}}Ore.exports=mJe});var _re=_((CRt,Ure)=>{var yJe=Mre(),EJe=yJe();Ure.exports=EJe});var qN=_((l1,Km)=>{var CJe=ql(),Gre=typeof l1==\"object\"&&l1&&!l1.nodeType&&l1,Hre=Gre&&typeof Km==\"object\"&&Km&&!Km.nodeType&&Km,IJe=Hre&&Hre.exports===Gre,qre=IJe?CJe.Buffer:void 0,jre=qre?qre.allocUnsafe:void 0;function wJe(t,e){if(e)return t.slice();var r=t.length,o=jre?jre(r):new t.constructor(r);return t.copy(o),o}Km.exports=wJe});var bS=_((IRt,Yre)=>{var Wre=PN();function BJe(t){var e=new t.constructor(t.byteLength);return new Wre(e).set(new Wre(t)),e}Yre.exports=BJe});var jN=_((wRt,Kre)=>{var vJe=bS();function DJe(t,e){var r=e?vJe(t.buffer):t.buffer;return new t.constructor(r,t.byteOffset,t.length)}Kre.exports=DJe});var kS=_((BRt,Vre)=>{function PJe(t,e){var r=-1,o=t.length;for(e||(e=Array(o));++r<o;)e[r]=t[r];return e}Vre.exports=PJe});var Xre=_((vRt,Jre)=>{var SJe=cl(),zre=Object.create,xJe=function(){function t(){}return function(e){if(!SJe(e))return{};if(zre)return zre(e);t.prototype=e;var r=new t;return t.prototype=void 0,r}}();Jre.exports=xJe});var QS=_((DRt,Zre)=>{var bJe=FN(),kJe=bJe(Object.getPrototypeOf,Object);Zre.exports=kJe});var GN=_((PRt,$re)=>{var QJe=Xre(),FJe=QS(),RJe=DS();function TJe(t){return typeof t.constructor==\"function\"&&!RJe(t)?QJe(FJe(t)):{}}$re.exports=TJe});var tne=_((SRt,ene)=>{var LJe=o1(),NJe=Zu();function OJe(t){return NJe(t)&&LJe(t)}ene.exports=OJe});var WN=_((xRt,nne)=>{var MJe=mg(),UJe=QS(),_Je=Zu(),HJe=\"[object Object]\",qJe=Function.prototype,jJe=Object.prototype,rne=qJe.toString,GJe=jJe.hasOwnProperty,WJe=rne.call(Object);function YJe(t){if(!_Je(t)||MJe(t)!=HJe)return!1;var e=UJe(t);if(e===null)return!0;var r=GJe.call(e,\"constructor\")&&e.constructor;return typeof r==\"function\"&&r instanceof r&&rne.call(r)==WJe}nne.exports=YJe});var YN=_((bRt,ine)=>{function KJe(t,e){if(!(e===\"constructor\"&&typeof t[e]==\"function\")&&e!=\"__proto__\")return t[e]}ine.exports=KJe});var RS=_((kRt,sne)=>{var VJe=xS(),zJe=Um(),JJe=Object.prototype,XJe=JJe.hasOwnProperty;function ZJe(t,e,r){var o=t[e];(!(XJe.call(t,e)&&zJe(o,r))||r===void 0&&!(e in t))&&VJe(t,e,r)}sne.exports=ZJe});var Eg=_((QRt,one)=>{var $Je=RS(),eXe=xS();function tXe(t,e,r,o){var a=!r;r||(r={});for(var n=-1,u=e.length;++n<u;){var A=e[n],p=o?o(r[A],t[A],A,r,t):void 0;p===void 0&&(p=t[A]),a?eXe(r,A,p):$Je(r,A,p)}return r}one.exports=tXe});var lne=_((FRt,ane)=>{function rXe(t){var e=[];if(t!=null)for(var r in Object(t))e.push(r);return e}ane.exports=rXe});var une=_((RRt,cne)=>{var nXe=cl(),iXe=DS(),sXe=lne(),oXe=Object.prototype,aXe=oXe.hasOwnProperty;function lXe(t){if(!nXe(t))return sXe(t);var e=iXe(t),r=[];for(var o in t)o==\"constructor\"&&(e||!aXe.call(t,o))||r.push(o);return r}cne.exports=lXe});var Vm=_((TRt,Ane)=>{var cXe=QN(),uXe=une(),AXe=o1();function fXe(t){return AXe(t)?cXe(t,!0):uXe(t)}Ane.exports=fXe});var pne=_((LRt,fne)=>{var pXe=Eg(),hXe=Vm();function gXe(t){return pXe(t,hXe(t))}fne.exports=gXe});var Ene=_((NRt,yne)=>{var hne=HN(),dXe=qN(),mXe=jN(),yXe=kS(),EXe=GN(),gne=e1(),dne=jl(),CXe=tne(),IXe=r1(),wXe=hS(),BXe=cl(),vXe=WN(),DXe=vS(),mne=YN(),PXe=pne();function SXe(t,e,r,o,a,n,u){var A=mne(t,r),p=mne(e,r),h=u.get(p);if(h){hne(t,r,h);return}var E=n?n(A,p,r+\"\",t,e,u):void 0,w=E===void 0;if(w){var D=dne(p),b=!D&&IXe(p),C=!D&&!b&&DXe(p);E=p,D||b||C?dne(A)?E=A:CXe(A)?E=yXe(A):b?(w=!1,E=dXe(p,!0)):C?(w=!1,E=mXe(p,!0)):E=[]:vXe(p)||gne(p)?(E=A,gne(A)?E=PXe(A):(!BXe(A)||wXe(A))&&(E=EXe(p))):w=!1}w&&(u.set(p,E),a(E,p,o,n,u),u.delete(p)),hne(t,r,E)}yne.exports=SXe});var wne=_((ORt,Ine)=>{var xXe=mS(),bXe=HN(),kXe=_re(),QXe=Ene(),FXe=cl(),RXe=Vm(),TXe=YN();function Cne(t,e,r,o,a){t!==e&&kXe(e,function(n,u){if(a||(a=new xXe),FXe(n))QXe(t,e,u,r,Cne,o,a);else{var A=o?o(TXe(t,u),n,u+\"\",t,e,a):void 0;A===void 0&&(A=n),bXe(t,u,A)}},RXe)}Ine.exports=Cne});var KN=_((MRt,Bne)=>{function LXe(t){return t}Bne.exports=LXe});var Dne=_((URt,vne)=>{function NXe(t,e,r){switch(r.length){case 0:return t.call(e);case 1:return t.call(e,r[0]);case 2:return t.call(e,r[0],r[1]);case 3:return t.call(e,r[0],r[1],r[2])}return t.apply(e,r)}vne.exports=NXe});var VN=_((_Rt,Sne)=>{var OXe=Dne(),Pne=Math.max;function MXe(t,e,r){return e=Pne(e===void 0?t.length-1:e,0),function(){for(var o=arguments,a=-1,n=Pne(o.length-e,0),u=Array(n);++a<n;)u[a]=o[e+a];a=-1;for(var A=Array(e+1);++a<e;)A[a]=o[a];return A[e]=r(u),OXe(t,this,A)}}Sne.exports=MXe});var bne=_((HRt,xne)=>{function UXe(t){return function(){return t}}xne.exports=UXe});var Fne=_((qRt,Qne)=>{var _Xe=bne(),kne=_N(),HXe=KN(),qXe=kne?function(t,e){return kne(t,\"toString\",{configurable:!0,enumerable:!1,value:_Xe(e),writable:!0})}:HXe;Qne.exports=qXe});var Tne=_((jRt,Rne)=>{var jXe=800,GXe=16,WXe=Date.now;function YXe(t){var e=0,r=0;return function(){var o=WXe(),a=GXe-(o-r);if(r=o,a>0){if(++e>=jXe)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}Rne.exports=YXe});var zN=_((GRt,Lne)=>{var KXe=Fne(),VXe=Tne(),zXe=VXe(KXe);Lne.exports=zXe});var One=_((WRt,Nne)=>{var JXe=KN(),XXe=VN(),ZXe=zN();function $Xe(t,e){return ZXe(XXe(t,e,JXe),t+\"\")}Nne.exports=$Xe});var Une=_((YRt,Mne)=>{var eZe=Um(),tZe=o1(),rZe=n1(),nZe=cl();function iZe(t,e,r){if(!nZe(r))return!1;var o=typeof e;return(o==\"number\"?tZe(r)&&rZe(e,r.length):o==\"string\"&&e in r)?eZe(r[e],t):!1}Mne.exports=iZe});var Hne=_((KRt,_ne)=>{var sZe=One(),oZe=Une();function aZe(t){return sZe(function(e,r){var o=-1,a=r.length,n=a>1?r[a-1]:void 0,u=a>2?r[2]:void 0;for(n=t.length>3&&typeof n==\"function\"?(a--,n):void 0,u&&oZe(r[0],r[1],u)&&(n=a<3?void 0:n,a=1),e=Object(e);++o<a;){var A=r[o];A&&t(e,A,o,n)}return e})}_ne.exports=aZe});var jne=_((VRt,qne)=>{var lZe=wne(),cZe=Hne(),uZe=cZe(function(t,e,r,o){lZe(t,e,r,o)});qne.exports=uZe});var qe={};Kt(qe,{AsyncActions:()=>ZN,BufferStream:()=>XN,CachingStrategy:()=>tie,DefaultStream:()=>$N,allSettledSafe:()=>Wc,assertNever:()=>tO,bufferStream:()=>Xm,buildIgnorePattern:()=>mZe,convertMapsToIndexableObjects:()=>LS,dynamicRequire:()=>vf,escapeRegExp:()=>fZe,getArrayWithDefault:()=>u1,getFactoryWithDefault:()=>Al,getMapWithDefault:()=>A1,getSetWithDefault:()=>zm,groupBy:()=>CZe,isIndexableObject:()=>JN,isPathLike:()=>yZe,isTaggedYarnVersion:()=>AZe,makeDeferred:()=>Zne,mapAndFilter:()=>ul,mapAndFind:()=>eh,mergeIntoTarget:()=>nie,overrideType:()=>pZe,parseBoolean:()=>f1,parseInt:()=>Zm,parseOptionalBoolean:()=>rie,plural:()=>TS,prettifyAsyncErrors:()=>Jm,prettifySyncErrors:()=>rO,releaseAfterUseAsync:()=>gZe,replaceEnvVariables:()=>NS,sortMap:()=>Ps,toMerged:()=>EZe,tryParseOptionalBoolean:()=>nO,validateEnum:()=>hZe});function AZe(t){return!!(zne.default.valid(t)&&t.match(/^[^-]+(-rc\\.[0-9]+)?$/))}function TS(t,{one:e,more:r,zero:o=r}){return t===0?o:t===1?e:r}function fZe(t){return t.replace(/[.*+?^${}()|[\\]\\\\]/g,\"\\\\$&\")}function pZe(t){}function tO(t){throw new Error(`Assertion failed: Unexpected object '${t}'`)}function hZe(t,e){let r=Object.values(t);if(!r.includes(e))throw new ot(`Invalid value for enumeration: ${JSON.stringify(e)} (expected one of ${r.map(o=>JSON.stringify(o)).join(\", \")})`);return e}function ul(t,e){let r=[];for(let o of t){let a=e(o);a!==Jne&&r.push(a)}return r}function eh(t,e){for(let r of t){let o=e(r);if(o!==Xne)return o}}function JN(t){return typeof t==\"object\"&&t!==null}async function Wc(t){let e=await Promise.allSettled(t),r=[];for(let o of e){if(o.status===\"rejected\")throw o.reason;r.push(o.value)}return r}function LS(t){if(t instanceof Map&&(t=Object.fromEntries(t)),JN(t))for(let e of Object.keys(t)){let r=t[e];JN(r)&&(t[e]=LS(r))}return t}function Al(t,e,r){let o=t.get(e);return typeof o>\"u\"&&t.set(e,o=r()),o}function u1(t,e){let r=t.get(e);return typeof r>\"u\"&&t.set(e,r=[]),r}function zm(t,e){let r=t.get(e);return typeof r>\"u\"&&t.set(e,r=new Set),r}function A1(t,e){let r=t.get(e);return typeof r>\"u\"&&t.set(e,r=new Map),r}async function gZe(t,e){if(e==null)return await t();try{return await t()}finally{await e()}}async function Jm(t,e){try{return await t()}catch(r){throw r.message=e(r.message),r}}function rO(t,e){try{return t()}catch(r){throw r.message=e(r.message),r}}async function Xm(t){return await new Promise((e,r)=>{let o=[];t.on(\"error\",a=>{r(a)}),t.on(\"data\",a=>{o.push(a)}),t.on(\"end\",()=>{e(Buffer.concat(o))})})}function Zne(){let t,e;return{promise:new Promise((o,a)=>{t=o,e=a}),resolve:t,reject:e}}function $ne(t){return c1(Ae.fromPortablePath(t))}function eie(path){let physicalPath=Ae.fromPortablePath(path),currentCacheEntry=c1.cache[physicalPath];delete c1.cache[physicalPath];let result;try{result=$ne(physicalPath);let freshCacheEntry=c1.cache[physicalPath],dynamicModule=eval(\"module\"),freshCacheIndex=dynamicModule.children.indexOf(freshCacheEntry);freshCacheIndex!==-1&&dynamicModule.children.splice(freshCacheIndex,1)}finally{c1.cache[physicalPath]=currentCacheEntry}return result}function dZe(t){let e=Gne.get(t),r=ae.statSync(t);if(e?.mtime===r.mtimeMs)return e.instance;let o=eie(t);return Gne.set(t,{mtime:r.mtimeMs,instance:o}),o}function vf(t,{cachingStrategy:e=2}={}){switch(e){case 0:return eie(t);case 1:return dZe(t);case 2:return $ne(t);default:throw new Error(\"Unsupported caching strategy\")}}function Ps(t,e){let r=Array.from(t);Array.isArray(e)||(e=[e]);let o=[];for(let n of e)o.push(r.map(u=>n(u)));let a=r.map((n,u)=>u);return a.sort((n,u)=>{for(let A of o){let p=A[n]<A[u]?-1:A[n]>A[u]?1:0;if(p!==0)return p}return 0}),a.map(n=>r[n])}function mZe(t){return t.length===0?null:t.map(e=>`(${Kne.default.makeRe(e,{windows:!1,dot:!0}).source})`).join(\"|\")}function NS(t,{env:e}){let r=/\\${(?<variableName>[\\d\\w_]+)(?<colon>:)?(?:-(?<fallback>[^}]*))?}/g;return t.replace(r,(...o)=>{let{variableName:a,colon:n,fallback:u}=o[o.length-1],A=Object.hasOwn(e,a),p=e[a];if(p||A&&!n)return p;if(u!=null)return u;throw new ot(`Environment variable not found (${a})`)})}function f1(t){switch(t){case\"true\":case\"1\":case 1:case!0:return!0;case\"false\":case\"0\":case 0:case!1:return!1;default:throw new Error(`Couldn't parse \"${t}\" as a boolean`)}}function rie(t){return typeof t>\"u\"?t:f1(t)}function nO(t){try{return rie(t)}catch{return null}}function yZe(t){return!!(Ae.isAbsolute(t)||t.match(/^(\\.{1,2}|~)\\//))}function nie(t,...e){let r=u=>({value:u}),o=r(t),a=e.map(u=>r(u)),{value:n}=(0,Yne.default)(o,...a,(u,A)=>{if(Array.isArray(u)&&Array.isArray(A)){for(let p of A)u.find(h=>(0,Wne.default)(h,p))||u.push(p);return u}});return n}function EZe(...t){return nie({},...t)}function CZe(t,e){let r=Object.create(null);for(let o of t){let a=o[e];r[a]??=[],r[a].push(o)}return r}function Zm(t){return typeof t==\"string\"?Number.parseInt(t,10):t}var Wne,Yne,Kne,Vne,zne,eO,Jne,Xne,XN,ZN,$N,c1,Gne,tie,Gl=It(()=>{Pt();Gt();Wne=et(Fre()),Yne=et(jne()),Kne=et(Xo()),Vne=et(lg()),zne=et(ni()),eO=ve(\"stream\");Jne=Symbol();ul.skip=Jne;Xne=Symbol();eh.skip=Xne;XN=class extends eO.Transform{constructor(){super(...arguments);this.chunks=[]}_transform(r,o,a){if(o!==\"buffer\"||!Buffer.isBuffer(r))throw new Error(\"Assertion failed: BufferStream only accept buffers\");this.chunks.push(r),a(null,null)}_flush(r){r(null,Buffer.concat(this.chunks))}};ZN=class{constructor(e){this.deferred=new Map;this.promises=new Map;this.limit=(0,Vne.default)(e)}set(e,r){let o=this.deferred.get(e);typeof o>\"u\"&&this.deferred.set(e,o=Zne());let a=this.limit(()=>r());return this.promises.set(e,a),a.then(()=>{this.promises.get(e)===a&&o.resolve()},n=>{this.promises.get(e)===a&&o.reject(n)}),o.promise}reduce(e,r){let o=this.promises.get(e)??Promise.resolve();this.set(e,()=>r(o))}async wait(){await Promise.all(this.promises.values())}},$N=class extends eO.Transform{constructor(r=Buffer.alloc(0)){super();this.active=!0;this.ifEmpty=r}_transform(r,o,a){if(o!==\"buffer\"||!Buffer.isBuffer(r))throw new Error(\"Assertion failed: DefaultStream only accept buffers\");this.active=!1,a(null,r)}_flush(r){this.active&&this.ifEmpty.length>0?r(null,this.ifEmpty):r(null)}},c1=eval(\"require\");Gne=new Map;tie=(o=>(o[o.NoCache=0]=\"NoCache\",o[o.FsTime=1]=\"FsTime\",o[o.Node=2]=\"Node\",o))(tie||{})});var $m,iO,sO,iie=It(()=>{$m=(r=>(r.HARD=\"HARD\",r.SOFT=\"SOFT\",r))($m||{}),iO=(o=>(o.Dependency=\"Dependency\",o.PeerDependency=\"PeerDependency\",o.PeerDependencyMeta=\"PeerDependencyMeta\",o))(iO||{}),sO=(o=>(o.Inactive=\"inactive\",o.Redundant=\"redundant\",o.Active=\"active\",o))(sO||{})});var pe={};Kt(pe,{LogLevel:()=>HS,Style:()=>MS,Type:()=>Ct,addLogFilterSupport:()=>g1,applyColor:()=>Gs,applyHyperlink:()=>ty,applyStyle:()=>Cg,json:()=>Ig,jsonOrPretty:()=>BZe,mark:()=>uO,pretty:()=>Ut,prettyField:()=>$u,prettyList:()=>cO,prettyTruncatedLocatorList:()=>_S,stripAnsi:()=>ey.default,supportsColor:()=>US,supportsHyperlinks:()=>lO,tuple:()=>Yc});function sie(t){let e=[\"KiB\",\"MiB\",\"GiB\",\"TiB\"],r=e.length;for(;r>1&&t<1024**r;)r-=1;let o=1024**r;return`${Math.floor(t*100/o)/100} ${e[r-1]}`}function Yc(t,e){return[e,t]}function Cg(t,e,r){return t.get(\"enableColors\")&&r&2&&(e=h1.default.bold(e)),e}function Gs(t,e,r){if(!t.get(\"enableColors\"))return e;let o=IZe.get(r);if(o===null)return e;let a=typeof o>\"u\"?r:aO.level>=3?o[0]:o[1],n=typeof a==\"number\"?oO.ansi256(a):a.startsWith(\"#\")?oO.hex(a):oO[a];if(typeof n!=\"function\")throw new Error(`Invalid format type ${a}`);return n(e)}function ty(t,e,r){return t.get(\"enableHyperlinks\")?wZe?`\\x1B]8;;${r}\\x1B\\\\${e}\\x1B]8;;\\x1B\\\\`:`\\x1B]8;;${r}\\x07${e}\\x1B]8;;\\x07`:e}function Ut(t,e,r){if(e===null)return Gs(t,\"null\",Ct.NULL);if(Object.hasOwn(OS,r))return OS[r].pretty(t,e);if(typeof e!=\"string\")throw new Error(`Assertion failed: Expected the value to be a string, got ${typeof e}`);return Gs(t,e,r)}function cO(t,e,r,{separator:o=\", \"}={}){return[...e].map(a=>Ut(t,a,r)).join(o)}function Ig(t,e){if(t===null)return null;if(Object.hasOwn(OS,e))return OS[e].json(t);if(typeof t!=\"string\")throw new Error(`Assertion failed: Expected the value to be a string, got ${typeof t}`);return t}function BZe(t,e,[r,o]){return t?Ig(r,o):Ut(e,r,o)}function uO(t){return{Check:Gs(t,\"\\u2713\",\"green\"),Cross:Gs(t,\"\\u2718\",\"red\"),Question:Gs(t,\"?\",\"cyan\")}}function $u(t,{label:e,value:[r,o]}){return`${Ut(t,e,Ct.CODE)}: ${Ut(t,r,o)}`}function _S(t,e,r){let o=[],a=[...e],n=r;for(;a.length>0;){let h=a[0],E=`${jr(t,h)}, `,w=AO(h).length+2;if(o.length>0&&n<w)break;o.push([E,w]),n-=w,a.shift()}if(a.length===0)return o.map(([h])=>h).join(\"\").slice(0,-2);let u=\"X\".repeat(a.length.toString().length),A=`and ${u} more.`,p=a.length;for(;o.length>1&&n<A.length;)n+=o[o.length-1][1],p+=1,o.pop();return[o.map(([h])=>h).join(\"\"),A.replace(u,Ut(t,p,Ct.NUMBER))].join(\"\")}function g1(t,{configuration:e}){let r=e.get(\"logFilters\"),o=new Map,a=new Map,n=[];for(let w of r){let D=w.get(\"level\");if(typeof D>\"u\")continue;let b=w.get(\"code\");typeof b<\"u\"&&o.set(b,D);let C=w.get(\"text\");typeof C<\"u\"&&a.set(C,D);let T=w.get(\"pattern\");typeof T<\"u\"&&n.push([oie.default.matcher(T,{contains:!0}),D])}n.reverse();let u=(w,D,b)=>{if(w===null||w===0)return b;let C=a.size>0||n.length>0?(0,ey.default)(D):D;if(a.size>0){let T=a.get(C);if(typeof T<\"u\")return T??b}if(n.length>0){for(let[T,N]of n)if(T(C))return N??b}if(o.size>0){let T=o.get(zu(w));if(typeof T<\"u\")return T??b}return b},A=t.reportInfo,p=t.reportWarning,h=t.reportError,E=function(w,D,b,C){switch(u(D,b,C)){case\"info\":A.call(w,D,b);break;case\"warning\":p.call(w,D??0,b);break;case\"error\":h.call(w,D??0,b);break}};t.reportInfo=function(...w){return E(this,...w,\"info\")},t.reportWarning=function(...w){return E(this,...w,\"warning\")},t.reportError=function(...w){return E(this,...w,\"error\")}}var h1,p1,oie,ey,aie,Ct,MS,aO,US,lO,oO,IZe,Co,OS,wZe,HS,Wl=It(()=>{Pt();h1=et(sN()),p1=et(sg());Gt();oie=et(Xo()),ey=et(pS()),aie=ve(\"util\");jP();Io();Ct={NO_HINT:\"NO_HINT\",ID:\"ID\",NULL:\"NULL\",SCOPE:\"SCOPE\",NAME:\"NAME\",RANGE:\"RANGE\",REFERENCE:\"REFERENCE\",NUMBER:\"NUMBER\",PATH:\"PATH\",URL:\"URL\",ADDED:\"ADDED\",REMOVED:\"REMOVED\",CODE:\"CODE\",INSPECT:\"INSPECT\",DURATION:\"DURATION\",SIZE:\"SIZE\",SIZE_DIFF:\"SIZE_DIFF\",IDENT:\"IDENT\",DESCRIPTOR:\"DESCRIPTOR\",LOCATOR:\"LOCATOR\",RESOLUTION:\"RESOLUTION\",DEPENDENT:\"DEPENDENT\",PACKAGE_EXTENSION:\"PACKAGE_EXTENSION\",SETTING:\"SETTING\",MARKDOWN:\"MARKDOWN\",MARKDOWN_INLINE:\"MARKDOWN_INLINE\"},MS=(e=>(e[e.BOLD=2]=\"BOLD\",e))(MS||{}),aO=p1.default.GITHUB_ACTIONS?{level:2}:h1.default.supportsColor?{level:h1.default.supportsColor.level}:{level:0},US=aO.level!==0,lO=US&&!p1.default.GITHUB_ACTIONS&&!p1.default.CIRCLE&&!p1.default.GITLAB,oO=new h1.default.Instance(aO),IZe=new Map([[Ct.NO_HINT,null],[Ct.NULL,[\"#a853b5\",129]],[Ct.SCOPE,[\"#d75f00\",166]],[Ct.NAME,[\"#d7875f\",173]],[Ct.RANGE,[\"#00afaf\",37]],[Ct.REFERENCE,[\"#87afff\",111]],[Ct.NUMBER,[\"#ffd700\",220]],[Ct.PATH,[\"#d75fd7\",170]],[Ct.URL,[\"#d75fd7\",170]],[Ct.ADDED,[\"#5faf00\",70]],[Ct.REMOVED,[\"#ff3131\",160]],[Ct.CODE,[\"#87afff\",111]],[Ct.SIZE,[\"#ffd700\",220]]]),Co=t=>t;OS={[Ct.ID]:Co({pretty:(t,e)=>typeof e==\"number\"?Gs(t,`${e}`,Ct.NUMBER):Gs(t,e,Ct.CODE),json:t=>t}),[Ct.INSPECT]:Co({pretty:(t,e)=>(0,aie.inspect)(e,{depth:1/0,colors:t.get(\"enableColors\"),compact:!0,breakLength:1/0}),json:t=>t}),[Ct.NUMBER]:Co({pretty:(t,e)=>Gs(t,`${e}`,Ct.NUMBER),json:t=>t}),[Ct.IDENT]:Co({pretty:(t,e)=>Ui(t,e),json:t=>rn(t)}),[Ct.LOCATOR]:Co({pretty:(t,e)=>jr(t,e),json:t=>Qa(t)}),[Ct.DESCRIPTOR]:Co({pretty:(t,e)=>zn(t,e),json:t=>ka(t)}),[Ct.RESOLUTION]:Co({pretty:(t,{descriptor:e,locator:r})=>d1(t,e,r),json:({descriptor:t,locator:e})=>({descriptor:ka(t),locator:e!==null?Qa(e):null})}),[Ct.DEPENDENT]:Co({pretty:(t,{locator:e,descriptor:r})=>fO(t,e,r),json:({locator:t,descriptor:e})=>({locator:Qa(t),descriptor:ka(e)})}),[Ct.PACKAGE_EXTENSION]:Co({pretty:(t,e)=>{switch(e.type){case\"Dependency\":return`${Ui(t,e.parentDescriptor)} \\u27A4 ${Gs(t,\"dependencies\",Ct.CODE)} \\u27A4 ${Ui(t,e.descriptor)}`;case\"PeerDependency\":return`${Ui(t,e.parentDescriptor)} \\u27A4 ${Gs(t,\"peerDependencies\",Ct.CODE)} \\u27A4 ${Ui(t,e.descriptor)}`;case\"PeerDependencyMeta\":return`${Ui(t,e.parentDescriptor)} \\u27A4 ${Gs(t,\"peerDependenciesMeta\",Ct.CODE)} \\u27A4 ${Ui(t,Zo(e.selector))} \\u27A4 ${Gs(t,e.key,Ct.CODE)}`;default:throw new Error(`Assertion failed: Unsupported package extension type: ${e.type}`)}},json:t=>{switch(t.type){case\"Dependency\":return`${rn(t.parentDescriptor)} > ${rn(t.descriptor)}`;case\"PeerDependency\":return`${rn(t.parentDescriptor)} >> ${rn(t.descriptor)}`;case\"PeerDependencyMeta\":return`${rn(t.parentDescriptor)} >> ${t.selector} / ${t.key}`;default:throw new Error(`Assertion failed: Unsupported package extension type: ${t.type}`)}}}),[Ct.SETTING]:Co({pretty:(t,e)=>(t.get(e),ty(t,Gs(t,e,Ct.CODE),`https://yarnpkg.com/configuration/yarnrc#${e}`)),json:t=>t}),[Ct.DURATION]:Co({pretty:(t,e)=>{if(e>1e3*60){let r=Math.floor(e/1e3/60),o=Math.ceil((e-r*60*1e3)/1e3);return o===0?`${r}m`:`${r}m ${o}s`}else{let r=Math.floor(e/1e3),o=e-r*1e3;return o===0?`${r}s`:`${r}s ${o}ms`}},json:t=>t}),[Ct.SIZE]:Co({pretty:(t,e)=>Gs(t,sie(e),Ct.NUMBER),json:t=>t}),[Ct.SIZE_DIFF]:Co({pretty:(t,e)=>{let r=e>=0?\"+\":\"-\",o=r===\"+\"?Ct.REMOVED:Ct.ADDED;return Gs(t,`${r} ${sie(Math.max(Math.abs(e),1))}`,o)},json:t=>t}),[Ct.PATH]:Co({pretty:(t,e)=>Gs(t,Ae.fromPortablePath(e),Ct.PATH),json:t=>Ae.fromPortablePath(t)}),[Ct.MARKDOWN]:Co({pretty:(t,{text:e,format:r,paragraphs:o})=>yo(e,{format:r,paragraphs:o}),json:({text:t})=>t}),[Ct.MARKDOWN_INLINE]:Co({pretty:(t,e)=>(e=e.replace(/(`+)((?:.|[\\n])*?)\\1/g,(r,o,a)=>Ut(t,o+a+o,Ct.CODE)),e=e.replace(/(\\*\\*)((?:.|[\\n])*?)\\1/g,(r,o,a)=>Cg(t,a,2)),e),json:t=>t})};wZe=!!process.env.KONSOLE_VERSION;HS=(a=>(a.Error=\"error\",a.Warning=\"warning\",a.Info=\"info\",a.Discard=\"discard\",a))(HS||{})});var lie=_(ry=>{\"use strict\";Object.defineProperty(ry,\"__esModule\",{value:!0});ry.splitWhen=ry.flatten=void 0;function vZe(t){return t.reduce((e,r)=>[].concat(e,r),[])}ry.flatten=vZe;function DZe(t,e){let r=[[]],o=0;for(let a of t)e(a)?(o++,r[o]=[]):r[o].push(a);return r}ry.splitWhen=DZe});var cie=_(qS=>{\"use strict\";Object.defineProperty(qS,\"__esModule\",{value:!0});qS.isEnoentCodeError=void 0;function PZe(t){return t.code===\"ENOENT\"}qS.isEnoentCodeError=PZe});var uie=_(jS=>{\"use strict\";Object.defineProperty(jS,\"__esModule\",{value:!0});jS.createDirentFromStats=void 0;var pO=class{constructor(e,r){this.name=e,this.isBlockDevice=r.isBlockDevice.bind(r),this.isCharacterDevice=r.isCharacterDevice.bind(r),this.isDirectory=r.isDirectory.bind(r),this.isFIFO=r.isFIFO.bind(r),this.isFile=r.isFile.bind(r),this.isSocket=r.isSocket.bind(r),this.isSymbolicLink=r.isSymbolicLink.bind(r)}};function SZe(t,e){return new pO(t,e)}jS.createDirentFromStats=SZe});var hie=_(Vi=>{\"use strict\";Object.defineProperty(Vi,\"__esModule\",{value:!0});Vi.convertPosixPathToPattern=Vi.convertWindowsPathToPattern=Vi.convertPathToPattern=Vi.escapePosixPath=Vi.escapeWindowsPath=Vi.escape=Vi.removeLeadingDotSegment=Vi.makeAbsolute=Vi.unixify=void 0;var xZe=ve(\"os\"),bZe=ve(\"path\"),Aie=xZe.platform()===\"win32\",kZe=2,QZe=/(\\\\?)([()*?[\\]{|}]|^!|[!+@](?=\\()|\\\\(?![!()*+?@[\\]{|}]))/g,FZe=/(\\\\?)([()[\\]{}]|^!|[!+@](?=\\())/g,RZe=/^\\\\\\\\([.?])/,TZe=/\\\\(?![!()+@[\\]{}])/g;function LZe(t){return t.replace(/\\\\/g,\"/\")}Vi.unixify=LZe;function NZe(t,e){return bZe.resolve(t,e)}Vi.makeAbsolute=NZe;function OZe(t){if(t.charAt(0)===\".\"){let e=t.charAt(1);if(e===\"/\"||e===\"\\\\\")return t.slice(kZe)}return t}Vi.removeLeadingDotSegment=OZe;Vi.escape=Aie?hO:gO;function hO(t){return t.replace(FZe,\"\\\\$2\")}Vi.escapeWindowsPath=hO;function gO(t){return t.replace(QZe,\"\\\\$2\")}Vi.escapePosixPath=gO;Vi.convertPathToPattern=Aie?fie:pie;function fie(t){return hO(t).replace(RZe,\"//$1\").replace(TZe,\"/\")}Vi.convertWindowsPathToPattern=fie;function pie(t){return gO(t)}Vi.convertPosixPathToPattern=pie});var die=_((cTt,gie)=>{gie.exports=function(e){if(typeof e!=\"string\"||e===\"\")return!1;for(var r;r=/(\\\\).|([@?!+*]\\(.*\\))/g.exec(e);){if(r[2])return!0;e=e.slice(r.index+r[0].length)}return!1}});var Eie=_((uTt,yie)=>{var MZe=die(),mie={\"{\":\"}\",\"(\":\")\",\"[\":\"]\"},UZe=function(t){if(t[0]===\"!\")return!0;for(var e=0,r=-2,o=-2,a=-2,n=-2,u=-2;e<t.length;){if(t[e]===\"*\"||t[e+1]===\"?\"&&/[\\].+)]/.test(t[e])||o!==-1&&t[e]===\"[\"&&t[e+1]!==\"]\"&&(o<e&&(o=t.indexOf(\"]\",e)),o>e&&(u===-1||u>o||(u=t.indexOf(\"\\\\\",e),u===-1||u>o)))||a!==-1&&t[e]===\"{\"&&t[e+1]!==\"}\"&&(a=t.indexOf(\"}\",e),a>e&&(u=t.indexOf(\"\\\\\",e),u===-1||u>a))||n!==-1&&t[e]===\"(\"&&t[e+1]===\"?\"&&/[:!=]/.test(t[e+2])&&t[e+3]!==\")\"&&(n=t.indexOf(\")\",e),n>e&&(u=t.indexOf(\"\\\\\",e),u===-1||u>n))||r!==-1&&t[e]===\"(\"&&t[e+1]!==\"|\"&&(r<e&&(r=t.indexOf(\"|\",e)),r!==-1&&t[r+1]!==\")\"&&(n=t.indexOf(\")\",r),n>r&&(u=t.indexOf(\"\\\\\",r),u===-1||u>n))))return!0;if(t[e]===\"\\\\\"){var A=t[e+1];e+=2;var p=mie[A];if(p){var h=t.indexOf(p,e);h!==-1&&(e=h+1)}if(t[e]===\"!\")return!0}else e++}return!1},_Ze=function(t){if(t[0]===\"!\")return!0;for(var e=0;e<t.length;){if(/[*?{}()[\\]]/.test(t[e]))return!0;if(t[e]===\"\\\\\"){var r=t[e+1];e+=2;var o=mie[r];if(o){var a=t.indexOf(o,e);a!==-1&&(e=a+1)}if(t[e]===\"!\")return!0}else e++}return!1};yie.exports=function(e,r){if(typeof e!=\"string\"||e===\"\")return!1;if(MZe(e))return!0;var o=UZe;return r&&r.strict===!1&&(o=_Ze),o(e)}});var Iie=_((ATt,Cie)=>{\"use strict\";var HZe=Eie(),qZe=ve(\"path\").posix.dirname,jZe=ve(\"os\").platform()===\"win32\",dO=\"/\",GZe=/\\\\/g,WZe=/[\\{\\[].*[\\}\\]]$/,YZe=/(^|[^\\\\])([\\{\\[]|\\([^\\)]+$)/,KZe=/\\\\([\\!\\*\\?\\|\\[\\]\\(\\)\\{\\}])/g;Cie.exports=function(e,r){var o=Object.assign({flipBackslashes:!0},r);o.flipBackslashes&&jZe&&e.indexOf(dO)<0&&(e=e.replace(GZe,dO)),WZe.test(e)&&(e+=dO),e+=\"a\";do e=qZe(e);while(HZe(e)||YZe.test(e));return e.replace(KZe,\"$1\")}});var bie=_(Mr=>{\"use strict\";Object.defineProperty(Mr,\"__esModule\",{value:!0});Mr.removeDuplicateSlashes=Mr.matchAny=Mr.convertPatternsToRe=Mr.makeRe=Mr.getPatternParts=Mr.expandBraceExpansion=Mr.expandPatternsWithBraceExpansion=Mr.isAffectDepthOfReadingPattern=Mr.endsWithSlashGlobStar=Mr.hasGlobStar=Mr.getBaseDirectory=Mr.isPatternRelatedToParentDirectory=Mr.getPatternsOutsideCurrentDirectory=Mr.getPatternsInsideCurrentDirectory=Mr.getPositivePatterns=Mr.getNegativePatterns=Mr.isPositivePattern=Mr.isNegativePattern=Mr.convertToNegativePattern=Mr.convertToPositivePattern=Mr.isDynamicPattern=Mr.isStaticPattern=void 0;var VZe=ve(\"path\"),zZe=Iie(),mO=Xo(),wie=\"**\",JZe=\"\\\\\",XZe=/[*?]|^!/,ZZe=/\\[[^[]*]/,$Ze=/(?:^|[^!*+?@])\\([^(]*\\|[^|]*\\)/,e$e=/[!*+?@]\\([^(]*\\)/,t$e=/,|\\.\\./,r$e=/(?!^)\\/{2,}/g;function Bie(t,e={}){return!vie(t,e)}Mr.isStaticPattern=Bie;function vie(t,e={}){return t===\"\"?!1:!!(e.caseSensitiveMatch===!1||t.includes(JZe)||XZe.test(t)||ZZe.test(t)||$Ze.test(t)||e.extglob!==!1&&e$e.test(t)||e.braceExpansion!==!1&&n$e(t))}Mr.isDynamicPattern=vie;function n$e(t){let e=t.indexOf(\"{\");if(e===-1)return!1;let r=t.indexOf(\"}\",e+1);if(r===-1)return!1;let o=t.slice(e,r);return t$e.test(o)}function i$e(t){return GS(t)?t.slice(1):t}Mr.convertToPositivePattern=i$e;function s$e(t){return\"!\"+t}Mr.convertToNegativePattern=s$e;function GS(t){return t.startsWith(\"!\")&&t[1]!==\"(\"}Mr.isNegativePattern=GS;function Die(t){return!GS(t)}Mr.isPositivePattern=Die;function o$e(t){return t.filter(GS)}Mr.getNegativePatterns=o$e;function a$e(t){return t.filter(Die)}Mr.getPositivePatterns=a$e;function l$e(t){return t.filter(e=>!yO(e))}Mr.getPatternsInsideCurrentDirectory=l$e;function c$e(t){return t.filter(yO)}Mr.getPatternsOutsideCurrentDirectory=c$e;function yO(t){return t.startsWith(\"..\")||t.startsWith(\"./..\")}Mr.isPatternRelatedToParentDirectory=yO;function u$e(t){return zZe(t,{flipBackslashes:!1})}Mr.getBaseDirectory=u$e;function A$e(t){return t.includes(wie)}Mr.hasGlobStar=A$e;function Pie(t){return t.endsWith(\"/\"+wie)}Mr.endsWithSlashGlobStar=Pie;function f$e(t){let e=VZe.basename(t);return Pie(t)||Bie(e)}Mr.isAffectDepthOfReadingPattern=f$e;function p$e(t){return t.reduce((e,r)=>e.concat(Sie(r)),[])}Mr.expandPatternsWithBraceExpansion=p$e;function Sie(t){let e=mO.braces(t,{expand:!0,nodupes:!0,keepEscaping:!0});return e.sort((r,o)=>r.length-o.length),e.filter(r=>r!==\"\")}Mr.expandBraceExpansion=Sie;function h$e(t,e){let{parts:r}=mO.scan(t,Object.assign(Object.assign({},e),{parts:!0}));return r.length===0&&(r=[t]),r[0].startsWith(\"/\")&&(r[0]=r[0].slice(1),r.unshift(\"\")),r}Mr.getPatternParts=h$e;function xie(t,e){return mO.makeRe(t,e)}Mr.makeRe=xie;function g$e(t,e){return t.map(r=>xie(r,e))}Mr.convertPatternsToRe=g$e;function d$e(t,e){return e.some(r=>r.test(t))}Mr.matchAny=d$e;function m$e(t){return t.replace(r$e,\"/\")}Mr.removeDuplicateSlashes=m$e});var Rie=_((pTt,Fie)=>{\"use strict\";var y$e=ve(\"stream\"),kie=y$e.PassThrough,E$e=Array.prototype.slice;Fie.exports=C$e;function C$e(){let t=[],e=E$e.call(arguments),r=!1,o=e[e.length-1];o&&!Array.isArray(o)&&o.pipe==null?e.pop():o={};let a=o.end!==!1,n=o.pipeError===!0;o.objectMode==null&&(o.objectMode=!0),o.highWaterMark==null&&(o.highWaterMark=64*1024);let u=kie(o);function A(){for(let E=0,w=arguments.length;E<w;E++)t.push(Qie(arguments[E],o));return p(),this}function p(){if(r)return;r=!0;let E=t.shift();if(!E){process.nextTick(h);return}Array.isArray(E)||(E=[E]);let w=E.length+1;function D(){--w>0||(r=!1,p())}function b(C){function T(){C.removeListener(\"merge2UnpipeEnd\",T),C.removeListener(\"end\",T),n&&C.removeListener(\"error\",N),D()}function N(U){u.emit(\"error\",U)}if(C._readableState.endEmitted)return D();C.on(\"merge2UnpipeEnd\",T),C.on(\"end\",T),n&&C.on(\"error\",N),C.pipe(u,{end:!1}),C.resume()}for(let C=0;C<E.length;C++)b(E[C]);D()}function h(){r=!1,u.emit(\"queueDrain\"),a&&u.end()}return u.setMaxListeners(0),u.add=A,u.on(\"unpipe\",function(E){E.emit(\"merge2UnpipeEnd\")}),e.length&&A.apply(null,e),u}function Qie(t,e){if(Array.isArray(t))for(let r=0,o=t.length;r<o;r++)t[r]=Qie(t[r],e);else{if(!t._readableState&&t.pipe&&(t=t.pipe(kie(e))),!t._readableState||!t.pause||!t.pipe)throw new Error(\"Only readable stream can be merged.\");t.pause()}return t}});var Lie=_(WS=>{\"use strict\";Object.defineProperty(WS,\"__esModule\",{value:!0});WS.merge=void 0;var I$e=Rie();function w$e(t){let e=I$e(t);return t.forEach(r=>{r.once(\"error\",o=>e.emit(\"error\",o))}),e.once(\"close\",()=>Tie(t)),e.once(\"end\",()=>Tie(t)),e}WS.merge=w$e;function Tie(t){t.forEach(e=>e.emit(\"close\"))}});var Nie=_(ny=>{\"use strict\";Object.defineProperty(ny,\"__esModule\",{value:!0});ny.isEmpty=ny.isString=void 0;function B$e(t){return typeof t==\"string\"}ny.isString=B$e;function v$e(t){return t===\"\"}ny.isEmpty=v$e});var Df=_(wo=>{\"use strict\";Object.defineProperty(wo,\"__esModule\",{value:!0});wo.string=wo.stream=wo.pattern=wo.path=wo.fs=wo.errno=wo.array=void 0;var D$e=lie();wo.array=D$e;var P$e=cie();wo.errno=P$e;var S$e=uie();wo.fs=S$e;var x$e=hie();wo.path=x$e;var b$e=bie();wo.pattern=b$e;var k$e=Lie();wo.stream=k$e;var Q$e=Nie();wo.string=Q$e});var _ie=_(Bo=>{\"use strict\";Object.defineProperty(Bo,\"__esModule\",{value:!0});Bo.convertPatternGroupToTask=Bo.convertPatternGroupsToTasks=Bo.groupPatternsByBaseDirectory=Bo.getNegativePatternsAsPositive=Bo.getPositivePatterns=Bo.convertPatternsToTasks=Bo.generate=void 0;var Kc=Df();function F$e(t,e){let r=Oie(t,e),o=Oie(e.ignore,e),a=Mie(r),n=Uie(r,o),u=a.filter(E=>Kc.pattern.isStaticPattern(E,e)),A=a.filter(E=>Kc.pattern.isDynamicPattern(E,e)),p=EO(u,n,!1),h=EO(A,n,!0);return p.concat(h)}Bo.generate=F$e;function Oie(t,e){let r=t;return e.braceExpansion&&(r=Kc.pattern.expandPatternsWithBraceExpansion(r)),e.baseNameMatch&&(r=r.map(o=>o.includes(\"/\")?o:`**/${o}`)),r.map(o=>Kc.pattern.removeDuplicateSlashes(o))}function EO(t,e,r){let o=[],a=Kc.pattern.getPatternsOutsideCurrentDirectory(t),n=Kc.pattern.getPatternsInsideCurrentDirectory(t),u=CO(a),A=CO(n);return o.push(...IO(u,e,r)),\".\"in A?o.push(wO(\".\",n,e,r)):o.push(...IO(A,e,r)),o}Bo.convertPatternsToTasks=EO;function Mie(t){return Kc.pattern.getPositivePatterns(t)}Bo.getPositivePatterns=Mie;function Uie(t,e){return Kc.pattern.getNegativePatterns(t).concat(e).map(Kc.pattern.convertToPositivePattern)}Bo.getNegativePatternsAsPositive=Uie;function CO(t){let e={};return t.reduce((r,o)=>{let a=Kc.pattern.getBaseDirectory(o);return a in r?r[a].push(o):r[a]=[o],r},e)}Bo.groupPatternsByBaseDirectory=CO;function IO(t,e,r){return Object.keys(t).map(o=>wO(o,t[o],e,r))}Bo.convertPatternGroupsToTasks=IO;function wO(t,e,r,o){return{dynamic:o,positive:e,negative:r,base:t,patterns:[].concat(e,r.map(Kc.pattern.convertToNegativePattern))}}Bo.convertPatternGroupToTask=wO});var qie=_(YS=>{\"use strict\";Object.defineProperty(YS,\"__esModule\",{value:!0});YS.read=void 0;function R$e(t,e,r){e.fs.lstat(t,(o,a)=>{if(o!==null){Hie(r,o);return}if(!a.isSymbolicLink()||!e.followSymbolicLink){BO(r,a);return}e.fs.stat(t,(n,u)=>{if(n!==null){if(e.throwErrorOnBrokenSymbolicLink){Hie(r,n);return}BO(r,a);return}e.markSymbolicLink&&(u.isSymbolicLink=()=>!0),BO(r,u)})})}YS.read=R$e;function Hie(t,e){t(e)}function BO(t,e){t(null,e)}});var jie=_(KS=>{\"use strict\";Object.defineProperty(KS,\"__esModule\",{value:!0});KS.read=void 0;function T$e(t,e){let r=e.fs.lstatSync(t);if(!r.isSymbolicLink()||!e.followSymbolicLink)return r;try{let o=e.fs.statSync(t);return e.markSymbolicLink&&(o.isSymbolicLink=()=>!0),o}catch(o){if(!e.throwErrorOnBrokenSymbolicLink)return r;throw o}}KS.read=T$e});var Gie=_(th=>{\"use strict\";Object.defineProperty(th,\"__esModule\",{value:!0});th.createFileSystemAdapter=th.FILE_SYSTEM_ADAPTER=void 0;var VS=ve(\"fs\");th.FILE_SYSTEM_ADAPTER={lstat:VS.lstat,stat:VS.stat,lstatSync:VS.lstatSync,statSync:VS.statSync};function L$e(t){return t===void 0?th.FILE_SYSTEM_ADAPTER:Object.assign(Object.assign({},th.FILE_SYSTEM_ADAPTER),t)}th.createFileSystemAdapter=L$e});var Wie=_(DO=>{\"use strict\";Object.defineProperty(DO,\"__esModule\",{value:!0});var N$e=Gie(),vO=class{constructor(e={}){this._options=e,this.followSymbolicLink=this._getValue(this._options.followSymbolicLink,!0),this.fs=N$e.createFileSystemAdapter(this._options.fs),this.markSymbolicLink=this._getValue(this._options.markSymbolicLink,!1),this.throwErrorOnBrokenSymbolicLink=this._getValue(this._options.throwErrorOnBrokenSymbolicLink,!0)}_getValue(e,r){return e??r}};DO.default=vO});var wg=_(rh=>{\"use strict\";Object.defineProperty(rh,\"__esModule\",{value:!0});rh.statSync=rh.stat=rh.Settings=void 0;var Yie=qie(),O$e=jie(),PO=Wie();rh.Settings=PO.default;function M$e(t,e,r){if(typeof e==\"function\"){Yie.read(t,SO(),e);return}Yie.read(t,SO(e),r)}rh.stat=M$e;function U$e(t,e){let r=SO(e);return O$e.read(t,r)}rh.statSync=U$e;function SO(t={}){return t instanceof PO.default?t:new PO.default(t)}});var zie=_((BTt,Vie)=>{var Kie;Vie.exports=typeof queueMicrotask==\"function\"?queueMicrotask.bind(typeof window<\"u\"?window:global):t=>(Kie||(Kie=Promise.resolve())).then(t).catch(e=>setTimeout(()=>{throw e},0))});var Xie=_((vTt,Jie)=>{Jie.exports=H$e;var _$e=zie();function H$e(t,e){let r,o,a,n=!0;Array.isArray(t)?(r=[],o=t.length):(a=Object.keys(t),r={},o=a.length);function u(p){function h(){e&&e(p,r),e=null}n?_$e(h):h()}function A(p,h,E){r[p]=E,(--o===0||h)&&u(h)}o?a?a.forEach(function(p){t[p](function(h,E){A(p,h,E)})}):t.forEach(function(p,h){p(function(E,w){A(h,E,w)})}):u(null),n=!1}});var xO=_(JS=>{\"use strict\";Object.defineProperty(JS,\"__esModule\",{value:!0});JS.IS_SUPPORT_READDIR_WITH_FILE_TYPES=void 0;var zS=process.versions.node.split(\".\");if(zS[0]===void 0||zS[1]===void 0)throw new Error(`Unexpected behavior. The 'process.versions.node' variable has invalid value: ${process.versions.node}`);var Zie=Number.parseInt(zS[0],10),q$e=Number.parseInt(zS[1],10),$ie=10,j$e=10,G$e=Zie>$ie,W$e=Zie===$ie&&q$e>=j$e;JS.IS_SUPPORT_READDIR_WITH_FILE_TYPES=G$e||W$e});var ese=_(XS=>{\"use strict\";Object.defineProperty(XS,\"__esModule\",{value:!0});XS.createDirentFromStats=void 0;var bO=class{constructor(e,r){this.name=e,this.isBlockDevice=r.isBlockDevice.bind(r),this.isCharacterDevice=r.isCharacterDevice.bind(r),this.isDirectory=r.isDirectory.bind(r),this.isFIFO=r.isFIFO.bind(r),this.isFile=r.isFile.bind(r),this.isSocket=r.isSocket.bind(r),this.isSymbolicLink=r.isSymbolicLink.bind(r)}};function Y$e(t,e){return new bO(t,e)}XS.createDirentFromStats=Y$e});var kO=_(ZS=>{\"use strict\";Object.defineProperty(ZS,\"__esModule\",{value:!0});ZS.fs=void 0;var K$e=ese();ZS.fs=K$e});var QO=_($S=>{\"use strict\";Object.defineProperty($S,\"__esModule\",{value:!0});$S.joinPathSegments=void 0;function V$e(t,e,r){return t.endsWith(r)?t+e:t+r+e}$S.joinPathSegments=V$e});var ose=_(nh=>{\"use strict\";Object.defineProperty(nh,\"__esModule\",{value:!0});nh.readdir=nh.readdirWithFileTypes=nh.read=void 0;var z$e=wg(),tse=Xie(),J$e=xO(),rse=kO(),nse=QO();function X$e(t,e,r){if(!e.stats&&J$e.IS_SUPPORT_READDIR_WITH_FILE_TYPES){ise(t,e,r);return}sse(t,e,r)}nh.read=X$e;function ise(t,e,r){e.fs.readdir(t,{withFileTypes:!0},(o,a)=>{if(o!==null){ex(r,o);return}let n=a.map(A=>({dirent:A,name:A.name,path:nse.joinPathSegments(t,A.name,e.pathSegmentSeparator)}));if(!e.followSymbolicLinks){FO(r,n);return}let u=n.map(A=>Z$e(A,e));tse(u,(A,p)=>{if(A!==null){ex(r,A);return}FO(r,p)})})}nh.readdirWithFileTypes=ise;function Z$e(t,e){return r=>{if(!t.dirent.isSymbolicLink()){r(null,t);return}e.fs.stat(t.path,(o,a)=>{if(o!==null){if(e.throwErrorOnBrokenSymbolicLink){r(o);return}r(null,t);return}t.dirent=rse.fs.createDirentFromStats(t.name,a),r(null,t)})}}function sse(t,e,r){e.fs.readdir(t,(o,a)=>{if(o!==null){ex(r,o);return}let n=a.map(u=>{let A=nse.joinPathSegments(t,u,e.pathSegmentSeparator);return p=>{z$e.stat(A,e.fsStatSettings,(h,E)=>{if(h!==null){p(h);return}let w={name:u,path:A,dirent:rse.fs.createDirentFromStats(u,E)};e.stats&&(w.stats=E),p(null,w)})}});tse(n,(u,A)=>{if(u!==null){ex(r,u);return}FO(r,A)})})}nh.readdir=sse;function ex(t,e){t(e)}function FO(t,e){t(null,e)}});var Ase=_(ih=>{\"use strict\";Object.defineProperty(ih,\"__esModule\",{value:!0});ih.readdir=ih.readdirWithFileTypes=ih.read=void 0;var $$e=wg(),eet=xO(),ase=kO(),lse=QO();function tet(t,e){return!e.stats&&eet.IS_SUPPORT_READDIR_WITH_FILE_TYPES?cse(t,e):use(t,e)}ih.read=tet;function cse(t,e){return e.fs.readdirSync(t,{withFileTypes:!0}).map(o=>{let a={dirent:o,name:o.name,path:lse.joinPathSegments(t,o.name,e.pathSegmentSeparator)};if(a.dirent.isSymbolicLink()&&e.followSymbolicLinks)try{let n=e.fs.statSync(a.path);a.dirent=ase.fs.createDirentFromStats(a.name,n)}catch(n){if(e.throwErrorOnBrokenSymbolicLink)throw n}return a})}ih.readdirWithFileTypes=cse;function use(t,e){return e.fs.readdirSync(t).map(o=>{let a=lse.joinPathSegments(t,o,e.pathSegmentSeparator),n=$$e.statSync(a,e.fsStatSettings),u={name:o,path:a,dirent:ase.fs.createDirentFromStats(o,n)};return e.stats&&(u.stats=n),u})}ih.readdir=use});var fse=_(sh=>{\"use strict\";Object.defineProperty(sh,\"__esModule\",{value:!0});sh.createFileSystemAdapter=sh.FILE_SYSTEM_ADAPTER=void 0;var iy=ve(\"fs\");sh.FILE_SYSTEM_ADAPTER={lstat:iy.lstat,stat:iy.stat,lstatSync:iy.lstatSync,statSync:iy.statSync,readdir:iy.readdir,readdirSync:iy.readdirSync};function ret(t){return t===void 0?sh.FILE_SYSTEM_ADAPTER:Object.assign(Object.assign({},sh.FILE_SYSTEM_ADAPTER),t)}sh.createFileSystemAdapter=ret});var pse=_(TO=>{\"use strict\";Object.defineProperty(TO,\"__esModule\",{value:!0});var net=ve(\"path\"),iet=wg(),set=fse(),RO=class{constructor(e={}){this._options=e,this.followSymbolicLinks=this._getValue(this._options.followSymbolicLinks,!1),this.fs=set.createFileSystemAdapter(this._options.fs),this.pathSegmentSeparator=this._getValue(this._options.pathSegmentSeparator,net.sep),this.stats=this._getValue(this._options.stats,!1),this.throwErrorOnBrokenSymbolicLink=this._getValue(this._options.throwErrorOnBrokenSymbolicLink,!0),this.fsStatSettings=new iet.Settings({followSymbolicLink:this.followSymbolicLinks,fs:this.fs,throwErrorOnBrokenSymbolicLink:this.throwErrorOnBrokenSymbolicLink})}_getValue(e,r){return e??r}};TO.default=RO});var tx=_(oh=>{\"use strict\";Object.defineProperty(oh,\"__esModule\",{value:!0});oh.Settings=oh.scandirSync=oh.scandir=void 0;var hse=ose(),oet=Ase(),LO=pse();oh.Settings=LO.default;function aet(t,e,r){if(typeof e==\"function\"){hse.read(t,NO(),e);return}hse.read(t,NO(e),r)}oh.scandir=aet;function cet(t,e){let r=NO(e);return oet.read(t,r)}oh.scandirSync=cet;function NO(t={}){return t instanceof LO.default?t:new LO.default(t)}});var dse=_((TTt,gse)=>{\"use strict\";function uet(t){var e=new t,r=e;function o(){var n=e;return n.next?e=n.next:(e=new t,r=e),n.next=null,n}function a(n){r.next=n,r=n}return{get:o,release:a}}gse.exports=uet});var yse=_((LTt,OO)=>{\"use strict\";var Aet=dse();function mse(t,e,r){if(typeof t==\"function\"&&(r=e,e=t,t=null),!(r>=1))throw new Error(\"fastqueue concurrency must be equal to or greater than 1\");var o=Aet(fet),a=null,n=null,u=0,A=null,p={push:T,drain:Yl,saturated:Yl,pause:E,paused:!1,get concurrency(){return r},set concurrency(ce){if(!(ce>=1))throw new Error(\"fastqueue concurrency must be equal to or greater than 1\");if(r=ce,!p.paused)for(;a&&u<r;)u++,U()},running:h,resume:b,idle:C,length:w,getQueue:D,unshift:N,empty:Yl,kill:z,killAndDrain:te,error:le};return p;function h(){return u}function E(){p.paused=!0}function w(){for(var ce=a,ue=0;ce;)ce=ce.next,ue++;return ue}function D(){for(var ce=a,ue=[];ce;)ue.push(ce.value),ce=ce.next;return ue}function b(){if(p.paused){if(p.paused=!1,a===null){u++,U();return}for(;a&&u<r;)u++,U()}}function C(){return u===0&&p.length()===0}function T(ce,ue){var Ie=o.get();Ie.context=t,Ie.release=U,Ie.value=ce,Ie.callback=ue||Yl,Ie.errorHandler=A,u>=r||p.paused?n?(n.next=Ie,n=Ie):(a=Ie,n=Ie,p.saturated()):(u++,e.call(t,Ie.value,Ie.worked))}function N(ce,ue){var Ie=o.get();Ie.context=t,Ie.release=U,Ie.value=ce,Ie.callback=ue||Yl,Ie.errorHandler=A,u>=r||p.paused?a?(Ie.next=a,a=Ie):(a=Ie,n=Ie,p.saturated()):(u++,e.call(t,Ie.value,Ie.worked))}function U(ce){ce&&o.release(ce);var ue=a;ue&&u<=r?p.paused?u--:(n===a&&(n=null),a=ue.next,ue.next=null,e.call(t,ue.value,ue.worked),n===null&&p.empty()):--u===0&&p.drain()}function z(){a=null,n=null,p.drain=Yl}function te(){a=null,n=null,p.drain(),p.drain=Yl}function le(ce){A=ce}}function Yl(){}function fet(){this.value=null,this.callback=Yl,this.next=null,this.release=Yl,this.context=null,this.errorHandler=null;var t=this;this.worked=function(r,o){var a=t.callback,n=t.errorHandler,u=t.value;t.value=null,t.callback=Yl,t.errorHandler&&n(r,u),a.call(t.context,r,o),t.release(t)}}function pet(t,e,r){typeof t==\"function\"&&(r=e,e=t,t=null);function o(E,w){e.call(this,E).then(function(D){w(null,D)},w)}var a=mse(t,o,r),n=a.push,u=a.unshift;return a.push=A,a.unshift=p,a.drained=h,a;function A(E){var w=new Promise(function(D,b){n(E,function(C,T){if(C){b(C);return}D(T)})});return w.catch(Yl),w}function p(E){var w=new Promise(function(D,b){u(E,function(C,T){if(C){b(C);return}D(T)})});return w.catch(Yl),w}function h(){if(a.idle())return new Promise(function(D){D()});var E=a.drain,w=new Promise(function(D){a.drain=function(){E(),D()}});return w}}OO.exports=mse;OO.exports.promise=pet});var rx=_(eA=>{\"use strict\";Object.defineProperty(eA,\"__esModule\",{value:!0});eA.joinPathSegments=eA.replacePathSegmentSeparator=eA.isAppliedFilter=eA.isFatalError=void 0;function het(t,e){return t.errorFilter===null?!0:!t.errorFilter(e)}eA.isFatalError=het;function get(t,e){return t===null||t(e)}eA.isAppliedFilter=get;function det(t,e){return t.split(/[/\\\\]/).join(e)}eA.replacePathSegmentSeparator=det;function met(t,e,r){return t===\"\"?e:t.endsWith(r)?t+e:t+r+e}eA.joinPathSegments=met});var _O=_(UO=>{\"use strict\";Object.defineProperty(UO,\"__esModule\",{value:!0});var yet=rx(),MO=class{constructor(e,r){this._root=e,this._settings=r,this._root=yet.replacePathSegmentSeparator(e,r.pathSegmentSeparator)}};UO.default=MO});var jO=_(qO=>{\"use strict\";Object.defineProperty(qO,\"__esModule\",{value:!0});var Eet=ve(\"events\"),Cet=tx(),Iet=yse(),nx=rx(),wet=_O(),HO=class extends wet.default{constructor(e,r){super(e,r),this._settings=r,this._scandir=Cet.scandir,this._emitter=new Eet.EventEmitter,this._queue=Iet(this._worker.bind(this),this._settings.concurrency),this._isFatalError=!1,this._isDestroyed=!1,this._queue.drain=()=>{this._isFatalError||this._emitter.emit(\"end\")}}read(){return this._isFatalError=!1,this._isDestroyed=!1,setImmediate(()=>{this._pushToQueue(this._root,this._settings.basePath)}),this._emitter}get isDestroyed(){return this._isDestroyed}destroy(){if(this._isDestroyed)throw new Error(\"The reader is already destroyed\");this._isDestroyed=!0,this._queue.killAndDrain()}onEntry(e){this._emitter.on(\"entry\",e)}onError(e){this._emitter.once(\"error\",e)}onEnd(e){this._emitter.once(\"end\",e)}_pushToQueue(e,r){let o={directory:e,base:r};this._queue.push(o,a=>{a!==null&&this._handleError(a)})}_worker(e,r){this._scandir(e.directory,this._settings.fsScandirSettings,(o,a)=>{if(o!==null){r(o,void 0);return}for(let n of a)this._handleEntry(n,e.base);r(null,void 0)})}_handleError(e){this._isDestroyed||!nx.isFatalError(this._settings,e)||(this._isFatalError=!0,this._isDestroyed=!0,this._emitter.emit(\"error\",e))}_handleEntry(e,r){if(this._isDestroyed||this._isFatalError)return;let o=e.path;r!==void 0&&(e.path=nx.joinPathSegments(r,e.name,this._settings.pathSegmentSeparator)),nx.isAppliedFilter(this._settings.entryFilter,e)&&this._emitEntry(e),e.dirent.isDirectory()&&nx.isAppliedFilter(this._settings.deepFilter,e)&&this._pushToQueue(o,r===void 0?void 0:e.path)}_emitEntry(e){this._emitter.emit(\"entry\",e)}};qO.default=HO});var Ese=_(WO=>{\"use strict\";Object.defineProperty(WO,\"__esModule\",{value:!0});var Bet=jO(),GO=class{constructor(e,r){this._root=e,this._settings=r,this._reader=new Bet.default(this._root,this._settings),this._storage=[]}read(e){this._reader.onError(r=>{vet(e,r)}),this._reader.onEntry(r=>{this._storage.push(r)}),this._reader.onEnd(()=>{Det(e,this._storage)}),this._reader.read()}};WO.default=GO;function vet(t,e){t(e)}function Det(t,e){t(null,e)}});var Cse=_(KO=>{\"use strict\";Object.defineProperty(KO,\"__esModule\",{value:!0});var Pet=ve(\"stream\"),xet=jO(),YO=class{constructor(e,r){this._root=e,this._settings=r,this._reader=new xet.default(this._root,this._settings),this._stream=new Pet.Readable({objectMode:!0,read:()=>{},destroy:()=>{this._reader.isDestroyed||this._reader.destroy()}})}read(){return this._reader.onError(e=>{this._stream.emit(\"error\",e)}),this._reader.onEntry(e=>{this._stream.push(e)}),this._reader.onEnd(()=>{this._stream.push(null)}),this._reader.read(),this._stream}};KO.default=YO});var Ise=_(zO=>{\"use strict\";Object.defineProperty(zO,\"__esModule\",{value:!0});var bet=tx(),ix=rx(),ket=_O(),VO=class extends ket.default{constructor(){super(...arguments),this._scandir=bet.scandirSync,this._storage=[],this._queue=new Set}read(){return this._pushToQueue(this._root,this._settings.basePath),this._handleQueue(),this._storage}_pushToQueue(e,r){this._queue.add({directory:e,base:r})}_handleQueue(){for(let e of this._queue.values())this._handleDirectory(e.directory,e.base)}_handleDirectory(e,r){try{let o=this._scandir(e,this._settings.fsScandirSettings);for(let a of o)this._handleEntry(a,r)}catch(o){this._handleError(o)}}_handleError(e){if(ix.isFatalError(this._settings,e))throw e}_handleEntry(e,r){let o=e.path;r!==void 0&&(e.path=ix.joinPathSegments(r,e.name,this._settings.pathSegmentSeparator)),ix.isAppliedFilter(this._settings.entryFilter,e)&&this._pushToStorage(e),e.dirent.isDirectory()&&ix.isAppliedFilter(this._settings.deepFilter,e)&&this._pushToQueue(o,r===void 0?void 0:e.path)}_pushToStorage(e){this._storage.push(e)}};zO.default=VO});var wse=_(XO=>{\"use strict\";Object.defineProperty(XO,\"__esModule\",{value:!0});var Qet=Ise(),JO=class{constructor(e,r){this._root=e,this._settings=r,this._reader=new Qet.default(this._root,this._settings)}read(){return this._reader.read()}};XO.default=JO});var Bse=_($O=>{\"use strict\";Object.defineProperty($O,\"__esModule\",{value:!0});var Fet=ve(\"path\"),Ret=tx(),ZO=class{constructor(e={}){this._options=e,this.basePath=this._getValue(this._options.basePath,void 0),this.concurrency=this._getValue(this._options.concurrency,Number.POSITIVE_INFINITY),this.deepFilter=this._getValue(this._options.deepFilter,null),this.entryFilter=this._getValue(this._options.entryFilter,null),this.errorFilter=this._getValue(this._options.errorFilter,null),this.pathSegmentSeparator=this._getValue(this._options.pathSegmentSeparator,Fet.sep),this.fsScandirSettings=new Ret.Settings({followSymbolicLinks:this._options.followSymbolicLinks,fs:this._options.fs,pathSegmentSeparator:this._options.pathSegmentSeparator,stats:this._options.stats,throwErrorOnBrokenSymbolicLink:this._options.throwErrorOnBrokenSymbolicLink})}_getValue(e,r){return e??r}};$O.default=ZO});var ox=_(tA=>{\"use strict\";Object.defineProperty(tA,\"__esModule\",{value:!0});tA.Settings=tA.walkStream=tA.walkSync=tA.walk=void 0;var vse=Ese(),Tet=Cse(),Let=wse(),eM=Bse();tA.Settings=eM.default;function Net(t,e,r){if(typeof e==\"function\"){new vse.default(t,sx()).read(e);return}new vse.default(t,sx(e)).read(r)}tA.walk=Net;function Oet(t,e){let r=sx(e);return new Let.default(t,r).read()}tA.walkSync=Oet;function Met(t,e){let r=sx(e);return new Tet.default(t,r).read()}tA.walkStream=Met;function sx(t={}){return t instanceof eM.default?t:new eM.default(t)}});var ax=_(rM=>{\"use strict\";Object.defineProperty(rM,\"__esModule\",{value:!0});var Uet=ve(\"path\"),_et=wg(),Dse=Df(),tM=class{constructor(e){this._settings=e,this._fsStatSettings=new _et.Settings({followSymbolicLink:this._settings.followSymbolicLinks,fs:this._settings.fs,throwErrorOnBrokenSymbolicLink:this._settings.followSymbolicLinks})}_getFullEntryPath(e){return Uet.resolve(this._settings.cwd,e)}_makeEntry(e,r){let o={name:r,path:r,dirent:Dse.fs.createDirentFromStats(r,e)};return this._settings.stats&&(o.stats=e),o}_isFatalError(e){return!Dse.errno.isEnoentCodeError(e)&&!this._settings.suppressErrors}};rM.default=tM});var sM=_(iM=>{\"use strict\";Object.defineProperty(iM,\"__esModule\",{value:!0});var Het=ve(\"stream\"),qet=wg(),jet=ox(),Get=ax(),nM=class extends Get.default{constructor(){super(...arguments),this._walkStream=jet.walkStream,this._stat=qet.stat}dynamic(e,r){return this._walkStream(e,r)}static(e,r){let o=e.map(this._getFullEntryPath,this),a=new Het.PassThrough({objectMode:!0});a._write=(n,u,A)=>this._getEntry(o[n],e[n],r).then(p=>{p!==null&&r.entryFilter(p)&&a.push(p),n===o.length-1&&a.end(),A()}).catch(A);for(let n=0;n<o.length;n++)a.write(n);return a}_getEntry(e,r,o){return this._getStat(e).then(a=>this._makeEntry(a,r)).catch(a=>{if(o.errorFilter(a))return null;throw a})}_getStat(e){return new Promise((r,o)=>{this._stat(e,this._fsStatSettings,(a,n)=>a===null?r(n):o(a))})}};iM.default=nM});var Pse=_(aM=>{\"use strict\";Object.defineProperty(aM,\"__esModule\",{value:!0});var Wet=ox(),Yet=ax(),Ket=sM(),oM=class extends Yet.default{constructor(){super(...arguments),this._walkAsync=Wet.walk,this._readerStream=new Ket.default(this._settings)}dynamic(e,r){return new Promise((o,a)=>{this._walkAsync(e,r,(n,u)=>{n===null?o(u):a(n)})})}async static(e,r){let o=[],a=this._readerStream.static(e,r);return new Promise((n,u)=>{a.once(\"error\",u),a.on(\"data\",A=>o.push(A)),a.once(\"end\",()=>n(o))})}};aM.default=oM});var Sse=_(cM=>{\"use strict\";Object.defineProperty(cM,\"__esModule\",{value:!0});var m1=Df(),lM=class{constructor(e,r,o){this._patterns=e,this._settings=r,this._micromatchOptions=o,this._storage=[],this._fillStorage()}_fillStorage(){for(let e of this._patterns){let r=this._getPatternSegments(e),o=this._splitSegmentsIntoSections(r);this._storage.push({complete:o.length<=1,pattern:e,segments:r,sections:o})}}_getPatternSegments(e){return m1.pattern.getPatternParts(e,this._micromatchOptions).map(o=>m1.pattern.isDynamicPattern(o,this._settings)?{dynamic:!0,pattern:o,patternRe:m1.pattern.makeRe(o,this._micromatchOptions)}:{dynamic:!1,pattern:o})}_splitSegmentsIntoSections(e){return m1.array.splitWhen(e,r=>r.dynamic&&m1.pattern.hasGlobStar(r.pattern))}};cM.default=lM});var xse=_(AM=>{\"use strict\";Object.defineProperty(AM,\"__esModule\",{value:!0});var Vet=Sse(),uM=class extends Vet.default{match(e){let r=e.split(\"/\"),o=r.length,a=this._storage.filter(n=>!n.complete||n.segments.length>o);for(let n of a){let u=n.sections[0];if(!n.complete&&o>u.length||r.every((p,h)=>{let E=n.segments[h];return!!(E.dynamic&&E.patternRe.test(p)||!E.dynamic&&E.pattern===p)}))return!0}return!1}};AM.default=uM});var bse=_(pM=>{\"use strict\";Object.defineProperty(pM,\"__esModule\",{value:!0});var lx=Df(),zet=xse(),fM=class{constructor(e,r){this._settings=e,this._micromatchOptions=r}getFilter(e,r,o){let a=this._getMatcher(r),n=this._getNegativePatternsRe(o);return u=>this._filter(e,u,a,n)}_getMatcher(e){return new zet.default(e,this._settings,this._micromatchOptions)}_getNegativePatternsRe(e){let r=e.filter(lx.pattern.isAffectDepthOfReadingPattern);return lx.pattern.convertPatternsToRe(r,this._micromatchOptions)}_filter(e,r,o,a){if(this._isSkippedByDeep(e,r.path)||this._isSkippedSymbolicLink(r))return!1;let n=lx.path.removeLeadingDotSegment(r.path);return this._isSkippedByPositivePatterns(n,o)?!1:this._isSkippedByNegativePatterns(n,a)}_isSkippedByDeep(e,r){return this._settings.deep===1/0?!1:this._getEntryLevel(e,r)>=this._settings.deep}_getEntryLevel(e,r){let o=r.split(\"/\").length;if(e===\"\")return o;let a=e.split(\"/\").length;return o-a}_isSkippedSymbolicLink(e){return!this._settings.followSymbolicLinks&&e.dirent.isSymbolicLink()}_isSkippedByPositivePatterns(e,r){return!this._settings.baseNameMatch&&!r.match(e)}_isSkippedByNegativePatterns(e,r){return!lx.pattern.matchAny(e,r)}};pM.default=fM});var kse=_(gM=>{\"use strict\";Object.defineProperty(gM,\"__esModule\",{value:!0});var Bg=Df(),hM=class{constructor(e,r){this._settings=e,this._micromatchOptions=r,this.index=new Map}getFilter(e,r){let o=Bg.pattern.convertPatternsToRe(e,this._micromatchOptions),a=Bg.pattern.convertPatternsToRe(r,Object.assign(Object.assign({},this._micromatchOptions),{dot:!0}));return n=>this._filter(n,o,a)}_filter(e,r,o){let a=Bg.path.removeLeadingDotSegment(e.path);if(this._settings.unique&&this._isDuplicateEntry(a)||this._onlyFileFilter(e)||this._onlyDirectoryFilter(e)||this._isSkippedByAbsoluteNegativePatterns(a,o))return!1;let n=e.dirent.isDirectory(),u=this._isMatchToPatterns(a,r,n)&&!this._isMatchToPatterns(a,o,n);return this._settings.unique&&u&&this._createIndexRecord(a),u}_isDuplicateEntry(e){return this.index.has(e)}_createIndexRecord(e){this.index.set(e,void 0)}_onlyFileFilter(e){return this._settings.onlyFiles&&!e.dirent.isFile()}_onlyDirectoryFilter(e){return this._settings.onlyDirectories&&!e.dirent.isDirectory()}_isSkippedByAbsoluteNegativePatterns(e,r){if(!this._settings.absolute)return!1;let o=Bg.path.makeAbsolute(this._settings.cwd,e);return Bg.pattern.matchAny(o,r)}_isMatchToPatterns(e,r,o){let a=Bg.pattern.matchAny(e,r);return!a&&o?Bg.pattern.matchAny(e+\"/\",r):a}};gM.default=hM});var Qse=_(mM=>{\"use strict\";Object.defineProperty(mM,\"__esModule\",{value:!0});var Jet=Df(),dM=class{constructor(e){this._settings=e}getFilter(){return e=>this._isNonFatalError(e)}_isNonFatalError(e){return Jet.errno.isEnoentCodeError(e)||this._settings.suppressErrors}};mM.default=dM});var Rse=_(EM=>{\"use strict\";Object.defineProperty(EM,\"__esModule\",{value:!0});var Fse=Df(),yM=class{constructor(e){this._settings=e}getTransformer(){return e=>this._transform(e)}_transform(e){let r=e.path;return this._settings.absolute&&(r=Fse.path.makeAbsolute(this._settings.cwd,r),r=Fse.path.unixify(r)),this._settings.markDirectories&&e.dirent.isDirectory()&&(r+=\"/\"),this._settings.objectMode?Object.assign(Object.assign({},e),{path:r}):r}};EM.default=yM});var cx=_(IM=>{\"use strict\";Object.defineProperty(IM,\"__esModule\",{value:!0});var Xet=ve(\"path\"),Zet=bse(),$et=kse(),ett=Qse(),ttt=Rse(),CM=class{constructor(e){this._settings=e,this.errorFilter=new ett.default(this._settings),this.entryFilter=new $et.default(this._settings,this._getMicromatchOptions()),this.deepFilter=new Zet.default(this._settings,this._getMicromatchOptions()),this.entryTransformer=new ttt.default(this._settings)}_getRootDirectory(e){return Xet.resolve(this._settings.cwd,e.base)}_getReaderOptions(e){let r=e.base===\".\"?\"\":e.base;return{basePath:r,pathSegmentSeparator:\"/\",concurrency:this._settings.concurrency,deepFilter:this.deepFilter.getFilter(r,e.positive,e.negative),entryFilter:this.entryFilter.getFilter(e.positive,e.negative),errorFilter:this.errorFilter.getFilter(),followSymbolicLinks:this._settings.followSymbolicLinks,fs:this._settings.fs,stats:this._settings.stats,throwErrorOnBrokenSymbolicLink:this._settings.throwErrorOnBrokenSymbolicLink,transform:this.entryTransformer.getTransformer()}}_getMicromatchOptions(){return{dot:this._settings.dot,matchBase:this._settings.baseNameMatch,nobrace:!this._settings.braceExpansion,nocase:!this._settings.caseSensitiveMatch,noext:!this._settings.extglob,noglobstar:!this._settings.globstar,posix:!0,strictSlashes:!1}}};IM.default=CM});var Tse=_(BM=>{\"use strict\";Object.defineProperty(BM,\"__esModule\",{value:!0});var rtt=Pse(),ntt=cx(),wM=class extends ntt.default{constructor(){super(...arguments),this._reader=new rtt.default(this._settings)}async read(e){let r=this._getRootDirectory(e),o=this._getReaderOptions(e);return(await this.api(r,e,o)).map(n=>o.transform(n))}api(e,r,o){return r.dynamic?this._reader.dynamic(e,o):this._reader.static(r.patterns,o)}};BM.default=wM});var Lse=_(DM=>{\"use strict\";Object.defineProperty(DM,\"__esModule\",{value:!0});var itt=ve(\"stream\"),stt=sM(),ott=cx(),vM=class extends ott.default{constructor(){super(...arguments),this._reader=new stt.default(this._settings)}read(e){let r=this._getRootDirectory(e),o=this._getReaderOptions(e),a=this.api(r,e,o),n=new itt.Readable({objectMode:!0,read:()=>{}});return a.once(\"error\",u=>n.emit(\"error\",u)).on(\"data\",u=>n.emit(\"data\",o.transform(u))).once(\"end\",()=>n.emit(\"end\")),n.once(\"close\",()=>a.destroy()),n}api(e,r,o){return r.dynamic?this._reader.dynamic(e,o):this._reader.static(r.patterns,o)}};DM.default=vM});var Nse=_(SM=>{\"use strict\";Object.defineProperty(SM,\"__esModule\",{value:!0});var att=wg(),ltt=ox(),ctt=ax(),PM=class extends ctt.default{constructor(){super(...arguments),this._walkSync=ltt.walkSync,this._statSync=att.statSync}dynamic(e,r){return this._walkSync(e,r)}static(e,r){let o=[];for(let a of e){let n=this._getFullEntryPath(a),u=this._getEntry(n,a,r);u===null||!r.entryFilter(u)||o.push(u)}return o}_getEntry(e,r,o){try{let a=this._getStat(e);return this._makeEntry(a,r)}catch(a){if(o.errorFilter(a))return null;throw a}}_getStat(e){return this._statSync(e,this._fsStatSettings)}};SM.default=PM});var Ose=_(bM=>{\"use strict\";Object.defineProperty(bM,\"__esModule\",{value:!0});var utt=Nse(),Att=cx(),xM=class extends Att.default{constructor(){super(...arguments),this._reader=new utt.default(this._settings)}read(e){let r=this._getRootDirectory(e),o=this._getReaderOptions(e);return this.api(r,e,o).map(o.transform)}api(e,r,o){return r.dynamic?this._reader.dynamic(e,o):this._reader.static(r.patterns,o)}};bM.default=xM});var Mse=_(oy=>{\"use strict\";Object.defineProperty(oy,\"__esModule\",{value:!0});oy.DEFAULT_FILE_SYSTEM_ADAPTER=void 0;var sy=ve(\"fs\"),ftt=ve(\"os\"),ptt=Math.max(ftt.cpus().length,1);oy.DEFAULT_FILE_SYSTEM_ADAPTER={lstat:sy.lstat,lstatSync:sy.lstatSync,stat:sy.stat,statSync:sy.statSync,readdir:sy.readdir,readdirSync:sy.readdirSync};var kM=class{constructor(e={}){this._options=e,this.absolute=this._getValue(this._options.absolute,!1),this.baseNameMatch=this._getValue(this._options.baseNameMatch,!1),this.braceExpansion=this._getValue(this._options.braceExpansion,!0),this.caseSensitiveMatch=this._getValue(this._options.caseSensitiveMatch,!0),this.concurrency=this._getValue(this._options.concurrency,ptt),this.cwd=this._getValue(this._options.cwd,process.cwd()),this.deep=this._getValue(this._options.deep,1/0),this.dot=this._getValue(this._options.dot,!1),this.extglob=this._getValue(this._options.extglob,!0),this.followSymbolicLinks=this._getValue(this._options.followSymbolicLinks,!0),this.fs=this._getFileSystemMethods(this._options.fs),this.globstar=this._getValue(this._options.globstar,!0),this.ignore=this._getValue(this._options.ignore,[]),this.markDirectories=this._getValue(this._options.markDirectories,!1),this.objectMode=this._getValue(this._options.objectMode,!1),this.onlyDirectories=this._getValue(this._options.onlyDirectories,!1),this.onlyFiles=this._getValue(this._options.onlyFiles,!0),this.stats=this._getValue(this._options.stats,!1),this.suppressErrors=this._getValue(this._options.suppressErrors,!1),this.throwErrorOnBrokenSymbolicLink=this._getValue(this._options.throwErrorOnBrokenSymbolicLink,!1),this.unique=this._getValue(this._options.unique,!0),this.onlyDirectories&&(this.onlyFiles=!1),this.stats&&(this.objectMode=!0),this.ignore=[].concat(this.ignore)}_getValue(e,r){return e===void 0?r:e}_getFileSystemMethods(e={}){return Object.assign(Object.assign({},oy.DEFAULT_FILE_SYSTEM_ADAPTER),e)}};oy.default=kM});var ux=_((oLt,_se)=>{\"use strict\";var Use=_ie(),htt=Tse(),gtt=Lse(),dtt=Ose(),QM=Mse(),Kl=Df();async function FM(t,e){Vc(t);let r=RM(t,htt.default,e),o=await Promise.all(r);return Kl.array.flatten(o)}(function(t){t.glob=t,t.globSync=e,t.globStream=r,t.async=t;function e(h,E){Vc(h);let w=RM(h,dtt.default,E);return Kl.array.flatten(w)}t.sync=e;function r(h,E){Vc(h);let w=RM(h,gtt.default,E);return Kl.stream.merge(w)}t.stream=r;function o(h,E){Vc(h);let w=[].concat(h),D=new QM.default(E);return Use.generate(w,D)}t.generateTasks=o;function a(h,E){Vc(h);let w=new QM.default(E);return Kl.pattern.isDynamicPattern(h,w)}t.isDynamicPattern=a;function n(h){return Vc(h),Kl.path.escape(h)}t.escapePath=n;function u(h){return Vc(h),Kl.path.convertPathToPattern(h)}t.convertPathToPattern=u;let A;(function(h){function E(D){return Vc(D),Kl.path.escapePosixPath(D)}h.escapePath=E;function w(D){return Vc(D),Kl.path.convertPosixPathToPattern(D)}h.convertPathToPattern=w})(A=t.posix||(t.posix={}));let p;(function(h){function E(D){return Vc(D),Kl.path.escapeWindowsPath(D)}h.escapePath=E;function w(D){return Vc(D),Kl.path.convertWindowsPathToPattern(D)}h.convertPathToPattern=w})(p=t.win32||(t.win32={}))})(FM||(FM={}));function RM(t,e,r){let o=[].concat(t),a=new QM.default(r),n=Use.generate(o,a),u=new e(a);return n.map(u.read,u)}function Vc(t){if(![].concat(t).every(o=>Kl.string.isString(o)&&!Kl.string.isEmpty(o)))throw new TypeError(\"Patterns must be a string (non empty) or an array of strings\")}_se.exports=FM});var bn={};Kt(bn,{checksumFile:()=>fx,checksumPattern:()=>px,makeHash:()=>zi});function zi(...t){let e=(0,Ax.createHash)(\"sha512\"),r=\"\";for(let o of t)typeof o==\"string\"?r+=o:o&&(r&&(e.update(r),r=\"\"),e.update(o));return r&&e.update(r),e.digest(\"hex\")}async function fx(t,{baseFs:e,algorithm:r}={baseFs:ae,algorithm:\"sha512\"}){let o=await e.openPromise(t,\"r\");try{let n=Buffer.allocUnsafeSlow(65536),u=(0,Ax.createHash)(r),A=0;for(;(A=await e.readPromise(o,n,0,65536))!==0;)u.update(A===65536?n:n.slice(0,A));return u.digest(\"hex\")}finally{await e.closePromise(o)}}async function px(t,{cwd:e}){let o=(await(0,TM.default)(t,{cwd:Ae.fromPortablePath(e),onlyDirectories:!0})).map(A=>`${A}/**/*`),a=await(0,TM.default)([t,...o],{cwd:Ae.fromPortablePath(e),onlyFiles:!1});a.sort();let n=await Promise.all(a.map(async A=>{let p=[Buffer.from(A)],h=K.join(e,Ae.toPortablePath(A)),E=await ae.lstatPromise(h);return E.isSymbolicLink()?p.push(Buffer.from(await ae.readlinkPromise(h))):E.isFile()&&p.push(await ae.readFilePromise(h)),p.join(\"\\0\")})),u=(0,Ax.createHash)(\"sha512\");for(let A of n)u.update(A);return u.digest(\"hex\")}var Ax,TM,ah=It(()=>{Pt();Ax=ve(\"crypto\"),TM=et(ux())});var G={};Kt(G,{allPeerRequests:()=>S1,areDescriptorsEqual:()=>Wse,areIdentsEqual:()=>w1,areLocatorsEqual:()=>B1,areVirtualPackagesEquivalent:()=>Dtt,bindDescriptor:()=>Btt,bindLocator:()=>vtt,convertDescriptorToLocator:()=>hx,convertLocatorToDescriptor:()=>NM,convertPackageToLocator:()=>Ctt,convertToIdent:()=>Ett,convertToManifestRange:()=>Ltt,copyPackage:()=>E1,devirtualizeDescriptor:()=>C1,devirtualizeLocator:()=>I1,ensureDevirtualizedDescriptor:()=>Itt,ensureDevirtualizedLocator:()=>wtt,getIdentVendorPath:()=>_M,isPackageCompatible:()=>Ex,isVirtualDescriptor:()=>Pf,isVirtualLocator:()=>zc,makeDescriptor:()=>kn,makeIdent:()=>rA,makeLocator:()=>Ss,makeRange:()=>mx,parseDescriptor:()=>lh,parseFileStyleRange:()=>Rtt,parseIdent:()=>Zo,parseLocator:()=>Sf,parseRange:()=>vg,prettyDependent:()=>fO,prettyDescriptor:()=>zn,prettyIdent:()=>Ui,prettyLocator:()=>jr,prettyLocatorNoColors:()=>AO,prettyRange:()=>cy,prettyReference:()=>D1,prettyResolution:()=>d1,prettyWorkspace:()=>P1,renamePackage:()=>OM,slugifyIdent:()=>LM,slugifyLocator:()=>ly,sortDescriptors:()=>uy,stringifyDescriptor:()=>ka,stringifyIdent:()=>rn,stringifyLocator:()=>Qa,tryParseDescriptor:()=>v1,tryParseIdent:()=>Yse,tryParseLocator:()=>dx,tryParseRange:()=>Ftt,virtualizeDescriptor:()=>MM,virtualizePackage:()=>UM});function rA(t,e){if(t?.startsWith(\"@\"))throw new Error(\"Invalid scope: don't prefix it with '@'\");return{identHash:zi(t,e),scope:t,name:e}}function kn(t,e){return{identHash:t.identHash,scope:t.scope,name:t.name,descriptorHash:zi(t.identHash,e),range:e}}function Ss(t,e){return{identHash:t.identHash,scope:t.scope,name:t.name,locatorHash:zi(t.identHash,e),reference:e}}function Ett(t){return{identHash:t.identHash,scope:t.scope,name:t.name}}function hx(t){return{identHash:t.identHash,scope:t.scope,name:t.name,locatorHash:t.descriptorHash,reference:t.range}}function NM(t){return{identHash:t.identHash,scope:t.scope,name:t.name,descriptorHash:t.locatorHash,range:t.reference}}function Ctt(t){return{identHash:t.identHash,scope:t.scope,name:t.name,locatorHash:t.locatorHash,reference:t.reference}}function OM(t,e){return{identHash:e.identHash,scope:e.scope,name:e.name,locatorHash:e.locatorHash,reference:e.reference,version:t.version,languageName:t.languageName,linkType:t.linkType,conditions:t.conditions,dependencies:new Map(t.dependencies),peerDependencies:new Map(t.peerDependencies),dependenciesMeta:new Map(t.dependenciesMeta),peerDependenciesMeta:new Map(t.peerDependenciesMeta),bin:new Map(t.bin)}}function E1(t){return OM(t,t)}function MM(t,e){if(e.includes(\"#\"))throw new Error(\"Invalid entropy\");return kn(t,`virtual:${e}#${t.range}`)}function UM(t,e){if(e.includes(\"#\"))throw new Error(\"Invalid entropy\");return OM(t,Ss(t,`virtual:${e}#${t.reference}`))}function Pf(t){return t.range.startsWith(y1)}function zc(t){return t.reference.startsWith(y1)}function C1(t){if(!Pf(t))throw new Error(\"Not a virtual descriptor\");return kn(t,t.range.replace(gx,\"\"))}function I1(t){if(!zc(t))throw new Error(\"Not a virtual descriptor\");return Ss(t,t.reference.replace(gx,\"\"))}function Itt(t){return Pf(t)?kn(t,t.range.replace(gx,\"\")):t}function wtt(t){return zc(t)?Ss(t,t.reference.replace(gx,\"\")):t}function Btt(t,e){return t.range.includes(\"::\")?t:kn(t,`${t.range}::${ay.default.stringify(e)}`)}function vtt(t,e){return t.reference.includes(\"::\")?t:Ss(t,`${t.reference}::${ay.default.stringify(e)}`)}function w1(t,e){return t.identHash===e.identHash}function Wse(t,e){return t.descriptorHash===e.descriptorHash}function B1(t,e){return t.locatorHash===e.locatorHash}function Dtt(t,e){if(!zc(t))throw new Error(\"Invalid package type\");if(!zc(e))throw new Error(\"Invalid package type\");if(!w1(t,e)||t.dependencies.size!==e.dependencies.size)return!1;for(let r of t.dependencies.values()){let o=e.dependencies.get(r.identHash);if(!o||!Wse(r,o))return!1}return!0}function Zo(t){let e=Yse(t);if(!e)throw new Error(`Invalid ident (${t})`);return e}function Yse(t){let e=t.match(Ptt);if(!e)return null;let[,r,o]=e;return rA(typeof r<\"u\"?r:null,o)}function lh(t,e=!1){let r=v1(t,e);if(!r)throw new Error(`Invalid descriptor (${t})`);return r}function v1(t,e=!1){let r=e?t.match(Stt):t.match(xtt);if(!r)return null;let[,o,a,n]=r;if(n===\"unknown\")throw new Error(`Invalid range (${t})`);let u=typeof o<\"u\"?o:null,A=typeof n<\"u\"?n:\"unknown\";return kn(rA(u,a),A)}function Sf(t,e=!1){let r=dx(t,e);if(!r)throw new Error(`Invalid locator (${t})`);return r}function dx(t,e=!1){let r=e?t.match(btt):t.match(ktt);if(!r)return null;let[,o,a,n]=r;if(n===\"unknown\")throw new Error(`Invalid reference (${t})`);let u=typeof o<\"u\"?o:null,A=typeof n<\"u\"?n:\"unknown\";return Ss(rA(u,a),A)}function vg(t,e){let r=t.match(Qtt);if(r===null)throw new Error(`Invalid range (${t})`);let o=typeof r[1]<\"u\"?r[1]:null;if(typeof e?.requireProtocol==\"string\"&&o!==e.requireProtocol)throw new Error(`Invalid protocol (${o})`);if(e?.requireProtocol&&o===null)throw new Error(`Missing protocol (${o})`);let a=typeof r[3]<\"u\"?decodeURIComponent(r[2]):null;if(e?.requireSource&&a===null)throw new Error(`Missing source (${t})`);let n=typeof r[3]<\"u\"?decodeURIComponent(r[3]):decodeURIComponent(r[2]),u=e?.parseSelector?ay.default.parse(n):n,A=typeof r[4]<\"u\"?ay.default.parse(r[4]):null;return{protocol:o,source:a,selector:u,params:A}}function Ftt(t,e){try{return vg(t,e)}catch{return null}}function Rtt(t,{protocol:e}){let{selector:r,params:o}=vg(t,{requireProtocol:e,requireBindings:!0});if(typeof o.locator!=\"string\")throw new Error(`Assertion failed: Invalid bindings for ${t}`);return{parentLocator:Sf(o.locator,!0),path:r}}function Hse(t){return t=t.replaceAll(\"%\",\"%25\"),t=t.replaceAll(\":\",\"%3A\"),t=t.replaceAll(\"#\",\"%23\"),t}function Ttt(t){return t===null?!1:Object.entries(t).length>0}function mx({protocol:t,source:e,selector:r,params:o}){let a=\"\";return t!==null&&(a+=`${t}`),e!==null&&(a+=`${Hse(e)}#`),a+=Hse(r),Ttt(o)&&(a+=`::${ay.default.stringify(o)}`),a}function Ltt(t){let{params:e,protocol:r,source:o,selector:a}=vg(t);for(let n in e)n.startsWith(\"__\")&&delete e[n];return mx({protocol:r,source:o,params:e,selector:a})}function rn(t){return t.scope?`@${t.scope}/${t.name}`:`${t.name}`}function ka(t){return t.scope?`@${t.scope}/${t.name}@${t.range}`:`${t.name}@${t.range}`}function Qa(t){return t.scope?`@${t.scope}/${t.name}@${t.reference}`:`${t.name}@${t.reference}`}function LM(t){return t.scope!==null?`@${t.scope}-${t.name}`:t.name}function ly(t){let{protocol:e,selector:r}=vg(t.reference),o=e!==null?e.replace(Ntt,\"\"):\"exotic\",a=qse.default.valid(r),n=a!==null?`${o}-${a}`:`${o}`,u=10;return t.scope?`${LM(t)}-${n}-${t.locatorHash.slice(0,u)}`:`${LM(t)}-${n}-${t.locatorHash.slice(0,u)}`}function Ui(t,e){return e.scope?`${Ut(t,`@${e.scope}/`,Ct.SCOPE)}${Ut(t,e.name,Ct.NAME)}`:`${Ut(t,e.name,Ct.NAME)}`}function yx(t){if(t.startsWith(y1)){let e=yx(t.substring(t.indexOf(\"#\")+1)),r=t.substring(y1.length,y1.length+mtt);return`${e} [${r}]`}else return t.replace(Ott,\"?[...]\")}function cy(t,e){return`${Ut(t,yx(e),Ct.RANGE)}`}function zn(t,e){return`${Ui(t,e)}${Ut(t,\"@\",Ct.RANGE)}${cy(t,e.range)}`}function D1(t,e){return`${Ut(t,yx(e),Ct.REFERENCE)}`}function jr(t,e){return`${Ui(t,e)}${Ut(t,\"@\",Ct.REFERENCE)}${D1(t,e.reference)}`}function AO(t){return`${rn(t)}@${yx(t.reference)}`}function uy(t){return Ps(t,[e=>rn(e),e=>e.range])}function P1(t,e){return Ui(t,e.anchoredLocator)}function d1(t,e,r){let o=Pf(e)?C1(e):e;return r===null?`${zn(t,o)} \\u2192 ${uO(t).Cross}`:o.identHash===r.identHash?`${zn(t,o)} \\u2192 ${D1(t,r.reference)}`:`${zn(t,o)} \\u2192 ${jr(t,r)}`}function fO(t,e,r){return r===null?`${jr(t,e)}`:`${jr(t,e)} (via ${cy(t,r.range)})`}function _M(t){return`node_modules/${rn(t)}`}function Ex(t,e){return t.conditions?ytt(t.conditions,r=>{let[,o,a]=r.match(Gse),n=e[o];return n?n.includes(a):!0}):!0}function S1(t){let e=new Set;if(\"children\"in t)e.add(t);else for(let r of t.requests.values())e.add(r);for(let r of e)for(let o of r.children.values())e.add(o);return e}var ay,qse,jse,y1,mtt,Gse,ytt,gx,Ptt,Stt,xtt,btt,ktt,Qtt,Ntt,Ott,Io=It(()=>{ay=et(ve(\"querystring\")),qse=et(ni()),jse=et(MX());Wl();ah();Gl();Io();y1=\"virtual:\",mtt=5,Gse=/(os|cpu|libc)=([a-z0-9_-]+)/,ytt=(0,jse.makeParser)(Gse);gx=/^[^#]*#/;Ptt=/^(?:@([^/]+?)\\/)?([^@/]+)$/;Stt=/^(?:@([^/]+?)\\/)?([^@/]+?)(?:@(.+))$/,xtt=/^(?:@([^/]+?)\\/)?([^@/]+?)(?:@(.+))?$/;btt=/^(?:@([^/]+?)\\/)?([^@/]+?)(?:@(.+))$/,ktt=/^(?:@([^/]+?)\\/)?([^@/]+?)(?:@(.+))?$/;Qtt=/^([^#:]*:)?((?:(?!::)[^#])*)(?:#((?:(?!::).)*))?(?:::(.*))?$/;Ntt=/:$/;Ott=/\\?.*/});var Kse,Vse=It(()=>{Io();Kse={hooks:{reduceDependency:(t,e,r,o,{resolver:a,resolveOptions:n})=>{for(let{pattern:u,reference:A}of e.topLevelWorkspace.manifest.resolutions){if(u.from&&(u.from.fullName!==rn(r)||e.configuration.normalizeLocator(Ss(Zo(u.from.fullName),u.from.description??r.reference)).locatorHash!==r.locatorHash)||u.descriptor.fullName!==rn(t)||e.configuration.normalizeDependency(kn(Sf(u.descriptor.fullName),u.descriptor.description??t.range)).descriptorHash!==t.descriptorHash)continue;return a.bindDescriptor(e.configuration.normalizeDependency(kn(t,A)),e.topLevelWorkspace.anchoredLocator,n)}return t},validateProject:async(t,e)=>{for(let r of t.workspaces){let o=P1(t.configuration,r);await t.configuration.triggerHook(a=>a.validateWorkspace,r,{reportWarning:(a,n)=>e.reportWarning(a,`${o}: ${n}`),reportError:(a,n)=>e.reportError(a,`${o}: ${n}`)})}},validateWorkspace:async(t,e)=>{let{manifest:r}=t;r.resolutions.length&&t.cwd!==t.project.cwd&&r.errors.push(new Error(\"Resolutions field will be ignored\"));for(let o of r.errors)e.reportWarning(57,o.message)}}}});var ci,Dg=It(()=>{ci=class t{static{this.protocol=\"workspace:\"}supportsDescriptor(e,r){return!!(e.range.startsWith(t.protocol)||r.project.tryWorkspaceByDescriptor(e)!==null)}supportsLocator(e,r){return!!e.reference.startsWith(t.protocol)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){return[o.project.getWorkspaceByDescriptor(e).anchoredLocator]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){let o=r.project.getWorkspaceByCwd(e.reference.slice(t.protocol.length));return{...e,version:o.manifest.version||\"0.0.0\",languageName:\"unknown\",linkType:\"SOFT\",conditions:null,dependencies:r.project.configuration.normalizeDependencyMap(new Map([...o.manifest.dependencies,...o.manifest.devDependencies])),peerDependencies:new Map([...o.manifest.peerDependencies]),dependenciesMeta:o.manifest.dependenciesMeta,peerDependenciesMeta:o.manifest.peerDependenciesMeta,bin:o.manifest.bin}}}});var Ur={};Kt(Ur,{SemVer:()=>$se.SemVer,clean:()=>Utt,getComparator:()=>Xse,mergeComparators:()=>HM,satisfiesWithPrereleases:()=>nA,simplifyRanges:()=>qM,stringifyComparator:()=>Zse,validRange:()=>Fa});function nA(t,e,r=!1){if(!t)return!1;let o=`${e}${r}`,a=zse.get(o);if(typeof a>\"u\")try{a=new xf.default.Range(e,{includePrerelease:!0,loose:r})}catch{return!1}finally{zse.set(o,a||null)}else if(a===null)return!1;let n;try{n=new xf.default.SemVer(t,a)}catch{return!1}return a.test(n)?!0:(n.prerelease&&(n.prerelease=[]),a.set.some(u=>{for(let A of u)A.semver.prerelease&&(A.semver.prerelease=[]);return u.every(A=>A.test(n))}))}function Fa(t){if(t.indexOf(\":\")!==-1)return null;let e=Jse.get(t);if(typeof e<\"u\")return e;try{e=new xf.default.Range(t)}catch{e=null}return Jse.set(t,e),e}function Utt(t){let e=Mtt.exec(t);return e?e[1]:null}function Xse(t){if(t.semver===xf.default.Comparator.ANY)return{gt:null,lt:null};switch(t.operator){case\"\":return{gt:[\">=\",t.semver],lt:[\"<=\",t.semver]};case\">\":case\">=\":return{gt:[t.operator,t.semver],lt:null};case\"<\":case\"<=\":return{gt:null,lt:[t.operator,t.semver]};default:throw new Error(`Assertion failed: Unexpected comparator operator (${t.operator})`)}}function HM(t){if(t.length===0)return null;let e=null,r=null;for(let o of t){if(o.gt){let a=e!==null?xf.default.compare(o.gt[1],e[1]):null;(a===null||a>0||a===0&&o.gt[0]===\">\")&&(e=o.gt)}if(o.lt){let a=r!==null?xf.default.compare(o.lt[1],r[1]):null;(a===null||a<0||a===0&&o.lt[0]===\"<\")&&(r=o.lt)}}if(e&&r){let o=xf.default.compare(e[1],r[1]);if(o===0&&(e[0]===\">\"||r[0]===\"<\")||o>0)return null}return{gt:e,lt:r}}function Zse(t){if(t.gt&&t.lt){if(t.gt[0]===\">=\"&&t.lt[0]===\"<=\"&&t.gt[1].version===t.lt[1].version)return t.gt[1].version;if(t.gt[0]===\">=\"&&t.lt[0]===\"<\"){if(t.lt[1].version===`${t.gt[1].major+1}.0.0-0`)return`^${t.gt[1].version}`;if(t.lt[1].version===`${t.gt[1].major}.${t.gt[1].minor+1}.0-0`)return`~${t.gt[1].version}`}}let e=[];return t.gt&&e.push(t.gt[0]+t.gt[1].version),t.lt&&e.push(t.lt[0]+t.lt[1].version),e.length?e.join(\" \"):\"*\"}function qM(t){let e=t.map(_tt).map(o=>Fa(o).set.map(a=>a.map(n=>Xse(n)))),r=e.shift().map(o=>HM(o)).filter(o=>o!==null);for(let o of e){let a=[];for(let n of r)for(let u of o){let A=HM([n,...u]);A!==null&&a.push(A)}r=a}return r.length===0?null:r.map(o=>Zse(o)).join(\" || \")}function _tt(t){let e=t.split(\"||\");if(e.length>1){let r=new Set;for(let o of e)e.some(a=>a!==o&&xf.default.subset(o,a))||r.add(o);if(r.size<e.length)return[...r].join(\" || \")}return t}var xf,$se,zse,Jse,Mtt,bf=It(()=>{xf=et(ni()),$se=et(ni()),zse=new Map;Jse=new Map;Mtt=/^(?:[\\sv=]*?)((0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)(?:\\s*)$/});function eoe(t){let e=t.match(/^[ \\t]+/m);return e?e[0]:\"  \"}function toe(t){return t.charCodeAt(0)===65279?t.slice(1):t}function $o(t){return t.replace(/\\\\/g,\"/\")}function Cx(t,{yamlCompatibilityMode:e}){return e?nO(t):typeof t>\"u\"||typeof t==\"boolean\"?t:null}function roe(t,e){let r=e.search(/[^!]/);if(r===-1)return\"invalid\";let o=r%2===0?\"\":\"!\",a=e.slice(r);return`${o}${t}=${a}`}function jM(t,e){return e.length===1?roe(t,e[0]):`(${e.map(r=>roe(t,r)).join(\" | \")})`}var noe,_t,Ay=It(()=>{Pt();Ol();noe=et(ni());Dg();Gl();bf();Io();_t=class t{constructor(){this.indent=\"  \";this.name=null;this.version=null;this.os=null;this.cpu=null;this.libc=null;this.type=null;this.packageManager=null;this.private=!1;this.license=null;this.main=null;this.module=null;this.browser=null;this.languageName=null;this.bin=new Map;this.scripts=new Map;this.dependencies=new Map;this.devDependencies=new Map;this.peerDependencies=new Map;this.workspaceDefinitions=[];this.dependenciesMeta=new Map;this.peerDependenciesMeta=new Map;this.resolutions=[];this.files=null;this.publishConfig=null;this.installConfig=null;this.preferUnplugged=null;this.raw={};this.errors=[]}static{this.fileName=\"package.json\"}static{this.allDependencies=[\"dependencies\",\"devDependencies\",\"peerDependencies\"]}static{this.hardDependencies=[\"dependencies\",\"devDependencies\"]}static async tryFind(e,{baseFs:r=new _n}={}){let o=K.join(e,\"package.json\");try{return await t.fromFile(o,{baseFs:r})}catch(a){if(a.code===\"ENOENT\")return null;throw a}}static async find(e,{baseFs:r}={}){let o=await t.tryFind(e,{baseFs:r});if(o===null)throw new Error(\"Manifest not found\");return o}static async fromFile(e,{baseFs:r=new _n}={}){let o=new t;return await o.loadFile(e,{baseFs:r}),o}static fromText(e){let r=new t;return r.loadFromText(e),r}loadFromText(e){let r;try{r=JSON.parse(toe(e)||\"{}\")}catch(o){throw o.message+=` (when parsing ${e})`,o}this.load(r),this.indent=eoe(e)}async loadFile(e,{baseFs:r=new _n}){let o=await r.readFilePromise(e,\"utf8\"),a;try{a=JSON.parse(toe(o)||\"{}\")}catch(n){throw n.message+=` (when parsing ${e})`,n}this.load(a),this.indent=eoe(o)}load(e,{yamlCompatibilityMode:r=!1}={}){if(typeof e!=\"object\"||e===null)throw new Error(`Utterly invalid manifest data (${e})`);this.raw=e;let o=[];if(this.name=null,typeof e.name==\"string\")try{this.name=Zo(e.name)}catch{o.push(new Error(\"Parsing failed for the 'name' field\"))}if(typeof e.version==\"string\"?this.version=e.version:this.version=null,Array.isArray(e.os)){let n=[];this.os=n;for(let u of e.os)typeof u!=\"string\"?o.push(new Error(\"Parsing failed for the 'os' field\")):n.push(u)}else this.os=null;if(Array.isArray(e.cpu)){let n=[];this.cpu=n;for(let u of e.cpu)typeof u!=\"string\"?o.push(new Error(\"Parsing failed for the 'cpu' field\")):n.push(u)}else this.cpu=null;if(Array.isArray(e.libc)){let n=[];this.libc=n;for(let u of e.libc)typeof u!=\"string\"?o.push(new Error(\"Parsing failed for the 'libc' field\")):n.push(u)}else this.libc=null;if(typeof e.type==\"string\"?this.type=e.type:this.type=null,typeof e.packageManager==\"string\"?this.packageManager=e.packageManager:this.packageManager=null,typeof e.private==\"boolean\"?this.private=e.private:this.private=!1,typeof e.license==\"string\"?this.license=e.license:this.license=null,typeof e.languageName==\"string\"?this.languageName=e.languageName:this.languageName=null,typeof e.main==\"string\"?this.main=$o(e.main):this.main=null,typeof e.module==\"string\"?this.module=$o(e.module):this.module=null,e.browser!=null)if(typeof e.browser==\"string\")this.browser=$o(e.browser);else{this.browser=new Map;for(let[n,u]of Object.entries(e.browser))this.browser.set($o(n),typeof u==\"string\"?$o(u):u)}else this.browser=null;if(this.bin=new Map,typeof e.bin==\"string\")e.bin.trim()===\"\"?o.push(new Error(\"Invalid bin field\")):this.name!==null?this.bin.set(this.name.name,$o(e.bin)):o.push(new Error(\"String bin field, but no attached package name\"));else if(typeof e.bin==\"object\"&&e.bin!==null)for(let[n,u]of Object.entries(e.bin)){if(typeof u!=\"string\"||u.trim()===\"\"){o.push(new Error(`Invalid bin definition for '${n}'`));continue}let A=Zo(n);this.bin.set(A.name,$o(u))}if(this.scripts=new Map,typeof e.scripts==\"object\"&&e.scripts!==null)for(let[n,u]of Object.entries(e.scripts)){if(typeof u!=\"string\"){o.push(new Error(`Invalid script definition for '${n}'`));continue}this.scripts.set(n,u)}if(this.dependencies=new Map,typeof e.dependencies==\"object\"&&e.dependencies!==null)for(let[n,u]of Object.entries(e.dependencies)){if(typeof u!=\"string\"){o.push(new Error(`Invalid dependency range for '${n}'`));continue}let A;try{A=Zo(n)}catch{o.push(new Error(`Parsing failed for the dependency name '${n}'`));continue}let p=kn(A,u);this.dependencies.set(p.identHash,p)}if(this.devDependencies=new Map,typeof e.devDependencies==\"object\"&&e.devDependencies!==null)for(let[n,u]of Object.entries(e.devDependencies)){if(typeof u!=\"string\"){o.push(new Error(`Invalid dependency range for '${n}'`));continue}let A;try{A=Zo(n)}catch{o.push(new Error(`Parsing failed for the dependency name '${n}'`));continue}let p=kn(A,u);this.devDependencies.set(p.identHash,p)}if(this.peerDependencies=new Map,typeof e.peerDependencies==\"object\"&&e.peerDependencies!==null)for(let[n,u]of Object.entries(e.peerDependencies)){let A;try{A=Zo(n)}catch{o.push(new Error(`Parsing failed for the dependency name '${n}'`));continue}(typeof u!=\"string\"||!u.startsWith(ci.protocol)&&!Fa(u))&&(o.push(new Error(`Invalid dependency range for '${n}'`)),u=\"*\");let p=kn(A,u);this.peerDependencies.set(p.identHash,p)}typeof e.workspaces==\"object\"&&e.workspaces!==null&&e.workspaces.nohoist&&o.push(new Error(\"'nohoist' is deprecated, please use 'installConfig.hoistingLimits' instead\"));let a=Array.isArray(e.workspaces)?e.workspaces:typeof e.workspaces==\"object\"&&e.workspaces!==null&&Array.isArray(e.workspaces.packages)?e.workspaces.packages:[];this.workspaceDefinitions=[];for(let n of a){if(typeof n!=\"string\"){o.push(new Error(`Invalid workspace definition for '${n}'`));continue}this.workspaceDefinitions.push({pattern:n})}if(this.dependenciesMeta=new Map,typeof e.dependenciesMeta==\"object\"&&e.dependenciesMeta!==null)for(let[n,u]of Object.entries(e.dependenciesMeta)){if(typeof u!=\"object\"||u===null){o.push(new Error(`Invalid meta field for '${n}`));continue}let A=lh(n),p=this.ensureDependencyMeta(A),h=Cx(u.built,{yamlCompatibilityMode:r});if(h===null){o.push(new Error(`Invalid built meta field for '${n}'`));continue}let E=Cx(u.optional,{yamlCompatibilityMode:r});if(E===null){o.push(new Error(`Invalid optional meta field for '${n}'`));continue}let w=Cx(u.unplugged,{yamlCompatibilityMode:r});if(w===null){o.push(new Error(`Invalid unplugged meta field for '${n}'`));continue}Object.assign(p,{built:h,optional:E,unplugged:w})}if(this.peerDependenciesMeta=new Map,typeof e.peerDependenciesMeta==\"object\"&&e.peerDependenciesMeta!==null)for(let[n,u]of Object.entries(e.peerDependenciesMeta)){if(typeof u!=\"object\"||u===null){o.push(new Error(`Invalid meta field for '${n}'`));continue}let A=lh(n),p=this.ensurePeerDependencyMeta(A),h=Cx(u.optional,{yamlCompatibilityMode:r});if(h===null){o.push(new Error(`Invalid optional meta field for '${n}'`));continue}Object.assign(p,{optional:h})}if(this.resolutions=[],typeof e.resolutions==\"object\"&&e.resolutions!==null)for(let[n,u]of Object.entries(e.resolutions)){if(typeof u!=\"string\"){o.push(new Error(`Invalid resolution entry for '${n}'`));continue}try{this.resolutions.push({pattern:pP(n),reference:u})}catch(A){o.push(A);continue}}if(Array.isArray(e.files)){this.files=new Set;for(let n of e.files){if(typeof n!=\"string\"){o.push(new Error(`Invalid files entry for '${n}'`));continue}this.files.add(n)}}else this.files=null;if(typeof e.publishConfig==\"object\"&&e.publishConfig!==null){if(this.publishConfig={},typeof e.publishConfig.access==\"string\"&&(this.publishConfig.access=e.publishConfig.access),typeof e.publishConfig.main==\"string\"&&(this.publishConfig.main=$o(e.publishConfig.main)),typeof e.publishConfig.module==\"string\"&&(this.publishConfig.module=$o(e.publishConfig.module)),e.publishConfig.browser!=null)if(typeof e.publishConfig.browser==\"string\")this.publishConfig.browser=$o(e.publishConfig.browser);else{this.publishConfig.browser=new Map;for(let[n,u]of Object.entries(e.publishConfig.browser))this.publishConfig.browser.set($o(n),typeof u==\"string\"?$o(u):u)}if(typeof e.publishConfig.registry==\"string\"&&(this.publishConfig.registry=e.publishConfig.registry),typeof e.publishConfig.bin==\"string\")this.name!==null?this.publishConfig.bin=new Map([[this.name.name,$o(e.publishConfig.bin)]]):o.push(new Error(\"String bin field, but no attached package name\"));else if(typeof e.publishConfig.bin==\"object\"&&e.publishConfig.bin!==null){this.publishConfig.bin=new Map;for(let[n,u]of Object.entries(e.publishConfig.bin)){if(typeof u!=\"string\"){o.push(new Error(`Invalid bin definition for '${n}'`));continue}this.publishConfig.bin.set(n,$o(u))}}if(Array.isArray(e.publishConfig.executableFiles)){this.publishConfig.executableFiles=new Set;for(let n of e.publishConfig.executableFiles){if(typeof n!=\"string\"){o.push(new Error(\"Invalid executable file definition\"));continue}this.publishConfig.executableFiles.add($o(n))}}}else this.publishConfig=null;if(typeof e.installConfig==\"object\"&&e.installConfig!==null){this.installConfig={};for(let n of Object.keys(e.installConfig))n===\"hoistingLimits\"?typeof e.installConfig.hoistingLimits==\"string\"?this.installConfig.hoistingLimits=e.installConfig.hoistingLimits:o.push(new Error(\"Invalid hoisting limits definition\")):n==\"selfReferences\"?typeof e.installConfig.selfReferences==\"boolean\"?this.installConfig.selfReferences=e.installConfig.selfReferences:o.push(new Error(\"Invalid selfReferences definition, must be a boolean value\")):o.push(new Error(`Unrecognized installConfig key: ${n}`))}else this.installConfig=null;if(typeof e.optionalDependencies==\"object\"&&e.optionalDependencies!==null)for(let[n,u]of Object.entries(e.optionalDependencies)){if(typeof u!=\"string\"){o.push(new Error(`Invalid dependency range for '${n}'`));continue}let A;try{A=Zo(n)}catch{o.push(new Error(`Parsing failed for the dependency name '${n}'`));continue}let p=kn(A,u);this.dependencies.set(p.identHash,p);let h=kn(A,\"unknown\"),E=this.ensureDependencyMeta(h);Object.assign(E,{optional:!0})}typeof e.preferUnplugged==\"boolean\"?this.preferUnplugged=e.preferUnplugged:this.preferUnplugged=null,this.errors=o}getForScope(e){switch(e){case\"dependencies\":return this.dependencies;case\"devDependencies\":return this.devDependencies;case\"peerDependencies\":return this.peerDependencies;default:throw new Error(`Unsupported value (\"${e}\")`)}}hasConsumerDependency(e){return!!(this.dependencies.has(e.identHash)||this.peerDependencies.has(e.identHash))}hasHardDependency(e){return!!(this.dependencies.has(e.identHash)||this.devDependencies.has(e.identHash))}hasSoftDependency(e){return!!this.peerDependencies.has(e.identHash)}hasDependency(e){return!!(this.hasHardDependency(e)||this.hasSoftDependency(e))}getConditions(){let e=[];return this.os&&this.os.length>0&&e.push(jM(\"os\",this.os)),this.cpu&&this.cpu.length>0&&e.push(jM(\"cpu\",this.cpu)),this.libc&&this.libc.length>0&&e.push(jM(\"libc\",this.libc)),e.length>0?e.join(\" & \"):null}ensureDependencyMeta(e){if(e.range!==\"unknown\"&&!noe.default.valid(e.range))throw new Error(`Invalid meta field range for '${ka(e)}'`);let r=rn(e),o=e.range!==\"unknown\"?e.range:null,a=this.dependenciesMeta.get(r);a||this.dependenciesMeta.set(r,a=new Map);let n=a.get(o);return n||a.set(o,n={}),n}ensurePeerDependencyMeta(e){if(e.range!==\"unknown\")throw new Error(`Invalid meta field range for '${ka(e)}'`);let r=rn(e),o=this.peerDependenciesMeta.get(r);return o||this.peerDependenciesMeta.set(r,o={}),o}setRawField(e,r,{after:o=[]}={}){let a=new Set(o.filter(n=>Object.hasOwn(this.raw,n)));if(a.size===0||Object.hasOwn(this.raw,e))this.raw[e]=r;else{let n=this.raw,u=this.raw={},A=!1;for(let p of Object.keys(n))u[p]=n[p],A||(a.delete(p),a.size===0&&(u[e]=r,A=!0))}}exportTo(e,{compatibilityMode:r=!0}={}){if(Object.assign(e,this.raw),this.name!==null?e.name=rn(this.name):delete e.name,this.version!==null?e.version=this.version:delete e.version,this.os!==null?e.os=this.os:delete e.os,this.cpu!==null?e.cpu=this.cpu:delete e.cpu,this.type!==null?e.type=this.type:delete e.type,this.packageManager!==null?e.packageManager=this.packageManager:delete e.packageManager,this.private?e.private=!0:delete e.private,this.license!==null?e.license=this.license:delete e.license,this.languageName!==null?e.languageName=this.languageName:delete e.languageName,this.main!==null?e.main=this.main:delete e.main,this.module!==null?e.module=this.module:delete e.module,this.browser!==null){let n=this.browser;typeof n==\"string\"?e.browser=n:n instanceof Map&&(e.browser=Object.assign({},...Array.from(n.keys()).sort().map(u=>({[u]:n.get(u)}))))}else delete e.browser;this.bin.size===1&&this.name!==null&&this.bin.has(this.name.name)?e.bin=this.bin.get(this.name.name):this.bin.size>0?e.bin=Object.assign({},...Array.from(this.bin.keys()).sort().map(n=>({[n]:this.bin.get(n)}))):delete e.bin,this.workspaceDefinitions.length>0?this.raw.workspaces&&!Array.isArray(this.raw.workspaces)?e.workspaces={...this.raw.workspaces,packages:this.workspaceDefinitions.map(({pattern:n})=>n)}:e.workspaces=this.workspaceDefinitions.map(({pattern:n})=>n):this.raw.workspaces&&!Array.isArray(this.raw.workspaces)&&Object.keys(this.raw.workspaces).length>0?e.workspaces=this.raw.workspaces:delete e.workspaces;let o=[],a=[];for(let n of this.dependencies.values()){let u=this.dependenciesMeta.get(rn(n)),A=!1;if(r&&u){let p=u.get(null);p&&p.optional&&(A=!0)}A?a.push(n):o.push(n)}o.length>0?e.dependencies=Object.assign({},...uy(o).map(n=>({[rn(n)]:n.range}))):delete e.dependencies,a.length>0?e.optionalDependencies=Object.assign({},...uy(a).map(n=>({[rn(n)]:n.range}))):delete e.optionalDependencies,this.devDependencies.size>0?e.devDependencies=Object.assign({},...uy(this.devDependencies.values()).map(n=>({[rn(n)]:n.range}))):delete e.devDependencies,this.peerDependencies.size>0?e.peerDependencies=Object.assign({},...uy(this.peerDependencies.values()).map(n=>({[rn(n)]:n.range}))):delete e.peerDependencies,e.dependenciesMeta={};for(let[n,u]of Ps(this.dependenciesMeta.entries(),([A,p])=>A))for(let[A,p]of Ps(u.entries(),([h,E])=>h!==null?`0${h}`:\"1\")){let h=A!==null?ka(kn(Zo(n),A)):n,E={...p};r&&A===null&&delete E.optional,Object.keys(E).length!==0&&(e.dependenciesMeta[h]=E)}if(Object.keys(e.dependenciesMeta).length===0&&delete e.dependenciesMeta,this.peerDependenciesMeta.size>0?e.peerDependenciesMeta=Object.assign({},...Ps(this.peerDependenciesMeta.entries(),([n,u])=>n).map(([n,u])=>({[n]:u}))):delete e.peerDependenciesMeta,this.resolutions.length>0?e.resolutions=Object.assign({},...this.resolutions.map(({pattern:n,reference:u})=>({[hP(n)]:u}))):delete e.resolutions,this.files!==null?e.files=Array.from(this.files):delete e.files,this.preferUnplugged!==null?e.preferUnplugged=this.preferUnplugged:delete e.preferUnplugged,this.scripts!==null&&this.scripts.size>0){e.scripts??={};for(let n of Object.keys(e.scripts))this.scripts.has(n)||delete e.scripts[n];for(let[n,u]of this.scripts.entries())e.scripts[n]=u}else delete e.scripts;return e}}});var soe=_((ILt,ioe)=>{var Htt=ql(),qtt=function(){return Htt.Date.now()};ioe.exports=qtt});var aoe=_((wLt,ooe)=>{var jtt=/\\s/;function Gtt(t){for(var e=t.length;e--&&jtt.test(t.charAt(e)););return e}ooe.exports=Gtt});var coe=_((BLt,loe)=>{var Wtt=aoe(),Ytt=/^\\s+/;function Ktt(t){return t&&t.slice(0,Wtt(t)+1).replace(Ytt,\"\")}loe.exports=Ktt});var fy=_((vLt,uoe)=>{var Vtt=mg(),ztt=Zu(),Jtt=\"[object Symbol]\";function Xtt(t){return typeof t==\"symbol\"||ztt(t)&&Vtt(t)==Jtt}uoe.exports=Xtt});var hoe=_((DLt,poe)=>{var Ztt=coe(),Aoe=cl(),$tt=fy(),foe=NaN,ert=/^[-+]0x[0-9a-f]+$/i,trt=/^0b[01]+$/i,rrt=/^0o[0-7]+$/i,nrt=parseInt;function irt(t){if(typeof t==\"number\")return t;if($tt(t))return foe;if(Aoe(t)){var e=typeof t.valueOf==\"function\"?t.valueOf():t;t=Aoe(e)?e+\"\":e}if(typeof t!=\"string\")return t===0?t:+t;t=Ztt(t);var r=trt.test(t);return r||rrt.test(t)?nrt(t.slice(2),r?2:8):ert.test(t)?foe:+t}poe.exports=irt});var moe=_((PLt,doe)=>{var srt=cl(),GM=soe(),goe=hoe(),ort=\"Expected a function\",art=Math.max,lrt=Math.min;function crt(t,e,r){var o,a,n,u,A,p,h=0,E=!1,w=!1,D=!0;if(typeof t!=\"function\")throw new TypeError(ort);e=goe(e)||0,srt(r)&&(E=!!r.leading,w=\"maxWait\"in r,n=w?art(goe(r.maxWait)||0,e):n,D=\"trailing\"in r?!!r.trailing:D);function b(ue){var Ie=o,he=a;return o=a=void 0,h=ue,u=t.apply(he,Ie),u}function C(ue){return h=ue,A=setTimeout(U,e),E?b(ue):u}function T(ue){var Ie=ue-p,he=ue-h,De=e-Ie;return w?lrt(De,n-he):De}function N(ue){var Ie=ue-p,he=ue-h;return p===void 0||Ie>=e||Ie<0||w&&he>=n}function U(){var ue=GM();if(N(ue))return z(ue);A=setTimeout(U,T(ue))}function z(ue){return A=void 0,D&&o?b(ue):(o=a=void 0,u)}function te(){A!==void 0&&clearTimeout(A),h=0,o=p=a=A=void 0}function le(){return A===void 0?u:z(GM())}function ce(){var ue=GM(),Ie=N(ue);if(o=arguments,a=this,p=ue,Ie){if(A===void 0)return C(p);if(w)return clearTimeout(A),A=setTimeout(U,e),b(p)}return A===void 0&&(A=setTimeout(U,e)),u}return ce.cancel=te,ce.flush=le,ce}doe.exports=crt});var WM=_((SLt,yoe)=>{var urt=moe(),Art=cl(),frt=\"Expected a function\";function prt(t,e,r){var o=!0,a=!0;if(typeof t!=\"function\")throw new TypeError(frt);return Art(r)&&(o=\"leading\"in r?!!r.leading:o,a=\"trailing\"in r?!!r.trailing:a),urt(t,e,{leading:o,maxWait:e,trailing:a})}yoe.exports=prt});function grt(t){return typeof t.reportCode<\"u\"}var Eoe,Coe,Ioe,hrt,zt,Ws,Vl=It(()=>{Eoe=et(WM()),Coe=ve(\"stream\"),Ioe=ve(\"string_decoder\"),hrt=15,zt=class extends Error{constructor(r,o,a){super(o);this.reportExtra=a;this.reportCode=r}};Ws=class{constructor(){this.cacheHits=new Set;this.cacheMisses=new Set;this.reportedInfos=new Set;this.reportedWarnings=new Set;this.reportedErrors=new Set}getRecommendedLength(){return 180}reportCacheHit(e){this.cacheHits.add(e.locatorHash)}reportCacheMiss(e,r){this.cacheMisses.add(e.locatorHash)}static progressViaCounter(e){let r=0,o,a=new Promise(p=>{o=p}),n=p=>{let h=o;a=new Promise(E=>{o=E}),r=p,h()},u=(p=0)=>{n(r+1)},A=async function*(){for(;r<e;)await a,yield{progress:r/e}}();return{[Symbol.asyncIterator](){return A},hasProgress:!0,hasTitle:!1,set:n,tick:u}}static progressViaTitle(){let e,r,o=new Promise(u=>{r=u}),a=(0,Eoe.default)(u=>{let A=r;o=new Promise(p=>{r=p}),e=u,A()},1e3/hrt),n=async function*(){for(;;)await o,yield{title:e}}();return{[Symbol.asyncIterator](){return n},hasProgress:!1,hasTitle:!0,setTitle:a}}async startProgressPromise(e,r){let o=this.reportProgress(e);try{return await r(e)}finally{o.stop()}}startProgressSync(e,r){let o=this.reportProgress(e);try{return r(e)}finally{o.stop()}}reportInfoOnce(e,r,o){let a=o&&o.key?o.key:r;this.reportedInfos.has(a)||(this.reportedInfos.add(a),this.reportInfo(e,r),o?.reportExtra?.(this))}reportWarningOnce(e,r,o){let a=o&&o.key?o.key:r;this.reportedWarnings.has(a)||(this.reportedWarnings.add(a),this.reportWarning(e,r),o?.reportExtra?.(this))}reportErrorOnce(e,r,o){let a=o&&o.key?o.key:r;this.reportedErrors.has(a)||(this.reportedErrors.add(a),this.reportError(e,r),o?.reportExtra?.(this))}reportExceptionOnce(e){grt(e)?this.reportErrorOnce(e.reportCode,e.message,{key:e,reportExtra:e.reportExtra}):this.reportErrorOnce(1,e.stack||e.message,{key:e})}createStreamReporter(e=null){let r=new Coe.PassThrough,o=new Ioe.StringDecoder,a=\"\";return r.on(\"data\",n=>{let u=o.write(n),A;do if(A=u.indexOf(`\n`),A!==-1){let p=a+u.substring(0,A);u=u.substring(A+1),a=\"\",e!==null?this.reportInfo(null,`${e} ${p}`):this.reportInfo(null,p)}while(A!==-1);a+=u}),r.on(\"end\",()=>{let n=o.end();n!==\"\"&&(e!==null?this.reportInfo(null,`${e} ${n}`):this.reportInfo(null,n))}),r}}});var py,YM=It(()=>{Vl();Io();py=class{constructor(e){this.fetchers=e}supports(e,r){return!!this.tryFetcher(e,r)}getLocalPath(e,r){return this.getFetcher(e,r).getLocalPath(e,r)}async fetch(e,r){return await this.getFetcher(e,r).fetch(e,r)}tryFetcher(e,r){let o=this.fetchers.find(a=>a.supports(e,r));return o||null}getFetcher(e,r){let o=this.fetchers.find(a=>a.supports(e,r));if(!o)throw new zt(11,`${jr(r.project.configuration,e)} isn't supported by any available fetcher`);return o}}});var Pg,KM=It(()=>{Io();Pg=class{constructor(e){this.resolvers=e.filter(r=>r)}supportsDescriptor(e,r){return!!this.tryResolverByDescriptor(e,r)}supportsLocator(e,r){return!!this.tryResolverByLocator(e,r)}shouldPersistResolution(e,r){return this.getResolverByLocator(e,r).shouldPersistResolution(e,r)}bindDescriptor(e,r,o){return this.getResolverByDescriptor(e,o).bindDescriptor(e,r,o)}getResolutionDependencies(e,r){return this.getResolverByDescriptor(e,r).getResolutionDependencies(e,r)}async getCandidates(e,r,o){return await this.getResolverByDescriptor(e,o).getCandidates(e,r,o)}async getSatisfying(e,r,o,a){return this.getResolverByDescriptor(e,a).getSatisfying(e,r,o,a)}async resolve(e,r){return await this.getResolverByLocator(e,r).resolve(e,r)}tryResolverByDescriptor(e,r){let o=this.resolvers.find(a=>a.supportsDescriptor(e,r));return o||null}getResolverByDescriptor(e,r){let o=this.resolvers.find(a=>a.supportsDescriptor(e,r));if(!o)throw new Error(`${zn(r.project.configuration,e)} isn't supported by any available resolver`);return o}tryResolverByLocator(e,r){let o=this.resolvers.find(a=>a.supportsLocator(e,r));return o||null}getResolverByLocator(e,r){let o=this.resolvers.find(a=>a.supportsLocator(e,r));if(!o)throw new Error(`${jr(r.project.configuration,e)} isn't supported by any available resolver`);return o}}});var hy,VM=It(()=>{Pt();Io();hy=class{supports(e){return!!e.reference.startsWith(\"virtual:\")}getLocalPath(e,r){let o=e.reference.indexOf(\"#\");if(o===-1)throw new Error(\"Invalid virtual package reference\");let a=e.reference.slice(o+1),n=Ss(e,a);return r.fetcher.getLocalPath(n,r)}async fetch(e,r){let o=e.reference.indexOf(\"#\");if(o===-1)throw new Error(\"Invalid virtual package reference\");let a=e.reference.slice(o+1),n=Ss(e,a),u=await r.fetcher.fetch(n,r);return await this.ensureVirtualLink(e,u,r)}getLocatorFilename(e){return ly(e)}async ensureVirtualLink(e,r,o){let a=r.packageFs.getRealPath(),n=o.project.configuration.get(\"virtualFolder\"),u=this.getLocatorFilename(e),A=qs.makeVirtualPath(n,u,a),p=new ju(A,{baseFs:r.packageFs,pathUtils:K});return{...r,packageFs:p}}}});var Ix,woe=It(()=>{Ix=class t{static{this.protocol=\"virtual:\"}static isVirtualDescriptor(e){return!!e.range.startsWith(t.protocol)}static isVirtualLocator(e){return!!e.reference.startsWith(t.protocol)}supportsDescriptor(e,r){return t.isVirtualDescriptor(e)}supportsLocator(e,r){return t.isVirtualLocator(e)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){throw new Error('Assertion failed: calling \"bindDescriptor\" on a virtual descriptor is unsupported')}getResolutionDependencies(e,r){throw new Error('Assertion failed: calling \"getResolutionDependencies\" on a virtual descriptor is unsupported')}async getCandidates(e,r,o){throw new Error('Assertion failed: calling \"getCandidates\" on a virtual descriptor is unsupported')}async getSatisfying(e,r,o,a){throw new Error('Assertion failed: calling \"getSatisfying\" on a virtual descriptor is unsupported')}async resolve(e,r){throw new Error('Assertion failed: calling \"resolve\" on a virtual locator is unsupported')}}});var gy,zM=It(()=>{Pt();Dg();gy=class{supports(e){return!!e.reference.startsWith(ci.protocol)}getLocalPath(e,r){return this.getWorkspace(e,r).cwd}async fetch(e,r){let o=this.getWorkspace(e,r).cwd;return{packageFs:new En(o),prefixPath:Bt.dot,localPath:o}}getWorkspace(e,r){return r.project.getWorkspaceByCwd(e.reference.slice(ci.protocol.length))}}});function x1(t){return typeof t==\"object\"&&t!==null&&!Array.isArray(t)}function Boe(t){return typeof t>\"u\"?3:x1(t)?0:Array.isArray(t)?1:2}function ZM(t,e){return Object.hasOwn(t,e)}function mrt(t){return x1(t)&&ZM(t,\"onConflict\")&&typeof t.onConflict==\"string\"}function yrt(t){if(typeof t>\"u\")return{onConflict:\"default\",value:t};if(!mrt(t))return{onConflict:\"default\",value:t};if(ZM(t,\"value\"))return t;let{onConflict:e,...r}=t;return{onConflict:e,value:r}}function voe(t,e){let r=x1(t)&&ZM(t,e)?t[e]:void 0;return yrt(r)}function dy(t,e){return[t,e,Doe]}function $M(t){return Array.isArray(t)?t[2]===Doe:!1}function JM(t,e){if(x1(t)){let r={};for(let o of Object.keys(t))r[o]=JM(t[o],e);return dy(e,r)}return Array.isArray(t)?dy(e,t.map(r=>JM(r,e))):dy(e,t)}function XM(t,e,r,o,a){let n,u=[],A=a,p=0;for(let E=a-1;E>=o;--E){let[w,D]=t[E],{onConflict:b,value:C}=voe(D,r),T=Boe(C);if(T!==3){if(n??=T,T!==n||b===\"hardReset\"){p=A;break}if(T===2)return dy(w,C);if(u.unshift([w,C]),b===\"reset\"){p=E;break}b===\"extend\"&&E===o&&(o=0),A=E}}if(typeof n>\"u\")return null;let h=u.map(([E])=>E).join(\", \");switch(n){case 1:return dy(h,new Array().concat(...u.map(([E,w])=>w.map(D=>JM(D,E)))));case 0:{let E=Object.assign({},...u.map(([,T])=>T)),w=Object.keys(E),D={},b=t.map(([T,N])=>[T,voe(N,r).value]),C=drt(b,([T,N])=>{let U=Boe(N);return U!==0&&U!==3});if(C!==-1){let T=b.slice(C+1);for(let N of w)D[N]=XM(T,e,N,0,T.length)}else for(let T of w)D[T]=XM(b,e,T,p,b.length);return dy(h,D)}default:throw new Error(\"Assertion failed: Non-extendable value type\")}}function Poe(t){return XM(t.map(([e,r])=>[e,{\".\":r}]),[],\".\",0,t.length)}function b1(t){return $M(t)?t[1]:t}function wx(t){let e=$M(t)?t[1]:t;if(Array.isArray(e))return e.map(r=>wx(r));if(x1(e)){let r={};for(let[o,a]of Object.entries(e))r[o]=wx(a);return r}return e}function e4(t){return $M(t)?t[0]:null}var drt,Doe,Soe=It(()=>{drt=(t,e,r)=>{let o=[...t];return o.reverse(),o.findIndex(e,r)};Doe=Symbol()});var Bx={};Kt(Bx,{getDefaultGlobalFolder:()=>r4,getHomeFolder:()=>my,isFolderInside:()=>n4});function r4(){if(process.platform===\"win32\"){let t=Ae.toPortablePath(process.env.LOCALAPPDATA||Ae.join((0,t4.homedir)(),\"AppData\",\"Local\"));return K.resolve(t,\"Yarn/Berry\")}if(process.env.XDG_DATA_HOME){let t=Ae.toPortablePath(process.env.XDG_DATA_HOME);return K.resolve(t,\"yarn/berry\")}return K.resolve(my(),\".yarn/berry\")}function my(){return Ae.toPortablePath((0,t4.homedir)()||\"/usr/local/share\")}function n4(t,e){let r=K.relative(e,t);return r&&!r.startsWith(\"..\")&&!K.isAbsolute(r)}var t4,vx=It(()=>{Pt();t4=ve(\"os\")});var Qoe=_(yy=>{\"use strict\";var _Lt=ve(\"net\"),Crt=ve(\"tls\"),i4=ve(\"http\"),xoe=ve(\"https\"),Irt=ve(\"events\"),HLt=ve(\"assert\"),wrt=ve(\"util\");yy.httpOverHttp=Brt;yy.httpsOverHttp=vrt;yy.httpOverHttps=Drt;yy.httpsOverHttps=Prt;function Brt(t){var e=new kf(t);return e.request=i4.request,e}function vrt(t){var e=new kf(t);return e.request=i4.request,e.createSocket=boe,e.defaultPort=443,e}function Drt(t){var e=new kf(t);return e.request=xoe.request,e}function Prt(t){var e=new kf(t);return e.request=xoe.request,e.createSocket=boe,e.defaultPort=443,e}function kf(t){var e=this;e.options=t||{},e.proxyOptions=e.options.proxy||{},e.maxSockets=e.options.maxSockets||i4.Agent.defaultMaxSockets,e.requests=[],e.sockets=[],e.on(\"free\",function(o,a,n,u){for(var A=koe(a,n,u),p=0,h=e.requests.length;p<h;++p){var E=e.requests[p];if(E.host===A.host&&E.port===A.port){e.requests.splice(p,1),E.request.onSocket(o);return}}o.destroy(),e.removeSocket(o)})}wrt.inherits(kf,Irt.EventEmitter);kf.prototype.addRequest=function(e,r,o,a){var n=this,u=s4({request:e},n.options,koe(r,o,a));if(n.sockets.length>=this.maxSockets){n.requests.push(u);return}n.createSocket(u,function(A){A.on(\"free\",p),A.on(\"close\",h),A.on(\"agentRemove\",h),e.onSocket(A);function p(){n.emit(\"free\",A,u)}function h(E){n.removeSocket(A),A.removeListener(\"free\",p),A.removeListener(\"close\",h),A.removeListener(\"agentRemove\",h)}})};kf.prototype.createSocket=function(e,r){var o=this,a={};o.sockets.push(a);var n=s4({},o.proxyOptions,{method:\"CONNECT\",path:e.host+\":\"+e.port,agent:!1,headers:{host:e.host+\":\"+e.port}});e.localAddress&&(n.localAddress=e.localAddress),n.proxyAuth&&(n.headers=n.headers||{},n.headers[\"Proxy-Authorization\"]=\"Basic \"+new Buffer(n.proxyAuth).toString(\"base64\")),ch(\"making CONNECT request\");var u=o.request(n);u.useChunkedEncodingByDefault=!1,u.once(\"response\",A),u.once(\"upgrade\",p),u.once(\"connect\",h),u.once(\"error\",E),u.end();function A(w){w.upgrade=!0}function p(w,D,b){process.nextTick(function(){h(w,D,b)})}function h(w,D,b){if(u.removeAllListeners(),D.removeAllListeners(),w.statusCode!==200){ch(\"tunneling socket could not be established, statusCode=%d\",w.statusCode),D.destroy();var C=new Error(\"tunneling socket could not be established, statusCode=\"+w.statusCode);C.code=\"ECONNRESET\",e.request.emit(\"error\",C),o.removeSocket(a);return}if(b.length>0){ch(\"got illegal response body from proxy\"),D.destroy();var C=new Error(\"got illegal response body from proxy\");C.code=\"ECONNRESET\",e.request.emit(\"error\",C),o.removeSocket(a);return}return ch(\"tunneling connection has established\"),o.sockets[o.sockets.indexOf(a)]=D,r(D)}function E(w){u.removeAllListeners(),ch(`tunneling socket could not be established, cause=%s\n`,w.message,w.stack);var D=new Error(\"tunneling socket could not be established, cause=\"+w.message);D.code=\"ECONNRESET\",e.request.emit(\"error\",D),o.removeSocket(a)}};kf.prototype.removeSocket=function(e){var r=this.sockets.indexOf(e);if(r!==-1){this.sockets.splice(r,1);var o=this.requests.shift();o&&this.createSocket(o,function(a){o.request.onSocket(a)})}};function boe(t,e){var r=this;kf.prototype.createSocket.call(r,t,function(o){var a=t.request.getHeader(\"host\"),n=s4({},r.options,{socket:o,servername:a?a.replace(/:.*$/,\"\"):t.host}),u=Crt.connect(0,n);r.sockets[r.sockets.indexOf(o)]=u,e(u)})}function koe(t,e,r){return typeof t==\"string\"?{host:t,port:e,localAddress:r}:t}function s4(t){for(var e=1,r=arguments.length;e<r;++e){var o=arguments[e];if(typeof o==\"object\")for(var a=Object.keys(o),n=0,u=a.length;n<u;++n){var A=a[n];o[A]!==void 0&&(t[A]=o[A])}}return t}var ch;process.env.NODE_DEBUG&&/\\btunnel\\b/.test(process.env.NODE_DEBUG)?ch=function(){var t=Array.prototype.slice.call(arguments);typeof t[0]==\"string\"?t[0]=\"TUNNEL: \"+t[0]:t.unshift(\"TUNNEL:\"),console.error.apply(console,t)}:ch=function(){};yy.debug=ch});var Roe=_((jLt,Foe)=>{Foe.exports=Qoe()});var Ff=_((Qf,Dx)=>{\"use strict\";Object.defineProperty(Qf,\"__esModule\",{value:!0});var Toe=[\"Int8Array\",\"Uint8Array\",\"Uint8ClampedArray\",\"Int16Array\",\"Uint16Array\",\"Int32Array\",\"Uint32Array\",\"Float32Array\",\"Float64Array\",\"BigInt64Array\",\"BigUint64Array\"];function Srt(t){return Toe.includes(t)}var xrt=[\"Function\",\"Generator\",\"AsyncGenerator\",\"GeneratorFunction\",\"AsyncGeneratorFunction\",\"AsyncFunction\",\"Observable\",\"Array\",\"Buffer\",\"Blob\",\"Object\",\"RegExp\",\"Date\",\"Error\",\"Map\",\"Set\",\"WeakMap\",\"WeakSet\",\"ArrayBuffer\",\"SharedArrayBuffer\",\"DataView\",\"Promise\",\"URL\",\"FormData\",\"URLSearchParams\",\"HTMLElement\",...Toe];function brt(t){return xrt.includes(t)}var krt=[\"null\",\"undefined\",\"string\",\"number\",\"bigint\",\"boolean\",\"symbol\"];function Qrt(t){return krt.includes(t)}function Ey(t){return e=>typeof e===t}var{toString:Loe}=Object.prototype,k1=t=>{let e=Loe.call(t).slice(8,-1);if(/HTML\\w+Element/.test(e)&&Se.domElement(t))return\"HTMLElement\";if(brt(e))return e},ii=t=>e=>k1(e)===t;function Se(t){if(t===null)return\"null\";switch(typeof t){case\"undefined\":return\"undefined\";case\"string\":return\"string\";case\"number\":return\"number\";case\"boolean\":return\"boolean\";case\"function\":return\"Function\";case\"bigint\":return\"bigint\";case\"symbol\":return\"symbol\";default:}if(Se.observable(t))return\"Observable\";if(Se.array(t))return\"Array\";if(Se.buffer(t))return\"Buffer\";let e=k1(t);if(e)return e;if(t instanceof String||t instanceof Boolean||t instanceof Number)throw new TypeError(\"Please don't use object wrappers for primitive types\");return\"Object\"}Se.undefined=Ey(\"undefined\");Se.string=Ey(\"string\");var Frt=Ey(\"number\");Se.number=t=>Frt(t)&&!Se.nan(t);Se.bigint=Ey(\"bigint\");Se.function_=Ey(\"function\");Se.null_=t=>t===null;Se.class_=t=>Se.function_(t)&&t.toString().startsWith(\"class \");Se.boolean=t=>t===!0||t===!1;Se.symbol=Ey(\"symbol\");Se.numericString=t=>Se.string(t)&&!Se.emptyStringOrWhitespace(t)&&!Number.isNaN(Number(t));Se.array=(t,e)=>Array.isArray(t)?Se.function_(e)?t.every(e):!0:!1;Se.buffer=t=>{var e,r,o,a;return(a=(o=(r=(e=t)===null||e===void 0?void 0:e.constructor)===null||r===void 0?void 0:r.isBuffer)===null||o===void 0?void 0:o.call(r,t))!==null&&a!==void 0?a:!1};Se.blob=t=>ii(\"Blob\")(t);Se.nullOrUndefined=t=>Se.null_(t)||Se.undefined(t);Se.object=t=>!Se.null_(t)&&(typeof t==\"object\"||Se.function_(t));Se.iterable=t=>{var e;return Se.function_((e=t)===null||e===void 0?void 0:e[Symbol.iterator])};Se.asyncIterable=t=>{var e;return Se.function_((e=t)===null||e===void 0?void 0:e[Symbol.asyncIterator])};Se.generator=t=>{var e,r;return Se.iterable(t)&&Se.function_((e=t)===null||e===void 0?void 0:e.next)&&Se.function_((r=t)===null||r===void 0?void 0:r.throw)};Se.asyncGenerator=t=>Se.asyncIterable(t)&&Se.function_(t.next)&&Se.function_(t.throw);Se.nativePromise=t=>ii(\"Promise\")(t);var Rrt=t=>{var e,r;return Se.function_((e=t)===null||e===void 0?void 0:e.then)&&Se.function_((r=t)===null||r===void 0?void 0:r.catch)};Se.promise=t=>Se.nativePromise(t)||Rrt(t);Se.generatorFunction=ii(\"GeneratorFunction\");Se.asyncGeneratorFunction=t=>k1(t)===\"AsyncGeneratorFunction\";Se.asyncFunction=t=>k1(t)===\"AsyncFunction\";Se.boundFunction=t=>Se.function_(t)&&!t.hasOwnProperty(\"prototype\");Se.regExp=ii(\"RegExp\");Se.date=ii(\"Date\");Se.error=ii(\"Error\");Se.map=t=>ii(\"Map\")(t);Se.set=t=>ii(\"Set\")(t);Se.weakMap=t=>ii(\"WeakMap\")(t);Se.weakSet=t=>ii(\"WeakSet\")(t);Se.int8Array=ii(\"Int8Array\");Se.uint8Array=ii(\"Uint8Array\");Se.uint8ClampedArray=ii(\"Uint8ClampedArray\");Se.int16Array=ii(\"Int16Array\");Se.uint16Array=ii(\"Uint16Array\");Se.int32Array=ii(\"Int32Array\");Se.uint32Array=ii(\"Uint32Array\");Se.float32Array=ii(\"Float32Array\");Se.float64Array=ii(\"Float64Array\");Se.bigInt64Array=ii(\"BigInt64Array\");Se.bigUint64Array=ii(\"BigUint64Array\");Se.arrayBuffer=ii(\"ArrayBuffer\");Se.sharedArrayBuffer=ii(\"SharedArrayBuffer\");Se.dataView=ii(\"DataView\");Se.enumCase=(t,e)=>Object.values(e).includes(t);Se.directInstanceOf=(t,e)=>Object.getPrototypeOf(t)===e.prototype;Se.urlInstance=t=>ii(\"URL\")(t);Se.urlString=t=>{if(!Se.string(t))return!1;try{return new URL(t),!0}catch{return!1}};Se.truthy=t=>!!t;Se.falsy=t=>!t;Se.nan=t=>Number.isNaN(t);Se.primitive=t=>Se.null_(t)||Qrt(typeof t);Se.integer=t=>Number.isInteger(t);Se.safeInteger=t=>Number.isSafeInteger(t);Se.plainObject=t=>{if(Loe.call(t)!==\"[object Object]\")return!1;let e=Object.getPrototypeOf(t);return e===null||e===Object.getPrototypeOf({})};Se.typedArray=t=>Srt(k1(t));var Trt=t=>Se.safeInteger(t)&&t>=0;Se.arrayLike=t=>!Se.nullOrUndefined(t)&&!Se.function_(t)&&Trt(t.length);Se.inRange=(t,e)=>{if(Se.number(e))return t>=Math.min(0,e)&&t<=Math.max(e,0);if(Se.array(e)&&e.length===2)return t>=Math.min(...e)&&t<=Math.max(...e);throw new TypeError(`Invalid range: ${JSON.stringify(e)}`)};var Lrt=1,Nrt=[\"innerHTML\",\"ownerDocument\",\"style\",\"attributes\",\"nodeValue\"];Se.domElement=t=>Se.object(t)&&t.nodeType===Lrt&&Se.string(t.nodeName)&&!Se.plainObject(t)&&Nrt.every(e=>e in t);Se.observable=t=>{var e,r,o,a;return t?t===((r=(e=t)[Symbol.observable])===null||r===void 0?void 0:r.call(e))||t===((a=(o=t)[\"@@observable\"])===null||a===void 0?void 0:a.call(o)):!1};Se.nodeStream=t=>Se.object(t)&&Se.function_(t.pipe)&&!Se.observable(t);Se.infinite=t=>t===1/0||t===-1/0;var Noe=t=>e=>Se.integer(e)&&Math.abs(e%2)===t;Se.evenInteger=Noe(0);Se.oddInteger=Noe(1);Se.emptyArray=t=>Se.array(t)&&t.length===0;Se.nonEmptyArray=t=>Se.array(t)&&t.length>0;Se.emptyString=t=>Se.string(t)&&t.length===0;var Ort=t=>Se.string(t)&&!/\\S/.test(t);Se.emptyStringOrWhitespace=t=>Se.emptyString(t)||Ort(t);Se.nonEmptyString=t=>Se.string(t)&&t.length>0;Se.nonEmptyStringAndNotWhitespace=t=>Se.string(t)&&!Se.emptyStringOrWhitespace(t);Se.emptyObject=t=>Se.object(t)&&!Se.map(t)&&!Se.set(t)&&Object.keys(t).length===0;Se.nonEmptyObject=t=>Se.object(t)&&!Se.map(t)&&!Se.set(t)&&Object.keys(t).length>0;Se.emptySet=t=>Se.set(t)&&t.size===0;Se.nonEmptySet=t=>Se.set(t)&&t.size>0;Se.emptyMap=t=>Se.map(t)&&t.size===0;Se.nonEmptyMap=t=>Se.map(t)&&t.size>0;Se.propertyKey=t=>Se.any([Se.string,Se.number,Se.symbol],t);Se.formData=t=>ii(\"FormData\")(t);Se.urlSearchParams=t=>ii(\"URLSearchParams\")(t);var Ooe=(t,e,r)=>{if(!Se.function_(e))throw new TypeError(`Invalid predicate: ${JSON.stringify(e)}`);if(r.length===0)throw new TypeError(\"Invalid number of values\");return t.call(r,e)};Se.any=(t,...e)=>(Se.array(t)?t:[t]).some(o=>Ooe(Array.prototype.some,o,e));Se.all=(t,...e)=>Ooe(Array.prototype.every,t,e);var Mt=(t,e,r,o={})=>{if(!t){let{multipleValues:a}=o,n=a?`received values of types ${[...new Set(r.map(u=>`\\`${Se(u)}\\``))].join(\", \")}`:`received value of type \\`${Se(r)}\\``;throw new TypeError(`Expected value which is \\`${e}\\`, ${n}.`)}};Qf.assert={undefined:t=>Mt(Se.undefined(t),\"undefined\",t),string:t=>Mt(Se.string(t),\"string\",t),number:t=>Mt(Se.number(t),\"number\",t),bigint:t=>Mt(Se.bigint(t),\"bigint\",t),function_:t=>Mt(Se.function_(t),\"Function\",t),null_:t=>Mt(Se.null_(t),\"null\",t),class_:t=>Mt(Se.class_(t),\"Class\",t),boolean:t=>Mt(Se.boolean(t),\"boolean\",t),symbol:t=>Mt(Se.symbol(t),\"symbol\",t),numericString:t=>Mt(Se.numericString(t),\"string with a number\",t),array:(t,e)=>{Mt(Se.array(t),\"Array\",t),e&&t.forEach(e)},buffer:t=>Mt(Se.buffer(t),\"Buffer\",t),blob:t=>Mt(Se.blob(t),\"Blob\",t),nullOrUndefined:t=>Mt(Se.nullOrUndefined(t),\"null or undefined\",t),object:t=>Mt(Se.object(t),\"Object\",t),iterable:t=>Mt(Se.iterable(t),\"Iterable\",t),asyncIterable:t=>Mt(Se.asyncIterable(t),\"AsyncIterable\",t),generator:t=>Mt(Se.generator(t),\"Generator\",t),asyncGenerator:t=>Mt(Se.asyncGenerator(t),\"AsyncGenerator\",t),nativePromise:t=>Mt(Se.nativePromise(t),\"native Promise\",t),promise:t=>Mt(Se.promise(t),\"Promise\",t),generatorFunction:t=>Mt(Se.generatorFunction(t),\"GeneratorFunction\",t),asyncGeneratorFunction:t=>Mt(Se.asyncGeneratorFunction(t),\"AsyncGeneratorFunction\",t),asyncFunction:t=>Mt(Se.asyncFunction(t),\"AsyncFunction\",t),boundFunction:t=>Mt(Se.boundFunction(t),\"Function\",t),regExp:t=>Mt(Se.regExp(t),\"RegExp\",t),date:t=>Mt(Se.date(t),\"Date\",t),error:t=>Mt(Se.error(t),\"Error\",t),map:t=>Mt(Se.map(t),\"Map\",t),set:t=>Mt(Se.set(t),\"Set\",t),weakMap:t=>Mt(Se.weakMap(t),\"WeakMap\",t),weakSet:t=>Mt(Se.weakSet(t),\"WeakSet\",t),int8Array:t=>Mt(Se.int8Array(t),\"Int8Array\",t),uint8Array:t=>Mt(Se.uint8Array(t),\"Uint8Array\",t),uint8ClampedArray:t=>Mt(Se.uint8ClampedArray(t),\"Uint8ClampedArray\",t),int16Array:t=>Mt(Se.int16Array(t),\"Int16Array\",t),uint16Array:t=>Mt(Se.uint16Array(t),\"Uint16Array\",t),int32Array:t=>Mt(Se.int32Array(t),\"Int32Array\",t),uint32Array:t=>Mt(Se.uint32Array(t),\"Uint32Array\",t),float32Array:t=>Mt(Se.float32Array(t),\"Float32Array\",t),float64Array:t=>Mt(Se.float64Array(t),\"Float64Array\",t),bigInt64Array:t=>Mt(Se.bigInt64Array(t),\"BigInt64Array\",t),bigUint64Array:t=>Mt(Se.bigUint64Array(t),\"BigUint64Array\",t),arrayBuffer:t=>Mt(Se.arrayBuffer(t),\"ArrayBuffer\",t),sharedArrayBuffer:t=>Mt(Se.sharedArrayBuffer(t),\"SharedArrayBuffer\",t),dataView:t=>Mt(Se.dataView(t),\"DataView\",t),enumCase:(t,e)=>Mt(Se.enumCase(t,e),\"EnumCase\",t),urlInstance:t=>Mt(Se.urlInstance(t),\"URL\",t),urlString:t=>Mt(Se.urlString(t),\"string with a URL\",t),truthy:t=>Mt(Se.truthy(t),\"truthy\",t),falsy:t=>Mt(Se.falsy(t),\"falsy\",t),nan:t=>Mt(Se.nan(t),\"NaN\",t),primitive:t=>Mt(Se.primitive(t),\"primitive\",t),integer:t=>Mt(Se.integer(t),\"integer\",t),safeInteger:t=>Mt(Se.safeInteger(t),\"integer\",t),plainObject:t=>Mt(Se.plainObject(t),\"plain object\",t),typedArray:t=>Mt(Se.typedArray(t),\"TypedArray\",t),arrayLike:t=>Mt(Se.arrayLike(t),\"array-like\",t),domElement:t=>Mt(Se.domElement(t),\"HTMLElement\",t),observable:t=>Mt(Se.observable(t),\"Observable\",t),nodeStream:t=>Mt(Se.nodeStream(t),\"Node.js Stream\",t),infinite:t=>Mt(Se.infinite(t),\"infinite number\",t),emptyArray:t=>Mt(Se.emptyArray(t),\"empty array\",t),nonEmptyArray:t=>Mt(Se.nonEmptyArray(t),\"non-empty array\",t),emptyString:t=>Mt(Se.emptyString(t),\"empty string\",t),emptyStringOrWhitespace:t=>Mt(Se.emptyStringOrWhitespace(t),\"empty string or whitespace\",t),nonEmptyString:t=>Mt(Se.nonEmptyString(t),\"non-empty string\",t),nonEmptyStringAndNotWhitespace:t=>Mt(Se.nonEmptyStringAndNotWhitespace(t),\"non-empty string and not whitespace\",t),emptyObject:t=>Mt(Se.emptyObject(t),\"empty object\",t),nonEmptyObject:t=>Mt(Se.nonEmptyObject(t),\"non-empty object\",t),emptySet:t=>Mt(Se.emptySet(t),\"empty set\",t),nonEmptySet:t=>Mt(Se.nonEmptySet(t),\"non-empty set\",t),emptyMap:t=>Mt(Se.emptyMap(t),\"empty map\",t),nonEmptyMap:t=>Mt(Se.nonEmptyMap(t),\"non-empty map\",t),propertyKey:t=>Mt(Se.propertyKey(t),\"PropertyKey\",t),formData:t=>Mt(Se.formData(t),\"FormData\",t),urlSearchParams:t=>Mt(Se.urlSearchParams(t),\"URLSearchParams\",t),evenInteger:t=>Mt(Se.evenInteger(t),\"even integer\",t),oddInteger:t=>Mt(Se.oddInteger(t),\"odd integer\",t),directInstanceOf:(t,e)=>Mt(Se.directInstanceOf(t,e),\"T\",t),inRange:(t,e)=>Mt(Se.inRange(t,e),\"in range\",t),any:(t,...e)=>Mt(Se.any(t,...e),\"predicate returns truthy for any value\",e,{multipleValues:!0}),all:(t,...e)=>Mt(Se.all(t,...e),\"predicate returns truthy for all values\",e,{multipleValues:!0})};Object.defineProperties(Se,{class:{value:Se.class_},function:{value:Se.function_},null:{value:Se.null_}});Object.defineProperties(Qf.assert,{class:{value:Qf.assert.class_},function:{value:Qf.assert.function_},null:{value:Qf.assert.null_}});Qf.default=Se;Dx.exports=Se;Dx.exports.default=Se;Dx.exports.assert=Qf.assert});var Moe=_((GLt,o4)=>{\"use strict\";var Px=class extends Error{constructor(e){super(e||\"Promise was canceled\"),this.name=\"CancelError\"}get isCanceled(){return!0}},Sx=class t{static fn(e){return(...r)=>new t((o,a,n)=>{r.push(n),e(...r).then(o,a)})}constructor(e){this._cancelHandlers=[],this._isPending=!0,this._isCanceled=!1,this._rejectOnCancel=!0,this._promise=new Promise((r,o)=>{this._reject=o;let a=A=>{this._isPending=!1,r(A)},n=A=>{this._isPending=!1,o(A)},u=A=>{if(!this._isPending)throw new Error(\"The `onCancel` handler was attached after the promise settled.\");this._cancelHandlers.push(A)};return Object.defineProperties(u,{shouldReject:{get:()=>this._rejectOnCancel,set:A=>{this._rejectOnCancel=A}}}),e(a,n,u)})}then(e,r){return this._promise.then(e,r)}catch(e){return this._promise.catch(e)}finally(e){return this._promise.finally(e)}cancel(e){if(!(!this._isPending||this._isCanceled)){if(this._cancelHandlers.length>0)try{for(let r of this._cancelHandlers)r()}catch(r){this._reject(r)}this._isCanceled=!0,this._rejectOnCancel&&this._reject(new Px(e))}}get isCanceled(){return this._isCanceled}};Object.setPrototypeOf(Sx.prototype,Promise.prototype);o4.exports=Sx;o4.exports.CancelError=Px});var Uoe=_((l4,c4)=>{\"use strict\";Object.defineProperty(l4,\"__esModule\",{value:!0});function Mrt(t){return t.encrypted}var a4=(t,e)=>{let r;typeof e==\"function\"?r={connect:e}:r=e;let o=typeof r.connect==\"function\",a=typeof r.secureConnect==\"function\",n=typeof r.close==\"function\",u=()=>{o&&r.connect(),Mrt(t)&&a&&(t.authorized?r.secureConnect():t.authorizationError||t.once(\"secureConnect\",r.secureConnect)),n&&t.once(\"close\",r.close)};t.writable&&!t.connecting?u():t.connecting?t.once(\"connect\",u):t.destroyed&&n&&r.close(t._hadError)};l4.default=a4;c4.exports=a4;c4.exports.default=a4});var _oe=_((A4,f4)=>{\"use strict\";Object.defineProperty(A4,\"__esModule\",{value:!0});var Urt=Uoe(),_rt=Number(process.versions.node.split(\".\")[0]),u4=t=>{let e={start:Date.now(),socket:void 0,lookup:void 0,connect:void 0,secureConnect:void 0,upload:void 0,response:void 0,end:void 0,error:void 0,abort:void 0,phases:{wait:void 0,dns:void 0,tcp:void 0,tls:void 0,request:void 0,firstByte:void 0,download:void 0,total:void 0}};t.timings=e;let r=u=>{let A=u.emit.bind(u);u.emit=(p,...h)=>(p===\"error\"&&(e.error=Date.now(),e.phases.total=e.error-e.start,u.emit=A),A(p,...h))};r(t),t.prependOnceListener(\"abort\",()=>{e.abort=Date.now(),(!e.response||_rt>=13)&&(e.phases.total=Date.now()-e.start)});let o=u=>{e.socket=Date.now(),e.phases.wait=e.socket-e.start;let A=()=>{e.lookup=Date.now(),e.phases.dns=e.lookup-e.socket};u.prependOnceListener(\"lookup\",A),Urt.default(u,{connect:()=>{e.connect=Date.now(),e.lookup===void 0&&(u.removeListener(\"lookup\",A),e.lookup=e.connect,e.phases.dns=e.lookup-e.socket),e.phases.tcp=e.connect-e.lookup},secureConnect:()=>{e.secureConnect=Date.now(),e.phases.tls=e.secureConnect-e.connect}})};t.socket?o(t.socket):t.prependOnceListener(\"socket\",o);let a=()=>{var u;e.upload=Date.now(),e.phases.request=e.upload-(u=e.secureConnect,u??e.connect)};return(typeof t.writableFinished==\"boolean\"?t.writableFinished:t.finished&&t.outputSize===0&&(!t.socket||t.socket.writableLength===0))?a():t.prependOnceListener(\"finish\",a),t.prependOnceListener(\"response\",u=>{e.response=Date.now(),e.phases.firstByte=e.response-e.upload,u.timings=e,r(u),u.prependOnceListener(\"end\",()=>{e.end=Date.now(),e.phases.download=e.end-e.response,e.phases.total=e.end-e.start})}),e};A4.default=u4;f4.exports=u4;f4.exports.default=u4});var Koe=_((WLt,g4)=>{\"use strict\";var{V4MAPPED:Hrt,ADDRCONFIG:qrt,ALL:Yoe,promises:{Resolver:Hoe},lookup:jrt}=ve(\"dns\"),{promisify:p4}=ve(\"util\"),Grt=ve(\"os\"),Cy=Symbol(\"cacheableLookupCreateConnection\"),h4=Symbol(\"cacheableLookupInstance\"),qoe=Symbol(\"expires\"),Wrt=typeof Yoe==\"number\",joe=t=>{if(!(t&&typeof t.createConnection==\"function\"))throw new Error(\"Expected an Agent instance as the first argument\")},Yrt=t=>{for(let e of t)e.family!==6&&(e.address=`::ffff:${e.address}`,e.family=6)},Goe=()=>{let t=!1,e=!1;for(let r of Object.values(Grt.networkInterfaces()))for(let o of r)if(!o.internal&&(o.family===\"IPv6\"?e=!0:t=!0,t&&e))return{has4:t,has6:e};return{has4:t,has6:e}},Krt=t=>Symbol.iterator in t,Woe={ttl:!0},Vrt={all:!0},xx=class{constructor({cache:e=new Map,maxTtl:r=1/0,fallbackDuration:o=3600,errorTtl:a=.15,resolver:n=new Hoe,lookup:u=jrt}={}){if(this.maxTtl=r,this.errorTtl=a,this._cache=e,this._resolver=n,this._dnsLookup=p4(u),this._resolver instanceof Hoe?(this._resolve4=this._resolver.resolve4.bind(this._resolver),this._resolve6=this._resolver.resolve6.bind(this._resolver)):(this._resolve4=p4(this._resolver.resolve4.bind(this._resolver)),this._resolve6=p4(this._resolver.resolve6.bind(this._resolver))),this._iface=Goe(),this._pending={},this._nextRemovalTime=!1,this._hostnamesToFallback=new Set,o<1)this._fallback=!1;else{this._fallback=!0;let A=setInterval(()=>{this._hostnamesToFallback.clear()},o*1e3);A.unref&&A.unref()}this.lookup=this.lookup.bind(this),this.lookupAsync=this.lookupAsync.bind(this)}set servers(e){this.clear(),this._resolver.setServers(e)}get servers(){return this._resolver.getServers()}lookup(e,r,o){if(typeof r==\"function\"?(o=r,r={}):typeof r==\"number\"&&(r={family:r}),!o)throw new Error(\"Callback must be a function.\");this.lookupAsync(e,r).then(a=>{r.all?o(null,a):o(null,a.address,a.family,a.expires,a.ttl)},o)}async lookupAsync(e,r={}){typeof r==\"number\"&&(r={family:r});let o=await this.query(e);if(r.family===6){let a=o.filter(n=>n.family===6);r.hints&Hrt&&(Wrt&&r.hints&Yoe||a.length===0)?Yrt(o):o=a}else r.family===4&&(o=o.filter(a=>a.family===4));if(r.hints&qrt){let{_iface:a}=this;o=o.filter(n=>n.family===6?a.has6:a.has4)}if(o.length===0){let a=new Error(`cacheableLookup ENOTFOUND ${e}`);throw a.code=\"ENOTFOUND\",a.hostname=e,a}return r.all?o:o[0]}async query(e){let r=await this._cache.get(e);if(!r){let o=this._pending[e];if(o)r=await o;else{let a=this.queryAndCache(e);this._pending[e]=a,r=await a}}return r=r.map(o=>({...o})),r}async _resolve(e){let r=async h=>{try{return await h}catch(E){if(E.code===\"ENODATA\"||E.code===\"ENOTFOUND\")return[];throw E}},[o,a]=await Promise.all([this._resolve4(e,Woe),this._resolve6(e,Woe)].map(h=>r(h))),n=0,u=0,A=0,p=Date.now();for(let h of o)h.family=4,h.expires=p+h.ttl*1e3,n=Math.max(n,h.ttl);for(let h of a)h.family=6,h.expires=p+h.ttl*1e3,u=Math.max(u,h.ttl);return o.length>0?a.length>0?A=Math.min(n,u):A=n:A=u,{entries:[...o,...a],cacheTtl:A}}async _lookup(e){try{return{entries:await this._dnsLookup(e,{all:!0}),cacheTtl:0}}catch{return{entries:[],cacheTtl:0}}}async _set(e,r,o){if(this.maxTtl>0&&o>0){o=Math.min(o,this.maxTtl)*1e3,r[qoe]=Date.now()+o;try{await this._cache.set(e,r,o)}catch(a){this.lookupAsync=async()=>{let n=new Error(\"Cache Error. Please recreate the CacheableLookup instance.\");throw n.cause=a,n}}Krt(this._cache)&&this._tick(o)}}async queryAndCache(e){if(this._hostnamesToFallback.has(e))return this._dnsLookup(e,Vrt);try{let r=await this._resolve(e);r.entries.length===0&&this._fallback&&(r=await this._lookup(e),r.entries.length!==0&&this._hostnamesToFallback.add(e));let o=r.entries.length===0?this.errorTtl:r.cacheTtl;return await this._set(e,r.entries,o),delete this._pending[e],r.entries}catch(r){throw delete this._pending[e],r}}_tick(e){let r=this._nextRemovalTime;(!r||e<r)&&(clearTimeout(this._removalTimeout),this._nextRemovalTime=e,this._removalTimeout=setTimeout(()=>{this._nextRemovalTime=!1;let o=1/0,a=Date.now();for(let[n,u]of this._cache){let A=u[qoe];a>=A?this._cache.delete(n):A<o&&(o=A)}o!==1/0&&this._tick(o-a)},e),this._removalTimeout.unref&&this._removalTimeout.unref())}install(e){if(joe(e),Cy in e)throw new Error(\"CacheableLookup has been already installed\");e[Cy]=e.createConnection,e[h4]=this,e.createConnection=(r,o)=>(\"lookup\"in r||(r.lookup=this.lookup),e[Cy](r,o))}uninstall(e){if(joe(e),e[Cy]){if(e[h4]!==this)throw new Error(\"The agent is not owned by this CacheableLookup instance\");e.createConnection=e[Cy],delete e[Cy],delete e[h4]}}updateInterfaceInfo(){let{_iface:e}=this;this._iface=Goe(),(e.has4&&!this._iface.has4||e.has6&&!this._iface.has6)&&this._cache.clear()}clear(e){if(e){this._cache.delete(e);return}this._cache.clear()}};g4.exports=xx;g4.exports.default=xx});var Joe=_((YLt,d4)=>{\"use strict\";var zrt=typeof URL>\"u\"?ve(\"url\").URL:URL,Jrt=\"text/plain\",Xrt=\"us-ascii\",Voe=(t,e)=>e.some(r=>r instanceof RegExp?r.test(t):r===t),Zrt=(t,{stripHash:e})=>{let r=t.match(/^data:([^,]*?),([^#]*?)(?:#(.*))?$/);if(!r)throw new Error(`Invalid URL: ${t}`);let o=r[1].split(\";\"),a=r[2],n=e?\"\":r[3],u=!1;o[o.length-1]===\"base64\"&&(o.pop(),u=!0);let A=(o.shift()||\"\").toLowerCase(),h=[...o.map(E=>{let[w,D=\"\"]=E.split(\"=\").map(b=>b.trim());return w===\"charset\"&&(D=D.toLowerCase(),D===Xrt)?\"\":`${w}${D?`=${D}`:\"\"}`}).filter(Boolean)];return u&&h.push(\"base64\"),(h.length!==0||A&&A!==Jrt)&&h.unshift(A),`data:${h.join(\";\")},${u?a.trim():a}${n?`#${n}`:\"\"}`},zoe=(t,e)=>{if(e={defaultProtocol:\"http:\",normalizeProtocol:!0,forceHttp:!1,forceHttps:!1,stripAuthentication:!0,stripHash:!1,stripWWW:!0,removeQueryParameters:[/^utm_\\w+/i],removeTrailingSlash:!0,removeDirectoryIndex:!1,sortQueryParameters:!0,...e},Reflect.has(e,\"normalizeHttps\"))throw new Error(\"options.normalizeHttps is renamed to options.forceHttp\");if(Reflect.has(e,\"normalizeHttp\"))throw new Error(\"options.normalizeHttp is renamed to options.forceHttps\");if(Reflect.has(e,\"stripFragment\"))throw new Error(\"options.stripFragment is renamed to options.stripHash\");if(t=t.trim(),/^data:/i.test(t))return Zrt(t,e);let r=t.startsWith(\"//\");!r&&/^\\.*\\//.test(t)||(t=t.replace(/^(?!(?:\\w+:)?\\/\\/)|^\\/\\//,e.defaultProtocol));let a=new zrt(t);if(e.forceHttp&&e.forceHttps)throw new Error(\"The `forceHttp` and `forceHttps` options cannot be used together\");if(e.forceHttp&&a.protocol===\"https:\"&&(a.protocol=\"http:\"),e.forceHttps&&a.protocol===\"http:\"&&(a.protocol=\"https:\"),e.stripAuthentication&&(a.username=\"\",a.password=\"\"),e.stripHash&&(a.hash=\"\"),a.pathname&&(a.pathname=a.pathname.replace(/((?!:).|^)\\/{2,}/g,(n,u)=>/^(?!\\/)/g.test(u)?`${u}/`:\"/\")),a.pathname&&(a.pathname=decodeURI(a.pathname)),e.removeDirectoryIndex===!0&&(e.removeDirectoryIndex=[/^index\\.[a-z]+$/]),Array.isArray(e.removeDirectoryIndex)&&e.removeDirectoryIndex.length>0){let n=a.pathname.split(\"/\"),u=n[n.length-1];Voe(u,e.removeDirectoryIndex)&&(n=n.slice(0,n.length-1),a.pathname=n.slice(1).join(\"/\")+\"/\")}if(a.hostname&&(a.hostname=a.hostname.replace(/\\.$/,\"\"),e.stripWWW&&/^www\\.([a-z\\-\\d]{2,63})\\.([a-z.]{2,5})$/.test(a.hostname)&&(a.hostname=a.hostname.replace(/^www\\./,\"\"))),Array.isArray(e.removeQueryParameters))for(let n of[...a.searchParams.keys()])Voe(n,e.removeQueryParameters)&&a.searchParams.delete(n);return e.sortQueryParameters&&a.searchParams.sort(),e.removeTrailingSlash&&(a.pathname=a.pathname.replace(/\\/$/,\"\")),t=a.toString(),(e.removeTrailingSlash||a.pathname===\"/\")&&a.hash===\"\"&&(t=t.replace(/\\/$/,\"\")),r&&!e.normalizeProtocol&&(t=t.replace(/^http:\\/\\//,\"//\")),e.stripProtocol&&(t=t.replace(/^(?:https?:)?\\/\\//,\"\")),t};d4.exports=zoe;d4.exports.default=zoe});var $oe=_((KLt,Zoe)=>{Zoe.exports=Xoe;function Xoe(t,e){if(t&&e)return Xoe(t)(e);if(typeof t!=\"function\")throw new TypeError(\"need wrapper function\");return Object.keys(t).forEach(function(o){r[o]=t[o]}),r;function r(){for(var o=new Array(arguments.length),a=0;a<o.length;a++)o[a]=arguments[a];var n=t.apply(this,o),u=o[o.length-1];return typeof n==\"function\"&&n!==u&&Object.keys(u).forEach(function(A){n[A]=u[A]}),n}}});var y4=_((VLt,m4)=>{var eae=$oe();m4.exports=eae(bx);m4.exports.strict=eae(tae);bx.proto=bx(function(){Object.defineProperty(Function.prototype,\"once\",{value:function(){return bx(this)},configurable:!0}),Object.defineProperty(Function.prototype,\"onceStrict\",{value:function(){return tae(this)},configurable:!0})});function bx(t){var e=function(){return e.called?e.value:(e.called=!0,e.value=t.apply(this,arguments))};return e.called=!1,e}function tae(t){var e=function(){if(e.called)throw new Error(e.onceError);return e.called=!0,e.value=t.apply(this,arguments)},r=t.name||\"Function wrapped with `once`\";return e.onceError=r+\" shouldn't be called more than once\",e.called=!1,e}});var E4=_((zLt,nae)=>{var $rt=y4(),ent=function(){},tnt=function(t){return t.setHeader&&typeof t.abort==\"function\"},rnt=function(t){return t.stdio&&Array.isArray(t.stdio)&&t.stdio.length===3},rae=function(t,e,r){if(typeof e==\"function\")return rae(t,null,e);e||(e={}),r=$rt(r||ent);var o=t._writableState,a=t._readableState,n=e.readable||e.readable!==!1&&t.readable,u=e.writable||e.writable!==!1&&t.writable,A=function(){t.writable||p()},p=function(){u=!1,n||r.call(t)},h=function(){n=!1,u||r.call(t)},E=function(C){r.call(t,C?new Error(\"exited with error code: \"+C):null)},w=function(C){r.call(t,C)},D=function(){if(n&&!(a&&a.ended))return r.call(t,new Error(\"premature close\"));if(u&&!(o&&o.ended))return r.call(t,new Error(\"premature close\"))},b=function(){t.req.on(\"finish\",p)};return tnt(t)?(t.on(\"complete\",p),t.on(\"abort\",D),t.req?b():t.on(\"request\",b)):u&&!o&&(t.on(\"end\",A),t.on(\"close\",A)),rnt(t)&&t.on(\"exit\",E),t.on(\"end\",h),t.on(\"finish\",p),e.error!==!1&&t.on(\"error\",w),t.on(\"close\",D),function(){t.removeListener(\"complete\",p),t.removeListener(\"abort\",D),t.removeListener(\"request\",b),t.req&&t.req.removeListener(\"finish\",p),t.removeListener(\"end\",A),t.removeListener(\"close\",A),t.removeListener(\"finish\",p),t.removeListener(\"exit\",E),t.removeListener(\"end\",h),t.removeListener(\"error\",w),t.removeListener(\"close\",D)}};nae.exports=rae});var oae=_((JLt,sae)=>{var nnt=y4(),int=E4(),C4=ve(\"fs\"),Q1=function(){},snt=/^v?\\.0/.test(process.version),kx=function(t){return typeof t==\"function\"},ont=function(t){return!snt||!C4?!1:(t instanceof(C4.ReadStream||Q1)||t instanceof(C4.WriteStream||Q1))&&kx(t.close)},ant=function(t){return t.setHeader&&kx(t.abort)},lnt=function(t,e,r,o){o=nnt(o);var a=!1;t.on(\"close\",function(){a=!0}),int(t,{readable:e,writable:r},function(u){if(u)return o(u);a=!0,o()});var n=!1;return function(u){if(!a&&!n){if(n=!0,ont(t))return t.close(Q1);if(ant(t))return t.abort();if(kx(t.destroy))return t.destroy();o(u||new Error(\"stream was destroyed\"))}}},iae=function(t){t()},cnt=function(t,e){return t.pipe(e)},unt=function(){var t=Array.prototype.slice.call(arguments),e=kx(t[t.length-1]||Q1)&&t.pop()||Q1;if(Array.isArray(t[0])&&(t=t[0]),t.length<2)throw new Error(\"pump requires two streams per minimum\");var r,o=t.map(function(a,n){var u=n<t.length-1,A=n>0;return lnt(a,u,A,function(p){r||(r=p),p&&o.forEach(iae),!u&&(o.forEach(iae),e(r))})});return t.reduce(cnt)};sae.exports=unt});var lae=_((XLt,aae)=>{\"use strict\";var{PassThrough:Ant}=ve(\"stream\");aae.exports=t=>{t={...t};let{array:e}=t,{encoding:r}=t,o=r===\"buffer\",a=!1;e?a=!(r||o):r=r||\"utf8\",o&&(r=null);let n=new Ant({objectMode:a});r&&n.setEncoding(r);let u=0,A=[];return n.on(\"data\",p=>{A.push(p),a?u=A.length:u+=p.length}),n.getBufferedValue=()=>e?A:o?Buffer.concat(A,u):A.join(\"\"),n.getBufferedLength=()=>u,n}});var cae=_((ZLt,Iy)=>{\"use strict\";var fnt=oae(),pnt=lae(),Qx=class extends Error{constructor(){super(\"maxBuffer exceeded\"),this.name=\"MaxBufferError\"}};async function Fx(t,e){if(!t)return Promise.reject(new Error(\"Expected a stream\"));e={maxBuffer:1/0,...e};let{maxBuffer:r}=e,o;return await new Promise((a,n)=>{let u=A=>{A&&(A.bufferedData=o.getBufferedValue()),n(A)};o=fnt(t,pnt(e),A=>{if(A){u(A);return}a()}),o.on(\"data\",()=>{o.getBufferedLength()>r&&u(new Qx)})}),o.getBufferedValue()}Iy.exports=Fx;Iy.exports.default=Fx;Iy.exports.buffer=(t,e)=>Fx(t,{...e,encoding:\"buffer\"});Iy.exports.array=(t,e)=>Fx(t,{...e,array:!0});Iy.exports.MaxBufferError=Qx});var Aae=_((eNt,uae)=>{\"use strict\";var hnt=new Set([200,203,204,206,300,301,308,404,405,410,414,501]),gnt=new Set([200,203,204,300,301,302,303,307,308,404,405,410,414,501]),dnt=new Set([500,502,503,504]),mnt={date:!0,connection:!0,\"keep-alive\":!0,\"proxy-authenticate\":!0,\"proxy-authorization\":!0,te:!0,trailer:!0,\"transfer-encoding\":!0,upgrade:!0},ynt={\"content-length\":!0,\"content-encoding\":!0,\"transfer-encoding\":!0,\"content-range\":!0};function Sg(t){let e=parseInt(t,10);return isFinite(e)?e:0}function Ent(t){return t?dnt.has(t.status):!0}function I4(t){let e={};if(!t)return e;let r=t.trim().split(/,/);for(let o of r){let[a,n]=o.split(/=/,2);e[a.trim()]=n===void 0?!0:n.trim().replace(/^\"|\"$/g,\"\")}return e}function Cnt(t){let e=[];for(let r in t){let o=t[r];e.push(o===!0?r:r+\"=\"+o)}if(e.length)return e.join(\", \")}uae.exports=class{constructor(e,r,{shared:o,cacheHeuristic:a,immutableMinTimeToLive:n,ignoreCargoCult:u,_fromObject:A}={}){if(A){this._fromObject(A);return}if(!r||!r.headers)throw Error(\"Response headers missing\");this._assertRequestHasHeaders(e),this._responseTime=this.now(),this._isShared=o!==!1,this._cacheHeuristic=a!==void 0?a:.1,this._immutableMinTtl=n!==void 0?n:24*3600*1e3,this._status=\"status\"in r?r.status:200,this._resHeaders=r.headers,this._rescc=I4(r.headers[\"cache-control\"]),this._method=\"method\"in e?e.method:\"GET\",this._url=e.url,this._host=e.headers.host,this._noAuthorization=!e.headers.authorization,this._reqHeaders=r.headers.vary?e.headers:null,this._reqcc=I4(e.headers[\"cache-control\"]),u&&\"pre-check\"in this._rescc&&\"post-check\"in this._rescc&&(delete this._rescc[\"pre-check\"],delete this._rescc[\"post-check\"],delete this._rescc[\"no-cache\"],delete this._rescc[\"no-store\"],delete this._rescc[\"must-revalidate\"],this._resHeaders=Object.assign({},this._resHeaders,{\"cache-control\":Cnt(this._rescc)}),delete this._resHeaders.expires,delete this._resHeaders.pragma),r.headers[\"cache-control\"]==null&&/no-cache/.test(r.headers.pragma)&&(this._rescc[\"no-cache\"]=!0)}now(){return Date.now()}storable(){return!!(!this._reqcc[\"no-store\"]&&(this._method===\"GET\"||this._method===\"HEAD\"||this._method===\"POST\"&&this._hasExplicitExpiration())&&gnt.has(this._status)&&!this._rescc[\"no-store\"]&&(!this._isShared||!this._rescc.private)&&(!this._isShared||this._noAuthorization||this._allowsStoringAuthenticated())&&(this._resHeaders.expires||this._rescc[\"max-age\"]||this._isShared&&this._rescc[\"s-maxage\"]||this._rescc.public||hnt.has(this._status)))}_hasExplicitExpiration(){return this._isShared&&this._rescc[\"s-maxage\"]||this._rescc[\"max-age\"]||this._resHeaders.expires}_assertRequestHasHeaders(e){if(!e||!e.headers)throw Error(\"Request headers missing\")}satisfiesWithoutRevalidation(e){this._assertRequestHasHeaders(e);let r=I4(e.headers[\"cache-control\"]);return r[\"no-cache\"]||/no-cache/.test(e.headers.pragma)||r[\"max-age\"]&&this.age()>r[\"max-age\"]||r[\"min-fresh\"]&&this.timeToLive()<1e3*r[\"min-fresh\"]||this.stale()&&!(r[\"max-stale\"]&&!this._rescc[\"must-revalidate\"]&&(r[\"max-stale\"]===!0||r[\"max-stale\"]>this.age()-this.maxAge()))?!1:this._requestMatches(e,!1)}_requestMatches(e,r){return(!this._url||this._url===e.url)&&this._host===e.headers.host&&(!e.method||this._method===e.method||r&&e.method===\"HEAD\")&&this._varyMatches(e)}_allowsStoringAuthenticated(){return this._rescc[\"must-revalidate\"]||this._rescc.public||this._rescc[\"s-maxage\"]}_varyMatches(e){if(!this._resHeaders.vary)return!0;if(this._resHeaders.vary===\"*\")return!1;let r=this._resHeaders.vary.trim().toLowerCase().split(/\\s*,\\s*/);for(let o of r)if(e.headers[o]!==this._reqHeaders[o])return!1;return!0}_copyWithoutHopByHopHeaders(e){let r={};for(let o in e)mnt[o]||(r[o]=e[o]);if(e.connection){let o=e.connection.trim().split(/\\s*,\\s*/);for(let a of o)delete r[a]}if(r.warning){let o=r.warning.split(/,/).filter(a=>!/^\\s*1[0-9][0-9]/.test(a));o.length?r.warning=o.join(\",\").trim():delete r.warning}return r}responseHeaders(){let e=this._copyWithoutHopByHopHeaders(this._resHeaders),r=this.age();return r>3600*24&&!this._hasExplicitExpiration()&&this.maxAge()>3600*24&&(e.warning=(e.warning?`${e.warning}, `:\"\")+'113 - \"rfc7234 5.5.4\"'),e.age=`${Math.round(r)}`,e.date=new Date(this.now()).toUTCString(),e}date(){let e=Date.parse(this._resHeaders.date);return isFinite(e)?e:this._responseTime}age(){let e=this._ageValue(),r=(this.now()-this._responseTime)/1e3;return e+r}_ageValue(){return Sg(this._resHeaders.age)}maxAge(){if(!this.storable()||this._rescc[\"no-cache\"]||this._isShared&&this._resHeaders[\"set-cookie\"]&&!this._rescc.public&&!this._rescc.immutable||this._resHeaders.vary===\"*\")return 0;if(this._isShared){if(this._rescc[\"proxy-revalidate\"])return 0;if(this._rescc[\"s-maxage\"])return Sg(this._rescc[\"s-maxage\"])}if(this._rescc[\"max-age\"])return Sg(this._rescc[\"max-age\"]);let e=this._rescc.immutable?this._immutableMinTtl:0,r=this.date();if(this._resHeaders.expires){let o=Date.parse(this._resHeaders.expires);return Number.isNaN(o)||o<r?0:Math.max(e,(o-r)/1e3)}if(this._resHeaders[\"last-modified\"]){let o=Date.parse(this._resHeaders[\"last-modified\"]);if(isFinite(o)&&r>o)return Math.max(e,(r-o)/1e3*this._cacheHeuristic)}return e}timeToLive(){let e=this.maxAge()-this.age(),r=e+Sg(this._rescc[\"stale-if-error\"]),o=e+Sg(this._rescc[\"stale-while-revalidate\"]);return Math.max(0,e,r,o)*1e3}stale(){return this.maxAge()<=this.age()}_useStaleIfError(){return this.maxAge()+Sg(this._rescc[\"stale-if-error\"])>this.age()}useStaleWhileRevalidate(){return this.maxAge()+Sg(this._rescc[\"stale-while-revalidate\"])>this.age()}static fromObject(e){return new this(void 0,void 0,{_fromObject:e})}_fromObject(e){if(this._responseTime)throw Error(\"Reinitialized\");if(!e||e.v!==1)throw Error(\"Invalid serialization\");this._responseTime=e.t,this._isShared=e.sh,this._cacheHeuristic=e.ch,this._immutableMinTtl=e.imm!==void 0?e.imm:24*3600*1e3,this._status=e.st,this._resHeaders=e.resh,this._rescc=e.rescc,this._method=e.m,this._url=e.u,this._host=e.h,this._noAuthorization=e.a,this._reqHeaders=e.reqh,this._reqcc=e.reqcc}toObject(){return{v:1,t:this._responseTime,sh:this._isShared,ch:this._cacheHeuristic,imm:this._immutableMinTtl,st:this._status,resh:this._resHeaders,rescc:this._rescc,m:this._method,u:this._url,h:this._host,a:this._noAuthorization,reqh:this._reqHeaders,reqcc:this._reqcc}}revalidationHeaders(e){this._assertRequestHasHeaders(e);let r=this._copyWithoutHopByHopHeaders(e.headers);if(delete r[\"if-range\"],!this._requestMatches(e,!0)||!this.storable())return delete r[\"if-none-match\"],delete r[\"if-modified-since\"],r;if(this._resHeaders.etag&&(r[\"if-none-match\"]=r[\"if-none-match\"]?`${r[\"if-none-match\"]}, ${this._resHeaders.etag}`:this._resHeaders.etag),r[\"accept-ranges\"]||r[\"if-match\"]||r[\"if-unmodified-since\"]||this._method&&this._method!=\"GET\"){if(delete r[\"if-modified-since\"],r[\"if-none-match\"]){let a=r[\"if-none-match\"].split(/,/).filter(n=>!/^\\s*W\\//.test(n));a.length?r[\"if-none-match\"]=a.join(\",\").trim():delete r[\"if-none-match\"]}}else this._resHeaders[\"last-modified\"]&&!r[\"if-modified-since\"]&&(r[\"if-modified-since\"]=this._resHeaders[\"last-modified\"]);return r}revalidatedPolicy(e,r){if(this._assertRequestHasHeaders(e),this._useStaleIfError()&&Ent(r))return{modified:!1,matches:!1,policy:this};if(!r||!r.headers)throw Error(\"Response headers missing\");let o=!1;if(r.status!==void 0&&r.status!=304?o=!1:r.headers.etag&&!/^\\s*W\\//.test(r.headers.etag)?o=this._resHeaders.etag&&this._resHeaders.etag.replace(/^\\s*W\\//,\"\")===r.headers.etag:this._resHeaders.etag&&r.headers.etag?o=this._resHeaders.etag.replace(/^\\s*W\\//,\"\")===r.headers.etag.replace(/^\\s*W\\//,\"\"):this._resHeaders[\"last-modified\"]?o=this._resHeaders[\"last-modified\"]===r.headers[\"last-modified\"]:!this._resHeaders.etag&&!this._resHeaders[\"last-modified\"]&&!r.headers.etag&&!r.headers[\"last-modified\"]&&(o=!0),!o)return{policy:new this.constructor(e,r),modified:r.status!=304,matches:!1};let a={};for(let u in this._resHeaders)a[u]=u in r.headers&&!ynt[u]?r.headers[u]:this._resHeaders[u];let n=Object.assign({},r,{status:this._status,method:this._method,headers:a});return{policy:new this.constructor(e,n,{shared:this._isShared,cacheHeuristic:this._cacheHeuristic,immutableMinTimeToLive:this._immutableMinTtl}),modified:!1,matches:!0}}}});var Rx=_((tNt,fae)=>{\"use strict\";fae.exports=t=>{let e={};for(let[r,o]of Object.entries(t))e[r.toLowerCase()]=o;return e}});var hae=_((rNt,pae)=>{\"use strict\";var Int=ve(\"stream\").Readable,wnt=Rx(),w4=class extends Int{constructor(e,r,o,a){if(typeof e!=\"number\")throw new TypeError(\"Argument `statusCode` should be a number\");if(typeof r!=\"object\")throw new TypeError(\"Argument `headers` should be an object\");if(!(o instanceof Buffer))throw new TypeError(\"Argument `body` should be a buffer\");if(typeof a!=\"string\")throw new TypeError(\"Argument `url` should be a string\");super(),this.statusCode=e,this.headers=wnt(r),this.body=o,this.url=a}_read(){this.push(this.body),this.push(null)}};pae.exports=w4});var dae=_((nNt,gae)=>{\"use strict\";var Bnt=[\"destroy\",\"setTimeout\",\"socket\",\"headers\",\"trailers\",\"rawHeaders\",\"statusCode\",\"httpVersion\",\"httpVersionMinor\",\"httpVersionMajor\",\"rawTrailers\",\"statusMessage\"];gae.exports=(t,e)=>{let r=new Set(Object.keys(t).concat(Bnt));for(let o of r)o in e||(e[o]=typeof t[o]==\"function\"?t[o].bind(t):t[o])}});var yae=_((iNt,mae)=>{\"use strict\";var vnt=ve(\"stream\").PassThrough,Dnt=dae(),Pnt=t=>{if(!(t&&t.pipe))throw new TypeError(\"Parameter `response` must be a response stream.\");let e=new vnt;return Dnt(t,e),t.pipe(e)};mae.exports=Pnt});var Eae=_(B4=>{B4.stringify=function t(e){if(typeof e>\"u\")return e;if(e&&Buffer.isBuffer(e))return JSON.stringify(\":base64:\"+e.toString(\"base64\"));if(e&&e.toJSON&&(e=e.toJSON()),e&&typeof e==\"object\"){var r=\"\",o=Array.isArray(e);r=o?\"[\":\"{\";var a=!0;for(var n in e){var u=typeof e[n]==\"function\"||!o&&typeof e[n]>\"u\";Object.hasOwnProperty.call(e,n)&&!u&&(a||(r+=\",\"),a=!1,o?e[n]==null?r+=\"null\":r+=t(e[n]):e[n]!==void 0&&(r+=t(n)+\":\"+t(e[n])))}return r+=o?\"]\":\"}\",r}else return typeof e==\"string\"?JSON.stringify(/^:/.test(e)?\":\"+e:e):typeof e>\"u\"?\"null\":JSON.stringify(e)};B4.parse=function(t){return JSON.parse(t,function(e,r){return typeof r==\"string\"?/^:base64:/.test(r)?Buffer.from(r.substring(8),\"base64\"):/^:/.test(r)?r.substring(1):r:r})}});var Bae=_((oNt,wae)=>{\"use strict\";var Snt=ve(\"events\"),Cae=Eae(),xnt=t=>{let e={redis:\"@keyv/redis\",rediss:\"@keyv/redis\",mongodb:\"@keyv/mongo\",mongo:\"@keyv/mongo\",sqlite:\"@keyv/sqlite\",postgresql:\"@keyv/postgres\",postgres:\"@keyv/postgres\",mysql:\"@keyv/mysql\",etcd:\"@keyv/etcd\",offline:\"@keyv/offline\",tiered:\"@keyv/tiered\"};if(t.adapter||t.uri){let r=t.adapter||/^[^:+]*/.exec(t.uri)[0];return new(ve(e[r]))(t)}return new Map},Iae=[\"sqlite\",\"postgres\",\"mysql\",\"mongo\",\"redis\",\"tiered\"],v4=class extends Snt{constructor(e,{emitErrors:r=!0,...o}={}){if(super(),this.opts={namespace:\"keyv\",serialize:Cae.stringify,deserialize:Cae.parse,...typeof e==\"string\"?{uri:e}:e,...o},!this.opts.store){let n={...this.opts};this.opts.store=xnt(n)}if(this.opts.compression){let n=this.opts.compression;this.opts.serialize=n.serialize.bind(n),this.opts.deserialize=n.deserialize.bind(n)}typeof this.opts.store.on==\"function\"&&r&&this.opts.store.on(\"error\",n=>this.emit(\"error\",n)),this.opts.store.namespace=this.opts.namespace;let a=n=>async function*(){for await(let[u,A]of typeof n==\"function\"?n(this.opts.store.namespace):n){let p=await this.opts.deserialize(A);if(!(this.opts.store.namespace&&!u.includes(this.opts.store.namespace))){if(typeof p.expires==\"number\"&&Date.now()>p.expires){this.delete(u);continue}yield[this._getKeyUnprefix(u),p.value]}}};typeof this.opts.store[Symbol.iterator]==\"function\"&&this.opts.store instanceof Map?this.iterator=a(this.opts.store):typeof this.opts.store.iterator==\"function\"&&this.opts.store.opts&&this._checkIterableAdaptar()&&(this.iterator=a(this.opts.store.iterator.bind(this.opts.store)))}_checkIterableAdaptar(){return Iae.includes(this.opts.store.opts.dialect)||Iae.findIndex(e=>this.opts.store.opts.url.includes(e))>=0}_getKeyPrefix(e){return`${this.opts.namespace}:${e}`}_getKeyPrefixArray(e){return e.map(r=>`${this.opts.namespace}:${r}`)}_getKeyUnprefix(e){return e.split(\":\").splice(1).join(\":\")}get(e,r){let{store:o}=this.opts,a=Array.isArray(e),n=a?this._getKeyPrefixArray(e):this._getKeyPrefix(e);if(a&&o.getMany===void 0){let u=[];for(let A of n)u.push(Promise.resolve().then(()=>o.get(A)).then(p=>typeof p==\"string\"?this.opts.deserialize(p):this.opts.compression?this.opts.deserialize(p):p).then(p=>{if(p!=null)return typeof p.expires==\"number\"&&Date.now()>p.expires?this.delete(A).then(()=>{}):r&&r.raw?p:p.value}));return Promise.allSettled(u).then(A=>{let p=[];for(let h of A)p.push(h.value);return p})}return Promise.resolve().then(()=>a?o.getMany(n):o.get(n)).then(u=>typeof u==\"string\"?this.opts.deserialize(u):this.opts.compression?this.opts.deserialize(u):u).then(u=>{if(u!=null)return a?u.map((A,p)=>{if(typeof A==\"string\"&&(A=this.opts.deserialize(A)),A!=null){if(typeof A.expires==\"number\"&&Date.now()>A.expires){this.delete(e[p]).then(()=>{});return}return r&&r.raw?A:A.value}}):typeof u.expires==\"number\"&&Date.now()>u.expires?this.delete(e).then(()=>{}):r&&r.raw?u:u.value})}set(e,r,o){let a=this._getKeyPrefix(e);typeof o>\"u\"&&(o=this.opts.ttl),o===0&&(o=void 0);let{store:n}=this.opts;return Promise.resolve().then(()=>{let u=typeof o==\"number\"?Date.now()+o:null;return typeof r==\"symbol\"&&this.emit(\"error\",\"symbol cannot be serialized\"),r={value:r,expires:u},this.opts.serialize(r)}).then(u=>n.set(a,u,o)).then(()=>!0)}delete(e){let{store:r}=this.opts;if(Array.isArray(e)){let a=this._getKeyPrefixArray(e);if(r.deleteMany===void 0){let n=[];for(let u of a)n.push(r.delete(u));return Promise.allSettled(n).then(u=>u.every(A=>A.value===!0))}return Promise.resolve().then(()=>r.deleteMany(a))}let o=this._getKeyPrefix(e);return Promise.resolve().then(()=>r.delete(o))}clear(){let{store:e}=this.opts;return Promise.resolve().then(()=>e.clear())}has(e){let r=this._getKeyPrefix(e),{store:o}=this.opts;return Promise.resolve().then(async()=>typeof o.has==\"function\"?o.has(r):await o.get(r)!==void 0)}disconnect(){let{store:e}=this.opts;if(typeof e.disconnect==\"function\")return e.disconnect()}};wae.exports=v4});var Pae=_((lNt,Dae)=>{\"use strict\";var bnt=ve(\"events\"),Tx=ve(\"url\"),knt=Joe(),Qnt=cae(),D4=Aae(),vae=hae(),Fnt=Rx(),Rnt=yae(),Tnt=Bae(),F1=class t{constructor(e,r){if(typeof e!=\"function\")throw new TypeError(\"Parameter `request` must be a function\");return this.cache=new Tnt({uri:typeof r==\"string\"&&r,store:typeof r!=\"string\"&&r,namespace:\"cacheable-request\"}),this.createCacheableRequest(e)}createCacheableRequest(e){return(r,o)=>{let a;if(typeof r==\"string\")a=P4(Tx.parse(r)),r={};else if(r instanceof Tx.URL)a=P4(Tx.parse(r.toString())),r={};else{let[w,...D]=(r.path||\"\").split(\"?\"),b=D.length>0?`?${D.join(\"?\")}`:\"\";a=P4({...r,pathname:w,search:b})}r={headers:{},method:\"GET\",cache:!0,strictTtl:!1,automaticFailover:!1,...r,...Lnt(a)},r.headers=Fnt(r.headers);let n=new bnt,u=knt(Tx.format(a),{stripWWW:!1,removeTrailingSlash:!1,stripAuthentication:!1}),A=`${r.method}:${u}`,p=!1,h=!1,E=w=>{h=!0;let D=!1,b,C=new Promise(N=>{b=()=>{D||(D=!0,N())}}),T=N=>{if(p&&!w.forceRefresh){N.status=N.statusCode;let z=D4.fromObject(p.cachePolicy).revalidatedPolicy(w,N);if(!z.modified){let te=z.policy.responseHeaders();N=new vae(p.statusCode,te,p.body,p.url),N.cachePolicy=z.policy,N.fromCache=!0}}N.fromCache||(N.cachePolicy=new D4(w,N,w),N.fromCache=!1);let U;w.cache&&N.cachePolicy.storable()?(U=Rnt(N),(async()=>{try{let z=Qnt.buffer(N);if(await Promise.race([C,new Promise(ue=>N.once(\"end\",ue))]),D)return;let te=await z,le={cachePolicy:N.cachePolicy.toObject(),url:N.url,statusCode:N.fromCache?p.statusCode:N.statusCode,body:te},ce=w.strictTtl?N.cachePolicy.timeToLive():void 0;w.maxTtl&&(ce=ce?Math.min(ce,w.maxTtl):w.maxTtl),await this.cache.set(A,le,ce)}catch(z){n.emit(\"error\",new t.CacheError(z))}})()):w.cache&&p&&(async()=>{try{await this.cache.delete(A)}catch(z){n.emit(\"error\",new t.CacheError(z))}})(),n.emit(\"response\",U||N),typeof o==\"function\"&&o(U||N)};try{let N=e(w,T);N.once(\"error\",b),N.once(\"abort\",b),n.emit(\"request\",N)}catch(N){n.emit(\"error\",new t.RequestError(N))}};return(async()=>{let w=async b=>{await Promise.resolve();let C=b.cache?await this.cache.get(A):void 0;if(typeof C>\"u\")return E(b);let T=D4.fromObject(C.cachePolicy);if(T.satisfiesWithoutRevalidation(b)&&!b.forceRefresh){let N=T.responseHeaders(),U=new vae(C.statusCode,N,C.body,C.url);U.cachePolicy=T,U.fromCache=!0,n.emit(\"response\",U),typeof o==\"function\"&&o(U)}else p=C,b.headers=T.revalidationHeaders(b),E(b)},D=b=>n.emit(\"error\",new t.CacheError(b));this.cache.once(\"error\",D),n.on(\"response\",()=>this.cache.removeListener(\"error\",D));try{await w(r)}catch(b){r.automaticFailover&&!h&&E(r),n.emit(\"error\",new t.CacheError(b))}})(),n}}};function Lnt(t){let e={...t};return e.path=`${t.pathname||\"/\"}${t.search||\"\"}`,delete e.pathname,delete e.search,e}function P4(t){return{protocol:t.protocol,auth:t.auth,hostname:t.hostname||t.host||\"localhost\",port:t.port,pathname:t.pathname,search:t.search}}F1.RequestError=class extends Error{constructor(t){super(t.message),this.name=\"RequestError\",Object.assign(this,t)}};F1.CacheError=class extends Error{constructor(t){super(t.message),this.name=\"CacheError\",Object.assign(this,t)}};Dae.exports=F1});var xae=_((ANt,Sae)=>{\"use strict\";var Nnt=[\"aborted\",\"complete\",\"headers\",\"httpVersion\",\"httpVersionMinor\",\"httpVersionMajor\",\"method\",\"rawHeaders\",\"rawTrailers\",\"setTimeout\",\"socket\",\"statusCode\",\"statusMessage\",\"trailers\",\"url\"];Sae.exports=(t,e)=>{if(e._readableState.autoDestroy)throw new Error(\"The second stream must have the `autoDestroy` option set to `false`\");let r=new Set(Object.keys(t).concat(Nnt)),o={};for(let a of r)a in e||(o[a]={get(){let n=t[a];return typeof n==\"function\"?n.bind(t):n},set(n){t[a]=n},enumerable:!0,configurable:!1});return Object.defineProperties(e,o),t.once(\"aborted\",()=>{e.destroy(),e.emit(\"aborted\")}),t.once(\"close\",()=>{t.complete&&e.readable?e.once(\"end\",()=>{e.emit(\"close\")}):e.emit(\"close\")}),e}});var kae=_((fNt,bae)=>{\"use strict\";var{Transform:Ont,PassThrough:Mnt}=ve(\"stream\"),S4=ve(\"zlib\"),Unt=xae();bae.exports=t=>{let e=(t.headers[\"content-encoding\"]||\"\").toLowerCase();if(![\"gzip\",\"deflate\",\"br\"].includes(e))return t;let r=e===\"br\";if(r&&typeof S4.createBrotliDecompress!=\"function\")return t.destroy(new Error(\"Brotli is not supported on Node.js < 12\")),t;let o=!0,a=new Ont({transform(A,p,h){o=!1,h(null,A)},flush(A){A()}}),n=new Mnt({autoDestroy:!1,destroy(A,p){t.destroy(),p(A)}}),u=r?S4.createBrotliDecompress():S4.createUnzip();return u.once(\"error\",A=>{if(o&&!t.readable){n.end();return}n.destroy(A)}),Unt(t,n),t.pipe(a).pipe(u).pipe(n),n}});var b4=_((pNt,Qae)=>{\"use strict\";var x4=class{constructor(e={}){if(!(e.maxSize&&e.maxSize>0))throw new TypeError(\"`maxSize` must be a number greater than 0\");this.maxSize=e.maxSize,this.onEviction=e.onEviction,this.cache=new Map,this.oldCache=new Map,this._size=0}_set(e,r){if(this.cache.set(e,r),this._size++,this._size>=this.maxSize){if(this._size=0,typeof this.onEviction==\"function\")for(let[o,a]of this.oldCache.entries())this.onEviction(o,a);this.oldCache=this.cache,this.cache=new Map}}get(e){if(this.cache.has(e))return this.cache.get(e);if(this.oldCache.has(e)){let r=this.oldCache.get(e);return this.oldCache.delete(e),this._set(e,r),r}}set(e,r){return this.cache.has(e)?this.cache.set(e,r):this._set(e,r),this}has(e){return this.cache.has(e)||this.oldCache.has(e)}peek(e){if(this.cache.has(e))return this.cache.get(e);if(this.oldCache.has(e))return this.oldCache.get(e)}delete(e){let r=this.cache.delete(e);return r&&this._size--,this.oldCache.delete(e)||r}clear(){this.cache.clear(),this.oldCache.clear(),this._size=0}*keys(){for(let[e]of this)yield e}*values(){for(let[,e]of this)yield e}*[Symbol.iterator](){for(let e of this.cache)yield e;for(let e of this.oldCache){let[r]=e;this.cache.has(r)||(yield e)}}get size(){let e=0;for(let r of this.oldCache.keys())this.cache.has(r)||e++;return Math.min(this._size+e,this.maxSize)}};Qae.exports=x4});var Q4=_((hNt,Lae)=>{\"use strict\";var _nt=ve(\"events\"),Hnt=ve(\"tls\"),qnt=ve(\"http2\"),jnt=b4(),ea=Symbol(\"currentStreamsCount\"),Fae=Symbol(\"request\"),zl=Symbol(\"cachedOriginSet\"),wy=Symbol(\"gracefullyClosing\"),Gnt=[\"maxDeflateDynamicTableSize\",\"maxSessionMemory\",\"maxHeaderListPairs\",\"maxOutstandingPings\",\"maxReservedRemoteStreams\",\"maxSendHeaderBlockLength\",\"paddingStrategy\",\"localAddress\",\"path\",\"rejectUnauthorized\",\"minDHSize\",\"ca\",\"cert\",\"clientCertEngine\",\"ciphers\",\"key\",\"pfx\",\"servername\",\"minVersion\",\"maxVersion\",\"secureProtocol\",\"crl\",\"honorCipherOrder\",\"ecdhCurve\",\"dhparam\",\"secureOptions\",\"sessionIdContext\"],Wnt=(t,e,r)=>{let o=0,a=t.length;for(;o<a;){let n=o+a>>>1;r(t[n],e)?o=n+1:a=n}return o},Ynt=(t,e)=>t.remoteSettings.maxConcurrentStreams>e.remoteSettings.maxConcurrentStreams,k4=(t,e)=>{for(let r of t)r[zl].length<e[zl].length&&r[zl].every(o=>e[zl].includes(o))&&r[ea]+e[ea]<=e.remoteSettings.maxConcurrentStreams&&Tae(r)},Knt=(t,e)=>{for(let r of t)e[zl].length<r[zl].length&&e[zl].every(o=>r[zl].includes(o))&&e[ea]+r[ea]<=r.remoteSettings.maxConcurrentStreams&&Tae(e)},Rae=({agent:t,isFree:e})=>{let r={};for(let o in t.sessions){let n=t.sessions[o].filter(u=>{let A=u[xg.kCurrentStreamsCount]<u.remoteSettings.maxConcurrentStreams;return e?A:!A});n.length!==0&&(r[o]=n)}return r},Tae=t=>{t[wy]=!0,t[ea]===0&&t.close()},xg=class t extends _nt{constructor({timeout:e=6e4,maxSessions:r=1/0,maxFreeSessions:o=10,maxCachedTlsSessions:a=100}={}){super(),this.sessions={},this.queue={},this.timeout=e,this.maxSessions=r,this.maxFreeSessions=o,this._freeSessionsCount=0,this._sessionsCount=0,this.settings={enablePush:!1},this.tlsSessionCache=new jnt({maxSize:a})}static normalizeOrigin(e,r){return typeof e==\"string\"&&(e=new URL(e)),r&&e.hostname!==r&&(e.hostname=r),e.origin}normalizeOptions(e){let r=\"\";if(e)for(let o of Gnt)e[o]&&(r+=`:${e[o]}`);return r}_tryToCreateNewSession(e,r){if(!(e in this.queue)||!(r in this.queue[e]))return;let o=this.queue[e][r];this._sessionsCount<this.maxSessions&&!o.completed&&(o.completed=!0,o())}getSession(e,r,o){return new Promise((a,n)=>{Array.isArray(o)?(o=[...o],a()):o=[{resolve:a,reject:n}];let u=this.normalizeOptions(r),A=t.normalizeOrigin(e,r&&r.servername);if(A===void 0){for(let{reject:E}of o)E(new TypeError(\"The `origin` argument needs to be a string or an URL object\"));return}if(u in this.sessions){let E=this.sessions[u],w=-1,D=-1,b;for(let C of E){let T=C.remoteSettings.maxConcurrentStreams;if(T<w)break;if(C[zl].includes(A)){let N=C[ea];if(N>=T||C[wy]||C.destroyed)continue;b||(w=T),N>D&&(b=C,D=N)}}if(b){if(o.length!==1){for(let{reject:C}of o){let T=new Error(`Expected the length of listeners to be 1, got ${o.length}.\nPlease report this to https://github.com/szmarczak/http2-wrapper/`);C(T)}return}o[0].resolve(b);return}}if(u in this.queue){if(A in this.queue[u]){this.queue[u][A].listeners.push(...o),this._tryToCreateNewSession(u,A);return}}else this.queue[u]={};let p=()=>{u in this.queue&&this.queue[u][A]===h&&(delete this.queue[u][A],Object.keys(this.queue[u]).length===0&&delete this.queue[u])},h=()=>{let E=`${A}:${u}`,w=!1;try{let D=qnt.connect(e,{createConnection:this.createConnection,settings:this.settings,session:this.tlsSessionCache.get(E),...r});D[ea]=0,D[wy]=!1;let b=()=>D[ea]<D.remoteSettings.maxConcurrentStreams,C=!0;D.socket.once(\"session\",N=>{this.tlsSessionCache.set(E,N)}),D.once(\"error\",N=>{for(let{reject:U}of o)U(N);this.tlsSessionCache.delete(E)}),D.setTimeout(this.timeout,()=>{D.destroy()}),D.once(\"close\",()=>{if(w){C&&this._freeSessionsCount--,this._sessionsCount--;let N=this.sessions[u];N.splice(N.indexOf(D),1),N.length===0&&delete this.sessions[u]}else{let N=new Error(\"Session closed without receiving a SETTINGS frame\");N.code=\"HTTP2WRAPPER_NOSETTINGS\";for(let{reject:U}of o)U(N);p()}this._tryToCreateNewSession(u,A)});let T=()=>{if(!(!(u in this.queue)||!b())){for(let N of D[zl])if(N in this.queue[u]){let{listeners:U}=this.queue[u][N];for(;U.length!==0&&b();)U.shift().resolve(D);let z=this.queue[u];if(z[N].listeners.length===0&&(delete z[N],Object.keys(z).length===0)){delete this.queue[u];break}if(!b())break}}};D.on(\"origin\",()=>{D[zl]=D.originSet,b()&&(T(),k4(this.sessions[u],D))}),D.once(\"remoteSettings\",()=>{if(D.ref(),D.unref(),this._sessionsCount++,h.destroyed){let N=new Error(\"Agent has been destroyed\");for(let U of o)U.reject(N);D.destroy();return}D[zl]=D.originSet;{let N=this.sessions;if(u in N){let U=N[u];U.splice(Wnt(U,D,Ynt),0,D)}else N[u]=[D]}this._freeSessionsCount+=1,w=!0,this.emit(\"session\",D),T(),p(),D[ea]===0&&this._freeSessionsCount>this.maxFreeSessions&&D.close(),o.length!==0&&(this.getSession(A,r,o),o.length=0),D.on(\"remoteSettings\",()=>{T(),k4(this.sessions[u],D)})}),D[Fae]=D.request,D.request=(N,U)=>{if(D[wy])throw new Error(\"The session is gracefully closing. No new streams are allowed.\");let z=D[Fae](N,U);return D.ref(),++D[ea],D[ea]===D.remoteSettings.maxConcurrentStreams&&this._freeSessionsCount--,z.once(\"close\",()=>{if(C=b(),--D[ea],!D.destroyed&&!D.closed&&(Knt(this.sessions[u],D),b()&&!D.closed)){C||(this._freeSessionsCount++,C=!0);let te=D[ea]===0;te&&D.unref(),te&&(this._freeSessionsCount>this.maxFreeSessions||D[wy])?D.close():(k4(this.sessions[u],D),T())}}),z}}catch(D){for(let b of o)b.reject(D);p()}};h.listeners=o,h.completed=!1,h.destroyed=!1,this.queue[u][A]=h,this._tryToCreateNewSession(u,A)})}request(e,r,o,a){return new Promise((n,u)=>{this.getSession(e,r,[{reject:u,resolve:A=>{try{n(A.request(o,a))}catch(p){u(p)}}}])})}createConnection(e,r){return t.connect(e,r)}static connect(e,r){r.ALPNProtocols=[\"h2\"];let o=e.port||443,a=e.hostname||e.host;return typeof r.servername>\"u\"&&(r.servername=a),Hnt.connect(o,a,r)}closeFreeSessions(){for(let e of Object.values(this.sessions))for(let r of e)r[ea]===0&&r.close()}destroy(e){for(let r of Object.values(this.sessions))for(let o of r)o.destroy(e);for(let r of Object.values(this.queue))for(let o of Object.values(r))o.destroyed=!0;this.queue={}}get freeSessions(){return Rae({agent:this,isFree:!0})}get busySessions(){return Rae({agent:this,isFree:!1})}};xg.kCurrentStreamsCount=ea;xg.kGracefullyClosing=wy;Lae.exports={Agent:xg,globalAgent:new xg}});var R4=_((gNt,Nae)=>{\"use strict\";var{Readable:Vnt}=ve(\"stream\"),F4=class extends Vnt{constructor(e,r){super({highWaterMark:r,autoDestroy:!1}),this.statusCode=null,this.statusMessage=\"\",this.httpVersion=\"2.0\",this.httpVersionMajor=2,this.httpVersionMinor=0,this.headers={},this.trailers={},this.req=null,this.aborted=!1,this.complete=!1,this.upgrade=null,this.rawHeaders=[],this.rawTrailers=[],this.socket=e,this.connection=e,this._dumped=!1}_destroy(e){this.req._request.destroy(e)}setTimeout(e,r){return this.req.setTimeout(e,r),this}_dump(){this._dumped||(this._dumped=!0,this.removeAllListeners(\"data\"),this.resume())}_read(){this.req&&this.req._request.resume()}};Nae.exports=F4});var T4=_((dNt,Oae)=>{\"use strict\";Oae.exports=t=>{let e={protocol:t.protocol,hostname:typeof t.hostname==\"string\"&&t.hostname.startsWith(\"[\")?t.hostname.slice(1,-1):t.hostname,host:t.host,hash:t.hash,search:t.search,pathname:t.pathname,href:t.href,path:`${t.pathname||\"\"}${t.search||\"\"}`};return typeof t.port==\"string\"&&t.port.length!==0&&(e.port=Number(t.port)),(t.username||t.password)&&(e.auth=`${t.username||\"\"}:${t.password||\"\"}`),e}});var Uae=_((mNt,Mae)=>{\"use strict\";Mae.exports=(t,e,r)=>{for(let o of r)t.on(o,(...a)=>e.emit(o,...a))}});var Hae=_((yNt,_ae)=>{\"use strict\";_ae.exports=t=>{switch(t){case\":method\":case\":scheme\":case\":authority\":case\":path\":return!0;default:return!1}}});var jae=_((CNt,qae)=>{\"use strict\";var By=(t,e,r)=>{qae.exports[e]=class extends t{constructor(...a){super(typeof r==\"string\"?r:r(a)),this.name=`${super.name} [${e}]`,this.code=e}}};By(TypeError,\"ERR_INVALID_ARG_TYPE\",t=>{let e=t[0].includes(\".\")?\"property\":\"argument\",r=t[1],o=Array.isArray(r);return o&&(r=`${r.slice(0,-1).join(\", \")} or ${r.slice(-1)}`),`The \"${t[0]}\" ${e} must be ${o?\"one of\":\"of\"} type ${r}. Received ${typeof t[2]}`});By(TypeError,\"ERR_INVALID_PROTOCOL\",t=>`Protocol \"${t[0]}\" not supported. Expected \"${t[1]}\"`);By(Error,\"ERR_HTTP_HEADERS_SENT\",t=>`Cannot ${t[0]} headers after they are sent to the client`);By(TypeError,\"ERR_INVALID_HTTP_TOKEN\",t=>`${t[0]} must be a valid HTTP token [${t[1]}]`);By(TypeError,\"ERR_HTTP_INVALID_HEADER_VALUE\",t=>`Invalid value \"${t[0]} for header \"${t[1]}\"`);By(TypeError,\"ERR_INVALID_CHAR\",t=>`Invalid character in ${t[0]} [${t[1]}]`)});var U4=_((INt,Jae)=>{\"use strict\";var znt=ve(\"http2\"),{Writable:Jnt}=ve(\"stream\"),{Agent:Gae,globalAgent:Xnt}=Q4(),Znt=R4(),$nt=T4(),eit=Uae(),tit=Hae(),{ERR_INVALID_ARG_TYPE:L4,ERR_INVALID_PROTOCOL:rit,ERR_HTTP_HEADERS_SENT:Wae,ERR_INVALID_HTTP_TOKEN:nit,ERR_HTTP_INVALID_HEADER_VALUE:iit,ERR_INVALID_CHAR:sit}=jae(),{HTTP2_HEADER_STATUS:Yae,HTTP2_HEADER_METHOD:Kae,HTTP2_HEADER_PATH:Vae,HTTP2_METHOD_CONNECT:oit}=znt.constants,vo=Symbol(\"headers\"),N4=Symbol(\"origin\"),O4=Symbol(\"session\"),zae=Symbol(\"options\"),Lx=Symbol(\"flushedHeaders\"),R1=Symbol(\"jobs\"),ait=/^[\\^`\\-\\w!#$%&*+.|~]+$/,lit=/[^\\t\\u0020-\\u007E\\u0080-\\u00FF]/,M4=class extends Jnt{constructor(e,r,o){super({autoDestroy:!1});let a=typeof e==\"string\"||e instanceof URL;if(a&&(e=$nt(e instanceof URL?e:new URL(e))),typeof r==\"function\"||r===void 0?(o=r,r=a?e:{...e}):r={...e,...r},r.h2session)this[O4]=r.h2session;else if(r.agent===!1)this.agent=new Gae({maxFreeSessions:0});else if(typeof r.agent>\"u\"||r.agent===null)typeof r.createConnection==\"function\"?(this.agent=new Gae({maxFreeSessions:0}),this.agent.createConnection=r.createConnection):this.agent=Xnt;else if(typeof r.agent.request==\"function\")this.agent=r.agent;else throw new L4(\"options.agent\",[\"Agent-like Object\",\"undefined\",\"false\"],r.agent);if(r.protocol&&r.protocol!==\"https:\")throw new rit(r.protocol,\"https:\");let n=r.port||r.defaultPort||this.agent&&this.agent.defaultPort||443,u=r.hostname||r.host||\"localhost\";delete r.hostname,delete r.host,delete r.port;let{timeout:A}=r;if(r.timeout=void 0,this[vo]=Object.create(null),this[R1]=[],this.socket=null,this.connection=null,this.method=r.method||\"GET\",this.path=r.path,this.res=null,this.aborted=!1,this.reusedSocket=!1,r.headers)for(let[p,h]of Object.entries(r.headers))this.setHeader(p,h);r.auth&&!(\"authorization\"in this[vo])&&(this[vo].authorization=\"Basic \"+Buffer.from(r.auth).toString(\"base64\")),r.session=r.tlsSession,r.path=r.socketPath,this[zae]=r,n===443?(this[N4]=`https://${u}`,\":authority\"in this[vo]||(this[vo][\":authority\"]=u)):(this[N4]=`https://${u}:${n}`,\":authority\"in this[vo]||(this[vo][\":authority\"]=`${u}:${n}`)),A&&this.setTimeout(A),o&&this.once(\"response\",o),this[Lx]=!1}get method(){return this[vo][Kae]}set method(e){e&&(this[vo][Kae]=e.toUpperCase())}get path(){return this[vo][Vae]}set path(e){e&&(this[vo][Vae]=e)}get _mustNotHaveABody(){return this.method===\"GET\"||this.method===\"HEAD\"||this.method===\"DELETE\"}_write(e,r,o){if(this._mustNotHaveABody){o(new Error(\"The GET, HEAD and DELETE methods must NOT have a body\"));return}this.flushHeaders();let a=()=>this._request.write(e,r,o);this._request?a():this[R1].push(a)}_final(e){if(this.destroyed)return;this.flushHeaders();let r=()=>{if(this._mustNotHaveABody){e();return}this._request.end(e)};this._request?r():this[R1].push(r)}abort(){this.res&&this.res.complete||(this.aborted||process.nextTick(()=>this.emit(\"abort\")),this.aborted=!0,this.destroy())}_destroy(e,r){this.res&&this.res._dump(),this._request&&this._request.destroy(),r(e)}async flushHeaders(){if(this[Lx]||this.destroyed)return;this[Lx]=!0;let e=this.method===oit,r=o=>{if(this._request=o,this.destroyed){o.destroy();return}e||eit(o,this,[\"timeout\",\"continue\",\"close\",\"error\"]);let a=u=>(...A)=>{!this.writable&&!this.destroyed?u(...A):this.once(\"finish\",()=>{u(...A)})};o.once(\"response\",a((u,A,p)=>{let h=new Znt(this.socket,o.readableHighWaterMark);this.res=h,h.req=this,h.statusCode=u[Yae],h.headers=u,h.rawHeaders=p,h.once(\"end\",()=>{this.aborted?(h.aborted=!0,h.emit(\"aborted\")):(h.complete=!0,h.socket=null,h.connection=null)}),e?(h.upgrade=!0,this.emit(\"connect\",h,o,Buffer.alloc(0))?this.emit(\"close\"):o.destroy()):(o.on(\"data\",E=>{!h._dumped&&!h.push(E)&&o.pause()}),o.once(\"end\",()=>{h.push(null)}),this.emit(\"response\",h)||h._dump())})),o.once(\"headers\",a(u=>this.emit(\"information\",{statusCode:u[Yae]}))),o.once(\"trailers\",a((u,A,p)=>{let{res:h}=this;h.trailers=u,h.rawTrailers=p}));let{socket:n}=o.session;this.socket=n,this.connection=n;for(let u of this[R1])u();this.emit(\"socket\",this.socket)};if(this[O4])try{r(this[O4].request(this[vo]))}catch(o){this.emit(\"error\",o)}else{this.reusedSocket=!0;try{r(await this.agent.request(this[N4],this[zae],this[vo]))}catch(o){this.emit(\"error\",o)}}}getHeader(e){if(typeof e!=\"string\")throw new L4(\"name\",\"string\",e);return this[vo][e.toLowerCase()]}get headersSent(){return this[Lx]}removeHeader(e){if(typeof e!=\"string\")throw new L4(\"name\",\"string\",e);if(this.headersSent)throw new Wae(\"remove\");delete this[vo][e.toLowerCase()]}setHeader(e,r){if(this.headersSent)throw new Wae(\"set\");if(typeof e!=\"string\"||!ait.test(e)&&!tit(e))throw new nit(\"Header name\",e);if(typeof r>\"u\")throw new iit(r,e);if(lit.test(r))throw new sit(\"header content\",e);this[vo][e.toLowerCase()]=r}setNoDelay(){}setSocketKeepAlive(){}setTimeout(e,r){let o=()=>this._request.setTimeout(e,r);return this._request?o():this[R1].push(o),this}get maxHeadersCount(){if(!this.destroyed&&this._request)return this._request.session.localSettings.maxHeaderListSize}set maxHeadersCount(e){}};Jae.exports=M4});var Zae=_((wNt,Xae)=>{\"use strict\";var cit=ve(\"tls\");Xae.exports=(t={},e=cit.connect)=>new Promise((r,o)=>{let a=!1,n,u=async()=>{await p,n.off(\"timeout\",A),n.off(\"error\",o),t.resolveSocket?(r({alpnProtocol:n.alpnProtocol,socket:n,timeout:a}),a&&(await Promise.resolve(),n.emit(\"timeout\"))):(n.destroy(),r({alpnProtocol:n.alpnProtocol,timeout:a}))},A=async()=>{a=!0,u()},p=(async()=>{try{n=await e(t,u),n.on(\"error\",o),n.once(\"timeout\",A)}catch(h){o(h)}})()})});var ele=_((BNt,$ae)=>{\"use strict\";var uit=ve(\"net\");$ae.exports=t=>{let e=t.host,r=t.headers&&t.headers.host;return r&&(r.startsWith(\"[\")?r.indexOf(\"]\")===-1?e=r:e=r.slice(1,-1):e=r.split(\":\",1)[0]),uit.isIP(e)?\"\":e}});var nle=_((vNt,H4)=>{\"use strict\";var tle=ve(\"http\"),_4=ve(\"https\"),Ait=Zae(),fit=b4(),pit=U4(),hit=ele(),git=T4(),Nx=new fit({maxSize:100}),T1=new Map,rle=(t,e,r)=>{e._httpMessage={shouldKeepAlive:!0};let o=()=>{t.emit(\"free\",e,r)};e.on(\"free\",o);let a=()=>{t.removeSocket(e,r)};e.on(\"close\",a);let n=()=>{t.removeSocket(e,r),e.off(\"close\",a),e.off(\"free\",o),e.off(\"agentRemove\",n)};e.on(\"agentRemove\",n),t.emit(\"free\",e,r)},dit=async t=>{let e=`${t.host}:${t.port}:${t.ALPNProtocols.sort()}`;if(!Nx.has(e)){if(T1.has(e))return(await T1.get(e)).alpnProtocol;let{path:r,agent:o}=t;t.path=t.socketPath;let a=Ait(t);T1.set(e,a);try{let{socket:n,alpnProtocol:u}=await a;if(Nx.set(e,u),t.path=r,u===\"h2\")n.destroy();else{let{globalAgent:A}=_4,p=_4.Agent.prototype.createConnection;o?o.createConnection===p?rle(o,n,t):n.destroy():A.createConnection===p?rle(A,n,t):n.destroy()}return T1.delete(e),u}catch(n){throw T1.delete(e),n}}return Nx.get(e)};H4.exports=async(t,e,r)=>{if((typeof t==\"string\"||t instanceof URL)&&(t=git(new URL(t))),typeof e==\"function\"&&(r=e,e=void 0),e={ALPNProtocols:[\"h2\",\"http/1.1\"],...t,...e,resolveSocket:!0},!Array.isArray(e.ALPNProtocols)||e.ALPNProtocols.length===0)throw new Error(\"The `ALPNProtocols` option must be an Array with at least one entry\");e.protocol=e.protocol||\"https:\";let o=e.protocol===\"https:\";e.host=e.hostname||e.host||\"localhost\",e.session=e.tlsSession,e.servername=e.servername||hit(e),e.port=e.port||(o?443:80),e._defaultAgent=o?_4.globalAgent:tle.globalAgent;let a=e.agent;if(a){if(a.addRequest)throw new Error(\"The `options.agent` object can contain only `http`, `https` or `http2` properties\");e.agent=a[o?\"https\":\"http\"]}return o&&await dit(e)===\"h2\"?(a&&(e.agent=a.http2),new pit(e,r)):tle.request(e,r)};H4.exports.protocolCache=Nx});var sle=_((DNt,ile)=>{\"use strict\";var mit=ve(\"http2\"),yit=Q4(),q4=U4(),Eit=R4(),Cit=nle(),Iit=(t,e,r)=>new q4(t,e,r),wit=(t,e,r)=>{let o=new q4(t,e,r);return o.end(),o};ile.exports={...mit,ClientRequest:q4,IncomingMessage:Eit,...yit,request:Iit,get:wit,auto:Cit}});var G4=_(j4=>{\"use strict\";Object.defineProperty(j4,\"__esModule\",{value:!0});var ole=Ff();j4.default=t=>ole.default.nodeStream(t)&&ole.default.function_(t.getBoundary)});var ule=_(W4=>{\"use strict\";Object.defineProperty(W4,\"__esModule\",{value:!0});var lle=ve(\"fs\"),cle=ve(\"util\"),ale=Ff(),Bit=G4(),vit=cle.promisify(lle.stat);W4.default=async(t,e)=>{if(e&&\"content-length\"in e)return Number(e[\"content-length\"]);if(!t)return 0;if(ale.default.string(t))return Buffer.byteLength(t);if(ale.default.buffer(t))return t.length;if(Bit.default(t))return cle.promisify(t.getLength.bind(t))();if(t instanceof lle.ReadStream){let{size:r}=await vit(t.path);return r===0?void 0:r}}});var K4=_(Y4=>{\"use strict\";Object.defineProperty(Y4,\"__esModule\",{value:!0});function Dit(t,e,r){let o={};for(let a of r)o[a]=(...n)=>{e.emit(a,...n)},t.on(a,o[a]);return()=>{for(let a of r)t.off(a,o[a])}}Y4.default=Dit});var Ale=_(V4=>{\"use strict\";Object.defineProperty(V4,\"__esModule\",{value:!0});V4.default=()=>{let t=[];return{once(e,r,o){e.once(r,o),t.push({origin:e,event:r,fn:o})},unhandleAll(){for(let e of t){let{origin:r,event:o,fn:a}=e;r.removeListener(o,a)}t.length=0}}}});var ple=_(L1=>{\"use strict\";Object.defineProperty(L1,\"__esModule\",{value:!0});L1.TimeoutError=void 0;var Pit=ve(\"net\"),Sit=Ale(),fle=Symbol(\"reentry\"),xit=()=>{},Ox=class extends Error{constructor(e,r){super(`Timeout awaiting '${r}' for ${e}ms`),this.event=r,this.name=\"TimeoutError\",this.code=\"ETIMEDOUT\"}};L1.TimeoutError=Ox;L1.default=(t,e,r)=>{if(fle in t)return xit;t[fle]=!0;let o=[],{once:a,unhandleAll:n}=Sit.default(),u=(w,D,b)=>{var C;let T=setTimeout(D,w,w,b);(C=T.unref)===null||C===void 0||C.call(T);let N=()=>{clearTimeout(T)};return o.push(N),N},{host:A,hostname:p}=r,h=(w,D)=>{t.destroy(new Ox(w,D))},E=()=>{for(let w of o)w();n()};if(t.once(\"error\",w=>{if(E(),t.listenerCount(\"error\")===0)throw w}),t.once(\"close\",E),a(t,\"response\",w=>{a(w,\"end\",E)}),typeof e.request<\"u\"&&u(e.request,h,\"request\"),typeof e.socket<\"u\"){let w=()=>{h(e.socket,\"socket\")};t.setTimeout(e.socket,w),o.push(()=>{t.removeListener(\"timeout\",w)})}return a(t,\"socket\",w=>{var D;let{socketPath:b}=t;if(w.connecting){let C=!!(b??Pit.isIP((D=p??A)!==null&&D!==void 0?D:\"\")!==0);if(typeof e.lookup<\"u\"&&!C&&typeof w.address().address>\"u\"){let T=u(e.lookup,h,\"lookup\");a(w,\"lookup\",T)}if(typeof e.connect<\"u\"){let T=()=>u(e.connect,h,\"connect\");C?a(w,\"connect\",T()):a(w,\"lookup\",N=>{N===null&&a(w,\"connect\",T())})}typeof e.secureConnect<\"u\"&&r.protocol===\"https:\"&&a(w,\"connect\",()=>{let T=u(e.secureConnect,h,\"secureConnect\");a(w,\"secureConnect\",T)})}if(typeof e.send<\"u\"){let C=()=>u(e.send,h,\"send\");w.connecting?a(w,\"connect\",()=>{a(t,\"upload-complete\",C())}):a(t,\"upload-complete\",C())}}),typeof e.response<\"u\"&&a(t,\"upload-complete\",()=>{let w=u(e.response,h,\"response\");a(t,\"response\",w)}),E}});var gle=_(z4=>{\"use strict\";Object.defineProperty(z4,\"__esModule\",{value:!0});var hle=Ff();z4.default=t=>{t=t;let e={protocol:t.protocol,hostname:hle.default.string(t.hostname)&&t.hostname.startsWith(\"[\")?t.hostname.slice(1,-1):t.hostname,host:t.host,hash:t.hash,search:t.search,pathname:t.pathname,href:t.href,path:`${t.pathname||\"\"}${t.search||\"\"}`};return hle.default.string(t.port)&&t.port.length>0&&(e.port=Number(t.port)),(t.username||t.password)&&(e.auth=`${t.username||\"\"}:${t.password||\"\"}`),e}});var dle=_(J4=>{\"use strict\";Object.defineProperty(J4,\"__esModule\",{value:!0});var bit=ve(\"url\"),kit=[\"protocol\",\"host\",\"hostname\",\"port\",\"pathname\",\"search\"];J4.default=(t,e)=>{var r,o;if(e.path){if(e.pathname)throw new TypeError(\"Parameters `path` and `pathname` are mutually exclusive.\");if(e.search)throw new TypeError(\"Parameters `path` and `search` are mutually exclusive.\");if(e.searchParams)throw new TypeError(\"Parameters `path` and `searchParams` are mutually exclusive.\")}if(e.search&&e.searchParams)throw new TypeError(\"Parameters `search` and `searchParams` are mutually exclusive.\");if(!t){if(!e.protocol)throw new TypeError(\"No URL protocol specified\");t=`${e.protocol}//${(o=(r=e.hostname)!==null&&r!==void 0?r:e.host)!==null&&o!==void 0?o:\"\"}`}let a=new bit.URL(t);if(e.path){let n=e.path.indexOf(\"?\");n===-1?e.pathname=e.path:(e.pathname=e.path.slice(0,n),e.search=e.path.slice(n+1)),delete e.path}for(let n of kit)e[n]&&(a[n]=e[n].toString());return a}});var mle=_(Z4=>{\"use strict\";Object.defineProperty(Z4,\"__esModule\",{value:!0});var X4=class{constructor(){this.weakMap=new WeakMap,this.map=new Map}set(e,r){typeof e==\"object\"?this.weakMap.set(e,r):this.map.set(e,r)}get(e){return typeof e==\"object\"?this.weakMap.get(e):this.map.get(e)}has(e){return typeof e==\"object\"?this.weakMap.has(e):this.map.has(e)}};Z4.default=X4});var eU=_($4=>{\"use strict\";Object.defineProperty($4,\"__esModule\",{value:!0});var Qit=async t=>{let e=[],r=0;for await(let o of t)e.push(o),r+=Buffer.byteLength(o);return Buffer.isBuffer(e[0])?Buffer.concat(e,r):Buffer.from(e.join(\"\"))};$4.default=Qit});var Ele=_(bg=>{\"use strict\";Object.defineProperty(bg,\"__esModule\",{value:!0});bg.dnsLookupIpVersionToFamily=bg.isDnsLookupIpVersion=void 0;var yle={auto:0,ipv4:4,ipv6:6};bg.isDnsLookupIpVersion=t=>t in yle;bg.dnsLookupIpVersionToFamily=t=>{if(bg.isDnsLookupIpVersion(t))return yle[t];throw new Error(\"Invalid DNS lookup IP version\")}});var tU=_(Mx=>{\"use strict\";Object.defineProperty(Mx,\"__esModule\",{value:!0});Mx.isResponseOk=void 0;Mx.isResponseOk=t=>{let{statusCode:e}=t,r=t.request.options.followRedirect?299:399;return e>=200&&e<=r||e===304}});var Ile=_(rU=>{\"use strict\";Object.defineProperty(rU,\"__esModule\",{value:!0});var Cle=new Set;rU.default=t=>{Cle.has(t)||(Cle.add(t),process.emitWarning(`Got: ${t}`,{type:\"DeprecationWarning\"}))}});var wle=_(nU=>{\"use strict\";Object.defineProperty(nU,\"__esModule\",{value:!0});var mi=Ff(),Fit=(t,e)=>{if(mi.default.null_(t.encoding))throw new TypeError(\"To get a Buffer, set `options.responseType` to `buffer` instead\");mi.assert.any([mi.default.string,mi.default.undefined],t.encoding),mi.assert.any([mi.default.boolean,mi.default.undefined],t.resolveBodyOnly),mi.assert.any([mi.default.boolean,mi.default.undefined],t.methodRewriting),mi.assert.any([mi.default.boolean,mi.default.undefined],t.isStream),mi.assert.any([mi.default.string,mi.default.undefined],t.responseType),t.responseType===void 0&&(t.responseType=\"text\");let{retry:r}=t;if(e?t.retry={...e.retry}:t.retry={calculateDelay:o=>o.computedValue,limit:0,methods:[],statusCodes:[],errorCodes:[],maxRetryAfter:void 0},mi.default.object(r)?(t.retry={...t.retry,...r},t.retry.methods=[...new Set(t.retry.methods.map(o=>o.toUpperCase()))],t.retry.statusCodes=[...new Set(t.retry.statusCodes)],t.retry.errorCodes=[...new Set(t.retry.errorCodes)]):mi.default.number(r)&&(t.retry.limit=r),mi.default.undefined(t.retry.maxRetryAfter)&&(t.retry.maxRetryAfter=Math.min(...[t.timeout.request,t.timeout.connect].filter(mi.default.number))),mi.default.object(t.pagination)){e&&(t.pagination={...e.pagination,...t.pagination});let{pagination:o}=t;if(!mi.default.function_(o.transform))throw new Error(\"`options.pagination.transform` must be implemented\");if(!mi.default.function_(o.shouldContinue))throw new Error(\"`options.pagination.shouldContinue` must be implemented\");if(!mi.default.function_(o.filter))throw new TypeError(\"`options.pagination.filter` must be implemented\");if(!mi.default.function_(o.paginate))throw new Error(\"`options.pagination.paginate` must be implemented\")}return t.responseType===\"json\"&&t.headers.accept===void 0&&(t.headers.accept=\"application/json\"),t};nU.default=Fit});var Ble=_(N1=>{\"use strict\";Object.defineProperty(N1,\"__esModule\",{value:!0});N1.retryAfterStatusCodes=void 0;N1.retryAfterStatusCodes=new Set([413,429,503]);var Rit=({attemptCount:t,retryOptions:e,error:r,retryAfter:o})=>{if(t>e.limit)return 0;let a=e.methods.includes(r.options.method),n=e.errorCodes.includes(r.code),u=r.response&&e.statusCodes.includes(r.response.statusCode);if(!a||!n&&!u)return 0;if(r.response){if(o)return e.maxRetryAfter===void 0||o>e.maxRetryAfter?0:o;if(r.response.statusCode===413)return 0}let A=Math.random()*100;return 2**(t-1)*1e3+A};N1.default=Rit});var U1=_(Qn=>{\"use strict\";Object.defineProperty(Qn,\"__esModule\",{value:!0});Qn.UnsupportedProtocolError=Qn.ReadError=Qn.TimeoutError=Qn.UploadError=Qn.CacheError=Qn.HTTPError=Qn.MaxRedirectsError=Qn.RequestError=Qn.setNonEnumerableProperties=Qn.knownHookEvents=Qn.withoutBody=Qn.kIsNormalizedAlready=void 0;var vle=ve(\"util\"),Dle=ve(\"stream\"),Tit=ve(\"fs\"),uh=ve(\"url\"),Ple=ve(\"http\"),iU=ve(\"http\"),Lit=ve(\"https\"),Nit=_oe(),Oit=Koe(),Sle=Pae(),Mit=kae(),Uit=sle(),_it=Rx(),at=Ff(),Hit=ule(),xle=G4(),qit=K4(),ble=ple(),jit=gle(),kle=dle(),Git=mle(),Wit=eU(),Qle=Ele(),Yit=tU(),Ah=Ile(),Kit=wle(),Vit=Ble(),sU,Ys=Symbol(\"request\"),Hx=Symbol(\"response\"),vy=Symbol(\"responseSize\"),Dy=Symbol(\"downloadedSize\"),Py=Symbol(\"bodySize\"),Sy=Symbol(\"uploadedSize\"),Ux=Symbol(\"serverResponsesPiped\"),Fle=Symbol(\"unproxyEvents\"),Rle=Symbol(\"isFromCache\"),oU=Symbol(\"cancelTimeouts\"),Tle=Symbol(\"startedReading\"),xy=Symbol(\"stopReading\"),_x=Symbol(\"triggerRead\"),fh=Symbol(\"body\"),O1=Symbol(\"jobs\"),Lle=Symbol(\"originalResponse\"),Nle=Symbol(\"retryTimeout\");Qn.kIsNormalizedAlready=Symbol(\"isNormalizedAlready\");var zit=at.default.string(process.versions.brotli);Qn.withoutBody=new Set([\"GET\",\"HEAD\"]);Qn.knownHookEvents=[\"init\",\"beforeRequest\",\"beforeRedirect\",\"beforeError\",\"beforeRetry\",\"afterResponse\"];function Jit(t){for(let e in t){let r=t[e];if(!at.default.string(r)&&!at.default.number(r)&&!at.default.boolean(r)&&!at.default.null_(r)&&!at.default.undefined(r))throw new TypeError(`The \\`searchParams\\` value '${String(r)}' must be a string, number, boolean or null`)}}function Xit(t){return at.default.object(t)&&!(\"statusCode\"in t)}var aU=new Git.default,Zit=async t=>new Promise((e,r)=>{let o=a=>{r(a)};t.pending||e(),t.once(\"error\",o),t.once(\"ready\",()=>{t.off(\"error\",o),e()})}),$it=new Set([300,301,302,303,304,307,308]),est=[\"context\",\"body\",\"json\",\"form\"];Qn.setNonEnumerableProperties=(t,e)=>{let r={};for(let o of t)if(o)for(let a of est)a in o&&(r[a]={writable:!0,configurable:!0,enumerable:!1,value:o[a]});Object.defineProperties(e,r)};var Ji=class extends Error{constructor(e,r,o){var a;if(super(e),Error.captureStackTrace(this,this.constructor),this.name=\"RequestError\",this.code=r.code,o instanceof Vx?(Object.defineProperty(this,\"request\",{enumerable:!1,value:o}),Object.defineProperty(this,\"response\",{enumerable:!1,value:o[Hx]}),Object.defineProperty(this,\"options\",{enumerable:!1,value:o.options})):Object.defineProperty(this,\"options\",{enumerable:!1,value:o}),this.timings=(a=this.request)===null||a===void 0?void 0:a.timings,at.default.string(r.stack)&&at.default.string(this.stack)){let n=this.stack.indexOf(this.message)+this.message.length,u=this.stack.slice(n).split(`\n`).reverse(),A=r.stack.slice(r.stack.indexOf(r.message)+r.message.length).split(`\n`).reverse();for(;A.length!==0&&A[0]===u[0];)u.shift();this.stack=`${this.stack.slice(0,n)}${u.reverse().join(`\n`)}${A.reverse().join(`\n`)}`}}};Qn.RequestError=Ji;var qx=class extends Ji{constructor(e){super(`Redirected ${e.options.maxRedirects} times. Aborting.`,{},e),this.name=\"MaxRedirectsError\"}};Qn.MaxRedirectsError=qx;var jx=class extends Ji{constructor(e){super(`Response code ${e.statusCode} (${e.statusMessage})`,{},e.request),this.name=\"HTTPError\"}};Qn.HTTPError=jx;var Gx=class extends Ji{constructor(e,r){super(e.message,e,r),this.name=\"CacheError\"}};Qn.CacheError=Gx;var Wx=class extends Ji{constructor(e,r){super(e.message,e,r),this.name=\"UploadError\"}};Qn.UploadError=Wx;var Yx=class extends Ji{constructor(e,r,o){super(e.message,e,o),this.name=\"TimeoutError\",this.event=e.event,this.timings=r}};Qn.TimeoutError=Yx;var M1=class extends Ji{constructor(e,r){super(e.message,e,r),this.name=\"ReadError\"}};Qn.ReadError=M1;var Kx=class extends Ji{constructor(e){super(`Unsupported protocol \"${e.url.protocol}\"`,{},e),this.name=\"UnsupportedProtocolError\"}};Qn.UnsupportedProtocolError=Kx;var tst=[\"socket\",\"connect\",\"continue\",\"information\",\"upgrade\",\"timeout\"],Vx=class extends Dle.Duplex{constructor(e,r={},o){super({autoDestroy:!1,highWaterMark:0}),this[Dy]=0,this[Sy]=0,this.requestInitialized=!1,this[Ux]=new Set,this.redirects=[],this[xy]=!1,this[_x]=!1,this[O1]=[],this.retryCount=0,this._progressCallbacks=[];let a=()=>this._unlockWrite(),n=()=>this._lockWrite();this.on(\"pipe\",h=>{h.prependListener(\"data\",a),h.on(\"data\",n),h.prependListener(\"end\",a),h.on(\"end\",n)}),this.on(\"unpipe\",h=>{h.off(\"data\",a),h.off(\"data\",n),h.off(\"end\",a),h.off(\"end\",n)}),this.on(\"pipe\",h=>{h instanceof iU.IncomingMessage&&(this.options.headers={...h.headers,...this.options.headers})});let{json:u,body:A,form:p}=r;if((u||A||p)&&this._lockWrite(),Qn.kIsNormalizedAlready in r)this.options=r;else try{this.options=this.constructor.normalizeArguments(e,r,o)}catch(h){at.default.nodeStream(r.body)&&r.body.destroy(),this.destroy(h);return}(async()=>{var h;try{this.options.body instanceof Tit.ReadStream&&await Zit(this.options.body);let{url:E}=this.options;if(!E)throw new TypeError(\"Missing `url` property\");if(this.requestUrl=E.toString(),decodeURI(this.requestUrl),await this._finalizeBody(),await this._makeRequest(),this.destroyed){(h=this[Ys])===null||h===void 0||h.destroy();return}for(let w of this[O1])w();this[O1].length=0,this.requestInitialized=!0}catch(E){if(E instanceof Ji){this._beforeError(E);return}this.destroyed||this.destroy(E)}})()}static normalizeArguments(e,r,o){var a,n,u,A,p;let h=r;if(at.default.object(e)&&!at.default.urlInstance(e))r={...o,...e,...r};else{if(e&&r&&r.url!==void 0)throw new TypeError(\"The `url` option is mutually exclusive with the `input` argument\");r={...o,...r},e!==void 0&&(r.url=e),at.default.urlInstance(r.url)&&(r.url=new uh.URL(r.url.toString()))}if(r.cache===!1&&(r.cache=void 0),r.dnsCache===!1&&(r.dnsCache=void 0),at.assert.any([at.default.string,at.default.undefined],r.method),at.assert.any([at.default.object,at.default.undefined],r.headers),at.assert.any([at.default.string,at.default.urlInstance,at.default.undefined],r.prefixUrl),at.assert.any([at.default.object,at.default.undefined],r.cookieJar),at.assert.any([at.default.object,at.default.string,at.default.undefined],r.searchParams),at.assert.any([at.default.object,at.default.string,at.default.undefined],r.cache),at.assert.any([at.default.object,at.default.number,at.default.undefined],r.timeout),at.assert.any([at.default.object,at.default.undefined],r.context),at.assert.any([at.default.object,at.default.undefined],r.hooks),at.assert.any([at.default.boolean,at.default.undefined],r.decompress),at.assert.any([at.default.boolean,at.default.undefined],r.ignoreInvalidCookies),at.assert.any([at.default.boolean,at.default.undefined],r.followRedirect),at.assert.any([at.default.number,at.default.undefined],r.maxRedirects),at.assert.any([at.default.boolean,at.default.undefined],r.throwHttpErrors),at.assert.any([at.default.boolean,at.default.undefined],r.http2),at.assert.any([at.default.boolean,at.default.undefined],r.allowGetBody),at.assert.any([at.default.string,at.default.undefined],r.localAddress),at.assert.any([Qle.isDnsLookupIpVersion,at.default.undefined],r.dnsLookupIpVersion),at.assert.any([at.default.object,at.default.undefined],r.https),at.assert.any([at.default.boolean,at.default.undefined],r.rejectUnauthorized),r.https&&(at.assert.any([at.default.boolean,at.default.undefined],r.https.rejectUnauthorized),at.assert.any([at.default.function_,at.default.undefined],r.https.checkServerIdentity),at.assert.any([at.default.string,at.default.object,at.default.array,at.default.undefined],r.https.certificateAuthority),at.assert.any([at.default.string,at.default.object,at.default.array,at.default.undefined],r.https.key),at.assert.any([at.default.string,at.default.object,at.default.array,at.default.undefined],r.https.certificate),at.assert.any([at.default.string,at.default.undefined],r.https.passphrase),at.assert.any([at.default.string,at.default.buffer,at.default.array,at.default.undefined],r.https.pfx)),at.assert.any([at.default.object,at.default.undefined],r.cacheOptions),at.default.string(r.method)?r.method=r.method.toUpperCase():r.method=\"GET\",r.headers===o?.headers?r.headers={...r.headers}:r.headers=_it({...o?.headers,...r.headers}),\"slashes\"in r)throw new TypeError(\"The legacy `url.Url` has been deprecated. Use `URL` instead.\");if(\"auth\"in r)throw new TypeError(\"Parameter `auth` is deprecated. Use `username` / `password` instead.\");if(\"searchParams\"in r&&r.searchParams&&r.searchParams!==o?.searchParams){let b;if(at.default.string(r.searchParams)||r.searchParams instanceof uh.URLSearchParams)b=new uh.URLSearchParams(r.searchParams);else{Jit(r.searchParams),b=new uh.URLSearchParams;for(let C in r.searchParams){let T=r.searchParams[C];T===null?b.append(C,\"\"):T!==void 0&&b.append(C,T)}}(a=o?.searchParams)===null||a===void 0||a.forEach((C,T)=>{b.has(T)||b.append(T,C)}),r.searchParams=b}if(r.username=(n=r.username)!==null&&n!==void 0?n:\"\",r.password=(u=r.password)!==null&&u!==void 0?u:\"\",at.default.undefined(r.prefixUrl)?r.prefixUrl=(A=o?.prefixUrl)!==null&&A!==void 0?A:\"\":(r.prefixUrl=r.prefixUrl.toString(),r.prefixUrl!==\"\"&&!r.prefixUrl.endsWith(\"/\")&&(r.prefixUrl+=\"/\")),at.default.string(r.url)){if(r.url.startsWith(\"/\"))throw new Error(\"`input` must not start with a slash when using `prefixUrl`\");r.url=kle.default(r.prefixUrl+r.url,r)}else(at.default.undefined(r.url)&&r.prefixUrl!==\"\"||r.protocol)&&(r.url=kle.default(r.prefixUrl,r));if(r.url){\"port\"in r&&delete r.port;let{prefixUrl:b}=r;Object.defineProperty(r,\"prefixUrl\",{set:T=>{let N=r.url;if(!N.href.startsWith(T))throw new Error(`Cannot change \\`prefixUrl\\` from ${b} to ${T}: ${N.href}`);r.url=new uh.URL(T+N.href.slice(b.length)),b=T},get:()=>b});let{protocol:C}=r.url;if(C===\"unix:\"&&(C=\"http:\",r.url=new uh.URL(`http://unix${r.url.pathname}${r.url.search}`)),r.searchParams&&(r.url.search=r.searchParams.toString()),C!==\"http:\"&&C!==\"https:\")throw new Kx(r);r.username===\"\"?r.username=r.url.username:r.url.username=r.username,r.password===\"\"?r.password=r.url.password:r.url.password=r.password}let{cookieJar:E}=r;if(E){let{setCookie:b,getCookieString:C}=E;at.assert.function_(b),at.assert.function_(C),b.length===4&&C.length===0&&(b=vle.promisify(b.bind(r.cookieJar)),C=vle.promisify(C.bind(r.cookieJar)),r.cookieJar={setCookie:b,getCookieString:C})}let{cache:w}=r;if(w&&(aU.has(w)||aU.set(w,new Sle((b,C)=>{let T=b[Ys](b,C);return at.default.promise(T)&&(T.once=(N,U)=>{if(N===\"error\")T.catch(U);else if(N===\"abort\")(async()=>{try{(await T).once(\"abort\",U)}catch{}})();else throw new Error(`Unknown HTTP2 promise event: ${N}`);return T}),T},w))),r.cacheOptions={...r.cacheOptions},r.dnsCache===!0)sU||(sU=new Oit.default),r.dnsCache=sU;else if(!at.default.undefined(r.dnsCache)&&!r.dnsCache.lookup)throw new TypeError(`Parameter \\`dnsCache\\` must be a CacheableLookup instance or a boolean, got ${at.default(r.dnsCache)}`);at.default.number(r.timeout)?r.timeout={request:r.timeout}:o&&r.timeout!==o.timeout?r.timeout={...o.timeout,...r.timeout}:r.timeout={...r.timeout},r.context||(r.context={});let D=r.hooks===o?.hooks;r.hooks={...r.hooks};for(let b of Qn.knownHookEvents)if(b in r.hooks)if(at.default.array(r.hooks[b]))r.hooks[b]=[...r.hooks[b]];else throw new TypeError(`Parameter \\`${b}\\` must be an Array, got ${at.default(r.hooks[b])}`);else r.hooks[b]=[];if(o&&!D)for(let b of Qn.knownHookEvents)o.hooks[b].length>0&&(r.hooks[b]=[...o.hooks[b],...r.hooks[b]]);if(\"family\"in r&&Ah.default('\"options.family\" was never documented, please use \"options.dnsLookupIpVersion\"'),o?.https&&(r.https={...o.https,...r.https}),\"rejectUnauthorized\"in r&&Ah.default('\"options.rejectUnauthorized\" is now deprecated, please use \"options.https.rejectUnauthorized\"'),\"checkServerIdentity\"in r&&Ah.default('\"options.checkServerIdentity\" was never documented, please use \"options.https.checkServerIdentity\"'),\"ca\"in r&&Ah.default('\"options.ca\" was never documented, please use \"options.https.certificateAuthority\"'),\"key\"in r&&Ah.default('\"options.key\" was never documented, please use \"options.https.key\"'),\"cert\"in r&&Ah.default('\"options.cert\" was never documented, please use \"options.https.certificate\"'),\"passphrase\"in r&&Ah.default('\"options.passphrase\" was never documented, please use \"options.https.passphrase\"'),\"pfx\"in r&&Ah.default('\"options.pfx\" was never documented, please use \"options.https.pfx\"'),\"followRedirects\"in r)throw new TypeError(\"The `followRedirects` option does not exist. Use `followRedirect` instead.\");if(r.agent){for(let b in r.agent)if(b!==\"http\"&&b!==\"https\"&&b!==\"http2\")throw new TypeError(`Expected the \\`options.agent\\` properties to be \\`http\\`, \\`https\\` or \\`http2\\`, got \\`${b}\\``)}return r.maxRedirects=(p=r.maxRedirects)!==null&&p!==void 0?p:0,Qn.setNonEnumerableProperties([o,h],r),Kit.default(r,o)}_lockWrite(){let e=()=>{throw new TypeError(\"The payload has been already provided\")};this.write=e,this.end=e}_unlockWrite(){this.write=super.write,this.end=super.end}async _finalizeBody(){let{options:e}=this,{headers:r}=e,o=!at.default.undefined(e.form),a=!at.default.undefined(e.json),n=!at.default.undefined(e.body),u=o||a||n,A=Qn.withoutBody.has(e.method)&&!(e.method===\"GET\"&&e.allowGetBody);if(this._cannotHaveBody=A,u){if(A)throw new TypeError(`The \\`${e.method}\\` method cannot be used with a body`);if([n,o,a].filter(p=>p).length>1)throw new TypeError(\"The `body`, `json` and `form` options are mutually exclusive\");if(n&&!(e.body instanceof Dle.Readable)&&!at.default.string(e.body)&&!at.default.buffer(e.body)&&!xle.default(e.body))throw new TypeError(\"The `body` option must be a stream.Readable, string or Buffer\");if(o&&!at.default.object(e.form))throw new TypeError(\"The `form` option must be an Object\");{let p=!at.default.string(r[\"content-type\"]);n?(xle.default(e.body)&&p&&(r[\"content-type\"]=`multipart/form-data; boundary=${e.body.getBoundary()}`),this[fh]=e.body):o?(p&&(r[\"content-type\"]=\"application/x-www-form-urlencoded\"),this[fh]=new uh.URLSearchParams(e.form).toString()):(p&&(r[\"content-type\"]=\"application/json\"),this[fh]=e.stringifyJson(e.json));let h=await Hit.default(this[fh],e.headers);at.default.undefined(r[\"content-length\"])&&at.default.undefined(r[\"transfer-encoding\"])&&!A&&!at.default.undefined(h)&&(r[\"content-length\"]=String(h))}}else A?this._lockWrite():this._unlockWrite();this[Py]=Number(r[\"content-length\"])||void 0}async _onResponseBase(e){let{options:r}=this,{url:o}=r;this[Lle]=e,r.decompress&&(e=Mit(e));let a=e.statusCode,n=e;n.statusMessage=n.statusMessage?n.statusMessage:Ple.STATUS_CODES[a],n.url=r.url.toString(),n.requestUrl=this.requestUrl,n.redirectUrls=this.redirects,n.request=this,n.isFromCache=e.fromCache||!1,n.ip=this.ip,n.retryCount=this.retryCount,this[Rle]=n.isFromCache,this[vy]=Number(e.headers[\"content-length\"])||void 0,this[Hx]=e,e.once(\"end\",()=>{this[vy]=this[Dy],this.emit(\"downloadProgress\",this.downloadProgress)}),e.once(\"error\",A=>{e.destroy(),this._beforeError(new M1(A,this))}),e.once(\"aborted\",()=>{this._beforeError(new M1({name:\"Error\",message:\"The server aborted pending request\",code:\"ECONNRESET\"},this))}),this.emit(\"downloadProgress\",this.downloadProgress);let u=e.headers[\"set-cookie\"];if(at.default.object(r.cookieJar)&&u){let A=u.map(async p=>r.cookieJar.setCookie(p,o.toString()));r.ignoreInvalidCookies&&(A=A.map(async p=>p.catch(()=>{})));try{await Promise.all(A)}catch(p){this._beforeError(p);return}}if(r.followRedirect&&e.headers.location&&$it.has(a)){if(e.resume(),this[Ys]&&(this[oU](),delete this[Ys],this[Fle]()),(a===303&&r.method!==\"GET\"&&r.method!==\"HEAD\"||!r.methodRewriting)&&(r.method=\"GET\",\"body\"in r&&delete r.body,\"json\"in r&&delete r.json,\"form\"in r&&delete r.form,this[fh]=void 0,delete r.headers[\"content-length\"]),this.redirects.length>=r.maxRedirects){this._beforeError(new qx(this));return}try{let p=Buffer.from(e.headers.location,\"binary\").toString(),h=new uh.URL(p,o),E=h.toString();decodeURI(E),h.hostname!==o.hostname||h.port!==o.port?(\"host\"in r.headers&&delete r.headers.host,\"cookie\"in r.headers&&delete r.headers.cookie,\"authorization\"in r.headers&&delete r.headers.authorization,(r.username||r.password)&&(r.username=\"\",r.password=\"\")):(h.username=r.username,h.password=r.password),this.redirects.push(E),r.url=h;for(let w of r.hooks.beforeRedirect)await w(r,n);this.emit(\"redirect\",n,r),await this._makeRequest()}catch(p){this._beforeError(p);return}return}if(r.isStream&&r.throwHttpErrors&&!Yit.isResponseOk(n)){this._beforeError(new jx(n));return}e.on(\"readable\",()=>{this[_x]&&this._read()}),this.on(\"resume\",()=>{e.resume()}),this.on(\"pause\",()=>{e.pause()}),e.once(\"end\",()=>{this.push(null)}),this.emit(\"response\",e);for(let A of this[Ux])if(!A.headersSent){for(let p in e.headers){let h=r.decompress?p!==\"content-encoding\":!0,E=e.headers[p];h&&A.setHeader(p,E)}A.statusCode=a}}async _onResponse(e){try{await this._onResponseBase(e)}catch(r){this._beforeError(r)}}_onRequest(e){let{options:r}=this,{timeout:o,url:a}=r;Nit.default(e),this[oU]=ble.default(e,o,a);let n=r.cache?\"cacheableResponse\":\"response\";e.once(n,p=>{this._onResponse(p)}),e.once(\"error\",p=>{var h;e.destroy(),(h=e.res)===null||h===void 0||h.removeAllListeners(\"end\"),p=p instanceof ble.TimeoutError?new Yx(p,this.timings,this):new Ji(p.message,p,this),this._beforeError(p)}),this[Fle]=qit.default(e,this,tst),this[Ys]=e,this.emit(\"uploadProgress\",this.uploadProgress);let u=this[fh],A=this.redirects.length===0?this:e;at.default.nodeStream(u)?(u.pipe(A),u.once(\"error\",p=>{this._beforeError(new Wx(p,this))})):(this._unlockWrite(),at.default.undefined(u)?(this._cannotHaveBody||this._noPipe)&&(A.end(),this._lockWrite()):(this._writeRequest(u,void 0,()=>{}),A.end(),this._lockWrite())),this.emit(\"request\",e)}async _createCacheableRequest(e,r){return new Promise((o,a)=>{Object.assign(r,jit.default(e)),delete r.url;let n,u=aU.get(r.cache)(r,async A=>{A._readableState.autoDestroy=!1,n&&(await n).emit(\"cacheableResponse\",A),o(A)});r.url=e,u.once(\"error\",a),u.once(\"request\",async A=>{n=A,o(n)})})}async _makeRequest(){var e,r,o,a,n;let{options:u}=this,{headers:A}=u;for(let U in A)if(at.default.undefined(A[U]))delete A[U];else if(at.default.null_(A[U]))throw new TypeError(`Use \\`undefined\\` instead of \\`null\\` to delete the \\`${U}\\` header`);if(u.decompress&&at.default.undefined(A[\"accept-encoding\"])&&(A[\"accept-encoding\"]=zit?\"gzip, deflate, br\":\"gzip, deflate\"),u.cookieJar){let U=await u.cookieJar.getCookieString(u.url.toString());at.default.nonEmptyString(U)&&(u.headers.cookie=U)}for(let U of u.hooks.beforeRequest){let z=await U(u);if(!at.default.undefined(z)){u.request=()=>z;break}}u.body&&this[fh]!==u.body&&(this[fh]=u.body);let{agent:p,request:h,timeout:E,url:w}=u;if(u.dnsCache&&!(\"lookup\"in u)&&(u.lookup=u.dnsCache.lookup),w.hostname===\"unix\"){let U=/(?<socketPath>.+?):(?<path>.+)/.exec(`${w.pathname}${w.search}`);if(U?.groups){let{socketPath:z,path:te}=U.groups;Object.assign(u,{socketPath:z,path:te,host:\"\"})}}let D=w.protocol===\"https:\",b;u.http2?b=Uit.auto:b=D?Lit.request:Ple.request;let C=(e=u.request)!==null&&e!==void 0?e:b,T=u.cache?this._createCacheableRequest:C;p&&!u.http2&&(u.agent=p[D?\"https\":\"http\"]),u[Ys]=C,delete u.request,delete u.timeout;let N=u;if(N.shared=(r=u.cacheOptions)===null||r===void 0?void 0:r.shared,N.cacheHeuristic=(o=u.cacheOptions)===null||o===void 0?void 0:o.cacheHeuristic,N.immutableMinTimeToLive=(a=u.cacheOptions)===null||a===void 0?void 0:a.immutableMinTimeToLive,N.ignoreCargoCult=(n=u.cacheOptions)===null||n===void 0?void 0:n.ignoreCargoCult,u.dnsLookupIpVersion!==void 0)try{N.family=Qle.dnsLookupIpVersionToFamily(u.dnsLookupIpVersion)}catch{throw new Error(\"Invalid `dnsLookupIpVersion` option value\")}u.https&&(\"rejectUnauthorized\"in u.https&&(N.rejectUnauthorized=u.https.rejectUnauthorized),u.https.checkServerIdentity&&(N.checkServerIdentity=u.https.checkServerIdentity),u.https.certificateAuthority&&(N.ca=u.https.certificateAuthority),u.https.certificate&&(N.cert=u.https.certificate),u.https.key&&(N.key=u.https.key),u.https.passphrase&&(N.passphrase=u.https.passphrase),u.https.pfx&&(N.pfx=u.https.pfx));try{let U=await T(w,N);at.default.undefined(U)&&(U=b(w,N)),u.request=h,u.timeout=E,u.agent=p,u.https&&(\"rejectUnauthorized\"in u.https&&delete N.rejectUnauthorized,u.https.checkServerIdentity&&delete N.checkServerIdentity,u.https.certificateAuthority&&delete N.ca,u.https.certificate&&delete N.cert,u.https.key&&delete N.key,u.https.passphrase&&delete N.passphrase,u.https.pfx&&delete N.pfx),Xit(U)?this._onRequest(U):this.writable?(this.once(\"finish\",()=>{this._onResponse(U)}),this._unlockWrite(),this.end(),this._lockWrite()):this._onResponse(U)}catch(U){throw U instanceof Sle.CacheError?new Gx(U,this):new Ji(U.message,U,this)}}async _error(e){try{for(let r of this.options.hooks.beforeError)e=await r(e)}catch(r){e=new Ji(r.message,r,this)}this.destroy(e)}_beforeError(e){if(this[xy])return;let{options:r}=this,o=this.retryCount+1;this[xy]=!0,e instanceof Ji||(e=new Ji(e.message,e,this));let a=e,{response:n}=a;(async()=>{if(n&&!n.body){n.setEncoding(this._readableState.encoding);try{n.rawBody=await Wit.default(n),n.body=n.rawBody.toString()}catch{}}if(this.listenerCount(\"retry\")!==0){let u;try{let A;n&&\"retry-after\"in n.headers&&(A=Number(n.headers[\"retry-after\"]),Number.isNaN(A)?(A=Date.parse(n.headers[\"retry-after\"])-Date.now(),A<=0&&(A=1)):A*=1e3),u=await r.retry.calculateDelay({attemptCount:o,retryOptions:r.retry,error:a,retryAfter:A,computedValue:Vit.default({attemptCount:o,retryOptions:r.retry,error:a,retryAfter:A,computedValue:0})})}catch(A){this._error(new Ji(A.message,A,this));return}if(u){let A=async()=>{try{for(let p of this.options.hooks.beforeRetry)await p(this.options,a,o)}catch(p){this._error(new Ji(p.message,e,this));return}this.destroyed||(this.destroy(),this.emit(\"retry\",o,e))};this[Nle]=setTimeout(A,u);return}}this._error(a)})()}_read(){this[_x]=!0;let e=this[Hx];if(e&&!this[xy]){e.readableLength&&(this[_x]=!1);let r;for(;(r=e.read())!==null;){this[Dy]+=r.length,this[Tle]=!0;let o=this.downloadProgress;o.percent<1&&this.emit(\"downloadProgress\",o),this.push(r)}}}_write(e,r,o){let a=()=>{this._writeRequest(e,r,o)};this.requestInitialized?a():this[O1].push(a)}_writeRequest(e,r,o){this[Ys].destroyed||(this._progressCallbacks.push(()=>{this[Sy]+=Buffer.byteLength(e,r);let a=this.uploadProgress;a.percent<1&&this.emit(\"uploadProgress\",a)}),this[Ys].write(e,r,a=>{!a&&this._progressCallbacks.length>0&&this._progressCallbacks.shift()(),o(a)}))}_final(e){let r=()=>{for(;this._progressCallbacks.length!==0;)this._progressCallbacks.shift()();if(!(Ys in this)){e();return}if(this[Ys].destroyed){e();return}this[Ys].end(o=>{o||(this[Py]=this[Sy],this.emit(\"uploadProgress\",this.uploadProgress),this[Ys].emit(\"upload-complete\")),e(o)})};this.requestInitialized?r():this[O1].push(r)}_destroy(e,r){var o;this[xy]=!0,clearTimeout(this[Nle]),Ys in this&&(this[oU](),!((o=this[Hx])===null||o===void 0)&&o.complete||this[Ys].destroy()),e!==null&&!at.default.undefined(e)&&!(e instanceof Ji)&&(e=new Ji(e.message,e,this)),r(e)}get _isAboutToError(){return this[xy]}get ip(){var e;return(e=this.socket)===null||e===void 0?void 0:e.remoteAddress}get aborted(){var e,r,o;return((r=(e=this[Ys])===null||e===void 0?void 0:e.destroyed)!==null&&r!==void 0?r:this.destroyed)&&!(!((o=this[Lle])===null||o===void 0)&&o.complete)}get socket(){var e,r;return(r=(e=this[Ys])===null||e===void 0?void 0:e.socket)!==null&&r!==void 0?r:void 0}get downloadProgress(){let e;return this[vy]?e=this[Dy]/this[vy]:this[vy]===this[Dy]?e=1:e=0,{percent:e,transferred:this[Dy],total:this[vy]}}get uploadProgress(){let e;return this[Py]?e=this[Sy]/this[Py]:this[Py]===this[Sy]?e=1:e=0,{percent:e,transferred:this[Sy],total:this[Py]}}get timings(){var e;return(e=this[Ys])===null||e===void 0?void 0:e.timings}get isFromCache(){return this[Rle]}pipe(e,r){if(this[Tle])throw new Error(\"Failed to pipe. The response has been emitted already.\");return e instanceof iU.ServerResponse&&this[Ux].add(e),super.pipe(e,r)}unpipe(e){return e instanceof iU.ServerResponse&&this[Ux].delete(e),super.unpipe(e),this}};Qn.default=Vx});var _1=_(Jc=>{\"use strict\";var rst=Jc&&Jc.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),nst=Jc&&Jc.__exportStar||function(t,e){for(var r in t)r!==\"default\"&&!Object.prototype.hasOwnProperty.call(e,r)&&rst(e,t,r)};Object.defineProperty(Jc,\"__esModule\",{value:!0});Jc.CancelError=Jc.ParseError=void 0;var Ole=U1(),lU=class extends Ole.RequestError{constructor(e,r){let{options:o}=r.request;super(`${e.message} in \"${o.url.toString()}\"`,e,r.request),this.name=\"ParseError\"}};Jc.ParseError=lU;var cU=class extends Ole.RequestError{constructor(e){super(\"Promise was canceled\",{},e),this.name=\"CancelError\"}get isCanceled(){return!0}};Jc.CancelError=cU;nst(U1(),Jc)});var Ule=_(uU=>{\"use strict\";Object.defineProperty(uU,\"__esModule\",{value:!0});var Mle=_1(),ist=(t,e,r,o)=>{let{rawBody:a}=t;try{if(e===\"text\")return a.toString(o);if(e===\"json\")return a.length===0?\"\":r(a.toString());if(e===\"buffer\")return a;throw new Mle.ParseError({message:`Unknown body type '${e}'`,name:\"Error\"},t)}catch(n){throw new Mle.ParseError(n,t)}};uU.default=ist});var AU=_(ph=>{\"use strict\";var sst=ph&&ph.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),ost=ph&&ph.__exportStar||function(t,e){for(var r in t)r!==\"default\"&&!Object.prototype.hasOwnProperty.call(e,r)&&sst(e,t,r)};Object.defineProperty(ph,\"__esModule\",{value:!0});var ast=ve(\"events\"),lst=Ff(),cst=Moe(),zx=_1(),_le=Ule(),Hle=U1(),ust=K4(),Ast=eU(),qle=tU(),fst=[\"request\",\"response\",\"redirect\",\"uploadProgress\",\"downloadProgress\"];function jle(t){let e,r,o=new ast.EventEmitter,a=new cst((u,A,p)=>{let h=E=>{let w=new Hle.default(void 0,t);w.retryCount=E,w._noPipe=!0,p(()=>w.destroy()),p.shouldReject=!1,p(()=>A(new zx.CancelError(w))),e=w,w.once(\"response\",async C=>{var T;if(C.retryCount=E,C.request.aborted)return;let N;try{N=await Ast.default(w),C.rawBody=N}catch{return}if(w._isAboutToError)return;let U=((T=C.headers[\"content-encoding\"])!==null&&T!==void 0?T:\"\").toLowerCase(),z=[\"gzip\",\"deflate\",\"br\"].includes(U),{options:te}=w;if(z&&!te.decompress)C.body=N;else try{C.body=_le.default(C,te.responseType,te.parseJson,te.encoding)}catch(le){if(C.body=N.toString(),qle.isResponseOk(C)){w._beforeError(le);return}}try{for(let[le,ce]of te.hooks.afterResponse.entries())C=await ce(C,async ue=>{let Ie=Hle.default.normalizeArguments(void 0,{...ue,retry:{calculateDelay:()=>0},throwHttpErrors:!1,resolveBodyOnly:!1},te);Ie.hooks.afterResponse=Ie.hooks.afterResponse.slice(0,le);for(let De of Ie.hooks.beforeRetry)await De(Ie);let he=jle(Ie);return p(()=>{he.catch(()=>{}),he.cancel()}),he})}catch(le){w._beforeError(new zx.RequestError(le.message,le,w));return}if(!qle.isResponseOk(C)){w._beforeError(new zx.HTTPError(C));return}r=C,u(w.options.resolveBodyOnly?C.body:C)});let D=C=>{if(a.isCanceled)return;let{options:T}=w;if(C instanceof zx.HTTPError&&!T.throwHttpErrors){let{response:N}=C;u(w.options.resolveBodyOnly?N.body:N);return}A(C)};w.once(\"error\",D);let b=w.options.body;w.once(\"retry\",(C,T)=>{var N,U;if(b===((N=T.request)===null||N===void 0?void 0:N.options.body)&&lst.default.nodeStream((U=T.request)===null||U===void 0?void 0:U.options.body)){D(T);return}h(C)}),ust.default(w,o,fst)};h(0)});a.on=(u,A)=>(o.on(u,A),a);let n=u=>{let A=(async()=>{await a;let{options:p}=r.request;return _le.default(r,u,p.parseJson,p.encoding)})();return Object.defineProperties(A,Object.getOwnPropertyDescriptors(a)),A};return a.json=()=>{let{headers:u}=e.options;return!e.writableFinished&&u.accept===void 0&&(u.accept=\"application/json\"),n(\"json\")},a.buffer=()=>n(\"buffer\"),a.text=()=>n(\"text\"),a}ph.default=jle;ost(_1(),ph)});var Gle=_(fU=>{\"use strict\";Object.defineProperty(fU,\"__esModule\",{value:!0});var pst=_1();function hst(t,...e){let r=(async()=>{if(t instanceof pst.RequestError)try{for(let a of e)if(a)for(let n of a)t=await n(t)}catch(a){t=a}throw t})(),o=()=>r;return r.json=o,r.text=o,r.buffer=o,r.on=o,r}fU.default=hst});var Kle=_(pU=>{\"use strict\";Object.defineProperty(pU,\"__esModule\",{value:!0});var Wle=Ff();function Yle(t){for(let e of Object.values(t))(Wle.default.plainObject(e)||Wle.default.array(e))&&Yle(e);return Object.freeze(t)}pU.default=Yle});var zle=_(Vle=>{\"use strict\";Object.defineProperty(Vle,\"__esModule\",{value:!0})});var hU=_(Xl=>{\"use strict\";var gst=Xl&&Xl.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),dst=Xl&&Xl.__exportStar||function(t,e){for(var r in t)r!==\"default\"&&!Object.prototype.hasOwnProperty.call(e,r)&&gst(e,t,r)};Object.defineProperty(Xl,\"__esModule\",{value:!0});Xl.defaultHandler=void 0;var Jle=Ff(),Jl=AU(),mst=Gle(),Xx=U1(),yst=Kle(),Est={RequestError:Jl.RequestError,CacheError:Jl.CacheError,ReadError:Jl.ReadError,HTTPError:Jl.HTTPError,MaxRedirectsError:Jl.MaxRedirectsError,TimeoutError:Jl.TimeoutError,ParseError:Jl.ParseError,CancelError:Jl.CancelError,UnsupportedProtocolError:Jl.UnsupportedProtocolError,UploadError:Jl.UploadError},Cst=async t=>new Promise(e=>{setTimeout(e,t)}),{normalizeArguments:Jx}=Xx.default,Xle=(...t)=>{let e;for(let r of t)e=Jx(void 0,r,e);return e},Ist=t=>t.isStream?new Xx.default(void 0,t):Jl.default(t),wst=t=>\"defaults\"in t&&\"options\"in t.defaults,Bst=[\"get\",\"post\",\"put\",\"patch\",\"head\",\"delete\"];Xl.defaultHandler=(t,e)=>e(t);var Zle=(t,e)=>{if(t)for(let r of t)r(e)},$le=t=>{t._rawHandlers=t.handlers,t.handlers=t.handlers.map(o=>(a,n)=>{let u,A=o(a,p=>(u=n(p),u));if(A!==u&&!a.isStream&&u){let p=A,{then:h,catch:E,finally:w}=p;Object.setPrototypeOf(p,Object.getPrototypeOf(u)),Object.defineProperties(p,Object.getOwnPropertyDescriptors(u)),p.then=h,p.catch=E,p.finally=w}return A});let e=(o,a={},n)=>{var u,A;let p=0,h=E=>t.handlers[p++](E,p===t.handlers.length?Ist:h);if(Jle.default.plainObject(o)){let E={...o,...a};Xx.setNonEnumerableProperties([o,a],E),a=E,o=void 0}try{let E;try{Zle(t.options.hooks.init,a),Zle((u=a.hooks)===null||u===void 0?void 0:u.init,a)}catch(D){E=D}let w=Jx(o,a,n??t.options);if(w[Xx.kIsNormalizedAlready]=!0,E)throw new Jl.RequestError(E.message,E,w);return h(w)}catch(E){if(a.isStream)throw E;return mst.default(E,t.options.hooks.beforeError,(A=a.hooks)===null||A===void 0?void 0:A.beforeError)}};e.extend=(...o)=>{let a=[t.options],n=[...t._rawHandlers],u;for(let A of o)wst(A)?(a.push(A.defaults.options),n.push(...A.defaults._rawHandlers),u=A.defaults.mutableDefaults):(a.push(A),\"handlers\"in A&&n.push(...A.handlers),u=A.mutableDefaults);return n=n.filter(A=>A!==Xl.defaultHandler),n.length===0&&n.push(Xl.defaultHandler),$le({options:Xle(...a),handlers:n,mutableDefaults:!!u})};let r=async function*(o,a){let n=Jx(o,a,t.options);n.resolveBodyOnly=!1;let u=n.pagination;if(!Jle.default.object(u))throw new TypeError(\"`options.pagination` must be implemented\");let A=[],{countLimit:p}=u,h=0;for(;h<u.requestLimit;){h!==0&&await Cst(u.backoff);let E=await e(void 0,void 0,n),w=await u.transform(E),D=[];for(let C of w)if(u.filter(C,A,D)&&(!u.shouldContinue(C,A,D)||(yield C,u.stackAllItems&&A.push(C),D.push(C),--p<=0)))return;let b=u.paginate(E,A,D);if(b===!1)return;b===E.request.options?n=E.request.options:b!==void 0&&(n=Jx(void 0,b,n)),h++}};e.paginate=r,e.paginate.all=async(o,a)=>{let n=[];for await(let u of r(o,a))n.push(u);return n},e.paginate.each=r,e.stream=(o,a)=>e(o,{...a,isStream:!0});for(let o of Bst)e[o]=(a,n)=>e(a,{...n,method:o}),e.stream[o]=(a,n)=>e(a,{...n,method:o,isStream:!0});return Object.assign(e,Est),Object.defineProperty(e,\"defaults\",{value:t.mutableDefaults?t:yst.default(t),writable:t.mutableDefaults,configurable:t.mutableDefaults,enumerable:!0}),e.mergeOptions=Xle,e};Xl.default=$le;dst(zle(),Xl)});var rce=_((Rf,Zx)=>{\"use strict\";var vst=Rf&&Rf.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),ece=Rf&&Rf.__exportStar||function(t,e){for(var r in t)r!==\"default\"&&!Object.prototype.hasOwnProperty.call(e,r)&&vst(e,t,r)};Object.defineProperty(Rf,\"__esModule\",{value:!0});var Dst=ve(\"url\"),tce=hU(),Pst={options:{method:\"GET\",retry:{limit:2,methods:[\"GET\",\"PUT\",\"HEAD\",\"DELETE\",\"OPTIONS\",\"TRACE\"],statusCodes:[408,413,429,500,502,503,504,521,522,524],errorCodes:[\"ETIMEDOUT\",\"ECONNRESET\",\"EADDRINUSE\",\"ECONNREFUSED\",\"EPIPE\",\"ENOTFOUND\",\"ENETUNREACH\",\"EAI_AGAIN\"],maxRetryAfter:void 0,calculateDelay:({computedValue:t})=>t},timeout:{},headers:{\"user-agent\":\"got (https://github.com/sindresorhus/got)\"},hooks:{init:[],beforeRequest:[],beforeRedirect:[],beforeRetry:[],beforeError:[],afterResponse:[]},cache:void 0,dnsCache:void 0,decompress:!0,throwHttpErrors:!0,followRedirect:!0,isStream:!1,responseType:\"text\",resolveBodyOnly:!1,maxRedirects:10,prefixUrl:\"\",methodRewriting:!0,ignoreInvalidCookies:!1,context:{},http2:!1,allowGetBody:!1,https:void 0,pagination:{transform:t=>t.request.options.responseType===\"json\"?t.body:JSON.parse(t.body),paginate:t=>{if(!Reflect.has(t.headers,\"link\"))return!1;let e=t.headers.link.split(\",\"),r;for(let o of e){let a=o.split(\";\");if(a[1].includes(\"next\")){r=a[0].trimStart().trim(),r=r.slice(1,-1);break}}return r?{url:new Dst.URL(r)}:!1},filter:()=>!0,shouldContinue:()=>!0,countLimit:1/0,backoff:0,requestLimit:1e4,stackAllItems:!0},parseJson:t=>JSON.parse(t),stringifyJson:t=>JSON.stringify(t),cacheOptions:{}},handlers:[tce.defaultHandler],mutableDefaults:!1},gU=tce.default(Pst);Rf.default=gU;Zx.exports=gU;Zx.exports.default=gU;Zx.exports.__esModule=!0;ece(hU(),Rf);ece(AU(),Rf)});var on={};Kt(on,{Method:()=>cce,del:()=>Qst,get:()=>EU,getNetworkSettings:()=>lce,post:()=>CU,put:()=>kst,request:()=>H1});function sce(t){let e=new URL(t),r={host:e.hostname,headers:{}};return e.port&&(r.port=Number(e.port)),e.username&&e.password&&(r.proxyAuth=`${e.username}:${e.password}`),{proxy:r}}async function dU(t){return Al(ice,t,()=>ae.readFilePromise(t).then(e=>(ice.set(t,e),e)))}function bst({statusCode:t,statusMessage:e},r){let o=Ut(r,t,Ct.NUMBER),a=`https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/${t}`;return ty(r,`${o}${e?` (${e})`:\"\"}`,a)}async function $x(t,{configuration:e,customErrorMessage:r}){try{return await t}catch(o){if(o.name!==\"HTTPError\")throw o;let a=r?.(o,e)??o.response.body?.error;a==null&&(o.message.startsWith(\"Response code\")?a=\"The remote server failed to provide the requested resource\":a=o.message),o.code===\"ETIMEDOUT\"&&o.event===\"socket\"&&(a+=`(can be increased via ${Ut(e,\"httpTimeout\",Ct.SETTING)})`);let n=new zt(35,a,u=>{o.response&&u.reportError(35,`  ${$u(e,{label:\"Response Code\",value:Yc(Ct.NO_HINT,bst(o.response,e))})}`),o.request&&(u.reportError(35,`  ${$u(e,{label:\"Request Method\",value:Yc(Ct.NO_HINT,o.request.options.method)})}`),u.reportError(35,`  ${$u(e,{label:\"Request URL\",value:Yc(Ct.URL,o.request.requestUrl)})}`)),o.request.redirects.length>0&&u.reportError(35,`  ${$u(e,{label:\"Request Redirects\",value:Yc(Ct.NO_HINT,cO(e,o.request.redirects,Ct.URL))})}`),o.request.retryCount===o.request.options.retry.limit&&u.reportError(35,`  ${$u(e,{label:\"Request Retry Count\",value:Yc(Ct.NO_HINT,`${Ut(e,o.request.retryCount,Ct.NUMBER)} (can be increased via ${Ut(e,\"httpRetry\",Ct.SETTING)})`)})}`)});throw n.originalError=o,n}}function lce(t,e){let r=[...e.configuration.get(\"networkSettings\")].sort(([u],[A])=>A.length-u.length),o={enableNetwork:void 0,httpsCaFilePath:void 0,httpProxy:void 0,httpsProxy:void 0,httpsKeyFilePath:void 0,httpsCertFilePath:void 0},a=Object.keys(o),n=typeof t==\"string\"?new URL(t):t;for(let[u,A]of r)if(yU.default.isMatch(n.hostname,u))for(let p of a){let h=A.get(p);h!==null&&typeof o[p]>\"u\"&&(o[p]=h)}for(let u of a)typeof o[u]>\"u\"&&(o[u]=e.configuration.get(u));return o}async function H1(t,e,{configuration:r,headers:o,jsonRequest:a,jsonResponse:n,method:u=\"GET\",wrapNetworkRequest:A}){let p={target:t,body:e,configuration:r,headers:o,jsonRequest:a,jsonResponse:n,method:u},h=async()=>await Fst(t,e,p),E=typeof A<\"u\"?await A(h,p):h;return await(await r.reduceHook(D=>D.wrapNetworkRequest,E,p))()}async function EU(t,{configuration:e,jsonResponse:r,customErrorMessage:o,wrapNetworkRequest:a,...n}){let u=()=>$x(H1(t,null,{configuration:e,wrapNetworkRequest:a,...n}),{configuration:e,customErrorMessage:o}).then(p=>p.body),A=await(typeof a<\"u\"?u():Al(nce,t,()=>u().then(p=>(nce.set(t,p),p))));return r?JSON.parse(A.toString()):A}async function kst(t,e,{customErrorMessage:r,...o}){return(await $x(H1(t,e,{...o,method:\"PUT\"}),{customErrorMessage:r,configuration:o.configuration})).body}async function CU(t,e,{customErrorMessage:r,...o}){return(await $x(H1(t,e,{...o,method:\"POST\"}),{customErrorMessage:r,configuration:o.configuration})).body}async function Qst(t,{customErrorMessage:e,...r}){return(await $x(H1(t,null,{...r,method:\"DELETE\"}),{customErrorMessage:e,configuration:r.configuration})).body}async function Fst(t,e,{configuration:r,headers:o,jsonRequest:a,jsonResponse:n,method:u=\"GET\"}){let A=typeof t==\"string\"?new URL(t):t,p=lce(A,{configuration:r});if(p.enableNetwork===!1)throw new zt(80,`Request to '${A.href}' has been blocked because of your configuration settings`);if(A.protocol===\"http:\"&&!yU.default.isMatch(A.hostname,r.get(\"unsafeHttpWhitelist\")))throw new zt(81,`Unsafe http requests must be explicitly whitelisted in your configuration (${A.hostname})`);let E={agent:{http:p.httpProxy?mU.default.httpOverHttp(sce(p.httpProxy)):Sst,https:p.httpsProxy?mU.default.httpsOverHttp(sce(p.httpsProxy)):xst},headers:o,method:u};E.responseType=n?\"json\":\"buffer\",e!==null&&(Buffer.isBuffer(e)||!a&&typeof e==\"string\"?E.body=e:E.json=e);let w=r.get(\"httpTimeout\"),D=r.get(\"httpRetry\"),b=r.get(\"enableStrictSsl\"),C=p.httpsCaFilePath,T=p.httpsCertFilePath,N=p.httpsKeyFilePath,{default:U}=await Promise.resolve().then(()=>et(rce())),z=C?await dU(C):void 0,te=T?await dU(T):void 0,le=N?await dU(N):void 0,ce=U.extend({timeout:{socket:w},retry:D,https:{rejectUnauthorized:b,certificateAuthority:z,certificate:te,key:le},...E});return r.getLimit(\"networkConcurrency\")(()=>ce(A))}var oce,ace,yU,mU,nce,ice,Sst,xst,cce,eb=It(()=>{Pt();oce=ve(\"https\"),ace=ve(\"http\"),yU=et(Xo()),mU=et(Roe());Vl();Wl();Gl();nce=new Map,ice=new Map,Sst=new ace.Agent({keepAlive:!0}),xst=new oce.Agent({keepAlive:!0});cce=(a=>(a.GET=\"GET\",a.PUT=\"PUT\",a.POST=\"POST\",a.DELETE=\"DELETE\",a))(cce||{})});var Xi={};Kt(Xi,{availableParallelism:()=>wU,getArchitecture:()=>q1,getArchitectureName:()=>Ost,getArchitectureSet:()=>IU,getCaller:()=>Hst,major:()=>Rst,openUrl:()=>Tst});function Nst(){if(process.platform===\"darwin\"||process.platform===\"win32\")return null;let t;try{t=ae.readFileSync(Lst)}catch{}if(typeof t<\"u\"){if(t&&(t.includes(\"GLIBC\")||t.includes(\"libc\")))return\"glibc\";if(t&&t.includes(\"musl\"))return\"musl\"}let r=(process.report?.getReport()??{}).sharedObjects??[],o=/\\/(?:(ld-linux-|[^/]+-linux-gnu\\/)|(libc.musl-|ld-musl-))/;return eh(r,a=>{let n=a.match(o);if(!n)return eh.skip;if(n[1])return\"glibc\";if(n[2])return\"musl\";throw new Error(\"Assertion failed: Expected the libc variant to have been detected\")})??null}function q1(){return Ace=Ace??{os:process.platform,cpu:process.arch,libc:Nst()}}function Ost(t=q1()){return t.libc?`${t.os}-${t.cpu}-${t.libc}`:`${t.os}-${t.cpu}`}function IU(){let t=q1();return fce=fce??{os:[t.os],cpu:[t.cpu],libc:t.libc?[t.libc]:[]}}function _st(t){let e=Mst.exec(t);if(!e)return null;let r=e[2]&&e[2].indexOf(\"native\")===0,o=e[2]&&e[2].indexOf(\"eval\")===0,a=Ust.exec(e[2]);return o&&a!=null&&(e[2]=a[1],e[3]=a[2],e[4]=a[3]),{file:r?null:e[2],methodName:e[1]||\"<unknown>\",arguments:r?[e[2]]:[],line:e[3]?+e[3]:null,column:e[4]?+e[4]:null}}function Hst(){let e=new Error().stack.split(`\n`)[3];return _st(e)}function wU(){return typeof tb.default.availableParallelism<\"u\"?tb.default.availableParallelism():Math.max(1,tb.default.cpus().length)}var tb,Rst,uce,Tst,Lst,Ace,fce,Mst,Ust,rb=It(()=>{Pt();tb=et(ve(\"os\"));nb();Gl();Rst=Number(process.versions.node.split(\".\")[0]),uce=new Map([[\"darwin\",\"open\"],[\"linux\",\"xdg-open\"],[\"win32\",\"explorer.exe\"]]).get(process.platform),Tst=typeof uce<\"u\"?async t=>{try{return await BU(uce,[t],{cwd:K.cwd()}),!0}catch{return!1}}:void 0,Lst=\"/usr/bin/ldd\";Mst=/^\\s*at (.*?) ?\\(((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|\\/|[a-z]:\\\\|\\\\\\\\).*?)(?::(\\d+))?(?::(\\d+))?\\)?\\s*$/i,Ust=/\\((\\S*)(?::(\\d+))(?::(\\d+))\\)/});function xU(t,e,r,o,a){let n=b1(r);if(o.isArray||o.type===\"ANY\"&&Array.isArray(n))return Array.isArray(n)?n.map((u,A)=>vU(t,`${e}[${A}]`,u,o,a)):String(n).split(/,/).map(u=>vU(t,e,u,o,a));if(Array.isArray(n))throw new Error(`Non-array configuration settings \"${e}\" cannot be an array`);return vU(t,e,r,o,a)}function vU(t,e,r,o,a){let n=b1(r);switch(o.type){case\"ANY\":return wx(n);case\"SHAPE\":return Wst(t,e,r,o,a);case\"MAP\":return Yst(t,e,r,o,a)}if(n===null&&!o.isNullable&&o.default!==null)throw new Error(`Non-nullable configuration settings \"${e}\" cannot be set to null`);if(o.values?.includes(n))return n;let A=(()=>{if(o.type===\"BOOLEAN\"&&typeof n!=\"string\")return f1(n);if(typeof n!=\"string\")throw new Error(`Expected configuration setting \"${e}\" to be a string, got ${typeof n}`);let p=NS(n,{env:t.env});switch(o.type){case\"ABSOLUTE_PATH\":{let h=a,E=e4(r);return E&&E[0]!==\"<\"&&(h=K.dirname(E)),K.resolve(h,Ae.toPortablePath(p))}case\"LOCATOR_LOOSE\":return Sf(p,!1);case\"NUMBER\":return parseInt(p);case\"LOCATOR\":return Sf(p);case\"BOOLEAN\":return f1(p);default:return p}})();if(o.values&&!o.values.includes(A))throw new Error(`Invalid value, expected one of ${o.values.join(\", \")}`);return A}function Wst(t,e,r,o,a){let n=b1(r);if(typeof n!=\"object\"||Array.isArray(n))throw new ot(`Object configuration settings \"${e}\" must be an object`);let u=bU(t,o,{ignoreArrays:!0});if(n===null)return u;for(let[A,p]of Object.entries(n)){let h=`${e}.${A}`;if(!o.properties[A])throw new ot(`Unrecognized configuration settings found: ${e}.${A} - run \"yarn config -v\" to see the list of settings supported in Yarn`);u.set(A,xU(t,h,p,o.properties[A],a))}return u}function Yst(t,e,r,o,a){let n=b1(r),u=new Map;if(typeof n!=\"object\"||Array.isArray(n))throw new ot(`Map configuration settings \"${e}\" must be an object`);if(n===null)return u;for(let[A,p]of Object.entries(n)){let h=o.normalizeKeys?o.normalizeKeys(A):A,E=`${e}['${h}']`,w=o.valueDefinition;u.set(h,xU(t,E,p,w,a))}return u}function bU(t,e,{ignoreArrays:r=!1}={}){switch(e.type){case\"SHAPE\":{if(e.isArray&&!r)return[];let o=new Map;for(let[a,n]of Object.entries(e.properties))o.set(a,bU(t,n));return o}case\"MAP\":return e.isArray&&!r?[]:new Map;case\"ABSOLUTE_PATH\":return e.default===null?null:t.projectCwd===null?Array.isArray(e.default)?e.default.map(o=>K.normalize(o)):K.isAbsolute(e.default)?K.normalize(e.default):e.isNullable?null:void 0:Array.isArray(e.default)?e.default.map(o=>K.resolve(t.projectCwd,o)):K.resolve(t.projectCwd,e.default);default:return e.default}}function sb(t,e,r){if(e.type===\"SECRET\"&&typeof t==\"string\"&&r.hideSecrets)return Gst;if(e.type===\"ABSOLUTE_PATH\"&&typeof t==\"string\"&&r.getNativePaths)return Ae.fromPortablePath(t);if(e.isArray&&Array.isArray(t)){let o=[];for(let a of t)o.push(sb(a,e,r));return o}if(e.type===\"MAP\"&&t instanceof Map){if(t.size===0)return;let o=new Map;for(let[a,n]of t.entries()){let u=sb(n,e.valueDefinition,r);typeof u<\"u\"&&o.set(a,u)}return o}if(e.type===\"SHAPE\"&&t instanceof Map){if(t.size===0)return;let o=new Map;for(let[a,n]of t.entries()){let u=e.properties[a],A=sb(n,u,r);typeof A<\"u\"&&o.set(a,A)}return o}return t}function Kst(){let t={};for(let[e,r]of Object.entries(process.env))e=e.toLowerCase(),e.startsWith(ob)&&(e=(0,hce.default)(e.slice(ob.length)),t[e]=r);return t}function PU(){let t=`${ob}rc_filename`;for(let[e,r]of Object.entries(process.env))if(e.toLowerCase()===t&&typeof r==\"string\")return r;return SU}async function pce(t){try{return await ae.readFilePromise(t)}catch{return Buffer.of()}}async function Vst(t,e){return Buffer.compare(...await Promise.all([pce(t),pce(e)]))===0}async function zst(t,e){let[r,o]=await Promise.all([ae.statPromise(t),ae.statPromise(e)]);return r.dev===o.dev&&r.ino===o.ino}async function Xst({configuration:t,selfPath:e}){let r=t.get(\"yarnPath\");return t.get(\"ignorePath\")||r===null||r===e||await Jst(r,e)?null:r}var hce,Tf,gce,dce,mce,DU,qst,j1,jst,by,ob,SU,Gst,G1,yce,ab,ib,Jst,Je,W1=It(()=>{Pt();Ol();hce=et(jV()),Tf=et(sg());Gt();gce=et(Nz()),dce=ve(\"module\"),mce=et(lg()),DU=ve(\"stream\");Vse();Ay();YM();KM();VM();woe();zM();Dg();Soe();vx();Wl();ah();eb();Gl();rb();bf();Io();qst=function(){if(!Tf.GITHUB_ACTIONS||!process.env.GITHUB_EVENT_PATH)return!1;let t=Ae.toPortablePath(process.env.GITHUB_EVENT_PATH),e;try{e=ae.readJsonSync(t)}catch{return!1}return!(!(\"repository\"in e)||!e.repository||(e.repository.private??!0))}(),j1=new Set([\"@yarnpkg/plugin-constraints\",\"@yarnpkg/plugin-exec\",\"@yarnpkg/plugin-interactive-tools\",\"@yarnpkg/plugin-stage\",\"@yarnpkg/plugin-typescript\",\"@yarnpkg/plugin-version\",\"@yarnpkg/plugin-workspace-tools\"]),jst=new Set([\"isTestEnv\",\"injectNpmUser\",\"injectNpmPassword\",\"injectNpm2FaToken\",\"zipDataEpilogue\",\"cacheCheckpointOverride\",\"cacheVersionOverride\",\"lockfileVersionOverride\",\"binFolder\",\"version\",\"flags\",\"profile\",\"gpg\",\"ignoreNode\",\"wrapOutput\",\"home\",\"confDir\",\"registry\",\"ignoreCwd\"]),by=/^(?!v)[a-z0-9._-]+$/i,ob=\"yarn_\",SU=\".yarnrc.yml\",Gst=\"********\",G1=(E=>(E.ANY=\"ANY\",E.BOOLEAN=\"BOOLEAN\",E.ABSOLUTE_PATH=\"ABSOLUTE_PATH\",E.LOCATOR=\"LOCATOR\",E.LOCATOR_LOOSE=\"LOCATOR_LOOSE\",E.NUMBER=\"NUMBER\",E.STRING=\"STRING\",E.SECRET=\"SECRET\",E.SHAPE=\"SHAPE\",E.MAP=\"MAP\",E))(G1||{}),yce=Ct,ab=(r=>(r.JUNCTIONS=\"junctions\",r.SYMLINKS=\"symlinks\",r))(ab||{}),ib={lastUpdateCheck:{description:\"Last timestamp we checked whether new Yarn versions were available\",type:\"STRING\",default:null},yarnPath:{description:\"Path to the local executable that must be used over the global one\",type:\"ABSOLUTE_PATH\",default:null},ignorePath:{description:\"If true, the local executable will be ignored when using the global one\",type:\"BOOLEAN\",default:!1},globalFolder:{description:\"Folder where all system-global files are stored\",type:\"ABSOLUTE_PATH\",default:r4()},cacheFolder:{description:\"Folder where the cache files must be written\",type:\"ABSOLUTE_PATH\",default:\"./.yarn/cache\"},compressionLevel:{description:\"Zip files compression level, from 0 to 9 or mixed (a variant of 9, which stores some files uncompressed, when compression doesn't yield good results)\",type:\"NUMBER\",values:[\"mixed\",0,1,2,3,4,5,6,7,8,9],default:0},virtualFolder:{description:\"Folder where the virtual packages (cf doc) will be mapped on the disk (must be named __virtual__)\",type:\"ABSOLUTE_PATH\",default:\"./.yarn/__virtual__\"},installStatePath:{description:\"Path of the file where the install state will be persisted\",type:\"ABSOLUTE_PATH\",default:\"./.yarn/install-state.gz\"},immutablePatterns:{description:\"Array of glob patterns; files matching them won't be allowed to change during immutable installs\",type:\"STRING\",default:[],isArray:!0},rcFilename:{description:\"Name of the files where the configuration can be found\",type:\"STRING\",default:PU()},enableGlobalCache:{description:\"If true, the system-wide cache folder will be used regardless of `cache-folder`\",type:\"BOOLEAN\",default:!0},cacheMigrationMode:{description:\"Defines the conditions under which Yarn upgrades should cause the cache archives to be regenerated.\",type:\"STRING\",values:[\"always\",\"match-spec\",\"required-only\"],default:\"always\"},enableColors:{description:\"If true, the CLI is allowed to use colors in its output\",type:\"BOOLEAN\",default:US,defaultText:\"<dynamic>\"},enableHyperlinks:{description:\"If true, the CLI is allowed to use hyperlinks in its output\",type:\"BOOLEAN\",default:lO,defaultText:\"<dynamic>\"},enableInlineBuilds:{description:\"If true, the CLI will print the build output on the command line\",type:\"BOOLEAN\",default:Tf.isCI,defaultText:\"<dynamic>\"},enableMessageNames:{description:\"If true, the CLI will prefix most messages with codes suitable for search engines\",type:\"BOOLEAN\",default:!0},enableProgressBars:{description:\"If true, the CLI is allowed to show a progress bar for long-running events\",type:\"BOOLEAN\",default:!Tf.isCI,defaultText:\"<dynamic>\"},enableTimers:{description:\"If true, the CLI is allowed to print the time spent executing commands\",type:\"BOOLEAN\",default:!0},enableTips:{description:\"If true, installs will print a helpful message every day of the week\",type:\"BOOLEAN\",default:!Tf.isCI,defaultText:\"<dynamic>\"},preferInteractive:{description:\"If true, the CLI will automatically use the interactive mode when called from a TTY\",type:\"BOOLEAN\",default:!1},preferTruncatedLines:{description:\"If true, the CLI will truncate lines that would go beyond the size of the terminal\",type:\"BOOLEAN\",default:!1},progressBarStyle:{description:\"Which style of progress bar should be used (only when progress bars are enabled)\",type:\"STRING\",default:void 0,defaultText:\"<dynamic>\"},defaultLanguageName:{description:\"Default language mode that should be used when a package doesn't offer any insight\",type:\"STRING\",default:\"node\"},defaultProtocol:{description:\"Default resolution protocol used when resolving pure semver and tag ranges\",type:\"STRING\",default:\"npm:\"},enableTransparentWorkspaces:{description:\"If false, Yarn won't automatically resolve workspace dependencies unless they use the `workspace:` protocol\",type:\"BOOLEAN\",default:!0},supportedArchitectures:{description:\"Architectures that Yarn will fetch and inject into the resolver\",type:\"SHAPE\",properties:{os:{description:\"Array of supported process.platform strings, or null to target them all\",type:\"STRING\",isArray:!0,isNullable:!0,default:[\"current\"]},cpu:{description:\"Array of supported process.arch strings, or null to target them all\",type:\"STRING\",isArray:!0,isNullable:!0,default:[\"current\"]},libc:{description:\"Array of supported libc libraries, or null to target them all\",type:\"STRING\",isArray:!0,isNullable:!0,default:[\"current\"]}}},enableMirror:{description:\"If true, the downloaded packages will be retrieved and stored in both the local and global folders\",type:\"BOOLEAN\",default:!0},enableNetwork:{description:\"If false, Yarn will refuse to use the network if required to\",type:\"BOOLEAN\",default:!0},enableOfflineMode:{description:\"If true, Yarn will attempt to retrieve files and metadata from the global cache rather than the network\",type:\"BOOLEAN\",default:!1},httpProxy:{description:\"URL of the http proxy that must be used for outgoing http requests\",type:\"STRING\",default:null},httpsProxy:{description:\"URL of the http proxy that must be used for outgoing https requests\",type:\"STRING\",default:null},unsafeHttpWhitelist:{description:\"List of the hostnames for which http queries are allowed (glob patterns are supported)\",type:\"STRING\",default:[],isArray:!0},httpTimeout:{description:\"Timeout of each http request in milliseconds\",type:\"NUMBER\",default:6e4},httpRetry:{description:\"Retry times on http failure\",type:\"NUMBER\",default:3},networkConcurrency:{description:\"Maximal number of concurrent requests\",type:\"NUMBER\",default:50},taskPoolConcurrency:{description:\"Maximal amount of concurrent heavy task processing\",type:\"NUMBER\",default:wU()},taskPoolMode:{description:\"Execution strategy for heavy tasks\",type:\"STRING\",values:[\"async\",\"workers\"],default:\"workers\"},networkSettings:{description:\"Network settings per hostname (glob patterns are supported)\",type:\"MAP\",valueDefinition:{description:\"\",type:\"SHAPE\",properties:{httpsCaFilePath:{description:\"Path to file containing one or multiple Certificate Authority signing certificates\",type:\"ABSOLUTE_PATH\",default:null},enableNetwork:{description:\"If false, the package manager will refuse to use the network if required to\",type:\"BOOLEAN\",default:null},httpProxy:{description:\"URL of the http proxy that must be used for outgoing http requests\",type:\"STRING\",default:null},httpsProxy:{description:\"URL of the http proxy that must be used for outgoing https requests\",type:\"STRING\",default:null},httpsKeyFilePath:{description:\"Path to file containing private key in PEM format\",type:\"ABSOLUTE_PATH\",default:null},httpsCertFilePath:{description:\"Path to file containing certificate chain in PEM format\",type:\"ABSOLUTE_PATH\",default:null}}}},httpsCaFilePath:{description:\"A path to a file containing one or multiple Certificate Authority signing certificates\",type:\"ABSOLUTE_PATH\",default:null},httpsKeyFilePath:{description:\"Path to file containing private key in PEM format\",type:\"ABSOLUTE_PATH\",default:null},httpsCertFilePath:{description:\"Path to file containing certificate chain in PEM format\",type:\"ABSOLUTE_PATH\",default:null},enableStrictSsl:{description:\"If false, SSL certificate errors will be ignored\",type:\"BOOLEAN\",default:!0},logFilters:{description:\"Overrides for log levels\",type:\"SHAPE\",isArray:!0,concatenateValues:!0,properties:{code:{description:\"Code of the messages covered by this override\",type:\"STRING\",default:void 0},text:{description:\"Code of the texts covered by this override\",type:\"STRING\",default:void 0},pattern:{description:\"Code of the patterns covered by this override\",type:\"STRING\",default:void 0},level:{description:\"Log level override, set to null to remove override\",type:\"STRING\",values:Object.values(HS),isNullable:!0,default:void 0}}},enableTelemetry:{description:\"If true, telemetry will be periodically sent, following the rules in https://yarnpkg.com/advanced/telemetry\",type:\"BOOLEAN\",default:!0},telemetryInterval:{description:\"Minimal amount of time between two telemetry uploads, in days\",type:\"NUMBER\",default:7},telemetryUserId:{description:\"If you desire to tell us which project you are, you can set this field. Completely optional and opt-in.\",type:\"STRING\",default:null},enableHardenedMode:{description:\"If true, automatically enable --check-resolutions --refresh-lockfile on installs\",type:\"BOOLEAN\",default:Tf.isPR&&qst,defaultText:\"<true on public PRs>\"},enableScripts:{description:\"If true, packages are allowed to have install scripts by default\",type:\"BOOLEAN\",default:!0},enableStrictSettings:{description:\"If true, unknown settings will cause Yarn to abort\",type:\"BOOLEAN\",default:!0},enableImmutableCache:{description:\"If true, the cache is reputed immutable and actions that would modify it will throw\",type:\"BOOLEAN\",default:!1},checksumBehavior:{description:\"Enumeration defining what to do when a checksum doesn't match expectations\",type:\"STRING\",default:\"throw\"},injectEnvironmentFiles:{description:\"List of all the environment files that Yarn should inject inside the process when it starts\",type:\"ABSOLUTE_PATH\",default:[\".env.yarn?\"],isArray:!0},packageExtensions:{description:\"Map of package corrections to apply on the dependency tree\",type:\"MAP\",valueDefinition:{description:\"The extension that will be applied to any package whose version matches the specified range\",type:\"SHAPE\",properties:{dependencies:{description:\"The set of dependencies that must be made available to the current package in order for it to work properly\",type:\"MAP\",valueDefinition:{description:\"A range\",type:\"STRING\"}},peerDependencies:{description:\"Inherited dependencies - the consumer of the package will be tasked to provide them\",type:\"MAP\",valueDefinition:{description:\"A semver range\",type:\"STRING\"}},peerDependenciesMeta:{description:\"Extra information related to the dependencies listed in the peerDependencies field\",type:\"MAP\",valueDefinition:{description:\"The peerDependency meta\",type:\"SHAPE\",properties:{optional:{description:\"If true, the selected peer dependency will be marked as optional by the package manager and the consumer omitting it won't be reported as an error\",type:\"BOOLEAN\",default:!1}}}}}}}};Jst=process.platform===\"win32\"?Vst:zst;Je=class t{constructor(e){this.isCI=Tf.isCI;this.projectCwd=null;this.plugins=new Map;this.settings=new Map;this.values=new Map;this.sources=new Map;this.invalid=new Map;this.env={};this.limits=new Map;this.packageExtensions=null;this.startingCwd=e}static{this.deleteProperty=Symbol()}static{this.telemetry=null}static create(e,r,o){let a=new t(e);typeof r<\"u\"&&!(r instanceof Map)&&(a.projectCwd=r),a.importSettings(ib);let n=typeof o<\"u\"?o:r instanceof Map?r:new Map;for(let[u,A]of n)a.activatePlugin(u,A);return a}static async find(e,r,{strict:o=!0,usePathCheck:a=null,useRc:n=!0}={}){let u=Kst();delete u.rcFilename;let A=new t(e),p=await t.findRcFiles(e),h=await t.findFolderRcFile(my());h&&(p.find(Ie=>Ie.path===h.path)||p.unshift(h));let E=Poe(p.map(ue=>[ue.path,ue.data])),w=Bt.dot,D=new Set(Object.keys(ib)),b=({yarnPath:ue,ignorePath:Ie,injectEnvironmentFiles:he})=>({yarnPath:ue,ignorePath:Ie,injectEnvironmentFiles:he}),C=({yarnPath:ue,ignorePath:Ie,injectEnvironmentFiles:he,...De})=>{let Ee={};for(let[g,me]of Object.entries(De))D.has(g)&&(Ee[g]=me);return Ee},T=({yarnPath:ue,ignorePath:Ie,...he})=>{let De={};for(let[Ee,g]of Object.entries(he))D.has(Ee)||(De[Ee]=g);return De};if(A.importSettings(b(ib)),A.useWithSource(\"<environment>\",b(u),e,{strict:!1}),E){let[ue,Ie]=E;A.useWithSource(ue,b(Ie),w,{strict:!1})}if(a){if(await Xst({configuration:A,selfPath:a})!==null)return A;A.useWithSource(\"<override>\",{ignorePath:!0},e,{strict:!1,overwrite:!0})}let N=await t.findProjectCwd(e);A.startingCwd=e,A.projectCwd=N;let U=Object.assign(Object.create(null),process.env);A.env=U;let z=await Promise.all(A.get(\"injectEnvironmentFiles\").map(async ue=>{let Ie=ue.endsWith(\"?\")?await ae.readFilePromise(ue.slice(0,-1),\"utf8\").catch(()=>\"\"):await ae.readFilePromise(ue,\"utf8\");return(0,gce.parse)(Ie)}));for(let ue of z)for(let[Ie,he]of Object.entries(ue))A.env[Ie]=NS(he,{env:U});if(A.importSettings(C(ib)),A.useWithSource(\"<environment>\",C(u),e,{strict:o}),E){let[ue,Ie]=E;A.useWithSource(ue,C(Ie),w,{strict:o})}let te=ue=>\"default\"in ue?ue.default:ue,le=new Map([[\"@@core\",Kse]]);if(r!==null)for(let ue of r.plugins.keys())le.set(ue,te(r.modules.get(ue)));for(let[ue,Ie]of le)A.activatePlugin(ue,Ie);let ce=new Map([]);if(r!==null){let ue=new Map;for(let[De,Ee]of r.modules)ue.set(De,()=>Ee);let Ie=new Set,he=async(De,Ee)=>{let{factory:g,name:me}=vf(De);if(!g||Ie.has(me))return;let Ce=new Map(ue),fe=Z=>{if((0,dce.isBuiltin)(Z))return vf(Z);if(Ce.has(Z))return Ce.get(Z)();throw new ot(`This plugin cannot access the package referenced via ${Z} which is neither a builtin, nor an exposed entry`)},ie=await Jm(async()=>te(await g(fe)),Z=>`${Z} (when initializing ${me}, defined in ${Ee})`);ue.set(me,()=>ie),Ie.add(me),ce.set(me,ie)};if(u.plugins)for(let De of u.plugins.split(\";\")){let Ee=K.resolve(e,Ae.toPortablePath(De));await he(Ee,\"<environment>\")}for(let{path:De,cwd:Ee,data:g}of p)if(n&&Array.isArray(g.plugins))for(let me of g.plugins){let Ce=typeof me!=\"string\"?me.path:me,fe=me?.spec??\"\",ie=me?.checksum??\"\";if(j1.has(fe))continue;let Z=K.resolve(Ee,Ae.toPortablePath(Ce));if(!await ae.existsPromise(Z)){if(!fe){let ht=Ut(A,K.basename(Z,\".cjs\"),Ct.NAME),q=Ut(A,\".gitignore\",Ct.NAME),nt=Ut(A,A.values.get(\"rcFilename\"),Ct.NAME),Le=Ut(A,\"https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored\",Ct.URL);throw new ot(`Missing source for the ${ht} plugin - please try to remove the plugin from ${nt} then reinstall it manually. This error usually occurs because ${q} is incorrect, check ${Le} to make sure your plugin folder isn't gitignored.`)}if(!fe.match(/^https?:/)){let ht=Ut(A,K.basename(Z,\".cjs\"),Ct.NAME),q=Ut(A,A.values.get(\"rcFilename\"),Ct.NAME);throw new ot(`Failed to recognize the source for the ${ht} plugin - please try to delete the plugin from ${q} then reinstall it manually.`)}let Pe=await EU(fe,{configuration:A}),Re=zi(Pe);if(ie&&ie!==Re){let ht=Ut(A,K.basename(Z,\".cjs\"),Ct.NAME),q=Ut(A,A.values.get(\"rcFilename\"),Ct.NAME),nt=Ut(A,`yarn plugin import ${fe}`,Ct.CODE);throw new ot(`Failed to fetch the ${ht} plugin from its remote location: its checksum seems to have changed. If this is expected, please remove the plugin from ${q} then run ${nt} to reimport it.`)}await ae.mkdirPromise(K.dirname(Z),{recursive:!0}),await ae.writeFilePromise(Z,Pe)}await he(Z,De)}}for(let[ue,Ie]of ce)A.activatePlugin(ue,Ie);if(A.useWithSource(\"<environment>\",T(u),e,{strict:o}),E){let[ue,Ie]=E;A.useWithSource(ue,T(Ie),w,{strict:o})}return A.get(\"enableGlobalCache\")&&(A.values.set(\"cacheFolder\",`${A.get(\"globalFolder\")}/cache`),A.sources.set(\"cacheFolder\",\"<internal>\")),A}static async findRcFiles(e){let r=PU(),o=[],a=e,n=null;for(;a!==n;){n=a;let u=K.join(n,r);if(ae.existsSync(u)){let A=await ae.readFilePromise(u,\"utf8\"),p;try{p=Ki(A)}catch{let E=\"\";throw A.match(/^\\s+(?!-)[^:]+\\s+\\S+/m)&&(E=\" (in particular, make sure you list the colons after each key name)\"),new ot(`Parse error when loading ${u}; please check it's proper Yaml${E}`)}o.unshift({path:u,cwd:n,data:p})}a=K.dirname(n)}return o}static async findFolderRcFile(e){let r=K.join(e,mr.rc),o;try{o=await ae.readFilePromise(r,\"utf8\")}catch(n){if(n.code===\"ENOENT\")return null;throw n}let a=Ki(o);return{path:r,cwd:e,data:a}}static async findProjectCwd(e){let r=null,o=e,a=null;for(;o!==a;){if(a=o,ae.existsSync(K.join(a,mr.lockfile)))return a;ae.existsSync(K.join(a,mr.manifest))&&(r=a),o=K.dirname(a)}return r}static async updateConfiguration(e,r,o={}){let a=PU(),n=K.join(e,a),u=ae.existsSync(n)?Ki(await ae.readFilePromise(n,\"utf8\")):{},A=!1,p;if(typeof r==\"function\"){try{p=r(u)}catch{p=r({})}if(p===u)return!1}else{p=u;for(let h of Object.keys(r)){let E=u[h],w=r[h],D;if(typeof w==\"function\")try{D=w(E)}catch{D=w(void 0)}else D=w;E!==D&&(D===t.deleteProperty?delete p[h]:p[h]=D,A=!0)}if(!A)return!1}return await ae.changeFilePromise(n,Pa(p),{automaticNewlines:!0}),!0}static async addPlugin(e,r){r.length!==0&&await t.updateConfiguration(e,o=>{let a=o.plugins??[];if(a.length===0)return{...o,plugins:r};let n=[],u=[...r];for(let A of a){let p=typeof A!=\"string\"?A.path:A,h=u.find(E=>E.path===p);h?(n.push(h),u=u.filter(E=>E!==h)):n.push(A)}return n.push(...u),{...o,plugins:n}})}static async updateHomeConfiguration(e){let r=my();return await t.updateConfiguration(r,e)}activatePlugin(e,r){this.plugins.set(e,r),typeof r.configuration<\"u\"&&this.importSettings(r.configuration)}importSettings(e){for(let[r,o]of Object.entries(e))if(o!=null){if(this.settings.has(r))throw new Error(`Cannot redefine settings \"${r}\"`);this.settings.set(r,o),this.values.set(r,bU(this,o))}}useWithSource(e,r,o,a){try{this.use(e,r,o,a)}catch(n){throw n.message+=` (in ${Ut(this,e,Ct.PATH)})`,n}}use(e,r,o,{strict:a=!0,overwrite:n=!1}={}){a=a&&this.get(\"enableStrictSettings\");for(let u of[\"enableStrictSettings\",...Object.keys(r)]){let A=r[u],p=e4(A);if(p&&(e=p),typeof A>\"u\"||u===\"plugins\"||e===\"<environment>\"&&jst.has(u))continue;if(u===\"rcFilename\")throw new ot(`The rcFilename settings can only be set via ${`${ob}RC_FILENAME`.toUpperCase()}, not via a rc file`);let h=this.settings.get(u);if(!h){let w=my(),D=e[0]!==\"<\"?K.dirname(e):null;if(a&&!(D!==null?w===D:!1))throw new ot(`Unrecognized or legacy configuration settings found: ${u} - run \"yarn config -v\" to see the list of settings supported in Yarn`);this.invalid.set(u,e);continue}if(this.sources.has(u)&&!(n||h.type===\"MAP\"||h.isArray&&h.concatenateValues))continue;let E;try{E=xU(this,u,A,h,o)}catch(w){throw w.message+=` in ${Ut(this,e,Ct.PATH)}`,w}if(u===\"enableStrictSettings\"&&e!==\"<environment>\"){a=E;continue}if(h.type===\"MAP\"){let w=this.values.get(u);this.values.set(u,new Map(n?[...w,...E]:[...E,...w])),this.sources.set(u,`${this.sources.get(u)}, ${e}`)}else if(h.isArray&&h.concatenateValues){let w=this.values.get(u);this.values.set(u,n?[...w,...E]:[...E,...w]),this.sources.set(u,`${this.sources.get(u)}, ${e}`)}else this.values.set(u,E),this.sources.set(u,e)}}get(e){if(!this.values.has(e))throw new Error(`Invalid configuration key \"${e}\"`);return this.values.get(e)}getSpecial(e,{hideSecrets:r=!1,getNativePaths:o=!1}){let a=this.get(e),n=this.settings.get(e);if(typeof n>\"u\")throw new ot(`Couldn't find a configuration settings named \"${e}\"`);return sb(a,n,{hideSecrets:r,getNativePaths:o})}getSubprocessStreams(e,{header:r,prefix:o,report:a}){let n,u,A=ae.createWriteStream(e);if(this.get(\"enableInlineBuilds\")){let p=a.createStreamReporter(`${o} ${Ut(this,\"STDOUT\",\"green\")}`),h=a.createStreamReporter(`${o} ${Ut(this,\"STDERR\",\"red\")}`);n=new DU.PassThrough,n.pipe(p),n.pipe(A),u=new DU.PassThrough,u.pipe(h),u.pipe(A)}else n=A,u=A,typeof r<\"u\"&&n.write(`${r}\n`);return{stdout:n,stderr:u}}makeResolver(){let e=[];for(let r of this.plugins.values())for(let o of r.resolvers||[])e.push(new o);return new Pg([new Ix,new ci,...e])}makeFetcher(){let e=[];for(let r of this.plugins.values())for(let o of r.fetchers||[])e.push(new o);return new py([new hy,new gy,...e])}getLinkers(){let e=[];for(let r of this.plugins.values())for(let o of r.linkers||[])e.push(new o);return e}getSupportedArchitectures(){let e=q1(),r=this.get(\"supportedArchitectures\"),o=r.get(\"os\");o!==null&&(o=o.map(u=>u===\"current\"?e.os:u));let a=r.get(\"cpu\");a!==null&&(a=a.map(u=>u===\"current\"?e.cpu:u));let n=r.get(\"libc\");return n!==null&&(n=ul(n,u=>u===\"current\"?e.libc??ul.skip:u)),{os:o,cpu:a,libc:n}}isInteractive({interactive:e,stdout:r}){return r.isTTY?e??this.get(\"preferInteractive\"):!1}async getPackageExtensions(){if(this.packageExtensions!==null)return this.packageExtensions;this.packageExtensions=new Map;let e=this.packageExtensions,r=(o,a,{userProvided:n=!1}={})=>{if(!Fa(o.range))throw new Error(\"Only semver ranges are allowed as keys for the packageExtensions setting\");let u=new _t;u.load(a,{yamlCompatibilityMode:!0});let A=u1(e,o.identHash),p=[];A.push([o.range,p]);let h={status:\"inactive\",userProvided:n,parentDescriptor:o};for(let E of u.dependencies.values())p.push({...h,type:\"Dependency\",descriptor:E});for(let E of u.peerDependencies.values())p.push({...h,type:\"PeerDependency\",descriptor:E});for(let[E,w]of u.peerDependenciesMeta)for(let[D,b]of Object.entries(w))p.push({...h,type:\"PeerDependencyMeta\",selector:E,key:D,value:b})};await this.triggerHook(o=>o.registerPackageExtensions,this,r);for(let[o,a]of this.get(\"packageExtensions\"))r(lh(o,!0),LS(a),{userProvided:!0});return e}normalizeLocator(e){return Fa(e.reference)?Ss(e,`${this.get(\"defaultProtocol\")}${e.reference}`):by.test(e.reference)?Ss(e,`${this.get(\"defaultProtocol\")}${e.reference}`):e}normalizeDependency(e){return Fa(e.range)?kn(e,`${this.get(\"defaultProtocol\")}${e.range}`):by.test(e.range)?kn(e,`${this.get(\"defaultProtocol\")}${e.range}`):e}normalizeDependencyMap(e){return new Map([...e].map(([r,o])=>[r,this.normalizeDependency(o)]))}normalizePackage(e,{packageExtensions:r}){let o=E1(e),a=r.get(e.identHash);if(typeof a<\"u\"){let u=e.version;if(u!==null){for(let[A,p]of a)if(nA(u,A))for(let h of p)switch(h.status===\"inactive\"&&(h.status=\"redundant\"),h.type){case\"Dependency\":typeof o.dependencies.get(h.descriptor.identHash)>\"u\"&&(h.status=\"active\",o.dependencies.set(h.descriptor.identHash,this.normalizeDependency(h.descriptor)));break;case\"PeerDependency\":typeof o.peerDependencies.get(h.descriptor.identHash)>\"u\"&&(h.status=\"active\",o.peerDependencies.set(h.descriptor.identHash,h.descriptor));break;case\"PeerDependencyMeta\":{let E=o.peerDependenciesMeta.get(h.selector);(typeof E>\"u\"||!Object.hasOwn(E,h.key)||E[h.key]!==h.value)&&(h.status=\"active\",Al(o.peerDependenciesMeta,h.selector,()=>({}))[h.key]=h.value)}break;default:tO(h)}}}let n=u=>u.scope?`${u.scope}__${u.name}`:`${u.name}`;for(let u of o.peerDependenciesMeta.keys()){let A=Zo(u);o.peerDependencies.has(A.identHash)||o.peerDependencies.set(A.identHash,kn(A,\"*\"))}for(let u of o.peerDependencies.values()){if(u.scope===\"types\")continue;let A=n(u),p=rA(\"types\",A),h=rn(p);o.peerDependencies.has(p.identHash)||o.peerDependenciesMeta.has(h)||(o.peerDependencies.set(p.identHash,kn(p,\"*\")),o.peerDependenciesMeta.set(h,{optional:!0}))}return o.dependencies=new Map(Ps(o.dependencies,([,u])=>ka(u))),o.peerDependencies=new Map(Ps(o.peerDependencies,([,u])=>ka(u))),o}getLimit(e){return Al(this.limits,e,()=>(0,mce.default)(this.get(e)))}async triggerHook(e,...r){for(let o of this.plugins.values()){let a=o.hooks;if(!a)continue;let n=e(a);n&&await n(...r)}}async triggerMultipleHooks(e,r){for(let o of r)await this.triggerHook(e,...o)}async reduceHook(e,r,...o){let a=r;for(let n of this.plugins.values()){let u=n.hooks;if(!u)continue;let A=e(u);A&&(a=await A(a,...o))}return a}async firstHook(e,...r){for(let o of this.plugins.values()){let a=o.hooks;if(!a)continue;let n=e(a);if(!n)continue;let u=await n(...r);if(typeof u<\"u\")return u}return null}}});var Hr={};Kt(Hr,{EndStrategy:()=>RU,ExecError:()=>lb,PipeError:()=>Y1,execvp:()=>BU,pipevp:()=>Xc});function kg(t){return t!==null&&typeof t.fd==\"number\"}function kU(){}function QU(){for(let t of Qg)t.kill()}async function Xc(t,e,{cwd:r,env:o=process.env,strict:a=!1,stdin:n=null,stdout:u,stderr:A,end:p=2}){let h=[\"pipe\",\"pipe\",\"pipe\"];n===null?h[0]=\"ignore\":kg(n)&&(h[0]=n),kg(u)&&(h[1]=u),kg(A)&&(h[2]=A);let E=(0,FU.default)(t,e,{cwd:Ae.fromPortablePath(r),env:{...o,PWD:Ae.fromPortablePath(r)},stdio:h});Qg.add(E),Qg.size===1&&(process.on(\"SIGINT\",kU),process.on(\"SIGTERM\",QU)),!kg(n)&&n!==null&&n.pipe(E.stdin),kg(u)||E.stdout.pipe(u,{end:!1}),kg(A)||E.stderr.pipe(A,{end:!1});let w=()=>{for(let D of new Set([u,A]))kg(D)||D.end()};return new Promise((D,b)=>{E.on(\"error\",C=>{Qg.delete(E),Qg.size===0&&(process.off(\"SIGINT\",kU),process.off(\"SIGTERM\",QU)),(p===2||p===1)&&w(),b(C)}),E.on(\"close\",(C,T)=>{Qg.delete(E),Qg.size===0&&(process.off(\"SIGINT\",kU),process.off(\"SIGTERM\",QU)),(p===2||p===1&&C!==0)&&w(),C===0||!a?D({code:TU(C,T)}):b(new Y1({fileName:t,code:C,signal:T}))})})}async function BU(t,e,{cwd:r,env:o=process.env,encoding:a=\"utf8\",strict:n=!1}){let u=[\"ignore\",\"pipe\",\"pipe\"],A=[],p=[],h=Ae.fromPortablePath(r);typeof o.PWD<\"u\"&&(o={...o,PWD:h});let E=(0,FU.default)(t,e,{cwd:h,env:o,stdio:u});return E.stdout.on(\"data\",w=>{A.push(w)}),E.stderr.on(\"data\",w=>{p.push(w)}),await new Promise((w,D)=>{E.on(\"error\",b=>{let C=Je.create(r),T=Ut(C,t,Ct.PATH);D(new zt(1,`Process ${T} failed to spawn`,N=>{N.reportError(1,`  ${$u(C,{label:\"Thrown Error\",value:Yc(Ct.NO_HINT,b.message)})}`)}))}),E.on(\"close\",(b,C)=>{let T=a===\"buffer\"?Buffer.concat(A):Buffer.concat(A).toString(a),N=a===\"buffer\"?Buffer.concat(p):Buffer.concat(p).toString(a);b===0||!n?w({code:TU(b,C),stdout:T,stderr:N}):D(new lb({fileName:t,code:b,signal:C,stdout:T,stderr:N}))})})}function TU(t,e){let r=Zst.get(e);return typeof r<\"u\"?128+r:t??1}function $st(t,e,{configuration:r,report:o}){o.reportError(1,`  ${$u(r,t!==null?{label:\"Exit Code\",value:Yc(Ct.NUMBER,t)}:{label:\"Exit Signal\",value:Yc(Ct.CODE,e)})}`)}var FU,RU,Y1,lb,Qg,Zst,nb=It(()=>{Pt();FU=et(MT());W1();Vl();Wl();RU=(o=>(o[o.Never=0]=\"Never\",o[o.ErrorCode=1]=\"ErrorCode\",o[o.Always=2]=\"Always\",o))(RU||{}),Y1=class extends zt{constructor({fileName:e,code:r,signal:o}){let a=Je.create(K.cwd()),n=Ut(a,e,Ct.PATH);super(1,`Child ${n} reported an error`,u=>{$st(r,o,{configuration:a,report:u})}),this.code=TU(r,o)}},lb=class extends Y1{constructor({fileName:e,code:r,signal:o,stdout:a,stderr:n}){super({fileName:e,code:r,signal:o}),this.stdout=a,this.stderr=n}};Qg=new Set;Zst=new Map([[\"SIGINT\",2],[\"SIGQUIT\",3],[\"SIGKILL\",9],[\"SIGTERM\",15]])});function Cce(t){Ece=t}function K1(){return typeof LU>\"u\"&&(LU=Ece()),LU}var LU,Ece,NU=It(()=>{Ece=()=>{throw new Error(\"Assertion failed: No libzip instance is available, and no factory was configured\")}});var Ice=_((ub,MU)=>{var eot=Object.assign({},ve(\"fs\")),OU=function(){var t=typeof document<\"u\"&&document.currentScript?document.currentScript.src:void 0;return typeof __filename<\"u\"&&(t=t||__filename),function(e){e=e||{};var r=typeof e<\"u\"?e:{},o,a;r.ready=new Promise(function(ze,it){o=ze,a=it});var n={},u;for(u in r)r.hasOwnProperty(u)&&(n[u]=r[u]);var A=[],p=\"./this.program\",h=function(ze,it){throw it},E=!1,w=!0,D=\"\";function b(ze){return r.locateFile?r.locateFile(ze,D):D+ze}var C,T,N,U;w&&(E?D=ve(\"path\").dirname(D)+\"/\":D=__dirname+\"/\",C=function(it,vt){var ar=ia(it);return ar?vt?ar:ar.toString():(N||(N=eot),U||(U=ve(\"path\")),it=U.normalize(it),N.readFileSync(it,vt?null:\"utf8\"))},T=function(it){var vt=C(it,!0);return vt.buffer||(vt=new Uint8Array(vt)),me(vt.buffer),vt},process.argv.length>1&&(p=process.argv[1].replace(/\\\\/g,\"/\")),A=process.argv.slice(2),h=function(ze){process.exit(ze)},r.inspect=function(){return\"[Emscripten Module object]\"});var z=r.print||console.log.bind(console),te=r.printErr||console.warn.bind(console);for(u in n)n.hasOwnProperty(u)&&(r[u]=n[u]);n=null,r.arguments&&(A=r.arguments),r.thisProgram&&(p=r.thisProgram),r.quit&&(h=r.quit);var le=0,ce=function(ze){le=ze},ue;r.wasmBinary&&(ue=r.wasmBinary);var Ie=r.noExitRuntime||!0;typeof WebAssembly!=\"object\"&&Hi(\"no native wasm support detected\");function he(ze,it,vt){switch(it=it||\"i8\",it.charAt(it.length-1)===\"*\"&&(it=\"i32\"),it){case\"i1\":return Ve[ze>>0];case\"i8\":return Ve[ze>>0];case\"i16\":return ap((ze>>1)*2);case\"i32\":return Rs((ze>>2)*4);case\"i64\":return Rs((ze>>2)*4);case\"float\":return gu((ze>>2)*4);case\"double\":return op((ze>>3)*8);default:Hi(\"invalid type for getValue: \"+it)}return null}var De,Ee=!1,g;function me(ze,it){ze||Hi(\"Assertion failed: \"+it)}function Ce(ze){var it=r[\"_\"+ze];return me(it,\"Cannot call unknown function \"+ze+\", make sure it is exported\"),it}function fe(ze,it,vt,ar,ee){var ye={string:function(Qi){var Pn=0;if(Qi!=null&&Qi!==0){var fa=(Qi.length<<2)+1;Pn=pi(fa),ht(Qi,Pn,fa)}return Pn},array:function(Qi){var Pn=pi(Qi.length);return Le(Qi,Pn),Pn}};function Ne(Qi){return it===\"string\"?Pe(Qi):it===\"boolean\"?!!Qi:Qi}var gt=Ce(ze),mt=[],Dt=0;if(ar)for(var er=0;er<ar.length;er++){var sn=ye[vt[er]];sn?(Dt===0&&(Dt=yu()),mt[er]=sn(ar[er])):mt[er]=ar[er]}var ei=gt.apply(null,mt);return ei=Ne(ei),Dt!==0&&Pl(Dt),ei}function ie(ze,it,vt,ar){vt=vt||[];var ee=vt.every(function(Ne){return Ne===\"number\"}),ye=it!==\"string\";return ye&&ee&&!ar?Ce(ze):function(){return fe(ze,it,vt,arguments,ar)}}var Z=new TextDecoder(\"utf8\");function Pe(ze,it){if(!ze)return\"\";for(var vt=ze+it,ar=ze;!(ar>=vt)&&xe[ar];)++ar;return Z.decode(xe.subarray(ze,ar))}function Re(ze,it,vt,ar){if(!(ar>0))return 0;for(var ee=vt,ye=vt+ar-1,Ne=0;Ne<ze.length;++Ne){var gt=ze.charCodeAt(Ne);if(gt>=55296&&gt<=57343){var mt=ze.charCodeAt(++Ne);gt=65536+((gt&1023)<<10)|mt&1023}if(gt<=127){if(vt>=ye)break;it[vt++]=gt}else if(gt<=2047){if(vt+1>=ye)break;it[vt++]=192|gt>>6,it[vt++]=128|gt&63}else if(gt<=65535){if(vt+2>=ye)break;it[vt++]=224|gt>>12,it[vt++]=128|gt>>6&63,it[vt++]=128|gt&63}else{if(vt+3>=ye)break;it[vt++]=240|gt>>18,it[vt++]=128|gt>>12&63,it[vt++]=128|gt>>6&63,it[vt++]=128|gt&63}}return it[vt]=0,vt-ee}function ht(ze,it,vt){return Re(ze,xe,it,vt)}function q(ze){for(var it=0,vt=0;vt<ze.length;++vt){var ar=ze.charCodeAt(vt);ar>=55296&&ar<=57343&&(ar=65536+((ar&1023)<<10)|ze.charCodeAt(++vt)&1023),ar<=127?++it:ar<=2047?it+=2:ar<=65535?it+=3:it+=4}return it}function nt(ze){var it=q(ze)+1,vt=aa(it);return vt&&Re(ze,Ve,vt,it),vt}function Le(ze,it){Ve.set(ze,it)}function Te(ze,it){return ze%it>0&&(ze+=it-ze%it),ze}var ke,Ve,xe,tt,He,x,I,S,y,R;function J(ze){ke=ze,r.HEAP_DATA_VIEW=R=new DataView(ze),r.HEAP8=Ve=new Int8Array(ze),r.HEAP16=tt=new Int16Array(ze),r.HEAP32=x=new Int32Array(ze),r.HEAPU8=xe=new Uint8Array(ze),r.HEAPU16=He=new Uint16Array(ze),r.HEAPU32=I=new Uint32Array(ze),r.HEAPF32=S=new Float32Array(ze),r.HEAPF64=y=new Float64Array(ze)}var X=r.INITIAL_MEMORY||16777216,$,se=[],be=[],Fe=[],lt=!1;function Et(){if(r.preRun)for(typeof r.preRun==\"function\"&&(r.preRun=[r.preRun]);r.preRun.length;)St(r.preRun.shift());hs(se)}function qt(){lt=!0,hs(be)}function nr(){if(r.postRun)for(typeof r.postRun==\"function\"&&(r.postRun=[r.postRun]);r.postRun.length;)Pr(r.postRun.shift());hs(Fe)}function St(ze){se.unshift(ze)}function cn(ze){be.unshift(ze)}function Pr(ze){Fe.unshift(ze)}var yr=0,Rr=null,Xr=null;function $n(ze){yr++,r.monitorRunDependencies&&r.monitorRunDependencies(yr)}function Xs(ze){if(yr--,r.monitorRunDependencies&&r.monitorRunDependencies(yr),yr==0&&(Rr!==null&&(clearInterval(Rr),Rr=null),Xr)){var it=Xr;Xr=null,it()}}r.preloadedImages={},r.preloadedAudios={};function Hi(ze){r.onAbort&&r.onAbort(ze),ze+=\"\",te(ze),Ee=!0,g=1,ze=\"abort(\"+ze+\"). Build with -s ASSERTIONS=1 for more info.\";var it=new WebAssembly.RuntimeError(ze);throw a(it),it}var Qs=\"data:application/octet-stream;base64,\";function Zs(ze){return ze.startsWith(Qs)}var bi=\"data:application/octet-stream;base64,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QCAAKAJIIgEgASADaiADEAcaAkAgAyAAKAJsIgFNBEAgACABIANrNgJsDAELIABCADcCbAsgACAAKAJoIANrIgE2AmggACAAKAJYIANrNgJYIAEgACgChC5JBEAgACABNgKELgsgAEH8gAEoAgARAwAgAiADaiECCwJAIAAoAgAiASgCBCIERQ0AIAAoAjwhBSAAIAIgBCACIARJGyICBH8gACgCSCAAKAJoaiAFaiEFIAEgBCACazYCBAJAAkACQAJAIAEoAhwiBCgCFEEBaw4CAQACCyAEQaABaiAFIAEoAgAgAkHcgAEoAgARCAAMAgsgASABKAIwIAUgASgCACACQcSAASgCABEEADYCMAwBCyAFIAEoAgAgAhAHGgsgASABKAIAIAJqNgIAIAEgASgCCCACajYCCCAAKAI8BSAFCyACaiICNgI8AkAgACgChC4iASACakEDSQ0AIAAoAmggAWshAQJAIAAoAnRBgQhPBEAgACAAIAAoAkggAWoiAi0AACACLQABIAAoAnwRAAA2AlQMAQsgAUUNACAAIAFBAWsgACgChAERAgAaCyAAKAKELiAAKAI8IgJBAUZrIgRFDQAgACABIAQgACgCgAERBQAgACAAKAKELiAEazYChC4gACgCPCECCyACQYUCSw0AIAAoAgAoAgRFDQAgACgCMCEBDAELCwJAIAAoAkQiAiAAKAJAIgNNDQAgAAJ/IAAoAjwgACgCaGoiASADSwRAIAAoAkggAWpBACACIAFrIgNBggIgA0GCAkkbIgMQGSABIANqDAELIAFBggJqIgEgA00NASAAKAJIIANqQQAgAiADayICIAEgA2siAyACIANJGyIDEBkgACgCQCADags2AkALC50CAQF/AkAgAAJ/IAAoAqAuIgFBwABGBEAgACgCBCAAKAIQaiAAKQOYLjcAACAAQgA3A5guIAAgACgCEEEIajYCEEEADAELIAFBIE4EQCAAKAIEIAAoAhBqIAApA5guPgAAIAAgAEGcLmo1AgA3A5guIAAgACgCEEEEajYCECAAIAAoAqAuQSBrIgE2AqAuCyABQRBOBEAgACgCBCAAKAIQaiAAKQOYLj0AACAAIAAoAhBBAmo2AhAgACAAKQOYLkIQiDcDmC4gACAAKAKgLkEQayIBNgKgLgsgAUEISA0BIAAgACgCECIBQQFqNgIQIAEgACgCBGogACkDmC48AAAgACAAKQOYLkIIiDcDmC4gACgCoC5BCGsLNgKgLgsLEAAgACgCCBAGIABBADYCCAvwAQECf0F/IQECQCAALQAoDQAgACgCJEEDRgRAIABBDGoEQCAAQQA2AhAgAEEXNgIMC0F/DwsCQCAAKAIgBEAgACkDGELAAINCAFINASAAQQxqBEAgAEEANgIQIABBHTYCDAtBfw8LAkAgACgCACICRQ0AIAIQMkF/Sg0AIAAoAgAhASAAQQxqIgAEQCAAIAEoAgw2AgAgACABKAIQNgIEC0F/DwsgAEEAQgBBABAOQn9VDQAgACgCACIARQ0BIAAQGhpBfw8LQQAhASAAQQA7ATQgAEEMagRAIABCADcCDAsgACAAKAIgQQFqNgIgCyABCzsAIAAtACgEfkJ/BSAAKAIgRQRAIABBDGoiAARAIABBADYCBCAAQRI2AgALQn8PCyAAQQBCAEEHEA4LC5oIAQt/IABFBEAgARAJDwsgAUFATwRAQYSEAUEwNgIAQQAPCwJ/QRAgAUELakF4cSABQQtJGyEGIABBCGsiBSgCBCIJQXhxIQQCQCAJQQNxRQRAQQAgBkGAAkkNAhogBkEEaiAETQRAIAUhAiAEIAZrQZSIASgCAEEBdE0NAgtBAAwCCyAEIAVqIQcCQCAEIAZPBEAgBCAGayIDQRBJDQEgBSAJQQFxIAZyQQJyNgIEIAUgBmoiAiADQQNyNgIEIAcgBygCBEEBcjYCBCACIAMQOwwBCyAHQcyEASgCAEYEQEHAhAEoAgAgBGoiBCAGTQ0CIAUgCUEBcSAGckECcjYCBCAFIAZqIgMgBCAGayICQQFyNgIEQcCEASACNgIAQcyEASADNgIADAELIAdByIQBKAIARgRAQbyEASgCACAEaiIDIAZJDQICQCADIAZrIgJBEE8EQCAFIAlBAXEgBnJBAnI2AgQgBSAGaiIEIAJBAXI2AgQgAyAFaiIDIAI2AgAgAyADKAIEQX5xNgIEDAELIAUgCUEBcSADckECcjYCBCADIAVqIgIgAigCBEEBcjYCBEEAIQJBACEEC0HIhAEgBDYCAEG8hAEgAjYCAAwBCyAHKAIEIgNBAnENASADQXhxIARqIgogBkkNASAKIAZrIQwCQCADQf8BTQRAIAcoAggiBCADQQN2IgJBA3RB3IQBakYaIAQgBygCDCIDRgRAQbSEAUG0hAEoAgBBfiACd3E2AgAMAgsgBCADNgIMIAMgBDYCCAwBCyAHKAIYIQsCQCAHIAcoAgwiCEcEQCAHKAIIIgJBxIQBKAIASRogAiAINgIMIAggAjYCCAwBCwJAIAdBFGoiBCgCACICDQAgB0EQaiIEKAIAIgINAEEAIQgMAQsDQCAEIQMgAiIIQRRqIgQoAgAiAg0AIAhBEGohBCAIKAIQIgINAAsgA0EANgIACyALRQ0AAkAgByAHKAIcIgNBAnRB5IYBaiICKAIARgRAIAIgCDYCACAIDQFBuIQBQbiEASgCAEF+IAN3cTYCAAwCCyALQRBBFCALKAIQIAdGG2ogCDYCACAIRQ0BCyAIIAs2AhggBygCECICBEAgCCACNgIQIAIgCDYCGAsgBygCFCICRQ0AIAggAjYCFCACIAg2AhgLIAxBD00EQCAFIAlBAXEgCnJBAnI2AgQgBSAKaiICIAIoAgRBAXI2AgQMAQsgBSAJQQFxIAZyQQJyNgIEIAUgBmoiAyAMQQNyNgIEIAUgCmoiAiACKAIEQQFyNgIEIAMgDBA7CyAFIQILIAILIgIEQCACQQhqDwsgARAJIgVFBEBBAA8LIAUgAEF8QXggAEEEaygCACICQQNxGyACQXhxaiICIAEgASACSxsQBxogABAGIAUL6QEBA38CQCABRQ0AIAJBgDBxIgIEfwJ/IAJBgCBHBEBBAiACQYAQRg0BGiADBEAgA0EANgIEIANBEjYCAAtBAA8LQQQLIQJBAAVBAQshBkEUEAkiBEUEQCADBEAgA0EANgIEIANBDjYCAAtBAA8LIAQgAUEBahAJIgU2AgAgBUUEQCAEEAZBAA8LIAUgACABEAcgAWpBADoAACAEQQA2AhAgBEIANwMIIAQgATsBBCAGDQAgBCACECNBBUcNACAEKAIAEAYgBCgCDBAGIAQQBkEAIQQgAwRAIANBADYCBCADQRI2AgALCyAEC7UBAQJ/AkACQAJAAkACQAJAAkAgAC0ABQRAIAAtAABBAnFFDQELIAAoAjAQECAAQQA2AjAgAC0ABUUNAQsgAC0AAEEIcUUNAQsgACgCNBAcIABBADYCNCAALQAFRQ0BCyAALQAAQQRxRQ0BCyAAKAI4EBAgAEEANgI4IAAtAAVFDQELIAAtAABBgAFxRQ0BCyAAKAJUIgEEfyABQQAgARAiEBkgACgCVAVBAAsQBiAAQQA2AlQLC9wMAgl/AX4jAEFAaiIGJAACQAJAAkACQAJAIAEoAjBBABAjIgVBAkZBACABKAI4QQAQIyIEQQFGGw0AIAVBAUZBACAEQQJGGw0AIAVBAkciAw0BIARBAkcNAQsgASABLwEMQYAQcjsBDEEAIQMMAQsgASABLwEMQf/vA3E7AQxBACEFIANFBEBB9eABIAEoAjAgAEEIahBpIgVFDQILIAJBgAJxBEAgBSEDDAELIARBAkcEQCAFIQMMAQtB9cYBIAEoAjggAEEIahBpIgNFBEAgBRAcDAILIAMgBTYCAAsgASABLwEMQf7/A3EgAS8BUiIFQQBHcjsBDAJAAkACQAJAAn8CQAJAIAEpAyhC/v///w9WDQAgASkDIEL+////D1YNACACQYAEcUUNASABKQNIQv////8PVA0BCyAFQYECa0H//wNxQQNJIQdBAQwBCyAFQYECa0H//wNxIQQgAkGACnFBgApHDQEgBEEDSSEHQQALIQkgBkIcEBciBEUEQCAAQQhqIgAEQCAAQQA2AgQgAEEONgIACyADEBwMBQsgAkGACHEhBQJAAkAgAkGAAnEEQAJAIAUNACABKQMgQv////8PVg0AIAEpAyhCgICAgBBUDQMLIAQgASkDKBAYIAEpAyAhDAwBCwJAAkACQCAFDQAgASkDIEL/////D1YNACABKQMoIgxC/////w9WDQEgASkDSEKAgICAEFQNBAsgASkDKCIMQv////8PVA0BCyAEIAwQGAsgASkDICIMQv////8PWgRAIAQgDBAYCyABKQNIIgxC/////w9UDQELIAQgDBAYCyAELQAARQRAIABBCGoiAARAIABBADYCBCAAQRQ2AgALIAQQCCADEBwMBQtBASEKQQEgBC0AAAR+IAQpAxAFQgALp0H//wNxIAYQRyEFIAQQCCAFIAM2AgAgBw0BDAILIAMhBSAEQQJLDQELIAZCBxAXIgRFBEAgAEEIaiIABEAgAEEANgIEIABBDjYCAAsgBRAcDAMLIARBAhANIARBhxJBAhAsIAQgAS0AUhBwIAQgAS8BEBANIAQtAABFBEAgAEEIaiIABEAgAEEANgIEIABBFDYCAAsgBBAIDAILQYGyAkEHIAYQRyEDIAQQCCADIAU2AgBBASEL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NgIEIABB7A42AhggGiEdDAMLIARB/wFxIgJBwABxRQRAIAggDSADLwECQQJ0aiAdp0F/IAJ0QX9zcUECdGoiAy0AASICayEIIB0gAq2IIR0gAy0AACIERQ0HDAELCyAEQSBxBEAgB0G//gA2AgQgASECDAgLIAdB0f4ANgIEIABB0A42AhggASECDAcLIB1BfyAGdEF/c62DIBt8IhunIQUgCCAEQQ9xIgNrIQggGiAErUIPg4ghHSABIBdrIgYgAjMBAiAaQX8gA3RBf3Otg3ynIgRPDQIgBCAGayIGIBlNDQEgBygCjEdFDQEgB0HR/gA2AgQgAEG5DDYCGAsgASECIAshBQwFCwJAIA5FBEAgDCARIAZraiEDDAELIAYgDk0EQCAMIA4gBmtqIQMMAQsgDCARIAYgDmsiBmtqIQMgBSAGTQ0AIAUgBmshBQJAAkAgASADTSABIA8gAWusIhogBq0iGyAaIBtUGyIapyIGaiICIANLcQ0AIAMgBmogAUsgASADT3ENACABIAMgBhAHGiACIQEMAQsgASADIAMgAWsiASABQR91IgFqIAFzIgIQByACaiEBIBogAq0iHn0iHFANACACIANqIQIDQAJAIBwgHiAcIB5UGyIbQiBUBEAgGyEaDAELIBsiGkIgfSIgQgWIQgF8QgODIh9QRQRAA0AgASACKQAANwAAIAEgAikAGDcAGCABIAIpABA3ABAgASACKQAINwAIIBpCIH0hGiACQSBqIQIgAUEgaiEBIB9CAX0iH0IAUg0ACwsgIELgAFQNAANAIAEgAikAADcAACABIAIpABg3ABggASACKQAQNwAQIAEgAikACDcACCABIAIpADg3ADggASACKQAwNwAwIAEgAikAKDcAKCABIAIpACA3ACAgASACKQBYNwBYIAEgAikAUDcAUCABIAIpAEg3AEggASACKQBANwBAIAEgAikAYDcAYCABIAIpAGg3AGggASACKQBwNwBwIAEgAikAeDcAeCACQYABaiECIAFBgAFqIQEgGkKAAX0iGkIfVg0ACwsgGkIQWgRAIAEgAikAADcAACABIAIpAAg3AAggGkIQfSEaIAJBEGohAiABQRBqIQELIBpCCFoEQCABIAIpAAA3AAAgGkIIfSEaIAJBCGohAiABQQhqIQELIBpCBFoEQCABIAIoAAA2AAAgGkIEfSEaIAJBBGohAiABQQRqIQELIBpCAloEQCABIAIvAAA7AAAgGkICfSEaIAJBAmohAiABQQJqIQELIBwgG30hHCAaUEUEQCABIAItAAA6AAAgAkEBaiECIAFBAWohAQsgHEIAUg0ACwsgDiEGIAwhAwsgBSAGSwRAAkACQCABIANNIAEgDyABa6wiGiAGrSIbIBogG1QbIhqnIglqIgIgA0txDQAgAyAJaiABSyABIANPcQ0AIAEgAyAJEAcaDAELIAEgAyADIAFrIgEgAUEfdSIBaiABcyIBEAcgAWohAiAaIAGtIh59IhxQDQAgASADaiEBA0ACQCAcIB4gHCAeVBsiG0IgVARAIBshGgwBCyAbIhpCIH0iIEIFiEIBfEIDgyIfUEUEQANAIAIgASkAADcAACACIAEpABg3ABggAiABKQAQNwAQIAIgASkACDcACCAaQiB9IRogAUEgaiEBIAJBIGohAiAfQgF9Ih9CAFINAAsLICBC4ABUDQADQCACIAEpAAA3AAAgAiABKQAYNwAYIAIgASkAEDcAECACIAEpAAg3AAggAiABKQA4NwA4IAIgASkAMDcAMCACIAEpACg3ACggAiABKQAgNwAgIAIgASkAWDcAWCACIAEpAFA3AFAgAiABKQBINwBIIAIgASkAQDcAQCACIAEpAGA3AGAgAiABKQBoNwBoIAIgASkAcDcAcCACIAEpAHg3AHggAUGAAWohASACQYABaiECIBpCgAF9IhpCH1YNAAsLIBpCEFoEQCACIAEpAAA3AAAgAiABKQAINwAIIBpCEH0hGiACQRBqIQIgAUEQaiEBCyAaQghaBEAgAiABKQAANwAAIBpCCH0hGiACQQhqIQIgAUEIaiEBCyAaQgRaBEAgAiABKAAANgAAIBpCBH0hGiACQQRqIQIgAUEEaiEBCyAaQgJaBEAgAiABLwAAOwAAIBpCAn0hGiACQQJqIQIgAUECaiEBCyAcIBt9IRwgGlBFBEAgAiABLQAAOgAAIAJBAWohAiABQQFqIQELIBxCAFINAAsLIAUgBmshAUEAIARrIQUCQCAEQQdLBEAgBCEDDAELIAEgBE0EQCAEIQMMAQsgAiAEayEFA0ACQCACIAUpAAA3AAAgBEEBdCEDIAEgBGshASACIARqIQIgBEEDSw0AIAMhBCABIANLDQELC0EAIANrIQULIAIgBWohBAJAIAUgDyACa6wiGiABrSIbIBogG1QbIhqnIgFIIAVBf0pxDQAgBUEBSCABIARqIAJLcQ0AIAIgBCABEAcgAWohAgwDCyACIAQgAyADQR91IgFqIAFzIgEQByABaiECIBogAa0iHn0iHFANAiABIARqIQEDQAJAIBwgHiAcIB5UGyIbQiBUBEAgGyEaDAELIBsiGkIgfSIgQgWIQgF8QgODIh9QRQRAA0AgAiABKQAANwAAIAIgASkAGDcAGCACIAEpABA3ABAgAiABKQAINwAIIBpCIH0hGiABQSBqIQEgAkEgaiECIB9CAX0iH0IAUg0ACwsgIELgAFQNAANAIAIgASkAADcAACACIAEpABg3ABggAiABKQAQNwAQIAIgASkACDcACCACIAEpADg3ADggAiABKQAwNwAwIAIgASkAKDcAKCACIAEpACA3ACAgAiABKQBYNwBYIAIgASkAUDcAUCACIAEpAEg3AEggAiABKQBANwBAIAIgASkAYDcAYCACIAEpAGg3AGggAiABKQBwNwBwIAIgASkAeDcAeCABQYABaiEBIAJBgAFqIQIgGkKAAX0iGkIfVg0ACwsgGkIQWgRAIAIgASkAADcAACACIAEpAAg3AAggGkIQfSEaIAJBEGohAiABQRBqIQELIBpCCFoEQCACIAEpAAA3AAAgGkIIfSEaIAJBCGohAiABQQhqIQELIBpCBFoEQCACIAEoAAA2AAAgGkIEfSEaIAJBBGohAiABQQRqIQELIBpCAloEQCACIAEvAAA7AAAgGkICfSEaIAJBAmohAiABQQJqIQELIBwgG30hHCAaUEUEQCACIAEtAAA6AAAgAkEBaiECIAFBAWohAQsgHFBFDQALDAILAkAgASADTSABIA8gAWusIhogBa0iGyAaIBtUGyIapyIEaiICIANLcQ0AIAMgBGogAUsgASADT3ENACABIAMgBBAHGgwCCyABIAMgAyABayIBIAFBH3UiAWogAXMiARAHIAFqIQIgGiABrSIefSIcUA0BIAEgA2ohAQNAAkAgHCAeIBwgHlQbIhtCIFQEQCAbIRoMAQsgGyIaQiB9IiBCBYhCAXxCA4MiH1BFBEADQCACIAEpAAA3AAAgAiABKQAYNwAYIAIgASkAEDcAECACIAEpAAg3AAggGkIgfSEaIAFBIGohASACQSBqIQIgH0IBfSIfQgBSDQALCyAgQuAAVA0AA0AgAiABKQAANwAAIAIgASkAGDcAGCACIAEpABA3ABAgAiABKQAINwAIIAIgASkAODcAOCACIAEpADA3ADAgAiABKQAoNwAoIAIgASkAIDcAICACIAEpAFg3AFggAiABKQBQNwBQIAIgASkASDcASCACIAEpAEA3AEAgAiABKQBgNwBgIAIgASkAaDcAaCACIAEpAHA3AHAgAiABKQB4NwB4IAFBgAFqIQEgAkGAAWohAiAaQoABfSIaQh9WDQALCyAaQhBaBEAgAiABKQAANwAAIAIgASkACDcACCAaQhB9IRogAkEQaiECIAFBEGohAQsgGkIIWgRAIAIgASkAADcAACAaQgh9IRogAkEIaiECIAFBCGohAQsgGkIEWgRAIAIgASgAADYAACAaQgR9IRogAkEEaiECIAFBBGohAQsgGkICWgRAIAIgAS8AADsAACAaQgJ9IRogAkECaiECIAFBAmohAQsgHCAbfSEcIBpQRQRAIAIgAS0AADoAACACQQFqIQIgAUEBaiEBCyAcUEUNAAsMAQsCQAJAIBYEQAJAIAQgBUkEQCAHKAKYRyAESw0BCyABIARrIQMCQEEAIARrIgVBf0ogDyABa6wiGiAbIBogG1QbIhqnIgIgBUpxDQAgBUEBSCACIANqIAFLcQ0AIAEgAyACEAcgAmohAgwFCyABIAMgBCAEQR91IgFqIAFzIgEQByABaiECIBogAa0iHn0iHFANBCABIANqIQEDQAJAIBwgHiAcIB5UGyIbQiBUBEAgGyEaDAELIBsiGkIgfSIgQgWIQgF8QgODIh9QRQRAA0AgAiABKQAANwAAIAIgASkAGDcAGCACIAEpABA3ABAgAiABKQAINwAIIBpCIH0hGiABQSBqIQEgAkEgaiECIB9CAX0iH0IAUg0ACwsgIELgAFQNAANAIAIgASkAADcAACACIAEpABg3ABggAiABKQAQNwAQIAIgASkACDcACCACIAEpADg3ADggAiABKQAwNwAwIAIgASkAKDcAKCACIAEpACA3ACAgAiABKQBYNwBYIAIgASkAUDcAUCACIAEpAEg3AEggAiABKQBANwBAIAIgASkAYDcAYCACIAEpAGg3AGggAiABKQBwNwBwIAIgASkAeDcAeCABQYABaiEBIAJBgAFqIQIgGkKAAX0iGkIfVg0ACwsgGkIQWgRAIAIgASkAADcAACACIAEpAAg3AAggGkIQfSEaIAJBEGohAiABQRBqIQELIBpCCFoEQCACIAEpAAA3AAAgGkIIfSEaIAJBCGohAiABQQhqIQELIBpCBFoEQCACIAEoAAA2AAAgGkIEfSEaIAJBBGohAiABQQRqIQELIBpCAloEQCACIAEvAAA7AAAgGkICfSEaIAJBAmohAiABQQJqIQELIBwgG30hHCAaUEUEQCACIAEtAAA6AAAgAkEBaiECIAFBAWohAQsgHFBFDQALDAQLIBAgAWsiCUEBaiIGIAUgBSAGSxshAyABIARrIQIgAUEHcUUNAiADRQ0CIAEgAi0AADoAACACQQFqIQIgAUEBaiIGQQdxQQAgA0EBayIFGw0BIAYhASAFIQMgCSEGDAILAkAgBCAFSQRAIAcoAphHIARLDQELIAEgASAEayIGKQAANwAAIAEgBUEBa0EHcUEBaiIDaiECIAUgA2siBEUNAyADIAZqIQEDQCACIAEpAAA3AAAgAUEIaiEBIAJBCGohAiAEQQhrIgQNAAsMAwsgASAEIAUQPyECDAILIAEgAi0AADoAASAJQQFrIQYgA0ECayEFIAJBAWohAgJAIAFBAmoiCkEHcUUNACAFRQ0AIAEgAi0AADoAAiAJQQJrIQYgA0EDayEFIAJBAWohAgJAIAFBA2oiCkEHcUUNACAFRQ0AIAEgAi0AADoAAyAJQQNrIQYgA0EEayEFIAJBAWohAgJAIAFBBGoiCkEHcUUNACAFRQ0AIAEgAi0AADoABCAJQQRrIQYgA0EFayEFIAJBAWohAgJAIAFBBWoiCkEHcUUNACAFRQ0AIAEgAi0AADoABSAJQQVrIQYgA0EGayEFIAJBAWohAgJAIAFBBmoiCkEHcUUNACAFRQ0AIAEgAi0AADoABiAJQQZrIQYgA0EHayEFIAJBAWohAgJAIAFBB2oiCkEHcUUNACAFRQ0AIAEgAi0AADoAByAJQQdrIQYgA0EIayEDIAFBCGohASACQQFqIQIMBgsgCiEBIAUhAwwFCyAKIQEgBSEDDAQLIAohASAFIQMMAwsgCiEBIAUhAwwCCyAKIQEgBSEDDAELIAohASAFIQMLAkACQCAGQRdNBEAgA0UNASADQQFrIQUgA0EHcSIEBEADQCABIAItAAA6AAAgA0EBayEDIAFBAWohASACQQFqIQIgBEEBayIEDQALCyAFQQdJDQEDQCABIAItAAA6AAAgASACLQABOgABIAEgAi0AAjoAAiABIAItAAM6AAMgASACLQAEOgAEIAEgAi0ABToABSABIAItAAY6AAYgASACLQAHOgAHIAFBCGohASACQQhqIQIgA0EIayIDDQALDAELIAMNAQsgASECDAELIAEgBCADED8hAgsgCyEFDAELIAEgAy0AAjoAACABQQFqIQILIAUgFE8NACACIBNJDQELCyAAIAI2AgwgACAFIAhBA3ZrIgE2AgAgACATIAJrQYMCajYCECAAIBQgAWtBDmo2AgQgByAIQQdxIgA2AogBIAcgHUJ/IACthkJ/hYM+AoQBC+cFAQR/IAMgAiACIANLGyEEIAAgAWshAgJAIABBB3FFDQAgBEUNACAAIAItAAA6AAAgA0EBayEGIAJBAWohAiAAQQFqIgdBB3FBACAEQQFrIgUbRQRAIAchACAFIQQgBiEDDAELIAAgAi0AADoAASADQQJrIQYgBEECayEFIAJBAWohAgJAIABBAmoiB0EHcUUNACAFRQ0AIAAgAi0AADoAAiADQQNrIQYgBEEDayEFIAJBAWohAgJAIABBA2oiB0EHcUUNACAFRQ0AIAAgAi0AADoAAyADQQRrIQYgBEEEayEFIAJBAWohAgJAIABBBGoiB0EHcUUNACAFRQ0AIAAgAi0AADoABCADQQVrIQYgBEEFayEFIAJBAWohAgJAIABBBWoiB0EHcUUNACAFRQ0AIAAgAi0AADoABSADQQZrIQYgBEEGayEFIAJBAWohAgJAIABBBmoiB0EHcUUNACAFRQ0AIAAgAi0AADoABiADQQdrIQYgBEEHayEFIAJBAWohAgJAIABBB2oiB0EHcUUNACAFRQ0AIAAgAi0AADoAByADQQhrIQMgBEEIayEEIABBCGohACACQQFqIQIMBgsgByEAIAUhBCAGIQMMBQsgByEAIAUhBCAGIQMMBAsgByEAIAUhBCAGIQMMAwsgByEAIAUhBCAGIQMMAgsgByEAIAUhBCAGIQMMAQsgByEAIAUhBCAGIQMLAkAgA0EXTQRAIARFDQEgBEEBayEBIARBB3EiAwRAA0AgACACLQAAOgAAIARBAWshBCAAQQFqIQAgAkEBaiECIANBAWsi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CyAAIAMtAAAEfiADKQMQBUIAC6dB//8DcSADKAIEEEcLIQUgAxAICyAEQRBqJAAgBQvgAQICfwF+QTAQCSICRQRAIAEEQCABQQA2AgQgAUEONgIAC0EADwsgAkIANwMIIAJBADYCACACQgA3AxAgAkIANwMYIAJCADcDICACQgA3ACUgAFAEQCACDwsCQCAAQv////8AVg0AIACnQQR0EAkiA0UNACACIAM2AgBBACEBQgEhBANAIAMgAUEEdGoiAUIANwIAIAFCADcABSAAIARSBEAgBKchASAEQgF8IQQMAQsLIAIgADcDCCACIAA3AxAgAg8LIAEEQCABQQA2AgQgAUEONgIAC0EAEBAgAhAGQQAL7gECA38BfiMAQRBrIgQkAAJAIARBDGpCBBAXIgNFBEBBfyECDAELAkAgAQRAIAJBgAZxIQUDQAJAIAUgASgCBHFFDQACQCADKQMIQgBUBEAgA0EAOgAADAELIANCADcDECADQQE6AAALIAMgAS8BCBANIAMgAS8BChANIAMtAABFBEAgAEEIaiIABEAgAEEANgIEIABBFDYCAAtBfyECDAQLQX8hAiAAIARBDGpCBBAbQQBIDQMgATMBCiIGUA0AIAAgASgCDCAGEBtBAEgNAwsgASgCACIBDQALC0EAIQILIAMQCAsgBEEQaiQAIAILPAEBfyAABEAgAUGABnEhAQNAIAEgACgCBHEEQCACIAAvAQpqQQRqIQILIAAoAgAiAA0ACwsgAkH//wNxC5wBAQN/IABFBEBBAA8LIAAhAwNAAn8CQAJAIAAvAQgiAUH04AFNBEAgAUEBRg0BIAFB9cYBRg0BDAILIAFBgbICRg0AIAFB9eABRw0BCyAAKAIAIQEgAEEANgIAIAAoAgwQBiAAEAYgASADIAAgA0YbIQMCQCACRQRAQQAhAgwBCyACIAE2AgALIAEMAQsgACICKAIACyIADQALIAMLsgQCBX8BfgJAAkACQCAAIAGtEBciAQRAIAEtAAANAUEAIQAMAgsgBARAIARBADYCBCAEQQ42AgALQQAPC0EAIQADQCABLQAABH4gASkDCCABKQMQfQVCAAtCBFQNASABEAwhByABIAEQDCIGrRATIghFBEBBACECIAQEQCAEQQA2AgQgBEEVNgIACyABEAggAEUNAwNAIAAoAgAhASAAKAIMEAYg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DCAAQRg2AggLDAMLIAAgBiAFLwFqQQAgBCABEQYAIQEgBhALIAFFDQILAkAgDUUEQCABIQMMAQsgACABIAUvAWgQgQEhAyABEAsgA0UNAQsCQCAJRSAMckUEQCADIQEMAQsgACADQQEQgAEhASADEAsgAUUNAQsgASEDDAELQQAhAwsgBUHwAGokACADC4UBAQF/IAFFBEAgAEEIaiIABEAgAEEANgIEIABBEjYCAAtBAA8LQTgQCSIDRQRAIABBCGoiAARAIABBADYCBCAAQQ42AgALQQAPCyADQQA2AhAgA0IANwIIIANCADcDKCADQQA2AgQgAyACNgIAIANCADcDGCADQQA2AjAgACABQTsgAxBCCw8AIAAgASACQQBBABCCAQusAgECfyABRQRAIABBCGoiAARAIABBADYCBCAAQRI2AgALQQAPCwJAIAJBfUsNACACQf//A3FBCEYNACAAQQhqIgAEQCAAQQA2AgQgAEEQNgIAC0EADwsCQEGwwAAQCSIFBEAgBUEANgIIIAVCADcCACAFQYiBAUGogQEgAxs2AqhAIAUgAjYCFCAFIAM6ABAgBUEAOgAPIAVBADsBDCAFIAMgAkF9SyIGcToADiAFQQggAiAGG0H//wNxIAQgBUGIgQFBqIEBIAMbKAIAEQAAIgI2AqxAIAINASAFEDEgBRAGCyAAQQhqIgAEQCAAQQA2AgQgAEEONgIAC0EADwsgACABQTogBRBCIgAEfyAABSAFKAKsQCAFKAKoQCgCBBEDACAFEDEgBRAGQQALC6ABAQF/IAIgACgCBCIDIAIgA0kbIgIEQCAAIAMgAms2AgQCQAJAAkACQCAAKAIcIgMoAhRBAWsOAgEAAgsgA0GgAWogASAAKAIAIAJB3IABKAIAEQgADAILIAAgACgCMCABIAAoAgAgAkHEgAEoAgARBAA2AjAMAQsgASAAKAIAIAIQBxoLIAAgACgCACACajYCACAAIAAoAgggAmo2AggLC7cCAQR/QX4hAgJAIABFDQAgACgCIEUNACAAKAIkIgRFDQAgACgCHCIBRQ0AIAEoAgAgAEcNAAJAAkAgASgCICIDQTlrDjkBAgICAgICAgICAgIBAgICAQICAgICAgICAgICAgICAgICAQICAgICAgICAgICAQICAgICAgICAgEACyADQZoFRg0AIANBKkcN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DCABajYCDCAGIAYoAgggAWo2AgggBSAFKAIUIAFqNgIUIAUgBSgCECABazYCECAGIAYoAhAgAWsiATYCECABDQAgBiAGKAIENgIIC0EAIQRBACEJIAMoAhBFDQAMCgsgAygCHCgCJCEGIAMgAygCGCIBQQFqNgIYIAEgBmotAAAhASADIARBAWo2AhAgAygCBCAEaiABOgAAIAEEQCADKAIQIQQMAQsLIAMoAhwoAixFDQAgAygCECIGIAlNDQAgBQJ/IAUoAjAhBEEAIAMoAgQgCWoiAUUNABogBCABIAYgCWtB1IABKAIAEQAACzYCMAsgA0HnADYCIAsCQCADKAIcKAIsBEAgAygCDCADKAIQIgFBAmpJBH8gBRAKIAMoAhANAkEABSABCyADKAIEaiAFKAIwOwAAIAMgAygCEEECajYCECADQaABakHkgAEoAgARAQAaCyADQfEANgIgIAUQCiADKAIQRQ0BDAcLDAYLIAUoAgQNAQsgAygCPA0AIApFDQEgAygCIEGaBUYNAQsCfyADKAKIASIBRQRAIAMgChCFAQwBCwJAAkACQCADKAKMAUECaw4CAAECCwJ/AkADQAJAAkAgAygCPA0AIAMQLyADKAI8DQAgCg0BQQAMBAsgAygCSCADKAJoai0AACEEIAMgAygC8C0iAUEBajYC8C0gASADKALsLWpBADoAACADIAMoAvAtIgFBAWo2AvAtIAEgAygC7C1qQQA6AAAgAyADKALwLSIBQQFqNgLwLSABIAMoAuwtaiAEOgAAIAMgBEECdGoiASABLwHkAUEBajsB5AEgAyADKAI8QQFrNgI8IAMgAygCaEEBaiIBNgJoIAMoAvAtIAMoAvQtRw0BQQAhBCADIAMoAlgiBkEATgR/IAMoAkggBmoFQQALIAEgBmtBABAPIAMgAygCaDYCWCADKAIAEAogAygCACgCEA0BDAILCyADQQA2AoQuIApBBEYEQCADIAMoAlgiAUEATgR/IAMoAkggAWoFQQALIAMoAmggAWtBARAPIAMgAygCaDYCWCADKAIAEApBA0ECIAMoAgAoAhAbDAILIAMoAvAtBEBBACEEIAMgAygCWCIBQQBOBH8gAygCSCABagVBAAsgAygCaCABa0EAEA8gAyADKAJoNgJYIAMoAgAQCiADKAIAKAIQRQ0BC0EBIQQLIAQL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bGl0ZXJhbC9sZW5ndGhzIHNldABpbnZhbGlkIGNvZGUgbGVuZ3RocyBzZXQAdW5rbm93biBoZWFkZXIgZmxhZ3Mgc2V0AGludmFsaWQgZGlzdGFuY2VzIHNldABpbnZhbGlkIGJpdCBsZW5ndGggcmVwZWF0AEZpbGUgYWxyZWFkeSBleGlzdHMAdG9vIG1hbnkgbGVuZ3RoIG9yIGRpc3RhbmNlIHN5bWJvbHMAaW52YWxpZCBzdG9yZWQgYmxvY2sgbGVuZ3RocwAlcyVzJXMAYnVmZmVyIGVycm9yAE5vIGVycm9yAHN0cmVhbSBlcnJvcgBUZWxsIGVycm9yAEludGVybmFsIGVycm9yAFNlZWsgZXJyb3IAV3JpdGUgZXJyb3IAZmlsZSBlcnJvcgBSZWFkIGVycm9yAFpsaWIgZXJyb3IAZGF0YSBlcnJvcgBDUkMgZXJyb3IAaW5jb21wYXRpYmxlIHZlcnNpb24AaW52YWxpZCBjb2RlIC0tIG1pc3NpbmcgZW5kLW9mLWJsb2NrAGluY29ycmVjdCBoZWFkZXIgY2hlY2sAaW5jb3JyZWN0IGxlbmd0aCBjaGVjawBpbmNvcnJlY3QgZGF0YSBjaGVjawBpbnZhbGlkIGRpc3RhbmNlIHRvbyBmYXIgYmFjawBoZWFkZXIgY3JjIG1pc21hdGNoADEuMi4xMy56bGliLW5nAGludmFsaWQgd2luZG93IHNpemUAUmVhZC1vbmx5IGFyY2hpdmUATm90IGEgemlwIGFyY2hpdmUAUmVzb3VyY2Ugc3RpbGwgaW4gdXNlAE1hbGxvYyBmYWlsdXJlAGludmFsaWQgYmxvY2sgdHlwZQBGYWlsdXJlIHRvIGNyZWF0ZSB0ZW1wb3JhcnkgZmlsZQBDYW4ndCBvcGVuIGZpbGUATm8gc3VjaCBmaWxlAFByZW1hdHVyZSBlbmQgb2YgZmlsZQBDYW4ndCByZW1vdmUgZmlsZQBpbnZhbGlkIGxpdGVyYWwvbGVuZ3RoIGNvZGUAaW52YWxpZCBkaXN0YW5jZSBjb2RlAHVua25vd24gY29tcHJlc3Npb24gbWV0aG9kAHN0cmVhbSBlbmQAQ29tcHJlc3NlZCBkYXRhIGludmFsaWQATXVsdGktZGlzayB6aXAgYXJjaGl2ZXMgbm90IHN1cHBvcnRl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UgAIANIACAAyAAgAsgAIAHIACADyAAgACgAIAIoACABKAAgAygAIACoACACqAAgAagAIAOoACAAaAAgAmgAIAFoACADaAAgAOgAIALoACAB6AAgA+gAIAAYACACGAAgARgAIAMYACAAmAAgApgAIAGYACADmAAgAFgAIAJYACABWAAgA1gAIADYACAC2AAgAdgAIAPYACAAOAAgAjgAIAE4ACADOAAgALgAIAK4ACABuAAgA7gAIAB4ACACeAAgAXgAIAN4ACAA+AAgAvgAIAH4ACAD+AAgAAQAIAIEACABBAAgAwQAIACEACAChAAgAYQAIAOEACAARAAgAkQAIAFEACADRAAgAMQAIALEACABxAAgA8QAIAAkACACJAAgASQAIAMkACAApAAgAqQAIAGkACADpAAgAGQAIAJkACABZAAgA2QAIADkACAC5AAgAeQAIAPkACAAFAAgAhQAIAEUACADFAAgAJQAIAKUACABlAAgA5QAIABUACACVAAgAVQAIANUACAA1AAgAtQAIAHUACAD1AAgADQAIAI0ACABNAAgAzQAIAC0ACACtAAgAbQAIAO0ACAAdAAgAnQAIAF0ACADdAAgAPQAIAL0ACAB9AAgA/QAIABMACQATAQkAkwAJAJMBCQBTAAkAUwEJANMACQDTAQkAMwAJADMBCQCzAAkAswEJAHMACQBzAQkA8wAJAPMBCQALAAkACwEJAIsACQCLAQkASwAJAEsBCQDLAAkAywEJACsACQArAQkAqwAJAKsBCQBrAAkAawEJAOsACQDrAQkAGwAJABsBCQCbAAkAmwEJAFsACQBbAQkA2wAJANsBCQA7AAkAOwEJALsACQC7AQkAewAJAHsBCQD7AAkA+wEJAAcACQAHAQkAhwAJAIcBCQBHAAkARwEJAMcACQDHAQkAJwAJACcBCQCnAAkApwEJAGcACQBnAQkA5wAJAOcBCQAXAAkAFwEJAJcACQCXAQkAVwAJAFcBCQDXAAkA1wEJADcACQA3AQkAtwAJALcBCQB3AAkAdwEJAPcACQD3AQkADwAJAA8BCQCPAAkAjwEJAE8ACQBPAQkAzwAJAM8BCQAvAAkALwEJAK8ACQCvAQkAbwAJAG8BCQDvAAkA7wEJAB8ACQAfAQkAnwAJAJ8BCQBfAAkAXwEJAN8ACQDfAQkAPwAJAD8BCQC/AAkAvwEJAH8ACQB/AQkA/wAJAP8BCQAAAAcAQAAHACAABwBgAAcAEAAHAFAABwAwAAcAcAAHAAgABwBIAAcAKAAHAGgABwAYAAcAWAAHADgABwB4AAcABAAHAEQABwAkAAcAZAAHABQABwBUAAcANAAHAHQABwADAAgAgwAIAEMACADDAAgAIwAIAKMACABjAAgA4wAIAAAABQAQAAUACAAFABgABQAEAAUAFAAFAAwABQAcAAUAAgAFABIABQAKAAUAGgAFAAYABQAWAAUADgAFAB4ABQABAAUAEQAFAAkABQAZAAUABQAFABUABQANAAUAHQAFAAMABQATAAUACwAFABsABQAHAAUAFwAFAEGBywAL7AYBAgMEBAUFBgYGBgcHBwcICAgICAgICAkJCQkJCQkJCgoKCgoKCgoKCgoKCgoKCgsLCwsLCwsLCwsLCwsLCwsMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8AABAREhITExQUFBQVFRUVFhYWFhYWFhYXFxcXFxcXFxgYGBgYGBgYGBgYGBgYGBgZGRkZGRkZGRkZGRkZGRkZGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhobGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwdHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dAAECAwQFBgcICAkJCgoLCwwMDAwNDQ0NDg4ODg8PDw8QEBAQEBAQEBEREREREREREhISEhISEhITExMTExMTExQUFBQUFBQUFBQUFBQUFBQVFRUVFRUVFRUVFRUVFRUVFhYWFhYWFhYWFhYWFhYWFhcXFxcXFxcXFxcXFxcXFxcYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhobGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbHAAAAAABAAAAAgAAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAoAAAAMAAAADgAAABAAAAAUAAAAGAAAABwAAAAgAAAAKAAAADAAAAA4AAAAQAAAAFAAAABgAAAAcAAAAIAAAACgAAAAwAAAAOAAQYTSAAutAQEAAAACAAAAAwAAAAQAAAAGAAAACAAAAAwAAAAQAAAAGAAAACAAAAAwAAAAQAAAAGAAAACAAAAAwAAAAAABAACAAQAAAAIAAAADAAAABAAAAAYAAAAIAAAADAAAABAAAAAYAAAAIAAAADAAAABAAAAAYAAAgCAAAMApAAABAQAAHgEAAA8AAAAAJQAAQCoAAAAAAAAeAAAADwAAAAAAAADAKgAAAAAAABMAAAAHAEHg0wALTQEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAAQAAAAEAAAABAAAAAQAAAAFAAAABQAAAAUAAAAFAEHQ1AALZQEAAAABAAAAAgAAAAIAAAADAAAAAwAAAAQAAAAEAAAABQAAAAUAAAAGAAAABgAAAAcAAAAHAAAACAAAAAgAAAAJAAAACQAAAAoAAAAKAAAACwAAAAsAAAAMAAAADAAAAA0AAAANAEGA1gALIwIAAAADAAAABwAAAAAAAAAQERIACAcJBgoFCwQMAw0CDgEPAEHQ1gALTQEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAAQAAAAEAAAABAAAAAQAAAAFAAAABQAAAAUAAAAFAEHA1wALZQEAAAABAAAAAgAAAAIAAAADAAAAAwAAAAQAAAAEAAAABQAAAAUAAAAGAAAABgAAAAcAAAAHAAAACAAAAAgAAAAJAAAACQAAAAoAAAAKAAAACwAAAAsAAAAMAAAADAAAAA0AAAANAEG42AALASwAQcTYAAthLQAAAAQABAAIAAQALgAAAAQABgAQAAYALwAAAAQADAAgABgALwAAAAgAEAAgACAALwAAAAgAEACAAIAALwAAAAgAIACAAAABMAAAACAAgAACAQAEMAAAACAAAgECAQAQMABBsNkAC6UTAwAEAAUABgAHAAgACQAKAAsADQAPABEAEwAXABsAHwAjACsAMwA7AEMAUwBjAHMAgwCjAMMA4wACAQAAAAAAABAAEAAQABAAEAAQABAAEAARABEAEQARABIAEgASABIAEwATABMAEwAUABQAFAAUABUAFQAVABUAEABNAMoAAAABAAIAAwAEAAUABwAJAA0AEQAZACEAMQBBAGEAgQDBAAEBgQEBAgEDAQQBBgEIAQwBEAEYASABMAFAAWAAAAAAEAAQABAAEAARABEAEgASABMAEwAUABQAFQAVABYAFgAXABcAGAAYABkAGQAaABoAGwAbABwAHAAdAB0AQABAAGAHAAAACFAAAAgQABQIcwASBx8AAAhwAAAIMAAACcAAEAcKAAAIYAAACCAAAAmgAAAIAAAACIAAAAhAAAAJ4AAQBwYAAAhYAAAIGAAACZAAEwc7AAAIeAAACDgAAAnQABEHEQAACGgAAAgoAAAJsAAACAgAAAiIAAAISAAACfAAEAcEAAAIVAAACBQAFQjjABMHKwAACHQAAAg0AAAJyAARBw0AAAhkAAAIJAAACagAAAgEAAAIhAAACEQAAAnoABAHCAAACFwAAAgcAAAJmAAUB1MAAAh8AAAIPAAACdgAEgcXAAAIbAAACCwAAAm4AAAIDAAACIwAAAhMAAAJ+AAQBwMAAAhSAAAIEgAVCKMAEwcjAAAIcgAACDIAAAnEABEHCwAACGIAAAgiAAAJpAAACAIAAAiCAAAIQgAACeQAEAcHAAAIWgAACBoAAAmUABQHQwAACHoAAAg6AAAJ1AASBxMAAAhqAAAIKgAACbQAAAgKAAAIigAACEoAAAn0ABAHBQAACFYAAAgWAEAIAAATBzMAAAh2AAAINgAACcwAEQcPAAAIZgAACCYAAAmsAAAIBgAACIYAAAhGAAAJ7AAQBwkAAAheAAAIHgAACZwAFAdjAAAIfgAACD4AAAncABIHGwAACG4AAAguAAAJvAAACA4AAAiOAAAITgAACfwAYAcAAAAIUQAACBEAFQiDABIHHwAACHEAAAgxAAAJwgAQBwoAAAhhAAAIIQAACaIAAAgBAAAIgQAACEEAAAniABAHBgAACFkAAAgZAAAJkgATBzsAAAh5AAAIOQAACdIAEQcRAAAIaQAACCkAAAmyAAAICQAACIkAAAhJAAAJ8gAQBwQAAAhVAAAIFQAQCAIBEwcrAAAIdQAACDUAAAnKABEHDQAACGUAAAglAAAJqgAACAUAAAiFAAAIRQAACeoAEAcIAAAIXQAACB0AAAmaABQHUwAACH0AAAg9AAAJ2gASBxcAAAhtAAAILQAACboAAAgNAAAIjQAACE0AAAn6ABAHAwAACFMAAAgTABUIwwATByMAAAhzAAAIMwAACcYAEQcLAAAIYwAACCMAAAmmAAAIAwAACIMAAAhDAAAJ5gAQBwcAAAhbAAAIGwAACZYAFAdDAAAIewAACDsAAAnWABIHEwAACGsAAAgrAAAJtgAACAsAAAiLAAAISwAACfYAEAcFAAAIVwAACBcAQAgAABMHMwAACHcAAAg3AAAJzgARBw8AAAhnAAAIJwAACa4AAAgHAAAIhwAACEcAAAnuABAHCQAACF8AAAgfAAAJngAUB2MAAAh/AAAIPwAACd4AEgcbAAAIbwAACC8AAAm+AAAIDwAACI8AAAhPAAAJ/gBgBwAAAAhQAAAIEAAUCHMAEgcfAAAIcAAACDAAAAnBABAHCgAACGAAAAggAAAJoQAACAAAAAiAAAAIQAAACeEAEAcGAAAIWAAACBgAAAmRABMHOwAACHgAAAg4AAAJ0QARBxEAAAhoAAAIKAAACbEAAAgIAAAIiAAACEgAAAnxABAHBAAACFQAAAgUABUI4wATBysAAAh0AAAINAAACckAEQcNAAAIZAAACCQAAAmpAAAIBAAACIQAAAhEAAAJ6QAQBwgAAAhcAAAIHAAACZkAFAdTAAAIfAAACDwAAAnZABIHFwAACGwAAAgsAAAJuQAACAwAAAiMAAAITAAACfkAEAcDAAAIUgAACBIAFQijABMHIwAACHIAAAgyAAAJxQARBwsAAAhiAAAIIgAACaUAAAgCAAAIggAACEIAAAnlABAHBwAACFoAAAgaAAAJlQAUB0MAAAh6AAAIOgAACdUAEgcTAAAIagAACCoAAAm1AAAICgAACIoAAAhKAAAJ9QAQBwUAAAhWAAAIFgBACAAAEwczAAAIdgAACDYAAAnNABEHDwAACGYAAAgmAAAJrQAACAYAAAiGAAAIRgAACe0AEAcJAAAIXgAACB4AAAmdABQHYwAACH4AAAg+AAAJ3QASBxsAAAhuAAAILgAACb0AAAgOAAAIjgAACE4AAAn9AGAHAAAACFEAAAgRABUIgwASBx8AAAhxAAAIMQAACcMAEAcKAAAIYQAACCEAAAmjAAAIAQAACIEAAAhBAAAJ4wAQBwYAAAhZAAAIGQAACZMAEwc7AAAIeQAACDkAAAnTABEHEQAACGkAAAgpAAAJswAACAkAAAiJAAAISQAACfMAEAcEAAAIVQAACBUAEAgCARMHKwAACHUAAAg1AAAJywARBw0AAAhlAAAIJQAACasAAAgFAAAIhQAACEUAAAnrABAHCAAACF0AAAgdAAAJmwAUB1MAAAh9AAAIPQAACdsAEgcXAAAIbQAACC0AAAm7AAAIDQAACI0AAAhNAAAJ+wAQBwMAAAhTAAAIEwAVCMMAEwcjAAAIcwAACDMAAAnHABEHCwAACGMAAAgjAAAJpwAACAMAAAiDAAAIQwAACecAEAcHAAAIWwAACBsAAAmXABQHQwAACHsAAAg7AAAJ1wASBxMAAAhrAAAIKwAACbcAAAgLAAAIiwAACEsAAAn3ABAHBQAACFcAAAgXAEAIAAATBzMAAAh3AAAINwAACc8AEQcPAAAIZwAACCcAAAmvAAAIBwAACIcAAAhHAAAJ7wAQBwkAAAhfAAAIHwAACZ8AFAdjAAAIfwAACD8AAAnfABIHGwAACG8AAAgvAAAJvwAACA8AAAiPAAAITwAACf8AEAUBABcFAQETBREAGwUBEBEFBQAZBQEEFQVBAB0FAUAQBQMAGAUBAhQFIQAcBQEgEgUJABoFAQgWBYEAQAUAABAFAgAXBYEBEwUZABsFARgRBQcAGQUBBhUFYQAdBQFgEAUEABgFAQMUBTEAHAUBMBIFDQAaBQEMFgXBAEAFAAAQABEAEgAAAAgABwAJAAYACgAFAAsABAAMAAMADQACAA4AAQAPAEHg7AALQREACgAREREAAAAABQAAAAAAAAkAAAAACwAAAAAAAAAAEQAPChEREQMKBwABAAkLCwAACQYLAAALAAYRAAAAERERAEGx7QALIQsAAAAAAAAAABEACgoREREACgAAAgAJCwAAAAkACwAACwBB6+0ACwEMAEH37QALFQwAAAAADAAAAAAJDAAAAAAADAAADABBpe4ACwEOAEGx7gALFQ0AAAAEDQAAAAAJDgAAAAAADgAADgBB3+4ACwEQAEHr7gALHg8AAAAADwAAAAAJEAAAAAAAEAAAEAAAEgAAABISEgBBou8ACw4SAAAAEhISAAAAAAAACQBB0+8ACwELAEHf7wALFQoAAAAACgAAAAAJCwAAAAAACwAACwBBjfAACwEMAEGZ8AALJwwAAAAADAAAAAAJDAAAAAAADAAADAAAMDEyMzQ1Njc4OUFCQ0RFRgBB5PAACwE+AEGL8QALBf//////AEHQ8QALVxkSRDsCPyxHFD0zMAobBkZLRTcPSQ6OFwNAHTxpKzYfSi0cASAlKSEIDBUWIi4QOD4LNDEYZHR1di9BCX85ESNDMkKJiosFBCYoJw0qHjWMBxpIkxOUlQBBsPIAC4oOSWxsZWdhbCBieXRlIHNlcXVlbmNlAERvbWFpbiBlcnJvcgBSZXN1bHQgbm90IHJlcHJlc2VudGFibGUATm90IGEgdHR5AFBlcm1pc3Npb24gZGVuaWVkAE9wZXJhdGlvbiBub3QgcGVybWl0dGVkAE5vIHN1Y2ggZmlsZSBvciBkaXJlY3RvcnkATm8gc3VjaCBwcm9jZXNzAEZpbGUgZXhpc3RzAFZhbHVlIHRvbyBsYXJnZSBmb3IgZGF0YSB0eXBlAE5vIHNwYWNlIGxlZnQgb24gZGV2aWNlAE91dCBvZiBtZW1vcnkAUmVzb3VyY2UgYnVzeQBJbnRlcnJ1cHRlZCBzeXN0ZW0gY2FsbABSZXNvdXJjZSB0ZW1wb3JhcmlseSB1bmF2YWlsYWJsZQBJbnZhbGlkIHNlZWsAQ3Jvc3MtZGV2aWNlIGxpbmsAUmVhZC1vbmx5IGZpbGUgc3lzdGVtAERpcmVjdG9yeSBub3QgZW1wdHkAQ29ubmVjdGlvbiByZXNldCBieSBwZWVyAE9wZXJhdGlvbiB0aW1lZCBvdXQAQ29ubmVjdGlvbiByZWZ1c2VkAEhvc3QgaXMgZG93bgBIb3N0IGlzIHVucmVhY2hhYmxlAEFkZHJlc3MgaW4gdXNlAEJyb2tlbiBwaXBlAEkvTyBlcnJvcgBObyBzdWNoIGRldmljZSBvciBhZGRyZXNzAEJsb2NrIGRldmljZSByZXF1aXJlZABObyBzdWNoIGRldmljZQBOb3QgYSBkaXJlY3RvcnkASXMgYSBkaXJlY3RvcnkAVGV4dCBmaWxlIGJ1c3kARXhlYyBmb3JtYXQgZXJyb3IASW52YWxpZCBhcmd1bWVudABBcmd1bWVudCBsaXN0IHRvbyBsb25nAFN5bWJvbGljIGxpbmsgbG9vcABGaWxlbmFtZSB0b28gbG9uZwBUb28gbWFueSBvcGVuIGZpbGVzIGluIHN5c3RlbQBObyBmaWxlIGRlc2NyaXB0b3JzIGF2YWlsYWJsZQBCYWQgZmlsZSBkZXNjcmlwdG9yAE5vIGNoaWxkIHByb2Nlc3MAQmFkIGFkZHJlc3MARmlsZSB0b28gbGFyZ2UAVG9vIG1hbnkgbGlua3MATm8gbG9ja3MgYXZhaWxhYmxlAFJlc291cmNlIGRlYWRsb2NrIHdvdWxkIG9jY3VyAFN0YXRlIG5vdCByZWNvdmVyYWJsZQBQcmV2aW91cyBvd25lciBkaWVkAE9wZXJhdGlvbiBjYW5jZWxlZABGdW5jdGlvbiBub3QgaW1wbGVtZW50ZWQATm8gbWVzc2FnZSBvZiBkZXNpcmVkIHR5cGUASWRlbnRpZmllciByZW1vdmVkAERldmljZSBub3QgYSBzdHJlYW0ATm8gZGF0YSBhdmFpbGFibGUARGV2aWNlIHRpbWVvdXQAT3V0IG9mIHN0cmVhbXMgcmVzb3VyY2VzAExpbmsgaGFzIGJlZW4gc2V2ZXJlZABQcm90b2NvbCBlcnJvcgBCYWQgbWVzc2FnZQBGaWxlIGRlc2NyaXB0b3IgaW4gYmFkIHN0YXRlAE5vdCBhIHNvY2tldABEZXN0aW5hdGlvbiBhZGRyZXNzIHJlcXVpcmVkAE1lc3NhZ2UgdG9vIGxhcmdlAFByb3RvY29sIHdyb25nIHR5cGUgZm9yIHNvY2tldABQcm90b2NvbCBub3QgYXZhaWxhYmxlAFByb3RvY29sIG5vdCBzdXBwb3J0ZWQAU29ja2V0IHR5cGUgbm90IHN1cHBvcnRlZABOb3Qgc3VwcG9ydGVkAFByb3RvY29sIGZhbWlseSBub3Qgc3VwcG9ydGVkAEFkZHJlc3MgZmFtaWx5IG5vdCBzdXBwb3J0ZWQgYnkgcHJvdG9jb2wAQWRkcmVzcyBub3QgYXZhaWxhYmxlAE5ldHdvcmsgaXMgZG93bgBOZXR3b3JrIHVucmVhY2hhYmxlAENvbm5lY3Rpb24gcmVzZXQgYnkgbmV0d29yawBDb25uZWN0aW9uIGFib3J0ZWQATm8gYnVmZmVyIHNwYWNlIGF2YWlsYWJsZQBTb2NrZXQgaXMgY29ubmVjdGVkAFNvY2tldCBub3QgY29ubmVjdGVkAENhbm5vdCBzZW5kIGFmdGVyIHNvY2tldCBzaHV0ZG93bgBPcGVyYXRpb24gYWxyZWFkeSBpbiBwcm9ncmVzcwBPcGVyYXRpb24gaW4gcHJvZ3Jlc3MAU3RhbGUgZmlsZSBoYW5kbGUAUmVtb3RlIEkvTyBlcnJvcgBRdW90YSBleGNlZWRlZABObyBtZWRpdW0gZm91bmQAV3JvbmcgbWVkaXVtIHR5cGUATm8gZXJyb3IgaW5mb3JtYXRpb24AQcCAAQuFARMAAAAUAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAGwAAABwAAAAdAAAAHgAAAB8AAAAgAAAAIQAAACIAAAAjAAAAgERQADEAAAAyAAAAMwAAADQAAAA1AAAANgAAADcAAAA4AAAAOQAAADIAAAAzAAAANAAAADUAAAA2AAAANwAAADgAQfSCAQsCXEQAQbCDAQsQ/////////////////////w==\";Zs(bi)||(bi=b(bi));function Fs(ze){try{if(ze==bi&&ue)return new Uint8Array(ue);var it=ia(ze);if(it)return it;if(T)return T(ze);throw\"sync fetching of the wasm failed: you can preload it to Module['wasmBinary'] manually, or emcc.py will do that for you when generating HTML (but not JS)\"}catch(vt){Hi(vt)}}function $s(ze,it){var vt,ar,ee;try{ee=Fs(ze),ar=new WebAssembly.Module(ee),vt=new WebAssembly.Instance(ar,it)}catch(Ne){var ye=Ne.toString();throw te(\"failed to compile wasm module: \"+ye),(ye.includes(\"imported Memory\")||ye.includes(\"memory import\"))&&te(\"Memory size incompatibility issues may be due to changing INITIAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set INITIAL_MEMORY at runtime to something smaller than it was at compile time).\"),Ne}return[vt,ar]}function SA(){var ze={a:dc};function it(ee,ye){var Ne=ee.exports;r.asm=Ne,De=r.asm.g,J(De.buffer),$=r.asm.W,cn(r.asm.h),Xs(\"wasm-instantiate\")}if($n(\"wasm-instantiate\"),r.instantiateWasm)try{var vt=r.instantiateWasm(ze,it);return vt}catch(ee){return te(\"Module.instantiateWasm callback failed with error: \"+ee),!1}var ar=$s(bi,ze);return it(ar[0]),r.asm}function gu(ze){return R.getFloat32(ze,!0)}function op(ze){return R.getFloat64(ze,!0)}function ap(ze){return R.getInt16(ze,!0)}function Rs(ze){return R.getInt32(ze,!0)}function Nn(ze,it){R.setInt32(ze,it,!0)}function hs(ze){for(;ze.length>0;){var it=ze.shift();if(typeof it==\"function\"){it(r);continue}var vt=it.func;typeof vt==\"number\"?it.arg===void 0?$.get(vt)():$.get(vt)(it.arg):vt(it.arg===void 0?null:it.arg)}}function Ts(ze,it){var vt=new Date(Rs((ze>>2)*4)*1e3);Nn((it>>2)*4,vt.getUTCSeconds()),Nn((it+4>>2)*4,vt.getUTCMinutes()),Nn((it+8>>2)*4,vt.getUTCHours()),Nn((it+12>>2)*4,vt.getUTCDate()),Nn((it+16>>2)*4,vt.getUTCMonth()),Nn((it+20>>2)*4,vt.getUTCFullYear()-1900),Nn((it+24>>2)*4,vt.getUTCDay()),Nn((it+36>>2)*4,0),Nn((it+32>>2)*4,0);var ar=Date.UTC(vt.getUTCFullYear(),0,1,0,0,0,0),ee=(vt.getTime()-ar)/(1e3*60*60*24)|0;return Nn((it+28>>2)*4,ee),Ts.GMTString||(Ts.GMTString=nt(\"GMT\")),Nn((it+40>>2)*4,Ts.GMTString),it}function pc(ze,it){return Ts(ze,it)}function hc(ze,it,vt){xe.copyWithin(ze,it,it+vt)}function gc(ze){try{return De.grow(ze-ke.byteLength+65535>>>16),J(De.buffer),1}catch{}}function xA(ze){var it=xe.length;ze=ze>>>0;var vt=2147483648;if(ze>vt)return!1;for(var ar=1;ar<=4;ar*=2){var ee=it*(1+.2/ar);ee=Math.min(ee,ze+100663296);var ye=Math.min(vt,Te(Math.max(ze,ee),65536)),Ne=gc(ye);if(Ne)return!0}return!1}function bA(ze){ce(ze)}function Ro(ze){var it=Date.now()/1e3|0;return ze&&Nn((ze>>2)*4,it),it}function To(){if(To.called)return;To.called=!0;var ze=new Date().getFullYear(),it=new Date(ze,0,1),vt=new Date(ze,6,1),ar=it.getTimezoneOffset(),ee=vt.getTimezoneOffset(),ye=Math.max(ar,ee);Nn((ja()>>2)*4,ye*60),Nn((rs()>>2)*4,+(ar!=ee));function Ne(sn){var ei=sn.toTimeString().match(/\\(([A-Za-z ]+)\\)$/);return ei?ei[1]:\"GMT\"}var gt=Ne(it),mt=Ne(vt),Dt=nt(gt),er=nt(mt);ee<ar?(Nn((Di()>>2)*4,Dt),Nn((Di()+4>>2)*4,er)):(Nn((Di()>>2)*4,er),Nn((Di()+4>>2)*4,Dt))}function kA(ze){To();var it=Date.UTC(Rs((ze+20>>2)*4)+1900,Rs((ze+16>>2)*4),Rs((ze+12>>2)*4),Rs((ze+8>>2)*4),Rs((ze+4>>2)*4),Rs((ze>>2)*4),0),vt=new Date(it);Nn((ze+24>>2)*4,vt.getUTCDay());var ar=Date.UTC(vt.getUTCFullYear(),0,1,0,0,0,0),ee=(vt.getTime()-ar)/(1e3*60*60*24)|0;return Nn((ze+28>>2)*4,ee),vt.getTime()/1e3|0}var pr=typeof atob==\"function\"?atob:function(ze){var it=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\",vt=\"\",ar,ee,ye,Ne,gt,mt,Dt,er=0;ze=ze.replace(/[^A-Za-z0-9\\+\\/\\=]/g,\"\");do Ne=it.indexOf(ze.charAt(er++)),gt=it.indexOf(ze.charAt(er++)),mt=it.indexOf(ze.charAt(er++)),Dt=it.indexOf(ze.charAt(er++)),ar=Ne<<2|gt>>4,ee=(gt&15)<<4|mt>>2,ye=(mt&3)<<6|Dt,vt=vt+String.fromCharCode(ar),mt!==64&&(vt=vt+String.fromCharCode(ee)),Dt!==64&&(vt=vt+String.fromCharCode(ye));while(er<ze.length);return vt};function Me(ze){if(typeof w==\"boolean\"&&w){var it;try{it=Buffer.from(ze,\"base64\")}catch{it=new Buffer(ze,\"base64\")}return new Uint8Array(it.buffer,it.byteOffset,it.byteLength)}try{for(var vt=pr(ze),ar=new Uint8Array(vt.length),ee=0;ee<vt.length;++ee)ar[ee]=vt.charCodeAt(ee);return ar}catch{throw new Error(\"Converting base64 string to bytes failed.\")}}function ia(ze){if(Zs(ze))return Me(ze.slice(Qs.length))}var dc={e:pc,c:hc,d:xA,a:bA,b:Ro,f:kA},Er=SA(),du=r.___wasm_call_ctors=Er.h,QA=r._zip_ext_count_symlinks=Er.i,FA=r._zip_file_get_external_attributes=Er.j,mc=r._zipstruct_statS=Er.k,yc=r._zipstruct_stat_size=Er.l,Il=r._zipstruct_stat_mtime=Er.m,we=r._zipstruct_stat_crc=Er.n,Tt=r._zipstruct_errorS=Er.o,wl=r._zipstruct_error_code_zip=Er.p,Bi=r._zipstruct_stat_comp_size=Er.q,Ls=r._zipstruct_stat_comp_method=Er.r,Ft=r._zip_close=Er.s,Bn=r._zip_delete=Er.t,Lo=r._zip_dir_add=Er.u,ki=r._zip_discard=Er.v,vi=r._zip_error_init_with_code=Er.w,sa=r._zip_get_error=Er.x,un=r._zip_file_get_error=Er.y,qn=r._zip_error_strerror=Er.z,Ec=r._zip_fclose=Er.A,lp=r._zip_file_add=Er.B,oa=r._free=Er.C,aa=r._malloc=Er.D,la=r._zip_source_error=Er.E,Ze=r._zip_source_seek=Er.F,ca=r._zip_file_set_external_attributes=Er.G,mu=r._zip_file_set_mtime=Er.H,Bl=r._zip_fopen_index=Er.I,dn=r._zip_fread=Er.J,No=r._zip_get_name=Er.K,RA=r._zip_get_num_entries=Er.L,TA=r._zip_source_read=Er.M,Oo=r._zip_name_locate=Er.N,qa=r._zip_open_from_source=Er.O,Ot=r._zip_set_file_compression=Er.P,vn=r._zip_source_buffer=Er.Q,Mo=r._zip_source_buffer_create=Er.R,ua=r._zip_source_close=Er.S,qi=r._zip_source_free=Er.T,vl=r._zip_source_keep=Er.U,Cc=r._zip_source_open=Er.V,Dl=r._zip_source_tell=Er.X,Aa=r._zip_stat_index=Er.Y,Di=r.__get_tzname=Er.Z,rs=r.__get_daylight=Er._,ja=r.__get_timezone=Er.$,yu=r.stackSave=Er.aa,Pl=r.stackRestore=Er.ba,pi=r.stackAlloc=Er.ca;r.cwrap=ie,r.getValue=he;var Dn;Xr=function ze(){Dn||Sl(),Dn||(Xr=ze)};function Sl(ze){if(ze=ze||A,yr>0||(Et(),yr>0))return;function it(){Dn||(Dn=!0,r.calledRun=!0,!Ee&&(qt(),o(r),r.onRuntimeInitialized&&r.onRuntimeInitialized(),nr()))}r.setStatus?(r.setStatus(\"Running...\"),setTimeout(function(){setTimeout(function(){r.setStatus(\"\")},1),it()},1)):it()}if(r.run=Sl,r.preInit)for(typeof r.preInit==\"function\"&&(r.preInit=[r.preInit]);r.preInit.length>0;)r.preInit.pop()();return Sl(),e}}();typeof ub==\"object\"&&typeof MU==\"object\"?MU.exports=OU:typeof define==\"function\"&&define.amd?define([],function(){return OU}):typeof ub==\"object\"&&(ub.createModule=OU)});var Lf,wce,Bce,vce=It(()=>{Lf=[\"number\",\"number\"],wce=(Z=>(Z[Z.ZIP_ER_OK=0]=\"ZIP_ER_OK\",Z[Z.ZIP_ER_MULTIDISK=1]=\"ZIP_ER_MULTIDISK\",Z[Z.ZIP_ER_RENAME=2]=\"ZIP_ER_RENAME\",Z[Z.ZIP_ER_CLOSE=3]=\"ZIP_ER_CLOSE\",Z[Z.ZIP_ER_SEEK=4]=\"ZIP_ER_SEEK\",Z[Z.ZIP_ER_READ=5]=\"ZIP_ER_READ\",Z[Z.ZIP_ER_WRITE=6]=\"ZIP_ER_WRITE\",Z[Z.ZIP_ER_CRC=7]=\"ZIP_ER_CRC\",Z[Z.ZIP_ER_ZIPCLOSED=8]=\"ZIP_ER_ZIPCLOSED\",Z[Z.ZIP_ER_NOENT=9]=\"ZIP_ER_NOENT\",Z[Z.ZIP_ER_EXISTS=10]=\"ZIP_ER_EXISTS\",Z[Z.ZIP_ER_OPEN=11]=\"ZIP_ER_OPEN\",Z[Z.ZIP_ER_TMPOPEN=12]=\"ZIP_ER_TMPOPEN\",Z[Z.ZIP_ER_ZLIB=13]=\"ZIP_ER_ZLIB\",Z[Z.ZIP_ER_MEMORY=14]=\"ZIP_ER_MEMORY\",Z[Z.ZIP_ER_CHANGED=15]=\"ZIP_ER_CHANGED\",Z[Z.ZIP_ER_COMPNOTSUPP=16]=\"ZIP_ER_COMPNOTSUPP\",Z[Z.ZIP_ER_EOF=17]=\"ZIP_ER_EOF\",Z[Z.ZIP_ER_INVAL=18]=\"ZIP_ER_INVAL\",Z[Z.ZIP_ER_NOZIP=19]=\"ZIP_ER_NOZIP\",Z[Z.ZIP_ER_INTERNAL=20]=\"ZIP_ER_INTERNAL\",Z[Z.ZIP_ER_INCONS=21]=\"ZIP_ER_INCONS\",Z[Z.ZIP_ER_REMOVE=22]=\"ZIP_ER_REMOVE\",Z[Z.ZIP_ER_DELETED=23]=\"ZIP_ER_DELETED\",Z[Z.ZIP_ER_ENCRNOTSUPP=24]=\"ZIP_ER_ENCRNOTSUPP\",Z[Z.ZIP_ER_RDONLY=25]=\"ZIP_ER_RDONLY\",Z[Z.ZIP_ER_NOPASSWD=26]=\"ZIP_ER_NOPASSWD\",Z[Z.ZIP_ER_WRONGPASSWD=27]=\"ZIP_ER_WRONGPASSWD\",Z[Z.ZIP_ER_OPNOTSUPP=28]=\"ZIP_ER_OPNOTSUPP\",Z[Z.ZIP_ER_INUSE=29]=\"ZIP_ER_INUSE\",Z[Z.ZIP_ER_TELL=30]=\"ZIP_ER_TELL\",Z[Z.ZIP_ER_COMPRESSED_DATA=31]=\"ZIP_ER_COMPRESSED_DATA\",Z))(wce||{}),Bce=t=>({get HEAPU8(){return t.HEAPU8},errors:wce,SEEK_SET:0,SEEK_CUR:1,SEEK_END:2,ZIP_CHECKCONS:4,ZIP_EXCL:2,ZIP_RDONLY:16,ZIP_FL_OVERWRITE:8192,ZIP_FL_COMPRESSED:4,ZIP_OPSYS_DOS:0,ZIP_OPSYS_AMIGA:1,ZIP_OPSYS_OPENVMS:2,ZIP_OPSYS_UNIX:3,ZIP_OPSYS_VM_CMS:4,ZIP_OPSYS_ATARI_ST:5,ZIP_OPSYS_OS_2:6,ZIP_OPSYS_MACINTOSH:7,ZIP_OPSYS_Z_SYSTEM:8,ZIP_OPSYS_CPM:9,ZIP_OPSYS_WINDOWS_NTFS:10,ZIP_OPSYS_MVS:11,ZIP_OPSYS_VSE:12,ZIP_OPSYS_ACORN_RISC:13,ZIP_OPSYS_VFAT:14,ZIP_OPSYS_ALTERNATE_MVS:15,ZIP_OPSYS_BEOS:16,ZIP_OPSYS_TANDEM:17,ZIP_OPSYS_OS_400:18,ZIP_OPSYS_OS_X:19,ZIP_CM_DEFAULT:-1,ZIP_CM_STORE:0,ZIP_CM_DEFLATE:8,uint08S:t._malloc(1),uint32S:t._malloc(4),malloc:t._malloc,free:t._free,getValue:t.getValue,openFromSource:t.cwrap(\"zip_open_from_source\",\"number\",[\"number\",\"number\",\"number\"]),close:t.cwrap(\"zip_close\",\"number\",[\"number\"]),discard:t.cwrap(\"zip_discard\",null,[\"number\"]),getError:t.cwrap(\"zip_get_error\",\"number\",[\"number\"]),getName:t.cwrap(\"zip_get_name\",\"string\",[\"number\",\"number\",\"number\"]),getNumEntries:t.cwrap(\"zip_get_num_entries\",\"number\",[\"number\",\"number\"]),delete:t.cwrap(\"zip_delete\",\"number\",[\"number\",\"number\"]),statIndex:t.cwrap(\"zip_stat_index\",\"number\",[\"number\",...Lf,\"number\",\"number\"]),fopenIndex:t.cwrap(\"zip_fopen_index\",\"number\",[\"number\",...Lf,\"number\"]),fread:t.cwrap(\"zip_fread\",\"number\",[\"number\",\"number\",\"number\",\"number\"]),fclose:t.cwrap(\"zip_fclose\",\"number\",[\"number\"]),dir:{add:t.cwrap(\"zip_dir_add\",\"number\",[\"number\",\"string\"])},file:{add:t.cwrap(\"zip_file_add\",\"number\",[\"number\",\"string\",\"number\",\"number\"]),getError:t.cwrap(\"zip_file_get_error\",\"number\",[\"number\"]),getExternalAttributes:t.cwrap(\"zip_file_get_external_attributes\",\"number\",[\"number\",...Lf,\"number\",\"number\",\"number\"]),setExternalAttributes:t.cwrap(\"zip_file_set_external_attributes\",\"number\",[\"number\",...Lf,\"number\",\"number\",\"number\"]),setMtime:t.cwrap(\"zip_file_set_mtime\",\"number\",[\"number\",...Lf,\"number\",\"number\"]),setCompression:t.cwrap(\"zip_set_file_compression\",\"number\",[\"number\",...Lf,\"number\",\"number\"])},ext:{countSymlinks:t.cwrap(\"zip_ext_count_symlinks\",\"number\",[\"number\"])},error:{initWithCode:t.cwrap(\"zip_error_init_with_code\",null,[\"number\",\"number\"]),strerror:t.cwrap(\"zip_error_strerror\",\"string\",[\"number\"])},name:{locate:t.cwrap(\"zip_name_locate\",\"number\",[\"number\",\"string\",\"number\"])},source:{fromUnattachedBuffer:t.cwrap(\"zip_source_buffer_create\",\"number\",[\"number\",...Lf,\"number\",\"number\"]),fromBuffer:t.cwrap(\"zip_source_buffer\",\"number\",[\"number\",\"number\",...Lf,\"number\"]),free:t.cwrap(\"zip_source_free\",null,[\"number\"]),keep:t.cwrap(\"zip_source_keep\",null,[\"number\"]),open:t.cwrap(\"zip_source_open\",\"number\",[\"number\"]),close:t.cwrap(\"zip_source_close\",\"number\",[\"number\"]),seek:t.cwrap(\"zip_source_seek\",\"number\",[\"number\",...Lf,\"number\"]),tell:t.cwrap(\"zip_source_tell\",\"number\",[\"number\"]),read:t.cwrap(\"zip_source_read\",\"number\",[\"number\",\"number\",\"number\"]),error:t.cwrap(\"zip_source_error\",\"number\",[\"number\"])},struct:{statS:t.cwrap(\"zipstruct_statS\",\"number\",[]),statSize:t.cwrap(\"zipstruct_stat_size\",\"number\",[\"number\"]),statCompSize:t.cwrap(\"zipstruct_stat_comp_size\",\"number\",[\"number\"]),statCompMethod:t.cwrap(\"zipstruct_stat_comp_method\",\"number\",[\"number\"]),statMtime:t.cwrap(\"zipstruct_stat_mtime\",\"number\",[\"number\"]),statCrc:t.cwrap(\"zipstruct_stat_crc\",\"number\",[\"number\"]),errorS:t.cwrap(\"zipstruct_errorS\",\"number\",[]),errorCodeZip:t.cwrap(\"zipstruct_error_code_zip\",\"number\",[\"number\"])}})});function UU(t,e){let r=t.indexOf(e);if(r<=0)return null;let o=r;for(;r>=0&&(o=r+e.length,t[o]!==K.sep);){if(t[r-1]===K.sep)return null;r=t.indexOf(e,o)}return t.length>o&&t[o]!==K.sep?null:t.slice(0,o)}var iA,Dce=It(()=>{Pt();Pt();sA();iA=class t extends Gp{static async openPromise(e,r){let o=new t(r);try{return await e(o)}finally{o.saveAndClose()}}constructor(e={}){let r=e.fileExtensions,o=e.readOnlyArchives,a=typeof r>\"u\"?A=>UU(A,\".zip\"):A=>{for(let p of r){let h=UU(A,p);if(h)return h}return null},n=(A,p)=>new Zi(p,{baseFs:A,readOnly:o,stats:A.statSync(p)}),u=async(A,p)=>{let h={baseFs:A,readOnly:o,stats:await A.statPromise(p)};return()=>new Zi(p,h)};super({...e,factorySync:n,factoryPromise:u,getMountPoint:a})}}});function tot(t){if(typeof t==\"string\"&&String(+t)===t)return+t;if(typeof t==\"number\"&&Number.isFinite(t))return t<0?Date.now()/1e3:t;if(Pce.types.isDate(t))return t.getTime()/1e3;throw new Error(\"Invalid time\")}function Ab(){return Buffer.from([80,75,5,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])}var ta,_U,Pce,HU,Sce,fb,Zi,qU=It(()=>{Pt();Pt();Pt();Pt();Pt();Pt();ta=ve(\"fs\"),_U=ve(\"stream\"),Pce=ve(\"util\"),HU=et(ve(\"zlib\"));NU();Sce=\"mixed\";fb=class extends Error{constructor(e,r){super(e),this.name=\"Libzip Error\",this.code=r}},Zi=class extends qu{constructor(r,o={}){super();this.listings=new Map;this.entries=new Map;this.fileSources=new Map;this.fds=new Map;this.nextFd=0;this.ready=!1;this.readOnly=!1;let a=o;if(this.level=typeof a.level<\"u\"?a.level:Sce,r??=Ab(),typeof r==\"string\"){let{baseFs:A=new _n}=a;this.baseFs=A,this.path=r}else this.path=null,this.baseFs=null;if(o.stats)this.stats=o.stats;else if(typeof r==\"string\")try{this.stats=this.baseFs.statSync(r)}catch(A){if(A.code===\"ENOENT\"&&a.create)this.stats=wa.makeDefaultStats();else throw A}else this.stats=wa.makeDefaultStats();this.libzip=K1();let n=this.libzip.malloc(4);try{let A=0;o.readOnly&&(A|=this.libzip.ZIP_RDONLY,this.readOnly=!0),typeof r==\"string\"&&(r=a.create?Ab():this.baseFs.readFileSync(r));let p=this.allocateUnattachedSource(r);try{this.zip=this.libzip.openFromSource(p,A,n),this.lzSource=p}catch(h){throw this.libzip.source.free(p),h}if(this.zip===0){let h=this.libzip.struct.errorS();throw this.libzip.error.initWithCode(h,this.libzip.getValue(n,\"i32\")),this.makeLibzipError(h)}}finally{this.libzip.free(n)}this.listings.set(Bt.root,new Set);let u=this.libzip.getNumEntries(this.zip,0);for(let A=0;A<u;++A){let p=this.libzip.getName(this.zip,A,0);if(K.isAbsolute(p))continue;let h=K.resolve(Bt.root,p);this.registerEntry(h,A),p.endsWith(\"/\")&&this.registerListing(h)}if(this.symlinkCount=this.libzip.ext.countSymlinks(this.zip),this.symlinkCount===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));this.ready=!0}makeLibzipError(r){let o=this.libzip.struct.errorCodeZip(r),a=this.libzip.error.strerror(r),n=new fb(a,this.libzip.errors[o]);if(o===this.libzip.errors.ZIP_ER_CHANGED)throw new Error(`Assertion failed: Unexpected libzip error: ${n.message}`);return n}getExtractHint(r){for(let o of this.entries.keys()){let a=this.pathUtils.extname(o);if(r.relevantExtensions.has(a))return!0}return!1}getAllFiles(){return Array.from(this.entries.keys())}getRealPath(){if(!this.path)throw new Error(\"ZipFS don't have real paths when loaded from a buffer\");return this.path}prepareClose(){if(!this.ready)throw sr.EBUSY(\"archive closed, close\");j0(this)}getBufferAndClose(){if(this.prepareClose(),this.entries.size===0)return this.discardAndClose(),Ab();try{if(this.libzip.source.keep(this.lzSource),this.libzip.close(this.zip)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));if(this.libzip.source.open(this.lzSource)===-1)throw this.makeLibzipError(this.libzip.source.error(this.lzSource));if(this.libzip.source.seek(this.lzSource,0,0,this.libzip.SEEK_END)===-1)throw this.makeLibzipError(this.libzip.source.error(this.lzSource));let r=this.libzip.source.tell(this.lzSource);if(r===-1)throw this.makeLibzipError(this.libzip.source.error(this.lzSource));if(this.libzip.source.seek(this.lzSource,0,0,this.libzip.SEEK_SET)===-1)throw this.makeLibzipError(this.libzip.source.error(this.lzSource));let o=this.libzip.malloc(r);if(!o)throw new Error(\"Couldn't allocate enough memory\");try{let a=this.libzip.source.read(this.lzSource,o,r);if(a===-1)throw this.makeLibzipError(this.libzip.source.error(this.lzSource));if(a<r)throw new Error(\"Incomplete read\");if(a>r)throw new Error(\"Overread\");let n=Buffer.from(this.libzip.HEAPU8.subarray(o,o+r));return process.env.YARN_IS_TEST_ENV&&process.env.YARN_ZIP_DATA_EPILOGUE&&(n=Buffer.concat([n,Buffer.from(process.env.YARN_ZIP_DATA_EPILOGUE)])),n}finally{this.libzip.free(o)}}finally{this.libzip.source.close(this.lzSource),this.libzip.source.free(this.lzSource),this.ready=!1}}discardAndClose(){this.prepareClose(),this.libzip.discard(this.zip),this.ready=!1}saveAndClose(){if(!this.path||!this.baseFs)throw new Error(\"ZipFS cannot be saved and must be discarded when loaded from a buffer\");if(this.readOnly){this.discardAndClose();return}let r=this.baseFs.existsSync(this.path)||this.stats.mode===wa.DEFAULT_MODE?void 0:this.stats.mode;this.baseFs.writeFileSync(this.path,this.getBufferAndClose(),{mode:r}),this.ready=!1}resolve(r){return K.resolve(Bt.root,r)}async openPromise(r,o,a){return this.openSync(r,o,a)}openSync(r,o,a){let n=this.nextFd++;return this.fds.set(n,{cursor:0,p:r}),n}hasOpenFileHandles(){return!!this.fds.size}async opendirPromise(r,o){return this.opendirSync(r,o)}opendirSync(r,o={}){let a=this.resolveFilename(`opendir '${r}'`,r);if(!this.entries.has(a)&&!this.listings.has(a))throw sr.ENOENT(`opendir '${r}'`);let n=this.listings.get(a);if(!n)throw sr.ENOTDIR(`opendir '${r}'`);let u=[...n],A=this.openSync(a,\"r\");return eP(this,a,u,{onClose:()=>{this.closeSync(A)}})}async readPromise(r,o,a,n,u){return this.readSync(r,o,a,n,u)}readSync(r,o,a=0,n=o.byteLength,u=-1){let A=this.fds.get(r);if(typeof A>\"u\")throw sr.EBADF(\"read\");let p=u===-1||u===null?A.cursor:u,h=this.readFileSync(A.p);h.copy(o,a,p,p+n);let E=Math.max(0,Math.min(h.length-p,n));return(u===-1||u===null)&&(A.cursor+=E),E}async writePromise(r,o,a,n,u){return typeof o==\"string\"?this.writeSync(r,o,u):this.writeSync(r,o,a,n,u)}writeSync(r,o,a,n,u){throw typeof this.fds.get(r)>\"u\"?sr.EBADF(\"read\"):new Error(\"Unimplemented\")}async closePromise(r){return this.closeSync(r)}closeSync(r){if(typeof this.fds.get(r)>\"u\")throw sr.EBADF(\"read\");this.fds.delete(r)}createReadStream(r,{encoding:o}={}){if(r===null)throw new Error(\"Unimplemented\");let a=this.openSync(r,\"r\"),n=Object.assign(new _U.PassThrough({emitClose:!0,autoDestroy:!0,destroy:(A,p)=>{clearImmediate(u),this.closeSync(a),p(A)}}),{close(){n.destroy()},bytesRead:0,path:r,pending:!1}),u=setImmediate(async()=>{try{let A=await this.readFilePromise(r,o);n.bytesRead=A.length,n.end(A)}catch(A){n.destroy(A)}});return n}createWriteStream(r,{encoding:o}={}){if(this.readOnly)throw sr.EROFS(`open '${r}'`);if(r===null)throw new Error(\"Unimplemented\");let a=[],n=this.openSync(r,\"w\"),u=Object.assign(new _U.PassThrough({autoDestroy:!0,emitClose:!0,destroy:(A,p)=>{try{A?p(A):(this.writeFileSync(r,Buffer.concat(a),o),p(null))}catch(h){p(h)}finally{this.closeSync(n)}}}),{close(){u.destroy()},bytesWritten:0,path:r,pending:!1});return u.on(\"data\",A=>{let p=Buffer.from(A);u.bytesWritten+=p.length,a.push(p)}),u}async realpathPromise(r){return this.realpathSync(r)}realpathSync(r){let o=this.resolveFilename(`lstat '${r}'`,r);if(!this.entries.has(o)&&!this.listings.has(o))throw sr.ENOENT(`lstat '${r}'`);return o}async existsPromise(r){return this.existsSync(r)}existsSync(r){if(!this.ready)throw sr.EBUSY(`archive closed, existsSync '${r}'`);if(this.symlinkCount===0){let a=K.resolve(Bt.root,r);return this.entries.has(a)||this.listings.has(a)}let o;try{o=this.resolveFilename(`stat '${r}'`,r,void 0,!1)}catch{return!1}return o===void 0?!1:this.entries.has(o)||this.listings.has(o)}async accessPromise(r,o){return this.accessSync(r,o)}accessSync(r,o=ta.constants.F_OK){let a=this.resolveFilename(`access '${r}'`,r);if(!this.entries.has(a)&&!this.listings.has(a))throw sr.ENOENT(`access '${r}'`);if(this.readOnly&&o&ta.constants.W_OK)throw sr.EROFS(`access '${r}'`)}async statPromise(r,o={bigint:!1}){return o.bigint?this.statSync(r,{bigint:!0}):this.statSync(r)}statSync(r,o={bigint:!1,throwIfNoEntry:!0}){let a=this.resolveFilename(`stat '${r}'`,r,void 0,o.throwIfNoEntry);if(a!==void 0){if(!this.entries.has(a)&&!this.listings.has(a)){if(o.throwIfNoEntry===!1)return;throw sr.ENOENT(`stat '${r}'`)}if(r[r.length-1]===\"/\"&&!this.listings.has(a))throw sr.ENOTDIR(`stat '${r}'`);return this.statImpl(`stat '${r}'`,a,o)}}async fstatPromise(r,o){return this.fstatSync(r,o)}fstatSync(r,o){let a=this.fds.get(r);if(typeof a>\"u\")throw sr.EBADF(\"fstatSync\");let{p:n}=a,u=this.resolveFilename(`stat '${n}'`,n);if(!this.entries.has(u)&&!this.listings.has(u))throw sr.ENOENT(`stat '${n}'`);if(n[n.length-1]===\"/\"&&!this.listings.has(u))throw sr.ENOTDIR(`stat '${n}'`);return this.statImpl(`fstat '${n}'`,u,o)}async lstatPromise(r,o={bigint:!1}){return o.bigint?this.lstatSync(r,{bigint:!0}):this.lstatSync(r)}lstatSync(r,o={bigint:!1,throwIfNoEntry:!0}){let a=this.resolveFilename(`lstat '${r}'`,r,!1,o.throwIfNoEntry);if(a!==void 0){if(!this.entries.has(a)&&!this.listings.has(a)){if(o.throwIfNoEntry===!1)return;throw sr.ENOENT(`lstat '${r}'`)}if(r[r.length-1]===\"/\"&&!this.listings.has(a))throw sr.ENOTDIR(`lstat '${r}'`);return this.statImpl(`lstat '${r}'`,a,o)}}statImpl(r,o,a={}){let n=this.entries.get(o);if(typeof n<\"u\"){let u=this.libzip.struct.statS();if(this.libzip.statIndex(this.zip,n,0,0,u)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));let p=this.stats.uid,h=this.stats.gid,E=this.libzip.struct.statSize(u)>>>0,w=512,D=Math.ceil(E/w),b=(this.libzip.struct.statMtime(u)>>>0)*1e3,C=b,T=b,N=b,U=new Date(C),z=new Date(T),te=new Date(N),le=new Date(b),ce=this.listings.has(o)?ta.constants.S_IFDIR:this.isSymbolicLink(n)?ta.constants.S_IFLNK:ta.constants.S_IFREG,ue=ce===ta.constants.S_IFDIR?493:420,Ie=ce|this.getUnixMode(n,ue)&511,he=this.libzip.struct.statCrc(u),De=Object.assign(new wa.StatEntry,{uid:p,gid:h,size:E,blksize:w,blocks:D,atime:U,birthtime:z,ctime:te,mtime:le,atimeMs:C,birthtimeMs:T,ctimeMs:N,mtimeMs:b,mode:Ie,crc:he});return a.bigint===!0?wa.convertToBigIntStats(De):De}if(this.listings.has(o)){let u=this.stats.uid,A=this.stats.gid,p=0,h=512,E=0,w=this.stats.mtimeMs,D=this.stats.mtimeMs,b=this.stats.mtimeMs,C=this.stats.mtimeMs,T=new Date(w),N=new Date(D),U=new Date(b),z=new Date(C),te=ta.constants.S_IFDIR|493,ce=Object.assign(new wa.StatEntry,{uid:u,gid:A,size:p,blksize:h,blocks:E,atime:T,birthtime:N,ctime:U,mtime:z,atimeMs:w,birthtimeMs:D,ctimeMs:b,mtimeMs:C,mode:te,crc:0});return a.bigint===!0?wa.convertToBigIntStats(ce):ce}throw new Error(\"Unreachable\")}getUnixMode(r,o){if(this.libzip.file.getExternalAttributes(this.zip,r,0,0,this.libzip.uint08S,this.libzip.uint32S)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));return this.libzip.getValue(this.libzip.uint08S,\"i8\")>>>0!==this.libzip.ZIP_OPSYS_UNIX?o:this.libzip.getValue(this.libzip.uint32S,\"i32\")>>>16}registerListing(r){let o=this.listings.get(r);if(o)return o;this.registerListing(K.dirname(r)).add(K.basename(r));let n=new Set;return this.listings.set(r,n),n}registerEntry(r,o){this.registerListing(K.dirname(r)).add(K.basename(r)),this.entries.set(r,o)}unregisterListing(r){this.listings.delete(r),this.listings.get(K.dirname(r))?.delete(K.basename(r))}unregisterEntry(r){this.unregisterListing(r);let o=this.entries.get(r);this.entries.delete(r),!(typeof o>\"u\")&&(this.fileSources.delete(o),this.isSymbolicLink(o)&&this.symlinkCount--)}deleteEntry(r,o){if(this.unregisterEntry(r),this.libzip.delete(this.zip,o)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip))}resolveFilename(r,o,a=!0,n=!0){if(!this.ready)throw sr.EBUSY(`archive closed, ${r}`);let u=K.resolve(Bt.root,o);if(u===\"/\")return Bt.root;let A=this.entries.get(u);if(a&&A!==void 0)if(this.symlinkCount!==0&&this.isSymbolicLink(A)){let p=this.getFileSource(A).toString();return this.resolveFilename(r,K.resolve(K.dirname(u),p),!0,n)}else return u;for(;;){let p=this.resolveFilename(r,K.dirname(u),!0,n);if(p===void 0)return p;let h=this.listings.has(p),E=this.entries.has(p);if(!h&&!E){if(n===!1)return;throw sr.ENOENT(r)}if(!h)throw sr.ENOTDIR(r);if(u=K.resolve(p,K.basename(u)),!a||this.symlinkCount===0)break;let w=this.libzip.name.locate(this.zip,u.slice(1),0);if(w===-1)break;if(this.isSymbolicLink(w)){let D=this.getFileSource(w).toString();u=K.resolve(K.dirname(u),D)}else break}return u}allocateBuffer(r){Buffer.isBuffer(r)||(r=Buffer.from(r));let o=this.libzip.malloc(r.byteLength);if(!o)throw new Error(\"Couldn't allocate enough memory\");return new Uint8Array(this.libzip.HEAPU8.buffer,o,r.byteLength).set(r),{buffer:o,byteLength:r.byteLength}}allocateUnattachedSource(r){let o=this.libzip.struct.errorS(),{buffer:a,byteLength:n}=this.allocateBuffer(r),u=this.libzip.source.fromUnattachedBuffer(a,n,0,1,o);if(u===0)throw this.libzip.free(o),this.makeLibzipError(o);return u}allocateSource(r){let{buffer:o,byteLength:a}=this.allocateBuffer(r),n=this.libzip.source.fromBuffer(this.zip,o,a,0,1);if(n===0)throw this.libzip.free(o),this.makeLibzipError(this.libzip.getError(this.zip));return n}setFileSource(r,o){let a=Buffer.isBuffer(o)?o:Buffer.from(o),n=K.relative(Bt.root,r),u=this.allocateSource(o);try{let A=this.libzip.file.add(this.zip,n,u,this.libzip.ZIP_FL_OVERWRITE);if(A===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));if(this.level!==\"mixed\"){let p=this.level===0?this.libzip.ZIP_CM_STORE:this.libzip.ZIP_CM_DEFLATE;if(this.libzip.file.setCompression(this.zip,A,0,p,this.level)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip))}return this.fileSources.set(A,a),A}catch(A){throw this.libzip.source.free(u),A}}isSymbolicLink(r){if(this.symlinkCount===0)return!1;if(this.libzip.file.getExternalAttributes(this.zip,r,0,0,this.libzip.uint08S,this.libzip.uint32S)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));return this.libzip.getValue(this.libzip.uint08S,\"i8\")>>>0!==this.libzip.ZIP_OPSYS_UNIX?!1:(this.libzip.getValue(this.libzip.uint32S,\"i32\")>>>16&ta.constants.S_IFMT)===ta.constants.S_IFLNK}getFileSource(r,o={asyncDecompress:!1}){let a=this.fileSources.get(r);if(typeof a<\"u\")return a;let n=this.libzip.struct.statS();if(this.libzip.statIndex(this.zip,r,0,0,n)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));let A=this.libzip.struct.statCompSize(n),p=this.libzip.struct.statCompMethod(n),h=this.libzip.malloc(A);try{let E=this.libzip.fopenIndex(this.zip,r,0,this.libzip.ZIP_FL_COMPRESSED);if(E===0)throw this.makeLibzipError(this.libzip.getError(this.zip));try{let w=this.libzip.fread(E,h,A,0);if(w===-1)throw this.makeLibzipError(this.libzip.file.getError(E));if(w<A)throw new Error(\"Incomplete read\");if(w>A)throw new Error(\"Overread\");let D=this.libzip.HEAPU8.subarray(h,h+A),b=Buffer.from(D);if(p===0)return this.fileSources.set(r,b),b;if(o.asyncDecompress)return new Promise((C,T)=>{HU.default.inflateRaw(b,(N,U)=>{N?T(N):(this.fileSources.set(r,U),C(U))})});{let C=HU.default.inflateRawSync(b);return this.fileSources.set(r,C),C}}finally{this.libzip.fclose(E)}}finally{this.libzip.free(h)}}async fchmodPromise(r,o){return this.chmodPromise(this.fdToPath(r,\"fchmod\"),o)}fchmodSync(r,o){return this.chmodSync(this.fdToPath(r,\"fchmodSync\"),o)}async chmodPromise(r,o){return this.chmodSync(r,o)}chmodSync(r,o){if(this.readOnly)throw sr.EROFS(`chmod '${r}'`);o&=493;let a=this.resolveFilename(`chmod '${r}'`,r,!1),n=this.entries.get(a);if(typeof n>\"u\")throw new Error(`Assertion failed: The entry should have been registered (${a})`);let A=this.getUnixMode(n,ta.constants.S_IFREG|0)&-512|o;if(this.libzip.file.setExternalAttributes(this.zip,n,0,0,this.libzip.ZIP_OPSYS_UNIX,A<<16)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip))}async fchownPromise(r,o,a){return this.chownPromise(this.fdToPath(r,\"fchown\"),o,a)}fchownSync(r,o,a){return this.chownSync(this.fdToPath(r,\"fchownSync\"),o,a)}async chownPromise(r,o,a){return this.chownSync(r,o,a)}chownSync(r,o,a){throw new Error(\"Unimplemented\")}async renamePromise(r,o){return this.renameSync(r,o)}renameSync(r,o){throw new Error(\"Unimplemented\")}async copyFilePromise(r,o,a){let{indexSource:n,indexDest:u,resolvedDestP:A}=this.prepareCopyFile(r,o,a),p=await this.getFileSource(n,{asyncDecompress:!0}),h=this.setFileSource(A,p);h!==u&&this.registerEntry(A,h)}copyFileSync(r,o,a=0){let{indexSource:n,indexDest:u,resolvedDestP:A}=this.prepareCopyFile(r,o,a),p=this.getFileSource(n),h=this.setFileSource(A,p);h!==u&&this.registerEntry(A,h)}prepareCopyFile(r,o,a=0){if(this.readOnly)throw sr.EROFS(`copyfile '${r} -> '${o}'`);if(a&ta.constants.COPYFILE_FICLONE_FORCE)throw sr.ENOSYS(\"unsupported clone operation\",`copyfile '${r}' -> ${o}'`);let n=this.resolveFilename(`copyfile '${r} -> ${o}'`,r),u=this.entries.get(n);if(typeof u>\"u\")throw sr.EINVAL(`copyfile '${r}' -> '${o}'`);let A=this.resolveFilename(`copyfile '${r}' -> ${o}'`,o),p=this.entries.get(A);if(a&(ta.constants.COPYFILE_EXCL|ta.constants.COPYFILE_FICLONE_FORCE)&&typeof p<\"u\")throw sr.EEXIST(`copyfile '${r}' -> '${o}'`);return{indexSource:u,resolvedDestP:A,indexDest:p}}async appendFilePromise(r,o,a){if(this.readOnly)throw sr.EROFS(`open '${r}'`);return typeof a>\"u\"?a={flag:\"a\"}:typeof a==\"string\"?a={flag:\"a\",encoding:a}:typeof a.flag>\"u\"&&(a={flag:\"a\",...a}),this.writeFilePromise(r,o,a)}appendFileSync(r,o,a={}){if(this.readOnly)throw sr.EROFS(`open '${r}'`);return typeof a>\"u\"?a={flag:\"a\"}:typeof a==\"string\"?a={flag:\"a\",encoding:a}:typeof a.flag>\"u\"&&(a={flag:\"a\",...a}),this.writeFileSync(r,o,a)}fdToPath(r,o){let a=this.fds.get(r)?.p;if(typeof a>\"u\")throw sr.EBADF(o);return a}async writeFilePromise(r,o,a){let{encoding:n,mode:u,index:A,resolvedP:p}=this.prepareWriteFile(r,a);A!==void 0&&typeof a==\"object\"&&a.flag&&a.flag.includes(\"a\")&&(o=Buffer.concat([await this.getFileSource(A,{asyncDecompress:!0}),Buffer.from(o)])),n!==null&&(o=o.toString(n));let h=this.setFileSource(p,o);h!==A&&this.registerEntry(p,h),u!==null&&await this.chmodPromise(p,u)}writeFileSync(r,o,a){let{encoding:n,mode:u,index:A,resolvedP:p}=this.prepareWriteFile(r,a);A!==void 0&&typeof a==\"object\"&&a.flag&&a.flag.includes(\"a\")&&(o=Buffer.concat([this.getFileSource(A),Buffer.from(o)])),n!==null&&(o=o.toString(n));let h=this.setFileSource(p,o);h!==A&&this.registerEntry(p,h),u!==null&&this.chmodSync(p,u)}prepareWriteFile(r,o){if(typeof r==\"number\"&&(r=this.fdToPath(r,\"read\")),this.readOnly)throw sr.EROFS(`open '${r}'`);let a=this.resolveFilename(`open '${r}'`,r);if(this.listings.has(a))throw sr.EISDIR(`open '${r}'`);let n=null,u=null;typeof o==\"string\"?n=o:typeof o==\"object\"&&({encoding:n=null,mode:u=null}=o);let A=this.entries.get(a);return{encoding:n,mode:u,resolvedP:a,index:A}}async unlinkPromise(r){return this.unlinkSync(r)}unlinkSync(r){if(this.readOnly)throw sr.EROFS(`unlink '${r}'`);let o=this.resolveFilename(`unlink '${r}'`,r);if(this.listings.has(o))throw sr.EISDIR(`unlink '${r}'`);let a=this.entries.get(o);if(typeof a>\"u\")throw sr.EINVAL(`unlink '${r}'`);this.deleteEntry(o,a)}async utimesPromise(r,o,a){return this.utimesSync(r,o,a)}utimesSync(r,o,a){if(this.readOnly)throw sr.EROFS(`utimes '${r}'`);let n=this.resolveFilename(`utimes '${r}'`,r);this.utimesImpl(n,a)}async lutimesPromise(r,o,a){return this.lutimesSync(r,o,a)}lutimesSync(r,o,a){if(this.readOnly)throw sr.EROFS(`lutimes '${r}'`);let n=this.resolveFilename(`utimes '${r}'`,r,!1);this.utimesImpl(n,a)}utimesImpl(r,o){this.listings.has(r)&&(this.entries.has(r)||this.hydrateDirectory(r));let a=this.entries.get(r);if(a===void 0)throw new Error(\"Unreachable\");if(this.libzip.file.setMtime(this.zip,a,0,tot(o),0)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip))}async mkdirPromise(r,o){return this.mkdirSync(r,o)}mkdirSync(r,{mode:o=493,recursive:a=!1}={}){if(a)return this.mkdirpSync(r,{chmod:o});if(this.readOnly)throw sr.EROFS(`mkdir '${r}'`);let n=this.resolveFilename(`mkdir '${r}'`,r);if(this.entries.has(n)||this.listings.has(n))throw sr.EEXIST(`mkdir '${r}'`);this.hydrateDirectory(n),this.chmodSync(n,o)}async rmdirPromise(r,o){return this.rmdirSync(r,o)}rmdirSync(r,{recursive:o=!1}={}){if(this.readOnly)throw sr.EROFS(`rmdir '${r}'`);if(o){this.removeSync(r);return}let a=this.resolveFilename(`rmdir '${r}'`,r),n=this.listings.get(a);if(!n)throw sr.ENOTDIR(`rmdir '${r}'`);if(n.size>0)throw sr.ENOTEMPTY(`rmdir '${r}'`);let u=this.entries.get(a);if(typeof u>\"u\")throw sr.EINVAL(`rmdir '${r}'`);this.deleteEntry(r,u)}async rmPromise(r,o){return this.rmSync(r,o)}rmSync(r,{recursive:o=!1}={}){if(this.readOnly)throw sr.EROFS(`rm '${r}'`);if(o){this.removeSync(r);return}let a=this.resolveFilename(`rm '${r}'`,r),n=this.listings.get(a);if(!n)throw sr.ENOTDIR(`rm '${r}'`);if(n.size>0)throw sr.ENOTEMPTY(`rm '${r}'`);let u=this.entries.get(a);if(typeof u>\"u\")throw sr.EINVAL(`rm '${r}'`);this.deleteEntry(r,u)}hydrateDirectory(r){let o=this.libzip.dir.add(this.zip,K.relative(Bt.root,r));if(o===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));return this.registerListing(r),this.registerEntry(r,o),o}async linkPromise(r,o){return this.linkSync(r,o)}linkSync(r,o){throw sr.EOPNOTSUPP(`link '${r}' -> '${o}'`)}async symlinkPromise(r,o){return this.symlinkSync(r,o)}symlinkSync(r,o){if(this.readOnly)throw sr.EROFS(`symlink '${r}' -> '${o}'`);let a=this.resolveFilename(`symlink '${r}' -> '${o}'`,o);if(this.listings.has(a))throw sr.EISDIR(`symlink '${r}' -> '${o}'`);if(this.entries.has(a))throw sr.EEXIST(`symlink '${r}' -> '${o}'`);let n=this.setFileSource(a,r);if(this.registerEntry(a,n),this.libzip.file.setExternalAttributes(this.zip,n,0,0,this.libzip.ZIP_OPSYS_UNIX,(ta.constants.S_IFLNK|511)<<16)===-1)throw this.makeLibzipError(this.libzip.getError(this.zip));this.symlinkCount+=1}async readFilePromise(r,o){typeof o==\"object\"&&(o=o?o.encoding:void 0);let a=await this.readFileBuffer(r,{asyncDecompress:!0});return o?a.toString(o):a}readFileSync(r,o){typeof o==\"object\"&&(o=o?o.encoding:void 0);let a=this.readFileBuffer(r);return o?a.toString(o):a}readFileBuffer(r,o={asyncDecompress:!1}){typeof r==\"number\"&&(r=this.fdToPath(r,\"read\"));let a=this.resolveFilename(`open '${r}'`,r);if(!this.entries.has(a)&&!this.listings.has(a))throw sr.ENOENT(`open '${r}'`);if(r[r.length-1]===\"/\"&&!this.listings.has(a))throw sr.ENOTDIR(`open '${r}'`);if(this.listings.has(a))throw sr.EISDIR(\"read\");let n=this.entries.get(a);if(n===void 0)throw new Error(\"Unreachable\");return this.getFileSource(n,o)}async readdirPromise(r,o){return this.readdirSync(r,o)}readdirSync(r,o){let a=this.resolveFilename(`scandir '${r}'`,r);if(!this.entries.has(a)&&!this.listings.has(a))throw sr.ENOENT(`scandir '${r}'`);let n=this.listings.get(a);if(!n)throw sr.ENOTDIR(`scandir '${r}'`);if(o?.recursive)if(o?.withFileTypes){let u=Array.from(n,A=>Object.assign(this.statImpl(\"lstat\",K.join(r,A)),{name:A,path:Bt.dot}));for(let A of u){if(!A.isDirectory())continue;let p=K.join(A.path,A.name),h=this.listings.get(K.join(a,p));for(let E of h)u.push(Object.assign(this.statImpl(\"lstat\",K.join(r,p,E)),{name:E,path:p}))}return u}else{let u=[...n];for(let A of u){let p=this.listings.get(K.join(a,A));if(!(typeof p>\"u\"))for(let h of p)u.push(K.join(A,h))}return u}else return o?.withFileTypes?Array.from(n,u=>Object.assign(this.statImpl(\"lstat\",K.join(r,u)),{name:u,path:void 0})):[...n]}async readlinkPromise(r){let o=this.prepareReadlink(r);return(await this.getFileSource(o,{asyncDecompress:!0})).toString()}readlinkSync(r){let o=this.prepareReadlink(r);return this.getFileSource(o).toString()}prepareReadlink(r){let o=this.resolveFilename(`readlink '${r}'`,r,!1);if(!this.entries.has(o)&&!this.listings.has(o))throw sr.ENOENT(`readlink '${r}'`);if(r[r.length-1]===\"/\"&&!this.listings.has(o))throw sr.ENOTDIR(`open '${r}'`);if(this.listings.has(o))throw sr.EINVAL(`readlink '${r}'`);let a=this.entries.get(o);if(a===void 0)throw new Error(\"Unreachable\");if(!this.isSymbolicLink(a))throw sr.EINVAL(`readlink '${r}'`);return a}async truncatePromise(r,o=0){let a=this.resolveFilename(`open '${r}'`,r),n=this.entries.get(a);if(typeof n>\"u\")throw sr.EINVAL(`open '${r}'`);let u=await this.getFileSource(n,{asyncDecompress:!0}),A=Buffer.alloc(o,0);return u.copy(A),await this.writeFilePromise(r,A)}truncateSync(r,o=0){let a=this.resolveFilename(`open '${r}'`,r),n=this.entries.get(a);if(typeof n>\"u\")throw sr.EINVAL(`open '${r}'`);let u=this.getFileSource(n),A=Buffer.alloc(o,0);return u.copy(A),this.writeFileSync(r,A)}async ftruncatePromise(r,o){return this.truncatePromise(this.fdToPath(r,\"ftruncate\"),o)}ftruncateSync(r,o){return this.truncateSync(this.fdToPath(r,\"ftruncateSync\"),o)}watch(r,o,a){let n;switch(typeof o){case\"function\":case\"string\":case\"undefined\":n=!0;break;default:({persistent:n=!0}=o);break}if(!n)return{on:()=>{},close:()=>{}};let u=setInterval(()=>{},24*60*60*1e3);return{on:()=>{},close:()=>{clearInterval(u)}}}watchFile(r,o,a){let n=K.resolve(Bt.root,r);return um(this,n,o,a)}unwatchFile(r,o){let a=K.resolve(Bt.root,r);return q0(this,a,o)}}});function bce(t,e,r=Buffer.alloc(0),o){let a=new Zi(r),n=w=>w===e||w.startsWith(`${e}/`)?w.slice(0,e.length):null,u=async(w,D)=>()=>a,A=(w,D)=>a,p={...t},h=new _n(p),E=new Gp({baseFs:h,getMountPoint:n,factoryPromise:u,factorySync:A,magicByte:21,maxAge:1/0,typeCheck:o?.typeCheck});return uw(xce.default,new Wp(E)),a}var xce,kce=It(()=>{Pt();xce=et(ve(\"fs\"));qU()});var Qce=It(()=>{Dce();qU();kce()});var V1={};Kt(V1,{DEFAULT_COMPRESSION_LEVEL:()=>Sce,LibzipError:()=>fb,ZipFS:()=>Zi,ZipOpenFS:()=>iA,getArchivePart:()=>UU,getLibzipPromise:()=>not,getLibzipSync:()=>rot,makeEmptyArchive:()=>Ab,mountMemoryDrive:()=>bce});function rot(){return K1()}async function not(){return K1()}var Fce,sA=It(()=>{NU();Fce=et(Ice());vce();Qce();Cce(()=>{let t=(0,Fce.default)();return Bce(t)})});var z1,Rce=It(()=>{Pt();Gt();J1();z1=class extends st{constructor(){super(...arguments);this.cwd=de.String(\"--cwd\",process.cwd(),{description:\"The directory to run the command in\"});this.commandName=de.String();this.args=de.Proxy()}static{this.usage={description:\"run a command using yarn's portable shell\",details:`\n      This command will run a command using Yarn's portable shell.\n\n      Make sure to escape glob patterns, redirections, and other features that might be expanded by your own shell.\n\n      Note: To escape something from Yarn's shell, you might have to escape it twice, the first time from your own shell.\n\n      Note: Don't use this command in Yarn scripts, as Yarn's shell is automatically used.\n\n      For a list of features, visit: https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-shell/README.md.\n    `,examples:[[\"Run a simple command\",\"$0 echo Hello\"],[\"Run a command with a glob pattern\",\"$0 echo '*.js'\"],[\"Run a command with a redirection\",\"$0 echo Hello World '>' hello.txt\"],[\"Run a command with an escaped glob pattern (The double escape is needed in Unix shells)\",`$0 echo '\"*.js\"'`],[\"Run a command with a variable (Double quotes are needed in Unix shells, to prevent them from expanding the variable)\",'$0 \"GREETING=Hello echo $GREETING World\"']]}}async execute(){let r=this.args.length>0?`${this.commandName} ${this.args.join(\" \")}`:this.commandName;return await ky(r,[],{cwd:Ae.toPortablePath(this.cwd),stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr})}}});var fl,Tce=It(()=>{fl=class extends Error{constructor(e){super(e),this.name=\"ShellError\"}}});var gb={};Kt(gb,{fastGlobOptions:()=>Oce,isBraceExpansion:()=>jU,isGlobPattern:()=>iot,match:()=>sot,micromatchOptions:()=>hb});function iot(t){if(!pb.default.scan(t,hb).isGlob)return!1;try{pb.default.parse(t,hb)}catch{return!1}return!0}function sot(t,{cwd:e,baseFs:r}){return(0,Lce.default)(t,{...Oce,cwd:Ae.fromPortablePath(e),fs:aP(Nce.default,new Wp(r))})}function jU(t){return pb.default.scan(t,hb).isBrace}var Lce,Nce,pb,hb,Oce,Mce=It(()=>{Pt();Lce=et(ux()),Nce=et(ve(\"fs\")),pb=et(Xo()),hb={strictBrackets:!0},Oce={onlyDirectories:!1,onlyFiles:!1}});function GU(){}function WU(){for(let t of Fg)t.kill()}function qce(t,e,r,o){return a=>{let n=a[0]instanceof oA.Transform?\"pipe\":a[0],u=a[1]instanceof oA.Transform?\"pipe\":a[1],A=a[2]instanceof oA.Transform?\"pipe\":a[2],p=(0,_ce.default)(t,e,{...o,stdio:[n,u,A]});return Fg.add(p),Fg.size===1&&(process.on(\"SIGINT\",GU),process.on(\"SIGTERM\",WU)),a[0]instanceof oA.Transform&&a[0].pipe(p.stdin),a[1]instanceof oA.Transform&&p.stdout.pipe(a[1],{end:!1}),a[2]instanceof oA.Transform&&p.stderr.pipe(a[2],{end:!1}),{stdin:p.stdin,promise:new Promise(h=>{p.on(\"error\",E=>{switch(Fg.delete(p),Fg.size===0&&(process.off(\"SIGINT\",GU),process.off(\"SIGTERM\",WU)),E.code){case\"ENOENT\":a[2].write(`command not found: ${t}\n`),h(127);break;case\"EACCES\":a[2].write(`permission denied: ${t}\n`),h(128);break;default:a[2].write(`uncaught error: ${E.message}\n`),h(1);break}}),p.on(\"close\",E=>{Fg.delete(p),Fg.size===0&&(process.off(\"SIGINT\",GU),process.off(\"SIGTERM\",WU)),h(E!==null?E:129)})})}}}function jce(t){return e=>{let r=e[0]===\"pipe\"?new oA.PassThrough:e[0];return{stdin:r,promise:Promise.resolve().then(()=>t({stdin:r,stdout:e[1],stderr:e[2]}))}}}function db(t,e){return KU.start(t,e)}function Uce(t,e=null){let r=new oA.PassThrough,o=new Hce.StringDecoder,a=\"\";return r.on(\"data\",n=>{let u=o.write(n),A;do if(A=u.indexOf(`\n`),A!==-1){let p=a+u.substring(0,A);u=u.substring(A+1),a=\"\",t(e!==null?`${e} ${p}`:p)}while(A!==-1);a+=u}),r.on(\"end\",()=>{let n=o.end();n!==\"\"&&t(e!==null?`${e} ${n}`:n)}),r}function Gce(t,{prefix:e}){return{stdout:Uce(r=>t.stdout.write(`${r}\n`),t.stdout.isTTY?e:null),stderr:Uce(r=>t.stderr.write(`${r}\n`),t.stderr.isTTY?e:null)}}var _ce,oA,Hce,Fg,Zl,YU,KU,VU=It(()=>{_ce=et(MT()),oA=ve(\"stream\"),Hce=ve(\"string_decoder\"),Fg=new Set;Zl=class{constructor(e){this.stream=e}close(){}get(){return this.stream}},YU=class{constructor(){this.stream=null}close(){if(this.stream===null)throw new Error(\"Assertion failed: No stream attached\");this.stream.end()}attach(e){this.stream=e}get(){if(this.stream===null)throw new Error(\"Assertion failed: No stream attached\");return this.stream}},KU=class t{constructor(e,r){this.stdin=null;this.stdout=null;this.stderr=null;this.pipe=null;this.ancestor=e,this.implementation=r}static start(e,{stdin:r,stdout:o,stderr:a}){let n=new t(null,e);return n.stdin=r,n.stdout=o,n.stderr=a,n}pipeTo(e,r=1){let o=new t(this,e),a=new YU;return o.pipe=a,o.stdout=this.stdout,o.stderr=this.stderr,(r&1)===1?this.stdout=a:this.ancestor!==null&&(this.stderr=this.ancestor.stdout),(r&2)===2?this.stderr=a:this.ancestor!==null&&(this.stderr=this.ancestor.stderr),o}async exec(){let e=[\"ignore\",\"ignore\",\"ignore\"];if(this.pipe)e[0]=\"pipe\";else{if(this.stdin===null)throw new Error(\"Assertion failed: No input stream registered\");e[0]=this.stdin.get()}let r;if(this.stdout===null)throw new Error(\"Assertion failed: No output stream registered\");r=this.stdout,e[1]=r.get();let o;if(this.stderr===null)throw new Error(\"Assertion failed: No error stream registered\");o=this.stderr,e[2]=o.get();let a=this.implementation(e);return this.pipe&&this.pipe.attach(a.stdin),await a.promise.then(n=>(r.close(),o.close(),n))}async run(){let e=[];for(let o=this;o;o=o.ancestor)e.push(o.exec());return(await Promise.all(e))[0]}}});var e2={};Kt(e2,{EntryCommand:()=>z1,ShellError:()=>fl,execute:()=>ky,globUtils:()=>gb});function Wce(t,e,r){let o=new pl.PassThrough({autoDestroy:!0});switch(t){case 0:(e&1)===1&&r.stdin.pipe(o,{end:!1}),(e&2)===2&&r.stdin instanceof pl.Writable&&o.pipe(r.stdin,{end:!1});break;case 1:(e&1)===1&&r.stdout.pipe(o,{end:!1}),(e&2)===2&&o.pipe(r.stdout,{end:!1});break;case 2:(e&1)===1&&r.stderr.pipe(o,{end:!1}),(e&2)===2&&o.pipe(r.stderr,{end:!1});break;default:throw new fl(`Bad file descriptor: \"${t}\"`)}return o}function yb(t,e={}){let r={...t,...e};return r.environment={...t.environment,...e.environment},r.variables={...t.variables,...e.variables},r}async function aot(t,e,r){let o=[],a=new pl.PassThrough;return a.on(\"data\",n=>o.push(n)),await Eb(t,e,yb(r,{stdout:a})),Buffer.concat(o).toString().replace(/[\\r\\n]+$/,\"\")}async function Yce(t,e,r){let o=t.map(async n=>{let u=await Rg(n.args,e,r);return{name:n.name,value:u.join(\" \")}});return(await Promise.all(o)).reduce((n,u)=>(n[u.name]=u.value,n),{})}function mb(t){return t.match(/[^ \\r\\n\\t]+/g)||[]}async function Zce(t,e,r,o,a=o){switch(t.name){case\"$\":o(String(process.pid));break;case\"#\":o(String(e.args.length));break;case\"@\":if(t.quoted)for(let n of e.args)a(n);else for(let n of e.args){let u=mb(n);for(let A=0;A<u.length-1;++A)a(u[A]);o(u[u.length-1])}break;case\"*\":{let n=e.args.join(\" \");if(t.quoted)o(n);else for(let u of mb(n))a(u)}break;case\"PPID\":o(String(process.ppid));break;case\"RANDOM\":o(String(Math.floor(Math.random()*32768)));break;default:{let n=parseInt(t.name,10),u,A=Number.isFinite(n);if(A?n>=0&&n<e.args.length&&(u=e.args[n]):Object.hasOwn(r.variables,t.name)?u=r.variables[t.name]:Object.hasOwn(r.environment,t.name)&&(u=r.environment[t.name]),typeof u<\"u\"&&t.alternativeValue?u=(await Rg(t.alternativeValue,e,r)).join(\" \"):typeof u>\"u\"&&(t.defaultValue?u=(await Rg(t.defaultValue,e,r)).join(\" \"):t.alternativeValue&&(u=\"\")),typeof u>\"u\")throw A?new fl(`Unbound argument #${n}`):new fl(`Unbound variable \"${t.name}\"`);if(t.quoted)o(u);else{let p=mb(u);for(let E=0;E<p.length-1;++E)a(p[E]);let h=p[p.length-1];typeof h<\"u\"&&o(h)}}break}}async function X1(t,e,r){if(t.type===\"number\"){if(Number.isInteger(t.value))return t.value;throw new Error(`Invalid number: \"${t.value}\", only integers are allowed`)}else if(t.type===\"variable\"){let o=[];await Zce({...t,quoted:!0},e,r,n=>o.push(n));let a=Number(o.join(\" \"));return Number.isNaN(a)?X1({type:\"variable\",name:o.join(\" \")},e,r):X1({type:\"number\",value:a},e,r)}else return lot[t.type](await X1(t.left,e,r),await X1(t.right,e,r))}async function Rg(t,e,r){let o=new Map,a=[],n=[],u=E=>{n.push(E)},A=()=>{n.length>0&&a.push(n.join(\"\")),n=[]},p=E=>{u(E),A()},h=(E,w,D)=>{let b=JSON.stringify({type:E,fd:w}),C=o.get(b);typeof C>\"u\"&&o.set(b,C=[]),C.push(D)};for(let E of t){let w=!1;switch(E.type){case\"redirection\":{let D=await Rg(E.args,e,r);for(let b of D)h(E.subtype,E.fd,b)}break;case\"argument\":for(let D of E.segments)switch(D.type){case\"text\":u(D.text);break;case\"glob\":u(D.pattern),w=!0;break;case\"shell\":{let b=await aot(D.shell,e,r);if(D.quoted)u(b);else{let C=mb(b);for(let T=0;T<C.length-1;++T)p(C[T]);u(C[C.length-1])}}break;case\"variable\":await Zce(D,e,r,u,p);break;case\"arithmetic\":u(String(await X1(D.arithmetic,e,r)));break}break}if(A(),w){let D=a.pop();if(typeof D>\"u\")throw new Error(\"Assertion failed: Expected a glob pattern to have been set\");let b=await e.glob.match(D,{cwd:r.cwd,baseFs:e.baseFs});if(b.length===0){let C=jU(D)?\". Note: Brace expansion of arbitrary strings isn't currently supported. For more details, please read this issue: https://github.com/yarnpkg/berry/issues/22\":\"\";throw new fl(`No matches found: \"${D}\"${C}`)}for(let C of b.sort())p(C)}}if(o.size>0){let E=[];for(let[w,D]of o.entries())E.splice(E.length,0,w,String(D.length),...D);a.splice(0,0,\"__ysh_set_redirects\",...E,\"--\")}return a}function Z1(t,e,r){e.builtins.has(t[0])||(t=[\"command\",...t]);let o=Ae.fromPortablePath(r.cwd),a=r.environment;typeof a.PWD<\"u\"&&(a={...a,PWD:o});let[n,...u]=t;if(n===\"command\")return qce(u[0],u.slice(1),e,{cwd:o,env:a});let A=e.builtins.get(n);if(typeof A>\"u\")throw new Error(`Assertion failed: A builtin should exist for \"${n}\"`);return jce(async({stdin:p,stdout:h,stderr:E})=>{let{stdin:w,stdout:D,stderr:b}=r;r.stdin=p,r.stdout=h,r.stderr=E;try{return await A(u,e,r)}finally{r.stdin=w,r.stdout=D,r.stderr=b}})}function cot(t,e,r){return o=>{let a=new pl.PassThrough,n=Eb(t,e,yb(r,{stdin:a}));return{stdin:a,promise:n}}}function uot(t,e,r){return o=>{let a=new pl.PassThrough,n=Eb(t,e,r);return{stdin:a,promise:n}}}function Kce(t,e,r,o){if(e.length===0)return t;{let a;do a=String(Math.random());while(Object.hasOwn(o.procedures,a));return o.procedures={...o.procedures},o.procedures[a]=t,Z1([...e,\"__ysh_run_procedure\",a],r,o)}}async function Vce(t,e,r){let o=t,a=null,n=null;for(;o;){let u=o.then?{...r}:r,A;switch(o.type){case\"command\":{let p=await Rg(o.args,e,r),h=await Yce(o.envs,e,r);A=o.envs.length?Z1(p,e,yb(u,{environment:h})):Z1(p,e,u)}break;case\"subshell\":{let p=await Rg(o.args,e,r),h=cot(o.subshell,e,u);A=Kce(h,p,e,u)}break;case\"group\":{let p=await Rg(o.args,e,r),h=uot(o.group,e,u);A=Kce(h,p,e,u)}break;case\"envs\":{let p=await Yce(o.envs,e,r);u.environment={...u.environment,...p},A=Z1([\"true\"],e,u)}break}if(typeof A>\"u\")throw new Error(\"Assertion failed: An action should have been generated\");if(a===null)n=db(A,{stdin:new Zl(u.stdin),stdout:new Zl(u.stdout),stderr:new Zl(u.stderr)});else{if(n===null)throw new Error(\"Assertion failed: The execution pipeline should have been setup\");switch(a){case\"|\":n=n.pipeTo(A,1);break;case\"|&\":n=n.pipeTo(A,3);break}}o.then?(a=o.then.type,o=o.then.chain):o=null}if(n===null)throw new Error(\"Assertion failed: The execution pipeline should have been setup\");return await n.run()}async function Aot(t,e,r,{background:o=!1}={}){function a(n){let u=[\"#2E86AB\",\"#A23B72\",\"#F18F01\",\"#C73E1D\",\"#CCE2A3\"],A=u[n%u.length];return zce.default.hex(A)}if(o){let n=r.nextBackgroundJobIndex++,u=a(n),A=`[${n}]`,p=u(A),{stdout:h,stderr:E}=Gce(r,{prefix:p});return r.backgroundJobs.push(Vce(t,e,yb(r,{stdout:h,stderr:E})).catch(w=>E.write(`${w.message}\n`)).finally(()=>{r.stdout.isTTY&&r.stdout.write(`Job ${p}, '${u(mm(t))}' has ended\n`)})),0}return await Vce(t,e,r)}async function fot(t,e,r,{background:o=!1}={}){let a,n=A=>{a=A,r.variables[\"?\"]=String(A)},u=async A=>{try{return await Aot(A.chain,e,r,{background:o&&typeof A.then>\"u\"})}catch(p){if(!(p instanceof fl))throw p;return r.stderr.write(`${p.message}\n`),1}};for(n(await u(t));t.then;){if(r.exitCode!==null)return r.exitCode;switch(t.then.type){case\"&&\":a===0&&n(await u(t.then.line));break;case\"||\":a!==0&&n(await u(t.then.line));break;default:throw new Error(`Assertion failed: Unsupported command type: \"${t.then.type}\"`)}t=t.then.line}return a}async function Eb(t,e,r){let o=r.backgroundJobs;r.backgroundJobs=[];let a=0;for(let{command:n,type:u}of t){if(a=await fot(n,e,r,{background:u===\"&\"}),r.exitCode!==null)return r.exitCode;r.variables[\"?\"]=String(a)}return await Promise.all(r.backgroundJobs),r.backgroundJobs=o,a}function $ce(t){switch(t.type){case\"variable\":return t.name===\"@\"||t.name===\"#\"||t.name===\"*\"||Number.isFinite(parseInt(t.name,10))||\"defaultValue\"in t&&!!t.defaultValue&&t.defaultValue.some(e=>$1(e))||\"alternativeValue\"in t&&!!t.alternativeValue&&t.alternativeValue.some(e=>$1(e));case\"arithmetic\":return zU(t.arithmetic);case\"shell\":return JU(t.shell);default:return!1}}function $1(t){switch(t.type){case\"redirection\":return t.args.some(e=>$1(e));case\"argument\":return t.segments.some(e=>$ce(e));default:throw new Error(`Assertion failed: Unsupported argument type: \"${t.type}\"`)}}function zU(t){switch(t.type){case\"variable\":return $ce(t);case\"number\":return!1;default:return zU(t.left)||zU(t.right)}}function JU(t){return t.some(({command:e})=>{for(;e;){let r=e.chain;for(;r;){let o;switch(r.type){case\"subshell\":o=JU(r.subshell);break;case\"command\":o=r.envs.some(a=>a.args.some(n=>$1(n)))||r.args.some(a=>$1(a));break}if(o)return!0;if(!r.then)break;r=r.then.chain}if(!e.then)break;e=e.then.line}return!1})}async function ky(t,e=[],{baseFs:r=new _n,builtins:o={},cwd:a=Ae.toPortablePath(process.cwd()),env:n=process.env,stdin:u=process.stdin,stdout:A=process.stdout,stderr:p=process.stderr,variables:h={},glob:E=gb}={}){let w={};for(let[C,T]of Object.entries(n))typeof T<\"u\"&&(w[C]=T);let D=new Map(oot);for(let[C,T]of Object.entries(o))D.set(C,T);u===null&&(u=new pl.PassThrough,u.end());let b=uP(t,E);if(!JU(b)&&b.length>0&&e.length>0){let{command:C}=b[b.length-1];for(;C.then;)C=C.then.line;let T=C.chain;for(;T.then;)T=T.then.chain;T.type===\"command\"&&(T.args=T.args.concat(e.map(N=>({type:\"argument\",segments:[{type:\"text\",text:N}]}))))}return await Eb(b,{args:e,baseFs:r,builtins:D,initialStdin:u,initialStdout:A,initialStderr:p,glob:E},{cwd:a,environment:w,exitCode:null,procedures:{},stdin:u,stdout:A,stderr:p,variables:Object.assign({},h,{\"?\":0}),nextBackgroundJobIndex:1,backgroundJobs:[]})}var zce,Jce,pl,Xce,oot,lot,J1=It(()=>{Pt();Ol();zce=et(sN()),Jce=ve(\"os\"),pl=ve(\"stream\"),Xce=ve(\"timers/promises\");Rce();Tce();Mce();VU();VU();oot=new Map([[\"cd\",async([t=(0,Jce.homedir)(),...e],r,o)=>{let a=K.resolve(o.cwd,Ae.toPortablePath(t));if(!(await r.baseFs.statPromise(a).catch(u=>{throw u.code===\"ENOENT\"?new fl(`cd: no such file or directory: ${t}`):u})).isDirectory())throw new fl(`cd: not a directory: ${t}`);return o.cwd=a,0}],[\"pwd\",async(t,e,r)=>(r.stdout.write(`${Ae.fromPortablePath(r.cwd)}\n`),0)],[\":\",async(t,e,r)=>0],[\"true\",async(t,e,r)=>0],[\"false\",async(t,e,r)=>1],[\"exit\",async([t,...e],r,o)=>o.exitCode=parseInt(t??o.variables[\"?\"],10)],[\"echo\",async(t,e,r)=>(r.stdout.write(`${t.join(\" \")}\n`),0)],[\"sleep\",async([t],e,r)=>{if(typeof t>\"u\")throw new fl(\"sleep: missing operand\");let o=Number(t);if(Number.isNaN(o))throw new fl(`sleep: invalid time interval '${t}'`);return await(0,Xce.setTimeout)(1e3*o,0)}],[\"unset\",async(t,e,r)=>{for(let o of t)delete r.environment[o],delete r.variables[o];return 0}],[\"__ysh_run_procedure\",async(t,e,r)=>{let o=r.procedures[t[0]];return await db(o,{stdin:new Zl(r.stdin),stdout:new Zl(r.stdout),stderr:new Zl(r.stderr)}).run()}],[\"__ysh_set_redirects\",async(t,e,r)=>{let o=r.stdin,a=r.stdout,n=r.stderr,u=[],A=[],p=[],h=0;for(;t[h]!==\"--\";){let w=t[h++],{type:D,fd:b}=JSON.parse(w),C=z=>{switch(b){case null:case 0:u.push(z);break;default:throw new Error(`Unsupported file descriptor: \"${b}\"`)}},T=z=>{switch(b){case null:case 1:A.push(z);break;case 2:p.push(z);break;default:throw new Error(`Unsupported file descriptor: \"${b}\"`)}},N=Number(t[h++]),U=h+N;for(let z=h;z<U;++h,++z)switch(D){case\"<\":C(()=>e.baseFs.createReadStream(K.resolve(r.cwd,Ae.toPortablePath(t[z]))));break;case\"<<<\":C(()=>{let te=new pl.PassThrough;return process.nextTick(()=>{te.write(`${t[z]}\n`),te.end()}),te});break;case\"<&\":C(()=>Wce(Number(t[z]),1,r));break;case\">\":case\">>\":{let te=K.resolve(r.cwd,Ae.toPortablePath(t[z]));T(te===\"/dev/null\"?new pl.Writable({autoDestroy:!0,emitClose:!0,write(le,ce,ue){setImmediate(ue)}}):e.baseFs.createWriteStream(te,D===\">>\"?{flags:\"a\"}:void 0))}break;case\">&\":T(Wce(Number(t[z]),2,r));break;default:throw new Error(`Assertion failed: Unsupported redirection type: \"${D}\"`)}}if(u.length>0){let w=new pl.PassThrough;o=w;let D=b=>{if(b===u.length)w.end();else{let C=u[b]();C.pipe(w,{end:!1}),C.on(\"end\",()=>{D(b+1)})}};D(0)}if(A.length>0){let w=new pl.PassThrough;a=w;for(let D of A)w.pipe(D)}if(p.length>0){let w=new pl.PassThrough;n=w;for(let D of p)w.pipe(D)}let E=await db(Z1(t.slice(h+1),e,r),{stdin:new Zl(o),stdout:new Zl(a),stderr:new Zl(n)}).run();return await Promise.all(A.map(w=>new Promise((D,b)=>{w.on(\"error\",C=>{b(C)}),w.on(\"close\",()=>{D()}),w.end()}))),await Promise.all(p.map(w=>new Promise((D,b)=>{w.on(\"error\",C=>{b(C)}),w.on(\"close\",()=>{D()}),w.end()}))),E}]]);lot={addition:(t,e)=>t+e,subtraction:(t,e)=>t-e,multiplication:(t,e)=>t*e,division:(t,e)=>Math.trunc(t/e)}});var Cb=_((MMt,eue)=>{function pot(t,e){for(var r=-1,o=t==null?0:t.length,a=Array(o);++r<o;)a[r]=e(t[r],r,t);return a}eue.exports=pot});var oue=_((UMt,sue)=>{var tue=dg(),hot=Cb(),got=jl(),dot=fy(),mot=1/0,rue=tue?tue.prototype:void 0,nue=rue?rue.toString:void 0;function iue(t){if(typeof t==\"string\")return t;if(got(t))return hot(t,iue)+\"\";if(dot(t))return nue?nue.call(t):\"\";var e=t+\"\";return e==\"0\"&&1/t==-mot?\"-0\":e}sue.exports=iue});var t2=_((_Mt,aue)=>{var yot=oue();function Eot(t){return t==null?\"\":yot(t)}aue.exports=Eot});var XU=_((HMt,lue)=>{function Cot(t,e,r){var o=-1,a=t.length;e<0&&(e=-e>a?0:a+e),r=r>a?a:r,r<0&&(r+=a),a=e>r?0:r-e>>>0,e>>>=0;for(var n=Array(a);++o<a;)n[o]=t[o+e];return n}lue.exports=Cot});var uue=_((qMt,cue)=>{var Iot=XU();function wot(t,e,r){var o=t.length;return r=r===void 0?o:r,!e&&r>=o?t:Iot(t,e,r)}cue.exports=wot});var ZU=_((jMt,Aue)=>{var Bot=\"\\\\ud800-\\\\udfff\",vot=\"\\\\u0300-\\\\u036f\",Dot=\"\\\\ufe20-\\\\ufe2f\",Pot=\"\\\\u20d0-\\\\u20ff\",Sot=vot+Dot+Pot,xot=\"\\\\ufe0e\\\\ufe0f\",bot=\"\\\\u200d\",kot=RegExp(\"[\"+bot+Bot+Sot+xot+\"]\");function Qot(t){return kot.test(t)}Aue.exports=Qot});var pue=_((GMt,fue)=>{function Fot(t){return t.split(\"\")}fue.exports=Fot});var Iue=_((WMt,Cue)=>{var hue=\"\\\\ud800-\\\\udfff\",Rot=\"\\\\u0300-\\\\u036f\",Tot=\"\\\\ufe20-\\\\ufe2f\",Lot=\"\\\\u20d0-\\\\u20ff\",Not=Rot+Tot+Lot,Oot=\"\\\\ufe0e\\\\ufe0f\",Mot=\"[\"+hue+\"]\",$U=\"[\"+Not+\"]\",e3=\"\\\\ud83c[\\\\udffb-\\\\udfff]\",Uot=\"(?:\"+$U+\"|\"+e3+\")\",gue=\"[^\"+hue+\"]\",due=\"(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}\",mue=\"[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]\",_ot=\"\\\\u200d\",yue=Uot+\"?\",Eue=\"[\"+Oot+\"]?\",Hot=\"(?:\"+_ot+\"(?:\"+[gue,due,mue].join(\"|\")+\")\"+Eue+yue+\")*\",qot=Eue+yue+Hot,jot=\"(?:\"+[gue+$U+\"?\",$U,due,mue,Mot].join(\"|\")+\")\",Got=RegExp(e3+\"(?=\"+e3+\")|\"+jot+qot,\"g\");function Wot(t){return t.match(Got)||[]}Cue.exports=Wot});var Bue=_((YMt,wue)=>{var Yot=pue(),Kot=ZU(),Vot=Iue();function zot(t){return Kot(t)?Vot(t):Yot(t)}wue.exports=zot});var Due=_((KMt,vue)=>{var Jot=uue(),Xot=ZU(),Zot=Bue(),$ot=t2();function eat(t){return function(e){e=$ot(e);var r=Xot(e)?Zot(e):void 0,o=r?r[0]:e.charAt(0),a=r?Jot(r,1).join(\"\"):e.slice(1);return o[t]()+a}}vue.exports=eat});var Sue=_((VMt,Pue)=>{var tat=Due(),rat=tat(\"toUpperCase\");Pue.exports=rat});var t3=_((zMt,xue)=>{var nat=t2(),iat=Sue();function sat(t){return iat(nat(t).toLowerCase())}xue.exports=sat});var bue=_((JMt,Ib)=>{function oat(){var t=0,e=1,r=2,o=3,a=4,n=5,u=6,A=7,p=8,h=9,E=10,w=11,D=12,b=13,C=14,T=15,N=16,U=17,z=0,te=1,le=2,ce=3,ue=4;function Ie(g,me){return 55296<=g.charCodeAt(me)&&g.charCodeAt(me)<=56319&&56320<=g.charCodeAt(me+1)&&g.charCodeAt(me+1)<=57343}function he(g,me){me===void 0&&(me=0);var Ce=g.charCodeAt(me);if(55296<=Ce&&Ce<=56319&&me<g.length-1){var fe=Ce,ie=g.charCodeAt(me+1);return 56320<=ie&&ie<=57343?(fe-55296)*1024+(ie-56320)+65536:fe}if(56320<=Ce&&Ce<=57343&&me>=1){var fe=g.charCodeAt(me-1),ie=Ce;return 55296<=fe&&fe<=56319?(fe-55296)*1024+(ie-56320)+65536:ie}return Ce}function De(g,me,Ce){var fe=[g].concat(me).concat([Ce]),ie=fe[fe.length-2],Z=Ce,Pe=fe.lastIndexOf(C);if(Pe>1&&fe.slice(1,Pe).every(function(q){return q==o})&&[o,b,U].indexOf(g)==-1)return le;var Re=fe.lastIndexOf(a);if(Re>0&&fe.slice(1,Re).every(function(q){return q==a})&&[D,a].indexOf(ie)==-1)return fe.filter(function(q){return q==a}).length%2==1?ce:ue;if(ie==t&&Z==e)return z;if(ie==r||ie==t||ie==e)return Z==C&&me.every(function(q){return q==o})?le:te;if(Z==r||Z==t||Z==e)return te;if(ie==u&&(Z==u||Z==A||Z==h||Z==E))return z;if((ie==h||ie==A)&&(Z==A||Z==p))return z;if((ie==E||ie==p)&&Z==p)return z;if(Z==o||Z==T)return z;if(Z==n)return z;if(ie==D)return z;var ht=fe.indexOf(o)!=-1?fe.lastIndexOf(o)-1:fe.length-2;return[b,U].indexOf(fe[ht])!=-1&&fe.slice(ht+1,-1).every(function(q){return q==o})&&Z==C||ie==T&&[N,U].indexOf(Z)!=-1?z:me.indexOf(a)!=-1?le:ie==a&&Z==a?z:te}this.nextBreak=function(g,me){if(me===void 0&&(me=0),me<0)return 0;if(me>=g.length-1)return g.length;for(var Ce=Ee(he(g,me)),fe=[],ie=me+1;ie<g.length;ie++)if(!Ie(g,ie-1)){var Z=Ee(he(g,ie));if(De(Ce,fe,Z))return ie;fe.push(Z)}return g.length},this.splitGraphemes=function(g){for(var me=[],Ce=0,fe;(fe=this.nextBreak(g,Ce))<g.length;)me.push(g.slice(Ce,fe)),Ce=fe;return Ce<g.length&&me.push(g.slice(Ce)),me},this.iterateGraphemes=function(g){var me=0,Ce={next:function(){var fe,ie;return(ie=this.nextBreak(g,me))<g.length?(fe=g.slice(me,ie),me=ie,{value:fe,done:!1}):me<g.length?(fe=g.slice(me),me=g.length,{value:fe,done:!1}):{value:void 0,done:!0}}.bind(this)};return typeof Symbol<\"u\"&&Symbol.iterator&&(Ce[Symbol.iterator]=function(){return Ce}),Ce},this.countGraphemes=function(g){for(var me=0,Ce=0,fe;(fe=this.nextBreak(g,Ce))<g.length;)Ce=fe,me++;return Ce<g.length&&me++,me};function Ee(g){return 1536<=g&&g<=1541||g==1757||g==1807||g==2274||g==3406||g==69821||70082<=g&&g<=70083||g==72250||72326<=g&&g<=72329||g==73030?D:g==13?t:g==10?e:0<=g&&g<=9||11<=g&&g<=12||14<=g&&g<=31||127<=g&&g<=159||g==173||g==1564||g==6158||g==8203||8206<=g&&g<=8207||g==8232||g==8233||8234<=g&&g<=8238||8288<=g&&g<=8292||g==8293||8294<=g&&g<=8303||55296<=g&&g<=57343||g==65279||65520<=g&&g<=65528||65529<=g&&g<=65531||113824<=g&&g<=113827||119155<=g&&g<=119162||g==917504||g==917505||917506<=g&&g<=917535||917632<=g&&g<=917759||918e3<=g&&g<=921599?r:768<=g&&g<=879||1155<=g&&g<=1159||1160<=g&&g<=1161||1425<=g&&g<=1469||g==1471||1473<=g&&g<=1474||1476<=g&&g<=1477||g==1479||1552<=g&&g<=1562||1611<=g&&g<=1631||g==1648||1750<=g&&g<=1756||1759<=g&&g<=1764||1767<=g&&g<=1768||1770<=g&&g<=1773||g==1809||1840<=g&&g<=1866||1958<=g&&g<=1968||2027<=g&&g<=2035||2070<=g&&g<=2073||2075<=g&&g<=2083||2085<=g&&g<=2087||2089<=g&&g<=2093||2137<=g&&g<=2139||2260<=g&&g<=2273||2275<=g&&g<=2306||g==2362||g==2364||2369<=g&&g<=2376||g==2381||2385<=g&&g<=2391||2402<=g&&g<=2403||g==2433||g==2492||g==2494||2497<=g&&g<=2500||g==2509||g==2519||2530<=g&&g<=2531||2561<=g&&g<=2562||g==2620||2625<=g&&g<=2626||2631<=g&&g<=2632||2635<=g&&g<=2637||g==2641||2672<=g&&g<=2673||g==2677||2689<=g&&g<=2690||g==2748||2753<=g&&g<=2757||2759<=g&&g<=2760||g==2765||2786<=g&&g<=2787||2810<=g&&g<=2815||g==2817||g==2876||g==2878||g==2879||2881<=g&&g<=2884||g==2893||g==2902||g==2903||2914<=g&&g<=2915||g==2946||g==3006||g==3008||g==3021||g==3031||g==3072||3134<=g&&g<=3136||3142<=g&&g<=3144||3146<=g&&g<=3149||3157<=g&&g<=3158||3170<=g&&g<=3171||g==3201||g==3260||g==3263||g==3266||g==3270||3276<=g&&g<=3277||3285<=g&&g<=3286||3298<=g&&g<=3299||3328<=g&&g<=3329||3387<=g&&g<=3388||g==3390||3393<=g&&g<=3396||g==3405||g==3415||3426<=g&&g<=3427||g==3530||g==3535||3538<=g&&g<=3540||g==3542||g==3551||g==3633||3636<=g&&g<=3642||3655<=g&&g<=3662||g==3761||3764<=g&&g<=3769||3771<=g&&g<=3772||3784<=g&&g<=3789||3864<=g&&g<=3865||g==3893||g==3895||g==3897||3953<=g&&g<=3966||3968<=g&&g<=3972||3974<=g&&g<=3975||3981<=g&&g<=3991||3993<=g&&g<=4028||g==4038||4141<=g&&g<=4144||4146<=g&&g<=4151||4153<=g&&g<=4154||4157<=g&&g<=4158||4184<=g&&g<=4185||4190<=g&&g<=4192||4209<=g&&g<=4212||g==4226||4229<=g&&g<=4230||g==4237||g==4253||4957<=g&&g<=4959||5906<=g&&g<=5908||5938<=g&&g<=5940||5970<=g&&g<=5971||6002<=g&&g<=6003||6068<=g&&g<=6069||6071<=g&&g<=6077||g==6086||6089<=g&&g<=6099||g==6109||6155<=g&&g<=6157||6277<=g&&g<=6278||g==6313||6432<=g&&g<=6434||6439<=g&&g<=6440||g==6450||6457<=g&&g<=6459||6679<=g&&g<=6680||g==6683||g==6742||6744<=g&&g<=6750||g==6752||g==6754||6757<=g&&g<=6764||6771<=g&&g<=6780||g==6783||6832<=g&&g<=6845||g==6846||6912<=g&&g<=6915||g==6964||6966<=g&&g<=6970||g==6972||g==6978||7019<=g&&g<=7027||7040<=g&&g<=7041||7074<=g&&g<=7077||7080<=g&&g<=7081||7083<=g&&g<=7085||g==7142||7144<=g&&g<=7145||g==7149||7151<=g&&g<=7153||7212<=g&&g<=7219||7222<=g&&g<=7223||7376<=g&&g<=7378||7380<=g&&g<=7392||7394<=g&&g<=7400||g==7405||g==7412||7416<=g&&g<=7417||7616<=g&&g<=7673||7675<=g&&g<=7679||g==8204||8400<=g&&g<=8412||8413<=g&&g<=8416||g==8417||8418<=g&&g<=8420||8421<=g&&g<=8432||11503<=g&&g<=11505||g==11647||11744<=g&&g<=11775||12330<=g&&g<=12333||12334<=g&&g<=12335||12441<=g&&g<=12442||g==42607||42608<=g&&g<=42610||42612<=g&&g<=42621||42654<=g&&g<=42655||42736<=g&&g<=42737||g==43010||g==43014||g==43019||43045<=g&&g<=43046||43204<=g&&g<=43205||43232<=g&&g<=43249||43302<=g&&g<=43309||43335<=g&&g<=43345||43392<=g&&g<=43394||g==43443||43446<=g&&g<=43449||g==43452||g==43493||43561<=g&&g<=43566||43569<=g&&g<=43570||43573<=g&&g<=43574||g==43587||g==43596||g==43644||g==43696||43698<=g&&g<=43700||43703<=g&&g<=43704||43710<=g&&g<=43711||g==43713||43756<=g&&g<=43757||g==43766||g==44005||g==44008||g==44013||g==64286||65024<=g&&g<=65039||65056<=g&&g<=65071||65438<=g&&g<=65439||g==66045||g==66272||66422<=g&&g<=66426||68097<=g&&g<=68099||68101<=g&&g<=68102||68108<=g&&g<=68111||68152<=g&&g<=68154||g==68159||68325<=g&&g<=68326||g==69633||69688<=g&&g<=69702||69759<=g&&g<=69761||69811<=g&&g<=69814||69817<=g&&g<=69818||69888<=g&&g<=69890||69927<=g&&g<=69931||69933<=g&&g<=69940||g==70003||70016<=g&&g<=70017||70070<=g&&g<=70078||70090<=g&&g<=70092||70191<=g&&g<=70193||g==70196||70198<=g&&g<=70199||g==70206||g==70367||70371<=g&&g<=70378||70400<=g&&g<=70401||g==70460||g==70462||g==70464||g==70487||70502<=g&&g<=70508||70512<=g&&g<=70516||70712<=g&&g<=70719||70722<=g&&g<=70724||g==70726||g==70832||70835<=g&&g<=70840||g==70842||g==70845||70847<=g&&g<=70848||70850<=g&&g<=70851||g==71087||71090<=g&&g<=71093||71100<=g&&g<=71101||71103<=g&&g<=71104||71132<=g&&g<=71133||71219<=g&&g<=71226||g==71229||71231<=g&&g<=71232||g==71339||g==71341||71344<=g&&g<=71349||g==71351||71453<=g&&g<=71455||71458<=g&&g<=71461||71463<=g&&g<=71467||72193<=g&&g<=72198||72201<=g&&g<=72202||72243<=g&&g<=72248||72251<=g&&g<=72254||g==72263||72273<=g&&g<=72278||72281<=g&&g<=72283||72330<=g&&g<=72342||72344<=g&&g<=72345||72752<=g&&g<=72758||72760<=g&&g<=72765||g==72767||72850<=g&&g<=72871||72874<=g&&g<=72880||72882<=g&&g<=72883||72885<=g&&g<=72886||73009<=g&&g<=73014||g==73018||73020<=g&&g<=73021||73023<=g&&g<=73029||g==73031||92912<=g&&g<=92916||92976<=g&&g<=92982||94095<=g&&g<=94098||113821<=g&&g<=113822||g==119141||119143<=g&&g<=119145||119150<=g&&g<=119154||119163<=g&&g<=119170||119173<=g&&g<=119179||119210<=g&&g<=119213||119362<=g&&g<=119364||121344<=g&&g<=121398||121403<=g&&g<=121452||g==121461||g==121476||121499<=g&&g<=121503||121505<=g&&g<=121519||122880<=g&&g<=122886||122888<=g&&g<=122904||122907<=g&&g<=122913||122915<=g&&g<=122916||122918<=g&&g<=122922||125136<=g&&g<=125142||125252<=g&&g<=125258||917536<=g&&g<=917631||917760<=g&&g<=917999?o:127462<=g&&g<=127487?a:g==2307||g==2363||2366<=g&&g<=2368||2377<=g&&g<=2380||2382<=g&&g<=2383||2434<=g&&g<=2435||2495<=g&&g<=2496||2503<=g&&g<=2504||2507<=g&&g<=2508||g==2563||2622<=g&&g<=2624||g==2691||2750<=g&&g<=2752||g==2761||2763<=g&&g<=2764||2818<=g&&g<=2819||g==2880||2887<=g&&g<=2888||2891<=g&&g<=2892||g==3007||3009<=g&&g<=3010||3014<=g&&g<=3016||3018<=g&&g<=3020||3073<=g&&g<=3075||3137<=g&&g<=3140||3202<=g&&g<=3203||g==3262||3264<=g&&g<=3265||3267<=g&&g<=3268||3271<=g&&g<=3272||3274<=g&&g<=3275||3330<=g&&g<=3331||3391<=g&&g<=3392||3398<=g&&g<=3400||3402<=g&&g<=3404||3458<=g&&g<=3459||3536<=g&&g<=3537||3544<=g&&g<=3550||3570<=g&&g<=3571||g==3635||g==3763||3902<=g&&g<=3903||g==3967||g==4145||4155<=g&&g<=4156||4182<=g&&g<=4183||g==4228||g==6070||6078<=g&&g<=6085||6087<=g&&g<=6088||6435<=g&&g<=6438||6441<=g&&g<=6443||6448<=g&&g<=6449||6451<=g&&g<=6456||6681<=g&&g<=6682||g==6741||g==6743||6765<=g&&g<=6770||g==6916||g==6965||g==6971||6973<=g&&g<=6977||6979<=g&&g<=6980||g==7042||g==7073||7078<=g&&g<=7079||g==7082||g==7143||7146<=g&&g<=7148||g==7150||7154<=g&&g<=7155||7204<=g&&g<=7211||7220<=g&&g<=7221||g==7393||7410<=g&&g<=7411||g==7415||43043<=g&&g<=43044||g==43047||43136<=g&&g<=43137||43188<=g&&g<=43203||43346<=g&&g<=43347||g==43395||43444<=g&&g<=43445||43450<=g&&g<=43451||43453<=g&&g<=43456||43567<=g&&g<=43568||43571<=g&&g<=43572||g==43597||g==43755||43758<=g&&g<=43759||g==43765||44003<=g&&g<=44004||44006<=g&&g<=44007||44009<=g&&g<=44010||g==44012||g==69632||g==69634||g==69762||69808<=g&&g<=69810||69815<=g&&g<=69816||g==69932||g==70018||70067<=g&&g<=70069||70079<=g&&g<=70080||70188<=g&&g<=70190||70194<=g&&g<=70195||g==70197||70368<=g&&g<=70370||70402<=g&&g<=70403||g==70463||70465<=g&&g<=70468||70471<=g&&g<=70472||70475<=g&&g<=70477||70498<=g&&g<=70499||70709<=g&&g<=70711||70720<=g&&g<=70721||g==70725||70833<=g&&g<=70834||g==70841||70843<=g&&g<=70844||g==70846||g==70849||71088<=g&&g<=71089||71096<=g&&g<=71099||g==71102||71216<=g&&g<=71218||71227<=g&&g<=71228||g==71230||g==71340||71342<=g&&g<=71343||g==71350||71456<=g&&g<=71457||g==71462||72199<=g&&g<=72200||g==72249||72279<=g&&g<=72280||g==72343||g==72751||g==72766||g==72873||g==72881||g==72884||94033<=g&&g<=94078||g==119142||g==119149?n:4352<=g&&g<=4447||43360<=g&&g<=43388?u:4448<=g&&g<=4519||55216<=g&&g<=55238?A:4520<=g&&g<=4607||55243<=g&&g<=55291?p:g==44032||g==44060||g==44088||g==44116||g==44144||g==44172||g==44200||g==44228||g==44256||g==44284||g==44312||g==44340||g==44368||g==44396||g==44424||g==44452||g==44480||g==44508||g==44536||g==44564||g==44592||g==44620||g==44648||g==44676||g==44704||g==44732||g==44760||g==44788||g==44816||g==44844||g==44872||g==44900||g==44928||g==44956||g==44984||g==45012||g==45040||g==45068||g==45096||g==45124||g==45152||g==45180||g==45208||g==45236||g==45264||g==45292||g==45320||g==45348||g==45376||g==45404||g==45432||g==45460||g==45488||g==45516||g==45544||g==45572||g==45600||g==45628||g==45656||g==45684||g==45712||g==45740||g==45768||g==45796||g==45824||g==45852||g==45880||g==45908||g==45936||g==45964||g==45992||g==46020||g==46048||g==46076||g==46104||g==46132||g==46160||g==46188||g==46216||g==46244||g==46272||g==46300||g==46328||g==46356||g==46384||g==46412||g==46440||g==46468||g==46496||g==46524||g==46552||g==46580||g==46608||g==46636||g==46664||g==46692||g==46720||g==46748||g==46776||g==46804||g==46832||g==46860||g==46888||g==46916||g==46944||g==46972||g==47e3||g==47028||g==47056||g==47084||g==47112||g==47140||g==47168||g==47196||g==47224||g==47252||g==47280||g==47308||g==47336||g==47364||g==47392||g==47420||g==47448||g==47476||g==47504||g==47532||g==47560||g==47588||g==47616||g==47644||g==47672||g==47700||g==47728||g==47756||g==47784||g==47812||g==47840||g==47868||g==47896||g==47924||g==47952||g==47980||g==48008||g==48036||g==48064||g==48092||g==48120||g==48148||g==48176||g==48204||g==48232||g==48260||g==48288||g==48316||g==48344||g==48372||g==48400||g==48428||g==48456||g==48484||g==48512||g==48540||g==48568||g==48596||g==48624||g==48652||g==48680||g==48708||g==48736||g==48764||g==48792||g==48820||g==48848||g==48876||g==48904||g==48932||g==48960||g==48988||g==49016||g==49044||g==49072||g==49100||g==49128||g==49156||g==49184||g==49212||g==49240||g==49268||g==49296||g==49324||g==49352||g==49380||g==49408||g==49436||g==49464||g==49492||g==49520||g==49548||g==49576||g==49604||g==49632||g==49660||g==49688||g==49716||g==49744||g==49772||g==49800||g==49828||g==49856||g==49884||g==49912||g==49940||g==49968||g==49996||g==50024||g==50052||g==50080||g==50108||g==50136||g==50164||g==50192||g==50220||g==50248||g==50276||g==50304||g==50332||g==50360||g==50388||g==50416||g==50444||g==50472||g==50500||g==50528||g==50556||g==50584||g==50612||g==50640||g==50668||g==50696||g==50724||g==50752||g==50780||g==50808||g==50836||g==50864||g==50892||g==50920||g==50948||g==50976||g==51004||g==51032||g==51060||g==51088||g==51116||g==51144||g==51172||g==51200||g==51228||g==51256||g==51284||g==51312||g==51340||g==51368||g==51396||g==51424||g==51452||g==51480||g==51508||g==51536||g==51564||g==51592||g==51620||g==51648||g==51676||g==51704||g==51732||g==51760||g==51788||g==51816||g==51844||g==51872||g==51900||g==51928||g==51956||g==51984||g==52012||g==52040||g==52068||g==52096||g==52124||g==52152||g==52180||g==52208||g==52236||g==52264||g==52292||g==52320||g==52348||g==52376||g==52404||g==52432||g==52460||g==52488||g==52516||g==52544||g==52572||g==52600||g==52628||g==52656||g==52684||g==52712||g==52740||g==52768||g==52796||g==52824||g==52852||g==52880||g==52908||g==52936||g==52964||g==52992||g==53020||g==53048||g==53076||g==53104||g==53132||g==53160||g==53188||g==53216||g==53244||g==53272||g==53300||g==53328||g==53356||g==53384||g==53412||g==53440||g==53468||g==53496||g==53524||g==53552||g==53580||g==53608||g==53636||g==53664||g==53692||g==53720||g==53748||g==53776||g==53804||g==53832||g==53860||g==53888||g==53916||g==53944||g==53972||g==54e3||g==54028||g==54056||g==54084||g==54112||g==54140||g==54168||g==54196||g==54224||g==54252||g==54280||g==54308||g==54336||g==54364||g==54392||g==54420||g==54448||g==54476||g==54504||g==54532||g==54560||g==54588||g==54616||g==54644||g==54672||g==54700||g==54728||g==54756||g==54784||g==54812||g==54840||g==54868||g==54896||g==54924||g==54952||g==54980||g==55008||g==55036||g==55064||g==55092||g==55120||g==55148||g==55176?h:44033<=g&&g<=44059||44061<=g&&g<=44087||44089<=g&&g<=44115||44117<=g&&g<=44143||44145<=g&&g<=44171||44173<=g&&g<=44199||44201<=g&&g<=44227||44229<=g&&g<=44255||44257<=g&&g<=44283||44285<=g&&g<=44311||44313<=g&&g<=44339||44341<=g&&g<=44367||44369<=g&&g<=44395||44397<=g&&g<=44423||44425<=g&&g<=44451||44453<=g&&g<=44479||44481<=g&&g<=44507||44509<=g&&g<=44535||44537<=g&&g<=44563||44565<=g&&g<=44591||44593<=g&&g<=44619||44621<=g&&g<=44647||44649<=g&&g<=44675||44677<=g&&g<=44703||44705<=g&&g<=44731||44733<=g&&g<=44759||44761<=g&&g<=44787||44789<=g&&g<=44815||44817<=g&&g<=44843||44845<=g&&g<=44871||44873<=g&&g<=44899||44901<=g&&g<=44927||44929<=g&&g<=44955||44957<=g&&g<=44983||44985<=g&&g<=45011||45013<=g&&g<=45039||45041<=g&&g<=45067||45069<=g&&g<=45095||45097<=g&&g<=45123||45125<=g&&g<=45151||45153<=g&&g<=45179||45181<=g&&g<=45207||45209<=g&&g<=45235||45237<=g&&g<=45263||45265<=g&&g<=45291||45293<=g&&g<=45319||45321<=g&&g<=45347||45349<=g&&g<=45375||45377<=g&&g<=45403||45405<=g&&g<=45431||45433<=g&&g<=45459||45461<=g&&g<=45487||45489<=g&&g<=45515||45517<=g&&g<=45543||45545<=g&&g<=45571||45573<=g&&g<=45599||45601<=g&&g<=45627||45629<=g&&g<=45655||45657<=g&&g<=45683||45685<=g&&g<=45711||45713<=g&&g<=45739||45741<=g&&g<=45767||45769<=g&&g<=45795||45797<=g&&g<=45823||45825<=g&&g<=45851||45853<=g&&g<=45879||45881<=g&&g<=45907||45909<=g&&g<=45935||45937<=g&&g<=45963||45965<=g&&g<=45991||45993<=g&&g<=46019||46021<=g&&g<=46047||46049<=g&&g<=46075||46077<=g&&g<=46103||46105<=g&&g<=46131||46133<=g&&g<=46159||46161<=g&&g<=46187||46189<=g&&g<=46215||46217<=g&&g<=46243||46245<=g&&g<=46271||46273<=g&&g<=46299||46301<=g&&g<=46327||46329<=g&&g<=46355||46357<=g&&g<=46383||46385<=g&&g<=46411||46413<=g&&g<=46439||46441<=g&&g<=46467||46469<=g&&g<=46495||46497<=g&&g<=46523||46525<=g&&g<=46551||46553<=g&&g<=46579||46581<=g&&g<=46607||46609<=g&&g<=46635||46637<=g&&g<=46663||46665<=g&&g<=46691||46693<=g&&g<=46719||46721<=g&&g<=46747||46749<=g&&g<=46775||46777<=g&&g<=46803||46805<=g&&g<=46831||46833<=g&&g<=46859||46861<=g&&g<=46887||46889<=g&&g<=46915||46917<=g&&g<=46943||46945<=g&&g<=46971||46973<=g&&g<=46999||47001<=g&&g<=47027||47029<=g&&g<=47055||47057<=g&&g<=47083||47085<=g&&g<=47111||47113<=g&&g<=47139||47141<=g&&g<=47167||47169<=g&&g<=47195||47197<=g&&g<=47223||47225<=g&&g<=47251||47253<=g&&g<=47279||47281<=g&&g<=47307||47309<=g&&g<=47335||47337<=g&&g<=47363||47365<=g&&g<=47391||47393<=g&&g<=47419||47421<=g&&g<=47447||47449<=g&&g<=47475||47477<=g&&g<=47503||47505<=g&&g<=47531||47533<=g&&g<=47559||47561<=g&&g<=47587||47589<=g&&g<=47615||47617<=g&&g<=47643||47645<=g&&g<=47671||47673<=g&&g<=47699||47701<=g&&g<=47727||47729<=g&&g<=47755||47757<=g&&g<=47783||47785<=g&&g<=47811||47813<=g&&g<=47839||47841<=g&&g<=47867||47869<=g&&g<=47895||47897<=g&&g<=47923||47925<=g&&g<=47951||47953<=g&&g<=47979||47981<=g&&g<=48007||48009<=g&&g<=48035||48037<=g&&g<=48063||48065<=g&&g<=48091||48093<=g&&g<=48119||48121<=g&&g<=48147||48149<=g&&g<=48175||48177<=g&&g<=48203||48205<=g&&g<=48231||48233<=g&&g<=48259||48261<=g&&g<=48287||48289<=g&&g<=48315||48317<=g&&g<=48343||48345<=g&&g<=48371||48373<=g&&g<=48399||48401<=g&&g<=48427||48429<=g&&g<=48455||48457<=g&&g<=48483||48485<=g&&g<=48511||48513<=g&&g<=48539||48541<=g&&g<=48567||48569<=g&&g<=48595||48597<=g&&g<=48623||48625<=g&&g<=48651||48653<=g&&g<=48679||48681<=g&&g<=48707||48709<=g&&g<=48735||48737<=g&&g<=48763||48765<=g&&g<=48791||48793<=g&&g<=48819||48821<=g&&g<=48847||48849<=g&&g<=48875||48877<=g&&g<=48903||48905<=g&&g<=48931||48933<=g&&g<=48959||48961<=g&&g<=48987||48989<=g&&g<=49015||49017<=g&&g<=49043||49045<=g&&g<=49071||49073<=g&&g<=49099||49101<=g&&g<=49127||49129<=g&&g<=49155||49157<=g&&g<=49183||49185<=g&&g<=49211||49213<=g&&g<=49239||49241<=g&&g<=49267||49269<=g&&g<=49295||49297<=g&&g<=49323||49325<=g&&g<=49351||49353<=g&&g<=49379||49381<=g&&g<=49407||49409<=g&&g<=49435||49437<=g&&g<=49463||49465<=g&&g<=49491||49493<=g&&g<=49519||49521<=g&&g<=49547||49549<=g&&g<=49575||49577<=g&&g<=49603||49605<=g&&g<=49631||49633<=g&&g<=49659||49661<=g&&g<=49687||49689<=g&&g<=49715||49717<=g&&g<=49743||49745<=g&&g<=49771||49773<=g&&g<=49799||49801<=g&&g<=49827||49829<=g&&g<=49855||49857<=g&&g<=49883||49885<=g&&g<=49911||49913<=g&&g<=49939||49941<=g&&g<=49967||49969<=g&&g<=49995||49997<=g&&g<=50023||50025<=g&&g<=50051||50053<=g&&g<=50079||50081<=g&&g<=50107||50109<=g&&g<=50135||50137<=g&&g<=50163||50165<=g&&g<=50191||50193<=g&&g<=50219||50221<=g&&g<=50247||50249<=g&&g<=50275||50277<=g&&g<=50303||50305<=g&&g<=50331||50333<=g&&g<=50359||50361<=g&&g<=50387||50389<=g&&g<=50415||50417<=g&&g<=50443||50445<=g&&g<=50471||50473<=g&&g<=50499||50501<=g&&g<=50527||50529<=g&&g<=50555||50557<=g&&g<=50583||50585<=g&&g<=50611||50613<=g&&g<=50639||50641<=g&&g<=50667||50669<=g&&g<=50695||50697<=g&&g<=50723||50725<=g&&g<=50751||50753<=g&&g<=50779||50781<=g&&g<=50807||50809<=g&&g<=50835||50837<=g&&g<=50863||50865<=g&&g<=50891||50893<=g&&g<=50919||50921<=g&&g<=50947||50949<=g&&g<=50975||50977<=g&&g<=51003||51005<=g&&g<=51031||51033<=g&&g<=51059||51061<=g&&g<=51087||51089<=g&&g<=51115||51117<=g&&g<=51143||51145<=g&&g<=51171||51173<=g&&g<=51199||51201<=g&&g<=51227||51229<=g&&g<=51255||51257<=g&&g<=51283||51285<=g&&g<=51311||51313<=g&&g<=51339||51341<=g&&g<=51367||51369<=g&&g<=51395||51397<=g&&g<=51423||51425<=g&&g<=51451||51453<=g&&g<=51479||51481<=g&&g<=51507||51509<=g&&g<=51535||51537<=g&&g<=51563||51565<=g&&g<=51591||51593<=g&&g<=51619||51621<=g&&g<=51647||51649<=g&&g<=51675||51677<=g&&g<=51703||51705<=g&&g<=51731||51733<=g&&g<=51759||51761<=g&&g<=51787||51789<=g&&g<=51815||51817<=g&&g<=51843||51845<=g&&g<=51871||51873<=g&&g<=51899||51901<=g&&g<=51927||51929<=g&&g<=51955||51957<=g&&g<=51983||51985<=g&&g<=52011||52013<=g&&g<=52039||52041<=g&&g<=52067||52069<=g&&g<=52095||52097<=g&&g<=52123||52125<=g&&g<=52151||52153<=g&&g<=52179||52181<=g&&g<=52207||52209<=g&&g<=52235||52237<=g&&g<=52263||52265<=g&&g<=52291||52293<=g&&g<=52319||52321<=g&&g<=52347||52349<=g&&g<=52375||52377<=g&&g<=52403||52405<=g&&g<=52431||52433<=g&&g<=52459||52461<=g&&g<=52487||52489<=g&&g<=52515||52517<=g&&g<=52543||52545<=g&&g<=52571||52573<=g&&g<=52599||52601<=g&&g<=52627||52629<=g&&g<=52655||52657<=g&&g<=52683||52685<=g&&g<=52711||52713<=g&&g<=52739||52741<=g&&g<=52767||52769<=g&&g<=52795||52797<=g&&g<=52823||52825<=g&&g<=52851||52853<=g&&g<=52879||52881<=g&&g<=52907||52909<=g&&g<=52935||52937<=g&&g<=52963||52965<=g&&g<=52991||52993<=g&&g<=53019||53021<=g&&g<=53047||53049<=g&&g<=53075||53077<=g&&g<=53103||53105<=g&&g<=53131||53133<=g&&g<=53159||53161<=g&&g<=53187||53189<=g&&g<=53215||53217<=g&&g<=53243||53245<=g&&g<=53271||53273<=g&&g<=53299||53301<=g&&g<=53327||53329<=g&&g<=53355||53357<=g&&g<=53383||53385<=g&&g<=53411||53413<=g&&g<=53439||53441<=g&&g<=53467||53469<=g&&g<=53495||53497<=g&&g<=53523||53525<=g&&g<=53551||53553<=g&&g<=53579||53581<=g&&g<=53607||53609<=g&&g<=53635||53637<=g&&g<=53663||53665<=g&&g<=53691||53693<=g&&g<=53719||53721<=g&&g<=53747||53749<=g&&g<=53775||53777<=g&&g<=53803||53805<=g&&g<=53831||53833<=g&&g<=53859||53861<=g&&g<=53887||53889<=g&&g<=53915||53917<=g&&g<=53943||53945<=g&&g<=53971||53973<=g&&g<=53999||54001<=g&&g<=54027||54029<=g&&g<=54055||54057<=g&&g<=54083||54085<=g&&g<=54111||54113<=g&&g<=54139||54141<=g&&g<=54167||54169<=g&&g<=54195||54197<=g&&g<=54223||54225<=g&&g<=54251||54253<=g&&g<=54279||54281<=g&&g<=54307||54309<=g&&g<=54335||54337<=g&&g<=54363||54365<=g&&g<=54391||54393<=g&&g<=54419||54421<=g&&g<=54447||54449<=g&&g<=54475||54477<=g&&g<=54503||54505<=g&&g<=54531||54533<=g&&g<=54559||54561<=g&&g<=54587||54589<=g&&g<=54615||54617<=g&&g<=54643||54645<=g&&g<=54671||54673<=g&&g<=54699||54701<=g&&g<=54727||54729<=g&&g<=54755||54757<=g&&g<=54783||54785<=g&&g<=54811||54813<=g&&g<=54839||54841<=g&&g<=54867||54869<=g&&g<=54895||54897<=g&&g<=54923||54925<=g&&g<=54951||54953<=g&&g<=54979||54981<=g&&g<=55007||55009<=g&&g<=55035||55037<=g&&g<=55063||55065<=g&&g<=55091||55093<=g&&g<=55119||55121<=g&&g<=55147||55149<=g&&g<=55175||55177<=g&&g<=55203?E:g==9757||g==9977||9994<=g&&g<=9997||g==127877||127938<=g&&g<=127940||g==127943||127946<=g&&g<=127948||128066<=g&&g<=128067||128070<=g&&g<=128080||g==128110||128112<=g&&g<=128120||g==128124||128129<=g&&g<=128131||128133<=g&&g<=128135||g==128170||128372<=g&&g<=128373||g==128378||g==128400||128405<=g&&g<=128406||128581<=g&&g<=128583||128587<=g&&g<=128591||g==128675||128692<=g&&g<=128694||g==128704||g==128716||129304<=g&&g<=129308||129310<=g&&g<=129311||g==129318||129328<=g&&g<=129337||129341<=g&&g<=129342||129489<=g&&g<=129501?b:127995<=g&&g<=127999?C:g==8205?T:g==9792||g==9794||9877<=g&&g<=9878||g==9992||g==10084||g==127752||g==127806||g==127859||g==127891||g==127908||g==127912||g==127979||g==127981||g==128139||128187<=g&&g<=128188||g==128295||g==128300||g==128488||g==128640||g==128658?N:128102<=g&&g<=128105?U:w}return this}typeof Ib<\"u\"&&Ib.exports&&(Ib.exports=oat)});var Que=_((XMt,kue)=>{var aat=/^(.*?)(\\x1b\\[[^m]+m|\\x1b\\]8;;.*?(\\x1b\\\\|\\u0007))/,wb;function lat(){if(wb)return wb;if(typeof Intl.Segmenter<\"u\"){let t=new Intl.Segmenter(\"en\",{granularity:\"grapheme\"});return wb=e=>Array.from(t.segment(e),({segment:r})=>r)}else{let t=bue(),e=new t;return wb=r=>e.splitGraphemes(r)}}kue.exports=(t,e=0,r=t.length)=>{if(e<0||r<0)throw new RangeError(\"Negative indices aren't supported by this implementation\");let o=r-e,a=\"\",n=0,u=0;for(;t.length>0;){let A=t.match(aat)||[t,t,void 0],p=lat()(A[1]),h=Math.min(e-n,p.length);p=p.slice(h);let E=Math.min(o-u,p.length);a+=p.slice(0,E).join(\"\"),n+=h,u+=E,typeof A[2]<\"u\"&&(a+=A[2]),t=t.slice(A[0].length)}return a}});var nn,r2=It(()=>{nn=process.env.YARN_IS_TEST_ENV?\"0.0.0\":\"4.5.3\"});function Oue(t,{configuration:e,json:r}){if(!e.get(\"enableMessageNames\"))return\"\";let a=zu(t===null?0:t);return!r&&t===null?Ut(e,a,\"grey\"):a}function r3(t,{configuration:e,json:r}){let o=Oue(t,{configuration:e,json:r});if(!o||t===null||t===0)return o;let a=vr[t],n=`https://yarnpkg.com/advanced/error-codes#${o}---${a}`.toLowerCase();return ty(e,o,n)}async function Qy({configuration:t,stdout:e,forceError:r},o){let a=await Lt.start({configuration:t,stdout:e,includeFooter:!1},async n=>{let u=!1,A=!1;for(let p of o)typeof p.option<\"u\"&&(p.error||r?(A=!0,n.reportError(50,p.message)):(u=!0,n.reportWarning(50,p.message)),p.callback?.());u&&!A&&n.reportSeparator()});return a.hasErrors()?a.exitCode():null}var Lue,Bb,cat,Fue,Rue,hh,Nue,Tue,uat,Aat,vb,fat,Lt,n2=It(()=>{Lue=et(Que()),Bb=et(sg());jP();Vl();r2();Wl();cat=\"\\xB7\",Fue=[\"\\u280B\",\"\\u2819\",\"\\u2839\",\"\\u2838\",\"\\u283C\",\"\\u2834\",\"\\u2826\",\"\\u2827\",\"\\u2807\",\"\\u280F\"],Rue=80,hh=Bb.default.GITHUB_ACTIONS?{start:t=>`::group::${t}\n`,end:t=>`::endgroup::\n`}:Bb.default.TRAVIS?{start:t=>`travis_fold:start:${t}\n`,end:t=>`travis_fold:end:${t}\n`}:Bb.default.GITLAB?{start:t=>`section_start:${Math.floor(Date.now()/1e3)}:${t.toLowerCase().replace(/\\W+/g,\"_\")}[collapsed=true]\\r\\x1B[0K${t}\n`,end:t=>`section_end:${Math.floor(Date.now()/1e3)}:${t.toLowerCase().replace(/\\W+/g,\"_\")}\\r\\x1B[0K`}:null,Nue=hh!==null,Tue=new Date,uat=[\"iTerm.app\",\"Apple_Terminal\",\"WarpTerminal\",\"vscode\"].includes(process.env.TERM_PROGRAM)||!!process.env.WT_SESSION,Aat=t=>t,vb=Aat({patrick:{date:[17,3],chars:[\"\\u{1F340}\",\"\\u{1F331}\"],size:40},simba:{date:[19,7],chars:[\"\\u{1F981}\",\"\\u{1F334}\"],size:40},jack:{date:[31,10],chars:[\"\\u{1F383}\",\"\\u{1F987}\"],size:40},hogsfather:{date:[31,12],chars:[\"\\u{1F389}\",\"\\u{1F384}\"],size:40},default:{chars:[\"=\",\"-\"],size:80}}),fat=uat&&Object.keys(vb).find(t=>{let e=vb[t];return!(e.date&&(e.date[0]!==Tue.getDate()||e.date[1]!==Tue.getMonth()+1))})||\"default\";Lt=class extends Ws{constructor({configuration:r,stdout:o,json:a=!1,forceSectionAlignment:n=!1,includeNames:u=!0,includePrefix:A=!0,includeFooter:p=!0,includeLogs:h=!a,includeInfos:E=h,includeWarnings:w=h}){super();this.uncommitted=new Set;this.warningCount=0;this.errorCount=0;this.timerFooter=[];this.startTime=Date.now();this.indent=0;this.level=0;this.progress=new Map;this.progressTime=0;this.progressFrame=0;this.progressTimeout=null;this.progressStyle=null;this.progressMaxScaledSize=null;if(g1(this,{configuration:r}),this.configuration=r,this.forceSectionAlignment=n,this.includeNames=u,this.includePrefix=A,this.includeFooter=p,this.includeInfos=E,this.includeWarnings=w,this.json=a,this.stdout=o,r.get(\"enableProgressBars\")&&!a&&o.isTTY&&o.columns>22){let D=r.get(\"progressBarStyle\")||fat;if(!Object.hasOwn(vb,D))throw new Error(\"Assertion failed: Invalid progress bar style\");this.progressStyle=vb[D];let b=Math.min(this.getRecommendedLength(),80);this.progressMaxScaledSize=Math.floor(this.progressStyle.size*b/80)}}static async start(r,o){let a=new this(r),n=process.emitWarning;process.emitWarning=(u,A)=>{if(typeof u!=\"string\"){let h=u;u=h.message,A=A??h.name}let p=typeof A<\"u\"?`${A}: ${u}`:u;a.reportWarning(0,p)},r.includeVersion&&a.reportInfo(0,Cg(r.configuration,`Yarn ${nn}`,2));try{await o(a)}catch(u){a.reportExceptionOnce(u)}finally{await a.finalize(),process.emitWarning=n}return a}hasErrors(){return this.errorCount>0}exitCode(){return this.hasErrors()?1:0}getRecommendedLength(){let o=this.progressStyle!==null?this.stdout.columns-1:super.getRecommendedLength();return Math.max(40,o-12-this.indent*2)}startSectionSync({reportHeader:r,reportFooter:o,skipIfEmpty:a},n){let u={committed:!1,action:()=>{r?.()}};a?this.uncommitted.add(u):(u.action(),u.committed=!0);let A=Date.now();try{return n()}catch(p){throw this.reportExceptionOnce(p),p}finally{let p=Date.now();this.uncommitted.delete(u),u.committed&&o?.(p-A)}}async startSectionPromise({reportHeader:r,reportFooter:o,skipIfEmpty:a},n){let u={committed:!1,action:()=>{r?.()}};a?this.uncommitted.add(u):(u.action(),u.committed=!0);let A=Date.now();try{return await n()}catch(p){throw this.reportExceptionOnce(p),p}finally{let p=Date.now();this.uncommitted.delete(u),u.committed&&o?.(p-A)}}startTimerImpl(r,o,a){return{cb:typeof o==\"function\"?o:a,reportHeader:()=>{this.level+=1,this.reportInfo(null,`\\u250C ${r}`),this.indent+=1,hh!==null&&!this.json&&this.includeInfos&&this.stdout.write(hh.start(r))},reportFooter:A=>{if(this.indent-=1,hh!==null&&!this.json&&this.includeInfos){this.stdout.write(hh.end(r));for(let p of this.timerFooter)p()}this.configuration.get(\"enableTimers\")&&A>200?this.reportInfo(null,`\\u2514 Completed in ${Ut(this.configuration,A,Ct.DURATION)}`):this.reportInfo(null,\"\\u2514 Completed\"),this.level-=1},skipIfEmpty:(typeof o==\"function\"?{}:o).skipIfEmpty}}startTimerSync(r,o,a){let{cb:n,...u}=this.startTimerImpl(r,o,a);return this.startSectionSync(u,n)}async startTimerPromise(r,o,a){let{cb:n,...u}=this.startTimerImpl(r,o,a);return this.startSectionPromise(u,n)}reportSeparator(){this.indent===0?this.writeLine(\"\"):this.reportInfo(null,\"\")}reportInfo(r,o){if(!this.includeInfos)return;this.commit();let a=this.formatNameWithHyperlink(r),n=a?`${a}: `:\"\",u=`${this.formatPrefix(n,\"blueBright\")}${o}`;this.json?this.reportJson({type:\"info\",name:r,displayName:this.formatName(r),indent:this.formatIndent(),data:o}):this.writeLine(u)}reportWarning(r,o){if(this.warningCount+=1,!this.includeWarnings)return;this.commit();let a=this.formatNameWithHyperlink(r),n=a?`${a}: `:\"\";this.json?this.reportJson({type:\"warning\",name:r,displayName:this.formatName(r),indent:this.formatIndent(),data:o}):this.writeLine(`${this.formatPrefix(n,\"yellowBright\")}${o}`)}reportError(r,o){this.errorCount+=1,this.timerFooter.push(()=>this.reportErrorImpl(r,o)),this.reportErrorImpl(r,o)}reportErrorImpl(r,o){this.commit();let a=this.formatNameWithHyperlink(r),n=a?`${a}: `:\"\";this.json?this.reportJson({type:\"error\",name:r,displayName:this.formatName(r),indent:this.formatIndent(),data:o}):this.writeLine(`${this.formatPrefix(n,\"redBright\")}${o}`,{truncate:!1})}reportFold(r,o){if(!hh)return;let a=`${hh.start(r)}${o}${hh.end(r)}`;this.timerFooter.push(()=>this.stdout.write(a))}reportProgress(r){if(this.progressStyle===null)return{...Promise.resolve(),stop:()=>{}};if(r.hasProgress&&r.hasTitle)throw new Error(\"Unimplemented: Progress bars can't have both progress and titles.\");let o=!1,a=Promise.resolve().then(async()=>{let u={progress:r.hasProgress?0:void 0,title:r.hasTitle?\"\":void 0};this.progress.set(r,{definition:u,lastScaledSize:r.hasProgress?-1:void 0,lastTitle:void 0}),this.refreshProgress({delta:-1});for await(let{progress:A,title:p}of r)o||u.progress===A&&u.title===p||(u.progress=A,u.title=p,this.refreshProgress());n()}),n=()=>{o||(o=!0,this.progress.delete(r),this.refreshProgress({delta:1}))};return{...a,stop:n}}reportJson(r){this.json&&this.writeLine(`${JSON.stringify(r)}`)}async finalize(){if(!this.includeFooter)return;let r=\"\";this.errorCount>0?r=\"Failed with errors\":this.warningCount>0?r=\"Done with warnings\":r=\"Done\";let o=Ut(this.configuration,Date.now()-this.startTime,Ct.DURATION),a=this.configuration.get(\"enableTimers\")?`${r} in ${o}`:r;this.errorCount>0?this.reportError(0,a):this.warningCount>0?this.reportWarning(0,a):this.reportInfo(0,a)}writeLine(r,{truncate:o}={}){this.clearProgress({clear:!0}),this.stdout.write(`${this.truncate(r,{truncate:o})}\n`),this.writeProgress()}writeLines(r,{truncate:o}={}){this.clearProgress({delta:r.length});for(let a of r)this.stdout.write(`${this.truncate(a,{truncate:o})}\n`);this.writeProgress()}commit(){let r=this.uncommitted;this.uncommitted=new Set;for(let o of r)o.committed=!0,o.action()}clearProgress({delta:r=0,clear:o=!1}){this.progressStyle!==null&&this.progress.size+r>0&&(this.stdout.write(`\\x1B[${this.progress.size+r}A`),(r>0||o)&&this.stdout.write(\"\\x1B[0J\"))}writeProgress(){if(this.progressStyle===null||(this.progressTimeout!==null&&clearTimeout(this.progressTimeout),this.progressTimeout=null,this.progress.size===0))return;let r=Date.now();r-this.progressTime>Rue&&(this.progressFrame=(this.progressFrame+1)%Fue.length,this.progressTime=r);let o=Fue[this.progressFrame];for(let a of this.progress.values()){let n=\"\";if(typeof a.lastScaledSize<\"u\"){let h=this.progressStyle.chars[0].repeat(a.lastScaledSize),E=this.progressStyle.chars[1].repeat(this.progressMaxScaledSize-a.lastScaledSize);n=` ${h}${E}`}let u=this.formatName(null),A=u?`${u}: `:\"\",p=a.definition.title?` ${a.definition.title}`:\"\";this.stdout.write(`${Ut(this.configuration,\"\\u27A4\",\"blueBright\")} ${A}${o}${n}${p}\n`)}this.progressTimeout=setTimeout(()=>{this.refreshProgress({force:!0})},Rue)}refreshProgress({delta:r=0,force:o=!1}={}){let a=!1,n=!1;if(o||this.progress.size===0)a=!0;else for(let u of this.progress.values()){let A=typeof u.definition.progress<\"u\"?Math.trunc(this.progressMaxScaledSize*u.definition.progress):void 0,p=u.lastScaledSize;u.lastScaledSize=A;let h=u.lastTitle;if(u.lastTitle=u.definition.title,A!==p||(n=h!==u.definition.title)){a=!0;break}}a&&(this.clearProgress({delta:r,clear:n}),this.writeProgress())}truncate(r,{truncate:o}={}){return this.progressStyle===null&&(o=!1),typeof o>\"u\"&&(o=this.configuration.get(\"preferTruncatedLines\")),o&&(r=(0,Lue.default)(r,0,this.stdout.columns-1)),r}formatName(r){return this.includeNames?Oue(r,{configuration:this.configuration,json:this.json}):\"\"}formatPrefix(r,o){return this.includePrefix?`${Ut(this.configuration,\"\\u27A4\",o)} ${r}${this.formatIndent()}`:\"\"}formatNameWithHyperlink(r){return this.includeNames?r3(r,{configuration:this.configuration,json:this.json}):\"\"}formatIndent(){return this.level>0||!this.forceSectionAlignment?\"\\u2502 \".repeat(this.indent):`${cat} `}}});var hn={};Kt(hn,{PackageManager:()=>_ue,detectPackageManager:()=>Hue,executePackageAccessibleBinary:()=>Yue,executePackageScript:()=>Db,executePackageShellcode:()=>n3,executeWorkspaceAccessibleBinary:()=>Eat,executeWorkspaceLifecycleScript:()=>Gue,executeWorkspaceScript:()=>jue,getPackageAccessibleBinaries:()=>Pb,getWorkspaceAccessibleBinaries:()=>Wue,hasPackageScript:()=>dat,hasWorkspaceScript:()=>i3,isNodeScript:()=>s3,makeScriptEnv:()=>i2,maybeExecuteWorkspaceLifecycleScript:()=>yat,prepareExternalProject:()=>gat});async function gh(t,e,r,o=[]){if(process.platform===\"win32\"){let a=`@goto #_undefined_# 2>NUL || @title %COMSPEC% & @setlocal & @\"${r}\" ${o.map(n=>`\"${n.replace('\"','\"\"')}\"`).join(\" \")} %*`;await ae.writeFilePromise(K.format({dir:t,name:e,ext:\".cmd\"}),a)}await ae.writeFilePromise(K.join(t,e),`#!/bin/sh\nexec \"${r}\" ${o.map(a=>`'${a.replace(/'/g,`'\"'\"'`)}'`).join(\" \")} \"$@\"\n`,{mode:493})}async function Hue(t){let e=await _t.tryFind(t);if(e?.packageManager){let o=dx(e.packageManager);if(o?.name){let a=`found ${JSON.stringify({packageManager:e.packageManager})} in manifest`,[n]=o.reference.split(\".\");switch(o.name){case\"yarn\":return{packageManagerField:!0,packageManager:Number(n)===1?\"Yarn Classic\":\"Yarn\",reason:a};case\"npm\":return{packageManagerField:!0,packageManager:\"npm\",reason:a};case\"pnpm\":return{packageManagerField:!0,packageManager:\"pnpm\",reason:a}}}}let r;try{r=await ae.readFilePromise(K.join(t,mr.lockfile),\"utf8\")}catch{}return r!==void 0?r.match(/^__metadata:$/m)?{packageManager:\"Yarn\",reason:'\"__metadata\" key found in yarn.lock'}:{packageManager:\"Yarn Classic\",reason:'\"__metadata\" key not found in yarn.lock, must be a Yarn classic lockfile'}:ae.existsSync(K.join(t,\"package-lock.json\"))?{packageManager:\"npm\",reason:`found npm's \"package-lock.json\" lockfile`}:ae.existsSync(K.join(t,\"pnpm-lock.yaml\"))?{packageManager:\"pnpm\",reason:`found pnpm's \"pnpm-lock.yaml\" lockfile`}:null}async function i2({project:t,locator:e,binFolder:r,ignoreCorepack:o,lifecycleScript:a,baseEnv:n=t?.configuration.env??process.env}){let u={};for(let[E,w]of Object.entries(n))typeof w<\"u\"&&(u[E.toLowerCase()!==\"path\"?E:\"PATH\"]=w);let A=Ae.fromPortablePath(r);u.BERRY_BIN_FOLDER=Ae.fromPortablePath(A);let p=process.env.COREPACK_ROOT&&!o?Ae.join(process.env.COREPACK_ROOT,\"dist/yarn.js\"):process.argv[1];if(await Promise.all([gh(r,\"node\",process.execPath),...nn!==null?[gh(r,\"run\",process.execPath,[p,\"run\"]),gh(r,\"yarn\",process.execPath,[p]),gh(r,\"yarnpkg\",process.execPath,[p]),gh(r,\"node-gyp\",process.execPath,[p,\"run\",\"--top-level\",\"node-gyp\"])]:[]]),t&&(u.INIT_CWD=Ae.fromPortablePath(t.configuration.startingCwd),u.PROJECT_CWD=Ae.fromPortablePath(t.cwd)),u.PATH=u.PATH?`${A}${Ae.delimiter}${u.PATH}`:`${A}`,u.npm_execpath=`${A}${Ae.sep}yarn`,u.npm_node_execpath=`${A}${Ae.sep}node`,e){if(!t)throw new Error(\"Assertion failed: Missing project\");let E=t.tryWorkspaceByLocator(e),w=E?E.manifest.version??\"\":t.storedPackages.get(e.locatorHash).version??\"\";u.npm_package_name=rn(e),u.npm_package_version=w;let D;if(E)D=E.cwd;else{let b=t.storedPackages.get(e.locatorHash);if(!b)throw new Error(`Package for ${jr(t.configuration,e)} not found in the project`);let C=t.configuration.getLinkers(),T={project:t,report:new Lt({stdout:new dh.PassThrough,configuration:t.configuration})},N=C.find(U=>U.supportsPackage(b,T));if(!N)throw new Error(`The package ${jr(t.configuration,b)} isn't supported by any of the available linkers`);D=await N.findPackageLocation(b,T)}u.npm_package_json=Ae.fromPortablePath(K.join(D,mr.manifest))}let h=nn!==null?`yarn/${nn}`:`yarn/${vf(\"@yarnpkg/core\").version}-core`;return u.npm_config_user_agent=`${h} npm/? node/${process.version} ${process.platform} ${process.arch}`,a&&(u.npm_lifecycle_event=a),t&&await t.configuration.triggerHook(E=>E.setupScriptEnvironment,t,u,async(E,w,D)=>await gh(r,E,w,D)),u}async function gat(t,e,{configuration:r,report:o,workspace:a=null,locator:n=null}){await hat(async()=>{await ae.mktempPromise(async u=>{let A=K.join(u,\"pack.log\"),p=null,{stdout:h,stderr:E}=r.getSubprocessStreams(A,{prefix:Ae.fromPortablePath(t),report:o}),w=n&&zc(n)?I1(n):n,D=w?Qa(w):\"an external project\";h.write(`Packing ${D} from sources\n`);let b=await Hue(t),C;b!==null?(h.write(`Using ${b.packageManager} for bootstrap. Reason: ${b.reason}\n\n`),C=b.packageManager):(h.write(`No package manager configuration detected; defaulting to Yarn\n\n`),C=\"Yarn\");let T=C===\"Yarn\"&&!b?.packageManagerField;await ae.mktempPromise(async N=>{let U=await i2({binFolder:N,ignoreCorepack:T,baseEnv:{...process.env,COREPACK_ENABLE_AUTO_PIN:\"0\"}}),te=new Map([[\"Yarn Classic\",async()=>{let ce=a!==null?[\"workspace\",a]:[],ue=K.join(t,mr.manifest),Ie=await ae.readFilePromise(ue),he=await Xc(process.execPath,[process.argv[1],\"set\",\"version\",\"classic\",\"--only-if-needed\",\"--yarn-path\"],{cwd:t,env:U,stdin:p,stdout:h,stderr:E,end:1});if(he.code!==0)return he.code;await ae.writeFilePromise(ue,Ie),await ae.appendFilePromise(K.join(t,\".npmignore\"),`/.yarn\n`),h.write(`\n`),delete U.NODE_ENV;let De=await Xc(\"yarn\",[\"install\"],{cwd:t,env:U,stdin:p,stdout:h,stderr:E,end:1});if(De.code!==0)return De.code;h.write(`\n`);let Ee=await Xc(\"yarn\",[...ce,\"pack\",\"--filename\",Ae.fromPortablePath(e)],{cwd:t,env:U,stdin:p,stdout:h,stderr:E});return Ee.code!==0?Ee.code:0}],[\"Yarn\",async()=>{let ce=a!==null?[\"workspace\",a]:[];U.YARN_ENABLE_INLINE_BUILDS=\"1\";let ue=K.join(t,mr.lockfile);await ae.existsPromise(ue)||await ae.writeFilePromise(ue,\"\");let Ie=await Xc(\"yarn\",[...ce,\"pack\",\"--install-if-needed\",\"--filename\",Ae.fromPortablePath(e)],{cwd:t,env:U,stdin:p,stdout:h,stderr:E});return Ie.code!==0?Ie.code:0}],[\"npm\",async()=>{if(a!==null){let me=new dh.PassThrough,Ce=Xm(me);me.pipe(h,{end:!1});let fe=await Xc(\"npm\",[\"--version\"],{cwd:t,env:U,stdin:p,stdout:me,stderr:E,end:0});if(me.end(),fe.code!==0)return h.end(),E.end(),fe.code;let ie=(await Ce).toString().trim();if(!nA(ie,\">=7.x\")){let Z=rA(null,\"npm\"),Pe=kn(Z,ie),Re=kn(Z,\">=7.x\");throw new Error(`Workspaces aren't supported by ${zn(r,Pe)}; please upgrade to ${zn(r,Re)} (npm has been detected as the primary package manager for ${Ut(r,t,Ct.PATH)})`)}}let ce=a!==null?[\"--workspace\",a]:[];delete U.npm_config_user_agent,delete U.npm_config_production,delete U.NPM_CONFIG_PRODUCTION,delete U.NODE_ENV;let ue=await Xc(\"npm\",[\"install\",\"--legacy-peer-deps\"],{cwd:t,env:U,stdin:p,stdout:h,stderr:E,end:1});if(ue.code!==0)return ue.code;let Ie=new dh.PassThrough,he=Xm(Ie);Ie.pipe(h);let De=await Xc(\"npm\",[\"pack\",\"--silent\",...ce],{cwd:t,env:U,stdin:p,stdout:Ie,stderr:E});if(De.code!==0)return De.code;let Ee=(await he).toString().trim().replace(/^.*\\n/s,\"\"),g=K.resolve(t,Ae.toPortablePath(Ee));return await ae.renamePromise(g,e),0}]]).get(C);if(typeof te>\"u\")throw new Error(\"Assertion failed: Unsupported workflow\");let le=await te();if(!(le===0||typeof le>\"u\"))throw ae.detachTemp(u),new zt(58,`Packing the package failed (exit code ${le}, logs can be found here: ${Ut(r,A,Ct.PATH)})`)})})})}async function dat(t,e,{project:r}){let o=r.tryWorkspaceByLocator(t);if(o!==null)return i3(o,e);let a=r.storedPackages.get(t.locatorHash);if(!a)throw new Error(`Package for ${jr(r.configuration,t)} not found in the project`);return await iA.openPromise(async n=>{let u=r.configuration,A=r.configuration.getLinkers(),p={project:r,report:new Lt({stdout:new dh.PassThrough,configuration:u})},h=A.find(b=>b.supportsPackage(a,p));if(!h)throw new Error(`The package ${jr(r.configuration,a)} isn't supported by any of the available linkers`);let E=await h.findPackageLocation(a,p),w=new En(E,{baseFs:n});return(await _t.find(Bt.dot,{baseFs:w})).scripts.has(e)})}async function Db(t,e,r,{cwd:o,project:a,stdin:n,stdout:u,stderr:A}){return await ae.mktempPromise(async p=>{let{manifest:h,env:E,cwd:w}=await que(t,{project:a,binFolder:p,cwd:o,lifecycleScript:e}),D=h.scripts.get(e);if(typeof D>\"u\")return 1;let b=async()=>await ky(D,r,{cwd:w,env:E,stdin:n,stdout:u,stderr:A});return await(await a.configuration.reduceHook(T=>T.wrapScriptExecution,b,a,t,e,{script:D,args:r,cwd:w,env:E,stdin:n,stdout:u,stderr:A}))()})}async function n3(t,e,r,{cwd:o,project:a,stdin:n,stdout:u,stderr:A}){return await ae.mktempPromise(async p=>{let{env:h,cwd:E}=await que(t,{project:a,binFolder:p,cwd:o});return await ky(e,r,{cwd:E,env:h,stdin:n,stdout:u,stderr:A})})}async function mat(t,{binFolder:e,cwd:r,lifecycleScript:o}){let a=await i2({project:t.project,locator:t.anchoredLocator,binFolder:e,lifecycleScript:o});return await o3(e,await Wue(t)),typeof r>\"u\"&&(r=K.dirname(await ae.realpathPromise(K.join(t.cwd,\"package.json\")))),{manifest:t.manifest,binFolder:e,env:a,cwd:r}}async function que(t,{project:e,binFolder:r,cwd:o,lifecycleScript:a}){let n=e.tryWorkspaceByLocator(t);if(n!==null)return mat(n,{binFolder:r,cwd:o,lifecycleScript:a});let u=e.storedPackages.get(t.locatorHash);if(!u)throw new Error(`Package for ${jr(e.configuration,t)} not found in the project`);return await iA.openPromise(async A=>{let p=e.configuration,h=e.configuration.getLinkers(),E={project:e,report:new Lt({stdout:new dh.PassThrough,configuration:p})},w=h.find(N=>N.supportsPackage(u,E));if(!w)throw new Error(`The package ${jr(e.configuration,u)} isn't supported by any of the available linkers`);let D=await i2({project:e,locator:t,binFolder:r,lifecycleScript:a});await o3(r,await Pb(t,{project:e}));let b=await w.findPackageLocation(u,E),C=new En(b,{baseFs:A}),T=await _t.find(Bt.dot,{baseFs:C});return typeof o>\"u\"&&(o=b),{manifest:T,binFolder:r,env:D,cwd:o}})}async function jue(t,e,r,{cwd:o,stdin:a,stdout:n,stderr:u}){return await Db(t.anchoredLocator,e,r,{cwd:o,project:t.project,stdin:a,stdout:n,stderr:u})}function i3(t,e){return t.manifest.scripts.has(e)}async function Gue(t,e,{cwd:r,report:o}){let{configuration:a}=t.project,n=null;await ae.mktempPromise(async u=>{let A=K.join(u,`${e}.log`),p=`# This file contains the result of Yarn calling the \"${e}\" lifecycle script inside a workspace (\"${Ae.fromPortablePath(t.cwd)}\")\n`,{stdout:h,stderr:E}=a.getSubprocessStreams(A,{report:o,prefix:jr(a,t.anchoredLocator),header:p});o.reportInfo(36,`Calling the \"${e}\" lifecycle script`);let w=await jue(t,e,[],{cwd:r,stdin:n,stdout:h,stderr:E});if(h.end(),E.end(),w!==0)throw ae.detachTemp(u),new zt(36,`${(0,Mue.default)(e)} script failed (exit code ${Ut(a,w,Ct.NUMBER)}, logs can be found here: ${Ut(a,A,Ct.PATH)}); run ${Ut(a,`yarn ${e}`,Ct.CODE)} to investigate`)})}async function yat(t,e,r){i3(t,e)&&await Gue(t,e,r)}function s3(t){let e=K.extname(t);if(e.match(/\\.[cm]?[jt]sx?$/))return!0;if(e===\".exe\"||e===\".bin\")return!1;let r=Buffer.alloc(4),o;try{o=ae.openSync(t,\"r\")}catch{return!0}try{ae.readSync(o,r,0,r.length,0)}finally{ae.closeSync(o)}let a=r.readUint32BE();return!(a===3405691582||a===3489328638||a===2135247942||(a&4294901760)===1297743872)}async function Pb(t,{project:e}){let r=e.configuration,o=new Map,a=e.storedPackages.get(t.locatorHash);if(!a)throw new Error(`Package for ${jr(r,t)} not found in the project`);let n=new dh.Writable,u=r.getLinkers(),A={project:e,report:new Lt({configuration:r,stdout:n})},p=new Set([t.locatorHash]);for(let E of a.dependencies.values()){let w=e.storedResolutions.get(E.descriptorHash);if(!w)throw new Error(`Assertion failed: The resolution (${zn(r,E)}) should have been registered`);p.add(w)}let h=await Promise.all(Array.from(p,async E=>{let w=e.storedPackages.get(E);if(!w)throw new Error(`Assertion failed: The package (${E}) should have been registered`);if(w.bin.size===0)return ul.skip;let D=u.find(C=>C.supportsPackage(w,A));if(!D)return ul.skip;let b=null;try{b=await D.findPackageLocation(w,A)}catch(C){if(C.code===\"LOCATOR_NOT_INSTALLED\")return ul.skip;throw C}return{dependency:w,packageLocation:b}}));for(let E of h){if(E===ul.skip)continue;let{dependency:w,packageLocation:D}=E;for(let[b,C]of w.bin){let T=K.resolve(D,C);o.set(b,[w,Ae.fromPortablePath(T),s3(T)])}}return o}async function Wue(t){return await Pb(t.anchoredLocator,{project:t.project})}async function o3(t,e){await Promise.all(Array.from(e,([r,[,o,a]])=>a?gh(t,r,process.execPath,[o]):gh(t,r,o,[])))}async function Yue(t,e,r,{cwd:o,project:a,stdin:n,stdout:u,stderr:A,nodeArgs:p=[],packageAccessibleBinaries:h}){h??=await Pb(t,{project:a});let E=h.get(e);if(!E)throw new Error(`Binary not found (${e}) for ${jr(a.configuration,t)}`);return await ae.mktempPromise(async w=>{let[,D]=E,b=await i2({project:a,locator:t,binFolder:w});await o3(b.BERRY_BIN_FOLDER,h);let C=s3(Ae.toPortablePath(D))?Xc(process.execPath,[...p,D,...r],{cwd:o,env:b,stdin:n,stdout:u,stderr:A}):Xc(D,r,{cwd:o,env:b,stdin:n,stdout:u,stderr:A}),T;try{T=await C}finally{await ae.removePromise(b.BERRY_BIN_FOLDER)}return T.code})}async function Eat(t,e,r,{cwd:o,stdin:a,stdout:n,stderr:u,packageAccessibleBinaries:A}){return await Yue(t.anchoredLocator,e,r,{project:t.project,cwd:o,stdin:a,stdout:n,stderr:u,packageAccessibleBinaries:A})}var Mue,Uue,dh,_ue,pat,hat,a3=It(()=>{Pt();Pt();sA();J1();Mue=et(t3()),Uue=et(lg()),dh=ve(\"stream\");Ay();Vl();n2();r2();nb();Wl();Gl();bf();Io();_ue=(a=>(a.Yarn1=\"Yarn Classic\",a.Yarn2=\"Yarn\",a.Npm=\"npm\",a.Pnpm=\"pnpm\",a))(_ue||{});pat=2,hat=(0,Uue.default)(pat)});var Fy=_((y4t,Vue)=>{\"use strict\";var Kue=new Map([[\"C\",\"cwd\"],[\"f\",\"file\"],[\"z\",\"gzip\"],[\"P\",\"preservePaths\"],[\"U\",\"unlink\"],[\"strip-components\",\"strip\"],[\"stripComponents\",\"strip\"],[\"keep-newer\",\"newer\"],[\"keepNewer\",\"newer\"],[\"keep-newer-files\",\"newer\"],[\"keepNewerFiles\",\"newer\"],[\"k\",\"keep\"],[\"keep-existing\",\"keep\"],[\"keepExisting\",\"keep\"],[\"m\",\"noMtime\"],[\"no-mtime\",\"noMtime\"],[\"p\",\"preserveOwner\"],[\"L\",\"follow\"],[\"h\",\"follow\"]]);Vue.exports=t=>t?Object.keys(t).map(e=>[Kue.has(e)?Kue.get(e):e,t[e]]).reduce((e,r)=>(e[r[0]]=r[1],e),Object.create(null)):{}});var Ty=_((E4t,nAe)=>{\"use strict\";var zue=typeof process==\"object\"&&process?process:{stdout:null,stderr:null},Cat=ve(\"events\"),Jue=ve(\"stream\"),Xue=ve(\"string_decoder\").StringDecoder,Nf=Symbol(\"EOF\"),Of=Symbol(\"maybeEmitEnd\"),mh=Symbol(\"emittedEnd\"),Sb=Symbol(\"emittingEnd\"),s2=Symbol(\"emittedError\"),xb=Symbol(\"closed\"),Zue=Symbol(\"read\"),bb=Symbol(\"flush\"),$ue=Symbol(\"flushChunk\"),Ra=Symbol(\"encoding\"),Mf=Symbol(\"decoder\"),kb=Symbol(\"flowing\"),o2=Symbol(\"paused\"),Ry=Symbol(\"resume\"),xs=Symbol(\"bufferLength\"),l3=Symbol(\"bufferPush\"),c3=Symbol(\"bufferShift\"),Do=Symbol(\"objectMode\"),Po=Symbol(\"destroyed\"),u3=Symbol(\"emitData\"),eAe=Symbol(\"emitEnd\"),A3=Symbol(\"emitEnd2\"),Uf=Symbol(\"async\"),a2=t=>Promise.resolve().then(t),tAe=global._MP_NO_ITERATOR_SYMBOLS_!==\"1\",Iat=tAe&&Symbol.asyncIterator||Symbol(\"asyncIterator not implemented\"),wat=tAe&&Symbol.iterator||Symbol(\"iterator not implemented\"),Bat=t=>t===\"end\"||t===\"finish\"||t===\"prefinish\",vat=t=>t instanceof ArrayBuffer||typeof t==\"object\"&&t.constructor&&t.constructor.name===\"ArrayBuffer\"&&t.byteLength>=0,Dat=t=>!Buffer.isBuffer(t)&&ArrayBuffer.isView(t),Qb=class{constructor(e,r,o){this.src=e,this.dest=r,this.opts=o,this.ondrain=()=>e[Ry](),r.on(\"drain\",this.ondrain)}unpipe(){this.dest.removeListener(\"drain\",this.ondrain)}proxyErrors(){}end(){this.unpipe(),this.opts.end&&this.dest.end()}},f3=class extends Qb{unpipe(){this.src.removeListener(\"error\",this.proxyErrors),super.unpipe()}constructor(e,r,o){super(e,r,o),this.proxyErrors=a=>r.emit(\"error\",a),e.on(\"error\",this.proxyErrors)}};nAe.exports=class rAe extends Jue{constructor(e){super(),this[kb]=!1,this[o2]=!1,this.pipes=[],this.buffer=[],this[Do]=e&&e.objectMode||!1,this[Do]?this[Ra]=null:this[Ra]=e&&e.encoding||null,this[Ra]===\"buffer\"&&(this[Ra]=null),this[Uf]=e&&!!e.async||!1,this[Mf]=this[Ra]?new Xue(this[Ra]):null,this[Nf]=!1,this[mh]=!1,this[Sb]=!1,this[xb]=!1,this[s2]=null,this.writable=!0,this.readable=!0,this[xs]=0,this[Po]=!1}get bufferLength(){return this[xs]}get encoding(){return this[Ra]}set encoding(e){if(this[Do])throw new Error(\"cannot set encoding in objectMode\");if(this[Ra]&&e!==this[Ra]&&(this[Mf]&&this[Mf].lastNeed||this[xs]))throw new Error(\"cannot change encoding\");this[Ra]!==e&&(this[Mf]=e?new Xue(e):null,this.buffer.length&&(this.buffer=this.buffer.map(r=>this[Mf].write(r)))),this[Ra]=e}setEncoding(e){this.encoding=e}get objectMode(){return this[Do]}set objectMode(e){this[Do]=this[Do]||!!e}get async(){return this[Uf]}set async(e){this[Uf]=this[Uf]||!!e}write(e,r,o){if(this[Nf])throw new Error(\"write after end\");if(this[Po])return this.emit(\"error\",Object.assign(new Error(\"Cannot call write after a stream was destroyed\"),{code:\"ERR_STREAM_DESTROYED\"})),!0;typeof r==\"function\"&&(o=r,r=\"utf8\"),r||(r=\"utf8\");let a=this[Uf]?a2:n=>n();return!this[Do]&&!Buffer.isBuffer(e)&&(Dat(e)?e=Buffer.from(e.buffer,e.byteOffset,e.byteLength):vat(e)?e=Buffer.from(e):typeof e!=\"string\"&&(this.objectMode=!0)),this[Do]?(this.flowing&&this[xs]!==0&&this[bb](!0),this.flowing?this.emit(\"data\",e):this[l3](e),this[xs]!==0&&this.emit(\"readable\"),o&&a(o),this.flowing):e.length?(typeof e==\"string\"&&!(r===this[Ra]&&!this[Mf].lastNeed)&&(e=Buffer.from(e,r)),Buffer.isBuffer(e)&&this[Ra]&&(e=this[Mf].write(e)),this.flowing&&this[xs]!==0&&this[bb](!0),this.flowing?this.emit(\"data\",e):this[l3](e),this[xs]!==0&&this.emit(\"readable\"),o&&a(o),this.flowing):(this[xs]!==0&&this.emit(\"readable\"),o&&a(o),this.flowing)}read(e){if(this[Po])return null;if(this[xs]===0||e===0||e>this[xs])return this[Of](),null;this[Do]&&(e=null),this.buffer.length>1&&!this[Do]&&(this.encoding?this.buffer=[this.buffer.join(\"\")]:this.buffer=[Buffer.concat(this.buffer,this[xs])]);let r=this[Zue](e||null,this.buffer[0]);return this[Of](),r}[Zue](e,r){return e===r.length||e===null?this[c3]():(this.buffer[0]=r.slice(e),r=r.slice(0,e),this[xs]-=e),this.emit(\"data\",r),!this.buffer.length&&!this[Nf]&&this.emit(\"drain\"),r}end(e,r,o){return typeof e==\"function\"&&(o=e,e=null),typeof r==\"function\"&&(o=r,r=\"utf8\"),e&&this.write(e,r),o&&this.once(\"end\",o),this[Nf]=!0,this.writable=!1,(this.flowing||!this[o2])&&this[Of](),this}[Ry](){this[Po]||(this[o2]=!1,this[kb]=!0,this.emit(\"resume\"),this.buffer.length?this[bb]():this[Nf]?this[Of]():this.emit(\"drain\"))}resume(){return this[Ry]()}pause(){this[kb]=!1,this[o2]=!0}get destroyed(){return this[Po]}get flowing(){return this[kb]}get paused(){return this[o2]}[l3](e){this[Do]?this[xs]+=1:this[xs]+=e.length,this.buffer.push(e)}[c3](){return this.buffer.length&&(this[Do]?this[xs]-=1:this[xs]-=this.buffer[0].length),this.buffer.shift()}[bb](e){do;while(this[$ue](this[c3]()));!e&&!this.buffer.length&&!this[Nf]&&this.emit(\"drain\")}[$ue](e){return e?(this.emit(\"data\",e),this.flowing):!1}pipe(e,r){if(this[Po])return;let o=this[mh];return r=r||{},e===zue.stdout||e===zue.stderr?r.end=!1:r.end=r.end!==!1,r.proxyErrors=!!r.proxyErrors,o?r.end&&e.end():(this.pipes.push(r.proxyErrors?new f3(this,e,r):new Qb(this,e,r)),this[Uf]?a2(()=>this[Ry]()):this[Ry]()),e}unpipe(e){let r=this.pipes.find(o=>o.dest===e);r&&(this.pipes.splice(this.pipes.indexOf(r),1),r.unpipe())}addListener(e,r){return this.on(e,r)}on(e,r){let o=super.on(e,r);return e===\"data\"&&!this.pipes.length&&!this.flowing?this[Ry]():e===\"readable\"&&this[xs]!==0?super.emit(\"readable\"):Bat(e)&&this[mh]?(super.emit(e),this.removeAllListeners(e)):e===\"error\"&&this[s2]&&(this[Uf]?a2(()=>r.call(this,this[s2])):r.call(this,this[s2])),o}get emittedEnd(){return this[mh]}[Of](){!this[Sb]&&!this[mh]&&!this[Po]&&this.buffer.length===0&&this[Nf]&&(this[Sb]=!0,this.emit(\"end\"),this.emit(\"prefinish\"),this.emit(\"finish\"),this[xb]&&this.emit(\"close\"),this[Sb]=!1)}emit(e,r,...o){if(e!==\"error\"&&e!==\"close\"&&e!==Po&&this[Po])return;if(e===\"data\")return r?this[Uf]?a2(()=>this[u3](r)):this[u3](r):!1;if(e===\"end\")return this[eAe]();if(e===\"close\"){if(this[xb]=!0,!this[mh]&&!this[Po])return;let n=super.emit(\"close\");return this.removeAllListeners(\"close\"),n}else if(e===\"error\"){this[s2]=r;let n=super.emit(\"error\",r);return this[Of](),n}else if(e===\"resume\"){let n=super.emit(\"resume\");return this[Of](),n}else if(e===\"finish\"||e===\"prefinish\"){let n=super.emit(e);return this.removeAllListeners(e),n}let a=super.emit(e,r,...o);return this[Of](),a}[u3](e){for(let o of this.pipes)o.dest.write(e)===!1&&this.pause();let r=super.emit(\"data\",e);return this[Of](),r}[eAe](){this[mh]||(this[mh]=!0,this.readable=!1,this[Uf]?a2(()=>this[A3]()):this[A3]())}[A3](){if(this[Mf]){let r=this[Mf].end();if(r){for(let o of this.pipes)o.dest.write(r);super.emit(\"data\",r)}}for(let r of this.pipes)r.end();let e=super.emit(\"end\");return this.removeAllListeners(\"end\"),e}collect(){let e=[];this[Do]||(e.dataLength=0);let r=this.promise();return this.on(\"data\",o=>{e.push(o),this[Do]||(e.dataLength+=o.length)}),r.then(()=>e)}concat(){return this[Do]?Promise.reject(new Error(\"cannot concat in objectMode\")):this.collect().then(e=>this[Do]?Promise.reject(new Error(\"cannot concat in objectMode\")):this[Ra]?e.join(\"\"):Buffer.concat(e,e.dataLength))}promise(){return new Promise((e,r)=>{this.on(Po,()=>r(new Error(\"stream destroyed\"))),this.on(\"error\",o=>r(o)),this.on(\"end\",()=>e())})}[Iat](){return{next:()=>{let r=this.read();if(r!==null)return Promise.resolve({done:!1,value:r});if(this[Nf])return Promise.resolve({done:!0});let o=null,a=null,n=h=>{this.removeListener(\"data\",u),this.removeListener(\"end\",A),a(h)},u=h=>{this.removeListener(\"error\",n),this.removeListener(\"end\",A),this.pause(),o({value:h,done:!!this[Nf]})},A=()=>{this.removeListener(\"error\",n),this.removeListener(\"data\",u),o({done:!0})},p=()=>n(new Error(\"stream destroyed\"));return new Promise((h,E)=>{a=E,o=h,this.once(Po,p),this.once(\"error\",n),this.once(\"end\",A),this.once(\"data\",u)})}}}[wat](){return{next:()=>{let r=this.read();return{value:r,done:r===null}}}}destroy(e){return this[Po]?(e?this.emit(\"error\",e):this.emit(Po),this):(this[Po]=!0,this.buffer.length=0,this[xs]=0,typeof this.close==\"function\"&&!this[xb]&&this.close(),e?this.emit(\"error\",e):this.emit(Po),this)}static isStream(e){return!!e&&(e instanceof rAe||e instanceof Jue||e instanceof Cat&&(typeof e.pipe==\"function\"||typeof e.write==\"function\"&&typeof e.end==\"function\"))}}});var sAe=_((C4t,iAe)=>{var Pat=ve(\"zlib\").constants||{ZLIB_VERNUM:4736};iAe.exports=Object.freeze(Object.assign(Object.create(null),{Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_MEM_ERROR:-4,Z_BUF_ERROR:-5,Z_VERSION_ERROR:-6,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,DEFLATE:1,INFLATE:2,GZIP:3,GUNZIP:4,DEFLATERAW:5,INFLATERAW:6,UNZIP:7,BROTLI_DECODE:8,BROTLI_ENCODE:9,Z_MIN_WINDOWBITS:8,Z_MAX_WINDOWBITS:15,Z_DEFAULT_WINDOWBITS:15,Z_MIN_CHUNK:64,Z_MAX_CHUNK:1/0,Z_DEFAULT_CHUNK:16384,Z_MIN_MEMLEVEL:1,Z_MAX_MEMLEVEL:9,Z_DEFAULT_MEMLEVEL:8,Z_MIN_LEVEL:-1,Z_MAX_LEVEL:9,Z_DEFAULT_LEVEL:-1,BROTLI_OPERATION_PROCESS:0,BROTLI_OPERATION_FLUSH:1,BROTLI_OPERATION_FINISH:2,BROTLI_OPERATION_EMIT_METADATA:3,BROTLI_MODE_GENERIC:0,BROTLI_MODE_TEXT:1,BROTLI_MODE_FONT:2,BROTLI_DEFAULT_MODE:0,BROTLI_MIN_QUALITY:0,BROTLI_MAX_QUALITY:11,BROTLI_DEFAULT_QUALITY:11,BROTLI_MIN_WINDOW_BITS:10,BROTLI_MAX_WINDOW_BITS:24,BROTLI_LARGE_MAX_WINDOW_BITS:30,BROTLI_DEFAULT_WINDOW:22,BROTLI_MIN_INPUT_BLOCK_BITS:16,BROTLI_MAX_INPUT_BLOCK_BITS:24,BROTLI_PARAM_MODE:0,BROTLI_PARAM_QUALITY:1,BROTLI_PARAM_LGWIN:2,BROTLI_PARAM_LGBLOCK:3,BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING:4,BROTLI_PARAM_SIZE_HINT:5,BROTLI_PARAM_LARGE_WINDOW:6,BROTLI_PARAM_NPOSTFIX:7,BROTLI_PARAM_NDIRECT:8,BROTLI_DECODER_RESULT_ERROR:0,BROTLI_DECODER_RESULT_SUCCESS:1,BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:2,BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:3,BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION:0,BROTLI_DECODER_PARAM_LARGE_WINDOW:1,BROTLI_DECODER_NO_ERROR:0,BROTLI_DECODER_SUCCESS:1,BROTLI_DECODER_NEEDS_MORE_INPUT:2,BROTLI_DECODER_NEEDS_MORE_OUTPUT:3,BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE:-1,BROTLI_DECODER_ERROR_FORMAT_RESERVED:-2,BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE:-3,BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET:-4,BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME:-5,BROTLI_DECODER_ERROR_FORMAT_CL_SPACE:-6,BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE:-7,BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT:-8,BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1:-9,BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2:-10,BROTLI_DECODER_ERROR_FORMAT_TRANSFORM:-11,BROTLI_DECODER_ERROR_FORMAT_DICTIONARY:-12,BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS:-13,BROTLI_DECODER_ERROR_FORMAT_PADDING_1:-14,BROTLI_DECODER_ERROR_FORMAT_PADDING_2:-15,BROTLI_DECODER_ERROR_FORMAT_DISTANCE:-16,BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET:-19,BROTLI_DECODER_ERROR_INVALID_ARGUMENTS:-20,BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES:-21,BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS:-22,BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP:-25,BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1:-26,BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2:-27,BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES:-30,BROTLI_DECODER_ERROR_UNREACHABLE:-31},Pat))});var x3=_(hl=>{\"use strict\";var m3=ve(\"assert\"),yh=ve(\"buffer\").Buffer,lAe=ve(\"zlib\"),Tg=hl.constants=sAe(),Sat=Ty(),oAe=yh.concat,Lg=Symbol(\"_superWrite\"),Ny=class extends Error{constructor(e){super(\"zlib: \"+e.message),this.code=e.code,this.errno=e.errno,this.code||(this.code=\"ZLIB_ERROR\"),this.message=\"zlib: \"+e.message,Error.captureStackTrace(this,this.constructor)}get name(){return\"ZlibError\"}},xat=Symbol(\"opts\"),l2=Symbol(\"flushFlag\"),aAe=Symbol(\"finishFlushFlag\"),S3=Symbol(\"fullFlushFlag\"),ui=Symbol(\"handle\"),Fb=Symbol(\"onError\"),Ly=Symbol(\"sawError\"),p3=Symbol(\"level\"),h3=Symbol(\"strategy\"),g3=Symbol(\"ended\"),I4t=Symbol(\"_defaultFullFlush\"),Rb=class extends Sat{constructor(e,r){if(!e||typeof e!=\"object\")throw new TypeError(\"invalid options for ZlibBase constructor\");super(e),this[Ly]=!1,this[g3]=!1,this[xat]=e,this[l2]=e.flush,this[aAe]=e.finishFlush;try{this[ui]=new lAe[r](e)}catch(o){throw new Ny(o)}this[Fb]=o=>{this[Ly]||(this[Ly]=!0,this.close(),this.emit(\"error\",o))},this[ui].on(\"error\",o=>this[Fb](new Ny(o))),this.once(\"end\",()=>this.close)}close(){this[ui]&&(this[ui].close(),this[ui]=null,this.emit(\"close\"))}reset(){if(!this[Ly])return m3(this[ui],\"zlib binding closed\"),this[ui].reset()}flush(e){this.ended||(typeof e!=\"number\"&&(e=this[S3]),this.write(Object.assign(yh.alloc(0),{[l2]:e})))}end(e,r,o){return e&&this.write(e,r),this.flush(this[aAe]),this[g3]=!0,super.end(null,null,o)}get ended(){return this[g3]}write(e,r,o){if(typeof r==\"function\"&&(o=r,r=\"utf8\"),typeof e==\"string\"&&(e=yh.from(e,r)),this[Ly])return;m3(this[ui],\"zlib binding closed\");let a=this[ui]._handle,n=a.close;a.close=()=>{};let u=this[ui].close;this[ui].close=()=>{},yh.concat=h=>h;let A;try{let h=typeof e[l2]==\"number\"?e[l2]:this[l2];A=this[ui]._processChunk(e,h),yh.concat=oAe}catch(h){yh.concat=oAe,this[Fb](new Ny(h))}finally{this[ui]&&(this[ui]._handle=a,a.close=n,this[ui].close=u,this[ui].removeAllListeners(\"error\"))}this[ui]&&this[ui].on(\"error\",h=>this[Fb](new Ny(h)));let p;if(A)if(Array.isArray(A)&&A.length>0){p=this[Lg](yh.from(A[0]));for(let h=1;h<A.length;h++)p=this[Lg](A[h])}else p=this[Lg](yh.from(A));return o&&o(),p}[Lg](e){return super.write(e)}},_f=class extends Rb{constructor(e,r){e=e||{},e.flush=e.flush||Tg.Z_NO_FLUSH,e.finishFlush=e.finishFlush||Tg.Z_FINISH,super(e,r),this[S3]=Tg.Z_FULL_FLUSH,this[p3]=e.level,this[h3]=e.strategy}params(e,r){if(!this[Ly]){if(!this[ui])throw new Error(\"cannot switch params when binding is closed\");if(!this[ui].params)throw new Error(\"not supported in this implementation\");if(this[p3]!==e||this[h3]!==r){this.flush(Tg.Z_SYNC_FLUSH),m3(this[ui],\"zlib binding closed\");let o=this[ui].flush;this[ui].flush=(a,n)=>{this.flush(a),n()};try{this[ui].params(e,r)}finally{this[ui].flush=o}this[ui]&&(this[p3]=e,this[h3]=r)}}}},y3=class extends _f{constructor(e){super(e,\"Deflate\")}},E3=class extends _f{constructor(e){super(e,\"Inflate\")}},d3=Symbol(\"_portable\"),C3=class extends _f{constructor(e){super(e,\"Gzip\"),this[d3]=e&&!!e.portable}[Lg](e){return this[d3]?(this[d3]=!1,e[9]=255,super[Lg](e)):super[Lg](e)}},I3=class extends _f{constructor(e){super(e,\"Gunzip\")}},w3=class extends _f{constructor(e){super(e,\"DeflateRaw\")}},B3=class extends _f{constructor(e){super(e,\"InflateRaw\")}},v3=class extends _f{constructor(e){super(e,\"Unzip\")}},Tb=class extends Rb{constructor(e,r){e=e||{},e.flush=e.flush||Tg.BROTLI_OPERATION_PROCESS,e.finishFlush=e.finishFlush||Tg.BROTLI_OPERATION_FINISH,super(e,r),this[S3]=Tg.BROTLI_OPERATION_FLUSH}},D3=class extends Tb{constructor(e){super(e,\"BrotliCompress\")}},P3=class extends Tb{constructor(e){super(e,\"BrotliDecompress\")}};hl.Deflate=y3;hl.Inflate=E3;hl.Gzip=C3;hl.Gunzip=I3;hl.DeflateRaw=w3;hl.InflateRaw=B3;hl.Unzip=v3;typeof lAe.BrotliCompress==\"function\"?(hl.BrotliCompress=D3,hl.BrotliDecompress=P3):hl.BrotliCompress=hl.BrotliDecompress=class{constructor(){throw new Error(\"Brotli is not supported in this version of Node.js\")}}});var Oy=_((v4t,cAe)=>{var bat=process.env.TESTING_TAR_FAKE_PLATFORM||process.platform;cAe.exports=bat!==\"win32\"?t=>t:t=>t&&t.replace(/\\\\/g,\"/\")});var Lb=_((P4t,uAe)=>{\"use strict\";var kat=Ty(),b3=Oy(),k3=Symbol(\"slurp\");uAe.exports=class extends kat{constructor(e,r,o){switch(super(),this.pause(),this.extended=r,this.globalExtended=o,this.header=e,this.startBlockSize=512*Math.ceil(e.size/512),this.blockRemain=this.startBlockSize,this.remain=e.size,this.type=e.type,this.meta=!1,this.ignore=!1,this.type){case\"File\":case\"OldFile\":case\"Link\":case\"SymbolicLink\":case\"CharacterDevice\":case\"BlockDevice\":case\"Directory\":case\"FIFO\":case\"ContiguousFile\":case\"GNUDumpDir\":break;case\"NextFileHasLongLinkpath\":case\"NextFileHasLongPath\":case\"OldGnuLongPath\":case\"GlobalExtendedHeader\":case\"ExtendedHeader\":case\"OldExtendedHeader\":this.meta=!0;break;default:this.ignore=!0}this.path=b3(e.path),this.mode=e.mode,this.mode&&(this.mode=this.mode&4095),this.uid=e.uid,this.gid=e.gid,this.uname=e.uname,this.gname=e.gname,this.size=e.size,this.mtime=e.mtime,this.atime=e.atime,this.ctime=e.ctime,this.linkpath=b3(e.linkpath),this.uname=e.uname,this.gname=e.gname,r&&this[k3](r),o&&this[k3](o,!0)}write(e){let r=e.length;if(r>this.blockRemain)throw new Error(\"writing more to entry than is appropriate\");let o=this.remain,a=this.blockRemain;return this.remain=Math.max(0,o-r),this.blockRemain=Math.max(0,a-r),this.ignore?!0:o>=r?super.write(e):super.write(e.slice(0,o))}[k3](e,r){for(let o in e)e[o]!==null&&e[o]!==void 0&&!(r&&o===\"path\")&&(this[o]=o===\"path\"||o===\"linkpath\"?b3(e[o]):e[o])}}});var Q3=_(Nb=>{\"use strict\";Nb.name=new Map([[\"0\",\"File\"],[\"\",\"OldFile\"],[\"1\",\"Link\"],[\"2\",\"SymbolicLink\"],[\"3\",\"CharacterDevice\"],[\"4\",\"BlockDevice\"],[\"5\",\"Directory\"],[\"6\",\"FIFO\"],[\"7\",\"ContiguousFile\"],[\"g\",\"GlobalExtendedHeader\"],[\"x\",\"ExtendedHeader\"],[\"A\",\"SolarisACL\"],[\"D\",\"GNUDumpDir\"],[\"I\",\"Inode\"],[\"K\",\"NextFileHasLongLinkpath\"],[\"L\",\"NextFileHasLongPath\"],[\"M\",\"ContinuationFile\"],[\"N\",\"OldGnuLongPath\"],[\"S\",\"SparseFile\"],[\"V\",\"TapeVolumeHeader\"],[\"X\",\"OldExtendedHeader\"]]);Nb.code=new Map(Array.from(Nb.name).map(t=>[t[1],t[0]]))});var hAe=_((x4t,pAe)=>{\"use strict\";var Qat=(t,e)=>{if(Number.isSafeInteger(t))t<0?Rat(t,e):Fat(t,e);else throw Error(\"cannot encode number outside of javascript safe integer range\");return e},Fat=(t,e)=>{e[0]=128;for(var r=e.length;r>1;r--)e[r-1]=t&255,t=Math.floor(t/256)},Rat=(t,e)=>{e[0]=255;var r=!1;t=t*-1;for(var o=e.length;o>1;o--){var a=t&255;t=Math.floor(t/256),r?e[o-1]=AAe(a):a===0?e[o-1]=0:(r=!0,e[o-1]=fAe(a))}},Tat=t=>{let e=t[0],r=e===128?Nat(t.slice(1,t.length)):e===255?Lat(t):null;if(r===null)throw Error(\"invalid base256 encoding\");if(!Number.isSafeInteger(r))throw Error(\"parsed number outside of javascript safe integer range\");return r},Lat=t=>{for(var e=t.length,r=0,o=!1,a=e-1;a>-1;a--){var n=t[a],u;o?u=AAe(n):n===0?u=n:(o=!0,u=fAe(n)),u!==0&&(r-=u*Math.pow(256,e-a-1))}return r},Nat=t=>{for(var e=t.length,r=0,o=e-1;o>-1;o--){var a=t[o];a!==0&&(r+=a*Math.pow(256,e-o-1))}return r},AAe=t=>(255^t)&255,fAe=t=>(255^t)+1&255;pAe.exports={encode:Qat,parse:Tat}});var Uy=_((b4t,dAe)=>{\"use strict\";var F3=Q3(),My=ve(\"path\").posix,gAe=hAe(),R3=Symbol(\"slurp\"),gl=Symbol(\"type\"),N3=class{constructor(e,r,o,a){this.cksumValid=!1,this.needPax=!1,this.nullBlock=!1,this.block=null,this.path=null,this.mode=null,this.uid=null,this.gid=null,this.size=null,this.mtime=null,this.cksum=null,this[gl]=\"0\",this.linkpath=null,this.uname=null,this.gname=null,this.devmaj=0,this.devmin=0,this.atime=null,this.ctime=null,Buffer.isBuffer(e)?this.decode(e,r||0,o,a):e&&this.set(e)}decode(e,r,o,a){if(r||(r=0),!e||!(e.length>=r+512))throw new Error(\"need 512 bytes for header\");if(this.path=Ng(e,r,100),this.mode=Eh(e,r+100,8),this.uid=Eh(e,r+108,8),this.gid=Eh(e,r+116,8),this.size=Eh(e,r+124,12),this.mtime=T3(e,r+136,12),this.cksum=Eh(e,r+148,12),this[R3](o),this[R3](a,!0),this[gl]=Ng(e,r+156,1),this[gl]===\"\"&&(this[gl]=\"0\"),this[gl]===\"0\"&&this.path.substr(-1)===\"/\"&&(this[gl]=\"5\"),this[gl]===\"5\"&&(this.size=0),this.linkpath=Ng(e,r+157,100),e.slice(r+257,r+265).toString()===\"ustar\\x0000\")if(this.uname=Ng(e,r+265,32),this.gname=Ng(e,r+297,32),this.devmaj=Eh(e,r+329,8),this.devmin=Eh(e,r+337,8),e[r+475]!==0){let u=Ng(e,r+345,155);this.path=u+\"/\"+this.path}else{let u=Ng(e,r+345,130);u&&(this.path=u+\"/\"+this.path),this.atime=T3(e,r+476,12),this.ctime=T3(e,r+488,12)}let n=8*32;for(let u=r;u<r+148;u++)n+=e[u];for(let u=r+156;u<r+512;u++)n+=e[u];this.cksumValid=n===this.cksum,this.cksum===null&&n===8*32&&(this.nullBlock=!0)}[R3](e,r){for(let o in e)e[o]!==null&&e[o]!==void 0&&!(r&&o===\"path\")&&(this[o]=e[o])}encode(e,r){if(e||(e=this.block=Buffer.alloc(512),r=0),r||(r=0),!(e.length>=r+512))throw new Error(\"need 512 bytes for header\");let o=this.ctime||this.atime?130:155,a=Oat(this.path||\"\",o),n=a[0],u=a[1];this.needPax=a[2],this.needPax=Og(e,r,100,n)||this.needPax,this.needPax=Ch(e,r+100,8,this.mode)||this.needPax,this.needPax=Ch(e,r+108,8,this.uid)||this.needPax,this.needPax=Ch(e,r+116,8,this.gid)||this.needPax,this.needPax=Ch(e,r+124,12,this.size)||this.needPax,this.needPax=L3(e,r+136,12,this.mtime)||this.needPax,e[r+156]=this[gl].charCodeAt(0),this.needPax=Og(e,r+157,100,this.linkpath)||this.needPax,e.write(\"ustar\\x0000\",r+257,8),this.needPax=Og(e,r+265,32,this.uname)||this.needPax,this.needPax=Og(e,r+297,32,this.gname)||this.needPax,this.needPax=Ch(e,r+329,8,this.devmaj)||this.needPax,this.needPax=Ch(e,r+337,8,this.devmin)||this.needPax,this.needPax=Og(e,r+345,o,u)||this.needPax,e[r+475]!==0?this.needPax=Og(e,r+345,155,u)||this.needPax:(this.needPax=Og(e,r+345,130,u)||this.needPax,this.needPax=L3(e,r+476,12,this.atime)||this.needPax,this.needPax=L3(e,r+488,12,this.ctime)||this.needPax);let A=8*32;for(let p=r;p<r+148;p++)A+=e[p];for(let p=r+156;p<r+512;p++)A+=e[p];return this.cksum=A,Ch(e,r+148,8,this.cksum),this.cksumValid=!0,this.needPax}set(e){for(let r in e)e[r]!==null&&e[r]!==void 0&&(this[r]=e[r])}get type(){return F3.name.get(this[gl])||this[gl]}get typeKey(){return this[gl]}set type(e){F3.code.has(e)?this[gl]=F3.code.get(e):this[gl]=e}},Oat=(t,e)=>{let o=t,a=\"\",n,u=My.parse(t).root||\".\";if(Buffer.byteLength(o)<100)n=[o,a,!1];else{a=My.dirname(o),o=My.basename(o);do Buffer.byteLength(o)<=100&&Buffer.byteLength(a)<=e?n=[o,a,!1]:Buffer.byteLength(o)>100&&Buffer.byteLength(a)<=e?n=[o.substr(0,99),a,!0]:(o=My.join(My.basename(a),o),a=My.dirname(a));while(a!==u&&!n);n||(n=[t.substr(0,99),\"\",!0])}return n},Ng=(t,e,r)=>t.slice(e,e+r).toString(\"utf8\").replace(/\\0.*/,\"\"),T3=(t,e,r)=>Mat(Eh(t,e,r)),Mat=t=>t===null?null:new Date(t*1e3),Eh=(t,e,r)=>t[e]&128?gAe.parse(t.slice(e,e+r)):_at(t,e,r),Uat=t=>isNaN(t)?null:t,_at=(t,e,r)=>Uat(parseInt(t.slice(e,e+r).toString(\"utf8\").replace(/\\0.*$/,\"\").trim(),8)),Hat={12:8589934591,8:2097151},Ch=(t,e,r,o)=>o===null?!1:o>Hat[r]||o<0?(gAe.encode(o,t.slice(e,e+r)),!0):(qat(t,e,r,o),!1),qat=(t,e,r,o)=>t.write(jat(o,r),e,r,\"ascii\"),jat=(t,e)=>Gat(Math.floor(t).toString(8),e),Gat=(t,e)=>(t.length===e-1?t:new Array(e-t.length-1).join(\"0\")+t+\" \")+\"\\0\",L3=(t,e,r,o)=>o===null?!1:Ch(t,e,r,o.getTime()/1e3),Wat=new Array(156).join(\"\\0\"),Og=(t,e,r,o)=>o===null?!1:(t.write(o+Wat,e,r,\"utf8\"),o.length!==Buffer.byteLength(o)||o.length>r);dAe.exports=N3});var Ob=_((k4t,mAe)=>{\"use strict\";var Yat=Uy(),Kat=ve(\"path\"),c2=class{constructor(e,r){this.atime=e.atime||null,this.charset=e.charset||null,this.comment=e.comment||null,this.ctime=e.ctime||null,this.gid=e.gid||null,this.gname=e.gname||null,this.linkpath=e.linkpath||null,this.mtime=e.mtime||null,this.path=e.path||null,this.size=e.size||null,this.uid=e.uid||null,this.uname=e.uname||null,this.dev=e.dev||null,this.ino=e.ino||null,this.nlink=e.nlink||null,this.global=r||!1}encode(){let e=this.encodeBody();if(e===\"\")return null;let r=Buffer.byteLength(e),o=512*Math.ceil(1+r/512),a=Buffer.allocUnsafe(o);for(let n=0;n<512;n++)a[n]=0;new Yat({path:(\"PaxHeader/\"+Kat.basename(this.path)).slice(0,99),mode:this.mode||420,uid:this.uid||null,gid:this.gid||null,size:r,mtime:this.mtime||null,type:this.global?\"GlobalExtendedHeader\":\"ExtendedHeader\",linkpath:\"\",uname:this.uname||\"\",gname:this.gname||\"\",devmaj:0,devmin:0,atime:this.atime||null,ctime:this.ctime||null}).encode(a),a.write(e,512,r,\"utf8\");for(let n=r+512;n<a.length;n++)a[n]=0;return a}encodeBody(){return this.encodeField(\"path\")+this.encodeField(\"ctime\")+this.encodeField(\"atime\")+this.encodeField(\"dev\")+this.encodeField(\"ino\")+this.encodeField(\"nlink\")+this.encodeField(\"charset\")+this.encodeField(\"comment\")+this.encodeField(\"gid\")+this.encodeField(\"gname\")+this.encodeField(\"linkpath\")+this.encodeField(\"mtime\")+this.encodeField(\"size\")+this.encodeField(\"uid\")+this.encodeField(\"uname\")}encodeField(e){if(this[e]===null||this[e]===void 0)return\"\";let r=this[e]instanceof Date?this[e].getTime()/1e3:this[e],o=\" \"+(e===\"dev\"||e===\"ino\"||e===\"nlink\"?\"SCHILY.\":\"\")+e+\"=\"+r+`\n`,a=Buffer.byteLength(o),n=Math.floor(Math.log(a)/Math.log(10))+1;return a+n>=Math.pow(10,n)&&(n+=1),n+a+o}};c2.parse=(t,e,r)=>new c2(Vat(zat(t),e),r);var Vat=(t,e)=>e?Object.keys(t).reduce((r,o)=>(r[o]=t[o],r),e):t,zat=t=>t.replace(/\\n$/,\"\").split(`\n`).reduce(Jat,Object.create(null)),Jat=(t,e)=>{let r=parseInt(e,10);if(r!==Buffer.byteLength(e)+1)return t;e=e.substr((r+\" \").length);let o=e.split(\"=\"),a=o.shift().replace(/^SCHILY\\.(dev|ino|nlink)/,\"$1\");if(!a)return t;let n=o.join(\"=\");return t[a]=/^([A-Z]+\\.)?([mac]|birth|creation)time$/.test(a)?new Date(n*1e3):/^[0-9]+$/.test(n)?+n:n,t};mAe.exports=c2});var _y=_((Q4t,yAe)=>{yAe.exports=t=>{let e=t.length-1,r=-1;for(;e>-1&&t.charAt(e)===\"/\";)r=e,e--;return r===-1?t:t.slice(0,r)}});var Mb=_((F4t,EAe)=>{\"use strict\";EAe.exports=t=>class extends t{warn(e,r,o={}){this.file&&(o.file=this.file),this.cwd&&(o.cwd=this.cwd),o.code=r instanceof Error&&r.code||e,o.tarCode=e,!this.strict&&o.recoverable!==!1?(r instanceof Error&&(o=Object.assign(r,o),r=r.message),this.emit(\"warn\",o.tarCode,r,o)):r instanceof Error?this.emit(\"error\",Object.assign(r,o)):this.emit(\"error\",Object.assign(new Error(`${e}: ${r}`),o))}}});var M3=_((T4t,CAe)=>{\"use strict\";var Ub=[\"|\",\"<\",\">\",\"?\",\":\"],O3=Ub.map(t=>String.fromCharCode(61440+t.charCodeAt(0))),Xat=new Map(Ub.map((t,e)=>[t,O3[e]])),Zat=new Map(O3.map((t,e)=>[t,Ub[e]]));CAe.exports={encode:t=>Ub.reduce((e,r)=>e.split(r).join(Xat.get(r)),t),decode:t=>O3.reduce((e,r)=>e.split(r).join(Zat.get(r)),t)}});var U3=_((L4t,wAe)=>{var{isAbsolute:$at,parse:IAe}=ve(\"path\").win32;wAe.exports=t=>{let e=\"\",r=IAe(t);for(;$at(t)||r.root;){let o=t.charAt(0)===\"/\"&&t.slice(0,4)!==\"//?/\"?\"/\":r.root;t=t.substr(o.length),e+=o,r=IAe(t)}return[e,t]}});var vAe=_((N4t,BAe)=>{\"use strict\";BAe.exports=(t,e,r)=>(t&=4095,r&&(t=(t|384)&-19),e&&(t&256&&(t|=64),t&32&&(t|=8),t&4&&(t|=1)),t)});var z3=_((U4t,MAe)=>{\"use strict\";var QAe=Ty(),FAe=Ob(),RAe=Uy(),lA=ve(\"fs\"),DAe=ve(\"path\"),aA=Oy(),elt=_y(),TAe=(t,e)=>e?(t=aA(t).replace(/^\\.(\\/|$)/,\"\"),elt(e)+\"/\"+t):aA(t),tlt=16*1024*1024,PAe=Symbol(\"process\"),SAe=Symbol(\"file\"),xAe=Symbol(\"directory\"),H3=Symbol(\"symlink\"),bAe=Symbol(\"hardlink\"),u2=Symbol(\"header\"),_b=Symbol(\"read\"),q3=Symbol(\"lstat\"),Hb=Symbol(\"onlstat\"),j3=Symbol(\"onread\"),G3=Symbol(\"onreadlink\"),W3=Symbol(\"openfile\"),Y3=Symbol(\"onopenfile\"),Ih=Symbol(\"close\"),qb=Symbol(\"mode\"),K3=Symbol(\"awaitDrain\"),_3=Symbol(\"ondrain\"),cA=Symbol(\"prefix\"),kAe=Symbol(\"hadError\"),LAe=Mb(),rlt=M3(),NAe=U3(),OAe=vAe(),jb=LAe(class extends QAe{constructor(e,r){if(r=r||{},super(r),typeof e!=\"string\")throw new TypeError(\"path is required\");this.path=aA(e),this.portable=!!r.portable,this.myuid=process.getuid&&process.getuid()||0,this.myuser=process.env.USER||\"\",this.maxReadSize=r.maxReadSize||tlt,this.linkCache=r.linkCache||new Map,this.statCache=r.statCache||new Map,this.preservePaths=!!r.preservePaths,this.cwd=aA(r.cwd||process.cwd()),this.strict=!!r.strict,this.noPax=!!r.noPax,this.noMtime=!!r.noMtime,this.mtime=r.mtime||null,this.prefix=r.prefix?aA(r.prefix):null,this.fd=null,this.blockLen=null,this.blockRemain=null,this.buf=null,this.offset=null,this.length=null,this.pos=null,this.remain=null,typeof r.onwarn==\"function\"&&this.on(\"warn\",r.onwarn);let o=!1;if(!this.preservePaths){let[a,n]=NAe(this.path);a&&(this.path=n,o=a)}this.win32=!!r.win32||process.platform===\"win32\",this.win32&&(this.path=rlt.decode(this.path.replace(/\\\\/g,\"/\")),e=e.replace(/\\\\/g,\"/\")),this.absolute=aA(r.absolute||DAe.resolve(this.cwd,e)),this.path===\"\"&&(this.path=\"./\"),o&&this.warn(\"TAR_ENTRY_INFO\",`stripping ${o} from absolute path`,{entry:this,path:o+this.path}),this.statCache.has(this.absolute)?this[Hb](this.statCache.get(this.absolute)):this[q3]()}emit(e,...r){return e===\"error\"&&(this[kAe]=!0),super.emit(e,...r)}[q3](){lA.lstat(this.absolute,(e,r)=>{if(e)return this.emit(\"error\",e);this[Hb](r)})}[Hb](e){this.statCache.set(this.absolute,e),this.stat=e,e.isFile()||(e.size=0),this.type=ilt(e),this.emit(\"stat\",e),this[PAe]()}[PAe](){switch(this.type){case\"File\":return this[SAe]();case\"Directory\":return this[xAe]();case\"SymbolicLink\":return this[H3]();default:return this.end()}}[qb](e){return OAe(e,this.type===\"Directory\",this.portable)}[cA](e){return TAe(e,this.prefix)}[u2](){this.type===\"Directory\"&&this.portable&&(this.noMtime=!0),this.header=new RAe({path:this[cA](this.path),linkpath:this.type===\"Link\"?this[cA](this.linkpath):this.linkpath,mode:this[qb](this.stat.mode),uid:this.portable?null:this.stat.uid,gid:this.portable?null:this.stat.gid,size:this.stat.size,mtime:this.noMtime?null:this.mtime||this.stat.mtime,type:this.type,uname:this.portable?null:this.stat.uid===this.myuid?this.myuser:\"\",atime:this.portable?null:this.stat.atime,ctime:this.portable?null:this.stat.ctime}),this.header.encode()&&!this.noPax&&super.write(new FAe({atime:this.portable?null:this.header.atime,ctime:this.portable?null:this.header.ctime,gid:this.portable?null:this.header.gid,mtime:this.noMtime?null:this.mtime||this.header.mtime,path:this[cA](this.path),linkpath:this.type===\"Link\"?this[cA](this.linkpath):this.linkpath,size:this.header.size,uid:this.portable?null:this.header.uid,uname:this.portable?null:this.header.uname,dev:this.portable?null:this.stat.dev,ino:this.portable?null:this.stat.ino,nlink:this.portable?null:this.stat.nlink}).encode()),super.write(this.header.block)}[xAe](){this.path.substr(-1)!==\"/\"&&(this.path+=\"/\"),this.stat.size=0,this[u2](),this.end()}[H3](){lA.readlink(this.absolute,(e,r)=>{if(e)return this.emit(\"error\",e);this[G3](r)})}[G3](e){this.linkpath=aA(e),this[u2](),this.end()}[bAe](e){this.type=\"Link\",this.linkpath=aA(DAe.relative(this.cwd,e)),this.stat.size=0,this[u2](),this.end()}[SAe](){if(this.stat.nlink>1){let e=this.stat.dev+\":\"+this.stat.ino;if(this.linkCache.has(e)){let r=this.linkCache.get(e);if(r.indexOf(this.cwd)===0)return this[bAe](r)}this.linkCache.set(e,this.absolute)}if(this[u2](),this.stat.size===0)return this.end();this[W3]()}[W3](){lA.open(this.absolute,\"r\",(e,r)=>{if(e)return this.emit(\"error\",e);this[Y3](r)})}[Y3](e){if(this.fd=e,this[kAe])return this[Ih]();this.blockLen=512*Math.ceil(this.stat.size/512),this.blockRemain=this.blockLen;let r=Math.min(this.blockLen,this.maxReadSize);this.buf=Buffer.allocUnsafe(r),this.offset=0,this.pos=0,this.remain=this.stat.size,this.length=this.buf.length,this[_b]()}[_b](){let{fd:e,buf:r,offset:o,length:a,pos:n}=this;lA.read(e,r,o,a,n,(u,A)=>{if(u)return this[Ih](()=>this.emit(\"error\",u));this[j3](A)})}[Ih](e){lA.close(this.fd,e)}[j3](e){if(e<=0&&this.remain>0){let a=new Error(\"encountered unexpected EOF\");return a.path=this.absolute,a.syscall=\"read\",a.code=\"EOF\",this[Ih](()=>this.emit(\"error\",a))}if(e>this.remain){let a=new Error(\"did not encounter expected EOF\");return a.path=this.absolute,a.syscall=\"read\",a.code=\"EOF\",this[Ih](()=>this.emit(\"error\",a))}if(e===this.remain)for(let a=e;a<this.length&&e<this.blockRemain;a++)this.buf[a+this.offset]=0,e++,this.remain++;let r=this.offset===0&&e===this.buf.length?this.buf:this.buf.slice(this.offset,this.offset+e);this.write(r)?this[_3]():this[K3](()=>this[_3]())}[K3](e){this.once(\"drain\",e)}write(e){if(this.blockRemain<e.length){let r=new Error(\"writing more data than expected\");return r.path=this.absolute,this.emit(\"error\",r)}return this.remain-=e.length,this.blockRemain-=e.length,this.pos+=e.length,this.offset+=e.length,super.write(e)}[_3](){if(!this.remain)return this.blockRemain&&super.write(Buffer.alloc(this.blockRemain)),this[Ih](e=>e?this.emit(\"error\",e):this.end());this.offset>=this.length&&(this.buf=Buffer.allocUnsafe(Math.min(this.blockRemain,this.buf.length)),this.offset=0),this.length=this.buf.length-this.offset,this[_b]()}}),V3=class extends jb{[q3](){this[Hb](lA.lstatSync(this.absolute))}[H3](){this[G3](lA.readlinkSync(this.absolute))}[W3](){this[Y3](lA.openSync(this.absolute,\"r\"))}[_b](){let e=!0;try{let{fd:r,buf:o,offset:a,length:n,pos:u}=this,A=lA.readSync(r,o,a,n,u);this[j3](A),e=!1}finally{if(e)try{this[Ih](()=>{})}catch{}}}[K3](e){e()}[Ih](e){lA.closeSync(this.fd),e()}},nlt=LAe(class extends QAe{constructor(e,r){r=r||{},super(r),this.preservePaths=!!r.preservePaths,this.portable=!!r.portable,this.strict=!!r.strict,this.noPax=!!r.noPax,this.noMtime=!!r.noMtime,this.readEntry=e,this.type=e.type,this.type===\"Directory\"&&this.portable&&(this.noMtime=!0),this.prefix=r.prefix||null,this.path=aA(e.path),this.mode=this[qb](e.mode),this.uid=this.portable?null:e.uid,this.gid=this.portable?null:e.gid,this.uname=this.portable?null:e.uname,this.gname=this.portable?null:e.gname,this.size=e.size,this.mtime=this.noMtime?null:r.mtime||e.mtime,this.atime=this.portable?null:e.atime,this.ctime=this.portable?null:e.ctime,this.linkpath=aA(e.linkpath),typeof r.onwarn==\"function\"&&this.on(\"warn\",r.onwarn);let o=!1;if(!this.preservePaths){let[a,n]=NAe(this.path);a&&(this.path=n,o=a)}this.remain=e.size,this.blockRemain=e.startBlockSize,this.header=new RAe({path:this[cA](this.path),linkpath:this.type===\"Link\"?this[cA](this.linkpath):this.linkpath,mode:this.mode,uid:this.portable?null:this.uid,gid:this.portable?null:this.gid,size:this.size,mtime:this.noMtime?null:this.mtime,type:this.type,uname:this.portable?null:this.uname,atime:this.portable?null:this.atime,ctime:this.portable?null:this.ctime}),o&&this.warn(\"TAR_ENTRY_INFO\",`stripping ${o} from absolute path`,{entry:this,path:o+this.path}),this.header.encode()&&!this.noPax&&super.write(new FAe({atime:this.portable?null:this.atime,ctime:this.portable?null:this.ctime,gid:this.portable?null:this.gid,mtime:this.noMtime?null:this.mtime,path:this[cA](this.path),linkpath:this.type===\"Link\"?this[cA](this.linkpath):this.linkpath,size:this.size,uid:this.portable?null:this.uid,uname:this.portable?null:this.uname,dev:this.portable?null:this.readEntry.dev,ino:this.portable?null:this.readEntry.ino,nlink:this.portable?null:this.readEntry.nlink}).encode()),super.write(this.header.block),e.pipe(this)}[cA](e){return TAe(e,this.prefix)}[qb](e){return OAe(e,this.type===\"Directory\",this.portable)}write(e){let r=e.length;if(r>this.blockRemain)throw new Error(\"writing more to entry than is appropriate\");return this.blockRemain-=r,super.write(e)}end(){return this.blockRemain&&super.write(Buffer.alloc(this.blockRemain)),super.end()}});jb.Sync=V3;jb.Tar=nlt;var ilt=t=>t.isFile()?\"File\":t.isDirectory()?\"Directory\":t.isSymbolicLink()?\"SymbolicLink\":\"Unsupported\";MAe.exports=jb});var Zb=_((H4t,WAe)=>{\"use strict\";var Jb=class{constructor(e,r){this.path=e||\"./\",this.absolute=r,this.entry=null,this.stat=null,this.readdir=null,this.pending=!1,this.ignore=!1,this.piped=!1}},slt=Ty(),olt=x3(),alt=Lb(),i_=z3(),llt=i_.Sync,clt=i_.Tar,ult=$P(),UAe=Buffer.alloc(1024),Yb=Symbol(\"onStat\"),Gb=Symbol(\"ended\"),uA=Symbol(\"queue\"),Hy=Symbol(\"current\"),Mg=Symbol(\"process\"),Wb=Symbol(\"processing\"),_Ae=Symbol(\"processJob\"),AA=Symbol(\"jobs\"),J3=Symbol(\"jobDone\"),Kb=Symbol(\"addFSEntry\"),HAe=Symbol(\"addTarEntry\"),e_=Symbol(\"stat\"),t_=Symbol(\"readdir\"),Vb=Symbol(\"onreaddir\"),zb=Symbol(\"pipe\"),qAe=Symbol(\"entry\"),X3=Symbol(\"entryOpt\"),r_=Symbol(\"writeEntryClass\"),GAe=Symbol(\"write\"),Z3=Symbol(\"ondrain\"),Xb=ve(\"fs\"),jAe=ve(\"path\"),Alt=Mb(),$3=Oy(),s_=Alt(class extends slt{constructor(e){super(e),e=e||Object.create(null),this.opt=e,this.file=e.file||\"\",this.cwd=e.cwd||process.cwd(),this.maxReadSize=e.maxReadSize,this.preservePaths=!!e.preservePaths,this.strict=!!e.strict,this.noPax=!!e.noPax,this.prefix=$3(e.prefix||\"\"),this.linkCache=e.linkCache||new Map,this.statCache=e.statCache||new Map,this.readdirCache=e.readdirCache||new Map,this[r_]=i_,typeof e.onwarn==\"function\"&&this.on(\"warn\",e.onwarn),this.portable=!!e.portable,this.zip=null,e.gzip?(typeof e.gzip!=\"object\"&&(e.gzip={}),this.portable&&(e.gzip.portable=!0),this.zip=new olt.Gzip(e.gzip),this.zip.on(\"data\",r=>super.write(r)),this.zip.on(\"end\",r=>super.end()),this.zip.on(\"drain\",r=>this[Z3]()),this.on(\"resume\",r=>this.zip.resume())):this.on(\"drain\",this[Z3]),this.noDirRecurse=!!e.noDirRecurse,this.follow=!!e.follow,this.noMtime=!!e.noMtime,this.mtime=e.mtime||null,this.filter=typeof e.filter==\"function\"?e.filter:r=>!0,this[uA]=new ult,this[AA]=0,this.jobs=+e.jobs||4,this[Wb]=!1,this[Gb]=!1}[GAe](e){return super.write(e)}add(e){return this.write(e),this}end(e){return e&&this.write(e),this[Gb]=!0,this[Mg](),this}write(e){if(this[Gb])throw new Error(\"write after end\");return e instanceof alt?this[HAe](e):this[Kb](e),this.flowing}[HAe](e){let r=$3(jAe.resolve(this.cwd,e.path));if(!this.filter(e.path,e))e.resume();else{let o=new Jb(e.path,r,!1);o.entry=new clt(e,this[X3](o)),o.entry.on(\"end\",a=>this[J3](o)),this[AA]+=1,this[uA].push(o)}this[Mg]()}[Kb](e){let r=$3(jAe.resolve(this.cwd,e));this[uA].push(new Jb(e,r)),this[Mg]()}[e_](e){e.pending=!0,this[AA]+=1;let r=this.follow?\"stat\":\"lstat\";Xb[r](e.absolute,(o,a)=>{e.pending=!1,this[AA]-=1,o?this.emit(\"error\",o):this[Yb](e,a)})}[Yb](e,r){this.statCache.set(e.absolute,r),e.stat=r,this.filter(e.path,r)||(e.ignore=!0),this[Mg]()}[t_](e){e.pending=!0,this[AA]+=1,Xb.readdir(e.absolute,(r,o)=>{if(e.pending=!1,this[AA]-=1,r)return this.emit(\"error\",r);this[Vb](e,o)})}[Vb](e,r){this.readdirCache.set(e.absolute,r),e.readdir=r,this[Mg]()}[Mg](){if(!this[Wb]){this[Wb]=!0;for(let e=this[uA].head;e!==null&&this[AA]<this.jobs;e=e.next)if(this[_Ae](e.value),e.value.ignore){let r=e.next;this[uA].removeNode(e),e.next=r}this[Wb]=!1,this[Gb]&&!this[uA].length&&this[AA]===0&&(this.zip?this.zip.end(UAe):(super.write(UAe),super.end()))}}get[Hy](){return this[uA]&&this[uA].head&&this[uA].head.value}[J3](e){this[uA].shift(),this[AA]-=1,this[Mg]()}[_Ae](e){if(!e.pending){if(e.entry){e===this[Hy]&&!e.piped&&this[zb](e);return}if(e.stat||(this.statCache.has(e.absolute)?this[Yb](e,this.statCache.get(e.absolute)):this[e_](e)),!!e.stat&&!e.ignore&&!(!this.noDirRecurse&&e.stat.isDirectory()&&!e.readdir&&(this.readdirCache.has(e.absolute)?this[Vb](e,this.readdirCache.get(e.absolute)):this[t_](e),!e.readdir))){if(e.entry=this[qAe](e),!e.entry){e.ignore=!0;return}e===this[Hy]&&!e.piped&&this[zb](e)}}}[X3](e){return{onwarn:(r,o,a)=>this.warn(r,o,a),noPax:this.noPax,cwd:this.cwd,absolute:e.absolute,preservePaths:this.preservePaths,maxReadSize:this.maxReadSize,strict:this.strict,portable:this.portable,linkCache:this.linkCache,statCache:this.statCache,noMtime:this.noMtime,mtime:this.mtime,prefix:this.prefix}}[qAe](e){this[AA]+=1;try{return new this[r_](e.path,this[X3](e)).on(\"end\",()=>this[J3](e)).on(\"error\",r=>this.emit(\"error\",r))}catch(r){this.emit(\"error\",r)}}[Z3](){this[Hy]&&this[Hy].entry&&this[Hy].entry.resume()}[zb](e){e.piped=!0,e.readdir&&e.readdir.forEach(a=>{let n=e.path,u=n===\"./\"?\"\":n.replace(/\\/*$/,\"/\");this[Kb](u+a)});let r=e.entry,o=this.zip;o?r.on(\"data\",a=>{o.write(a)||r.pause()}):r.on(\"data\",a=>{super.write(a)||r.pause()})}pause(){return this.zip&&this.zip.pause(),super.pause()}}),n_=class extends s_{constructor(e){super(e),this[r_]=llt}pause(){}resume(){}[e_](e){let r=this.follow?\"statSync\":\"lstatSync\";this[Yb](e,Xb[r](e.absolute))}[t_](e,r){this[Vb](e,Xb.readdirSync(e.absolute))}[zb](e){let r=e.entry,o=this.zip;e.readdir&&e.readdir.forEach(a=>{let n=e.path,u=n===\"./\"?\"\":n.replace(/\\/*$/,\"/\");this[Kb](u+a)}),o?r.on(\"data\",a=>{o.write(a)}):r.on(\"data\",a=>{super[GAe](a)})}};s_.Sync=n_;WAe.exports=s_});var zy=_(f2=>{\"use strict\";var flt=Ty(),plt=ve(\"events\").EventEmitter,Ta=ve(\"fs\"),l_=Ta.writev;if(!l_){let t=process.binding(\"fs\"),e=t.FSReqWrap||t.FSReqCallback;l_=(r,o,a,n)=>{let u=(p,h)=>n(p,h,o),A=new e;A.oncomplete=u,t.writeBuffers(r,o,a,A)}}var Ky=Symbol(\"_autoClose\"),Zc=Symbol(\"_close\"),A2=Symbol(\"_ended\"),Jn=Symbol(\"_fd\"),YAe=Symbol(\"_finished\"),Bh=Symbol(\"_flags\"),o_=Symbol(\"_flush\"),c_=Symbol(\"_handleChunk\"),u_=Symbol(\"_makeBuf\"),nk=Symbol(\"_mode\"),$b=Symbol(\"_needDrain\"),Wy=Symbol(\"_onerror\"),Vy=Symbol(\"_onopen\"),a_=Symbol(\"_onread\"),jy=Symbol(\"_onwrite\"),vh=Symbol(\"_open\"),Hf=Symbol(\"_path\"),Ug=Symbol(\"_pos\"),fA=Symbol(\"_queue\"),Gy=Symbol(\"_read\"),KAe=Symbol(\"_readSize\"),wh=Symbol(\"_reading\"),ek=Symbol(\"_remain\"),VAe=Symbol(\"_size\"),tk=Symbol(\"_write\"),qy=Symbol(\"_writing\"),rk=Symbol(\"_defaultFlag\"),Yy=Symbol(\"_errored\"),ik=class extends flt{constructor(e,r){if(r=r||{},super(r),this.readable=!0,this.writable=!1,typeof e!=\"string\")throw new TypeError(\"path must be a string\");this[Yy]=!1,this[Jn]=typeof r.fd==\"number\"?r.fd:null,this[Hf]=e,this[KAe]=r.readSize||16*1024*1024,this[wh]=!1,this[VAe]=typeof r.size==\"number\"?r.size:1/0,this[ek]=this[VAe],this[Ky]=typeof r.autoClose==\"boolean\"?r.autoClose:!0,typeof this[Jn]==\"number\"?this[Gy]():this[vh]()}get fd(){return this[Jn]}get path(){return this[Hf]}write(){throw new TypeError(\"this is a readable stream\")}end(){throw new TypeError(\"this is a readable stream\")}[vh](){Ta.open(this[Hf],\"r\",(e,r)=>this[Vy](e,r))}[Vy](e,r){e?this[Wy](e):(this[Jn]=r,this.emit(\"open\",r),this[Gy]())}[u_](){return Buffer.allocUnsafe(Math.min(this[KAe],this[ek]))}[Gy](){if(!this[wh]){this[wh]=!0;let e=this[u_]();if(e.length===0)return process.nextTick(()=>this[a_](null,0,e));Ta.read(this[Jn],e,0,e.length,null,(r,o,a)=>this[a_](r,o,a))}}[a_](e,r,o){this[wh]=!1,e?this[Wy](e):this[c_](r,o)&&this[Gy]()}[Zc](){if(this[Ky]&&typeof this[Jn]==\"number\"){let e=this[Jn];this[Jn]=null,Ta.close(e,r=>r?this.emit(\"error\",r):this.emit(\"close\"))}}[Wy](e){this[wh]=!0,this[Zc](),this.emit(\"error\",e)}[c_](e,r){let o=!1;return this[ek]-=e,e>0&&(o=super.write(e<r.length?r.slice(0,e):r)),(e===0||this[ek]<=0)&&(o=!1,this[Zc](),super.end()),o}emit(e,r){switch(e){case\"prefinish\":case\"finish\":break;case\"drain\":typeof this[Jn]==\"number\"&&this[Gy]();break;case\"error\":return this[Yy]?void 0:(this[Yy]=!0,super.emit(e,r));default:return super.emit(e,r)}}},A_=class extends ik{[vh](){let e=!0;try{this[Vy](null,Ta.openSync(this[Hf],\"r\")),e=!1}finally{e&&this[Zc]()}}[Gy](){let e=!0;try{if(!this[wh]){this[wh]=!0;do{let r=this[u_](),o=r.length===0?0:Ta.readSync(this[Jn],r,0,r.length,null);if(!this[c_](o,r))break}while(!0);this[wh]=!1}e=!1}finally{e&&this[Zc]()}}[Zc](){if(this[Ky]&&typeof this[Jn]==\"number\"){let e=this[Jn];this[Jn]=null,Ta.closeSync(e),this.emit(\"close\")}}},sk=class extends plt{constructor(e,r){r=r||{},super(r),this.readable=!1,this.writable=!0,this[Yy]=!1,this[qy]=!1,this[A2]=!1,this[$b]=!1,this[fA]=[],this[Hf]=e,this[Jn]=typeof r.fd==\"number\"?r.fd:null,this[nk]=r.mode===void 0?438:r.mode,this[Ug]=typeof r.start==\"number\"?r.start:null,this[Ky]=typeof r.autoClose==\"boolean\"?r.autoClose:!0;let o=this[Ug]!==null?\"r+\":\"w\";this[rk]=r.flags===void 0,this[Bh]=this[rk]?o:r.flags,this[Jn]===null&&this[vh]()}emit(e,r){if(e===\"error\"){if(this[Yy])return;this[Yy]=!0}return super.emit(e,r)}get fd(){return this[Jn]}get path(){return this[Hf]}[Wy](e){this[Zc](),this[qy]=!0,this.emit(\"error\",e)}[vh](){Ta.open(this[Hf],this[Bh],this[nk],(e,r)=>this[Vy](e,r))}[Vy](e,r){this[rk]&&this[Bh]===\"r+\"&&e&&e.code===\"ENOENT\"?(this[Bh]=\"w\",this[vh]()):e?this[Wy](e):(this[Jn]=r,this.emit(\"open\",r),this[o_]())}end(e,r){return e&&this.write(e,r),this[A2]=!0,!this[qy]&&!this[fA].length&&typeof this[Jn]==\"number\"&&this[jy](null,0),this}write(e,r){return typeof e==\"string\"&&(e=Buffer.from(e,r)),this[A2]?(this.emit(\"error\",new Error(\"write() after end()\")),!1):this[Jn]===null||this[qy]||this[fA].length?(this[fA].push(e),this[$b]=!0,!1):(this[qy]=!0,this[tk](e),!0)}[tk](e){Ta.write(this[Jn],e,0,e.length,this[Ug],(r,o)=>this[jy](r,o))}[jy](e,r){e?this[Wy](e):(this[Ug]!==null&&(this[Ug]+=r),this[fA].length?this[o_]():(this[qy]=!1,this[A2]&&!this[YAe]?(this[YAe]=!0,this[Zc](),this.emit(\"finish\")):this[$b]&&(this[$b]=!1,this.emit(\"drain\"))))}[o_](){if(this[fA].length===0)this[A2]&&this[jy](null,0);else if(this[fA].length===1)this[tk](this[fA].pop());else{let e=this[fA];this[fA]=[],l_(this[Jn],e,this[Ug],(r,o)=>this[jy](r,o))}}[Zc](){if(this[Ky]&&typeof this[Jn]==\"number\"){let e=this[Jn];this[Jn]=null,Ta.close(e,r=>r?this.emit(\"error\",r):this.emit(\"close\"))}}},f_=class extends sk{[vh](){let e;if(this[rk]&&this[Bh]===\"r+\")try{e=Ta.openSync(this[Hf],this[Bh],this[nk])}catch(r){if(r.code===\"ENOENT\")return this[Bh]=\"w\",this[vh]();throw r}else e=Ta.openSync(this[Hf],this[Bh],this[nk]);this[Vy](null,e)}[Zc](){if(this[Ky]&&typeof this[Jn]==\"number\"){let e=this[Jn];this[Jn]=null,Ta.closeSync(e),this.emit(\"close\")}}[tk](e){let r=!0;try{this[jy](null,Ta.writeSync(this[Jn],e,0,e.length,this[Ug])),r=!1}finally{if(r)try{this[Zc]()}catch{}}}};f2.ReadStream=ik;f2.ReadStreamSync=A_;f2.WriteStream=sk;f2.WriteStreamSync=f_});var fk=_((G4t,tfe)=>{\"use strict\";var hlt=Mb(),glt=Uy(),dlt=ve(\"events\"),mlt=$P(),ylt=1024*1024,Elt=Lb(),zAe=Ob(),Clt=x3(),p_=Buffer.from([31,139]),$l=Symbol(\"state\"),_g=Symbol(\"writeEntry\"),qf=Symbol(\"readEntry\"),h_=Symbol(\"nextEntry\"),JAe=Symbol(\"processEntry\"),ec=Symbol(\"extendedHeader\"),p2=Symbol(\"globalExtendedHeader\"),Dh=Symbol(\"meta\"),XAe=Symbol(\"emitMeta\"),yi=Symbol(\"buffer\"),jf=Symbol(\"queue\"),Hg=Symbol(\"ended\"),ZAe=Symbol(\"emittedEnd\"),qg=Symbol(\"emit\"),La=Symbol(\"unzip\"),ok=Symbol(\"consumeChunk\"),ak=Symbol(\"consumeChunkSub\"),g_=Symbol(\"consumeBody\"),$Ae=Symbol(\"consumeMeta\"),efe=Symbol(\"consumeHeader\"),lk=Symbol(\"consuming\"),d_=Symbol(\"bufferConcat\"),m_=Symbol(\"maybeEnd\"),h2=Symbol(\"writing\"),Ph=Symbol(\"aborted\"),ck=Symbol(\"onDone\"),jg=Symbol(\"sawValidEntry\"),uk=Symbol(\"sawNullBlock\"),Ak=Symbol(\"sawEOF\"),Ilt=t=>!0;tfe.exports=hlt(class extends dlt{constructor(e){e=e||{},super(e),this.file=e.file||\"\",this[jg]=null,this.on(ck,r=>{(this[$l]===\"begin\"||this[jg]===!1)&&this.warn(\"TAR_BAD_ARCHIVE\",\"Unrecognized archive format\")}),e.ondone?this.on(ck,e.ondone):this.on(ck,r=>{this.emit(\"prefinish\"),this.emit(\"finish\"),this.emit(\"end\"),this.emit(\"close\")}),this.strict=!!e.strict,this.maxMetaEntrySize=e.maxMetaEntrySize||ylt,this.filter=typeof e.filter==\"function\"?e.filter:Ilt,this.writable=!0,this.readable=!1,this[jf]=new mlt,this[yi]=null,this[qf]=null,this[_g]=null,this[$l]=\"begin\",this[Dh]=\"\",this[ec]=null,this[p2]=null,this[Hg]=!1,this[La]=null,this[Ph]=!1,this[uk]=!1,this[Ak]=!1,typeof e.onwarn==\"function\"&&this.on(\"warn\",e.onwarn),typeof e.onentry==\"function\"&&this.on(\"entry\",e.onentry)}[efe](e,r){this[jg]===null&&(this[jg]=!1);let o;try{o=new glt(e,r,this[ec],this[p2])}catch(a){return this.warn(\"TAR_ENTRY_INVALID\",a)}if(o.nullBlock)this[uk]?(this[Ak]=!0,this[$l]===\"begin\"&&(this[$l]=\"header\"),this[qg](\"eof\")):(this[uk]=!0,this[qg](\"nullBlock\"));else if(this[uk]=!1,!o.cksumValid)this.warn(\"TAR_ENTRY_INVALID\",\"checksum failure\",{header:o});else if(!o.path)this.warn(\"TAR_ENTRY_INVALID\",\"path is required\",{header:o});else{let a=o.type;if(/^(Symbolic)?Link$/.test(a)&&!o.linkpath)this.warn(\"TAR_ENTRY_INVALID\",\"linkpath required\",{header:o});else if(!/^(Symbolic)?Link$/.test(a)&&o.linkpath)this.warn(\"TAR_ENTRY_INVALID\",\"linkpath forbidden\",{header:o});else{let n=this[_g]=new Elt(o,this[ec],this[p2]);if(!this[jg])if(n.remain){let u=()=>{n.invalid||(this[jg]=!0)};n.on(\"end\",u)}else this[jg]=!0;n.meta?n.size>this.maxMetaEntrySize?(n.ignore=!0,this[qg](\"ignoredEntry\",n),this[$l]=\"ignore\",n.resume()):n.size>0&&(this[Dh]=\"\",n.on(\"data\",u=>this[Dh]+=u),this[$l]=\"meta\"):(this[ec]=null,n.ignore=n.ignore||!this.filter(n.path,n),n.ignore?(this[qg](\"ignoredEntry\",n),this[$l]=n.remain?\"ignore\":\"header\",n.resume()):(n.remain?this[$l]=\"body\":(this[$l]=\"header\",n.end()),this[qf]?this[jf].push(n):(this[jf].push(n),this[h_]())))}}}[JAe](e){let r=!0;return e?Array.isArray(e)?this.emit.apply(this,e):(this[qf]=e,this.emit(\"entry\",e),e.emittedEnd||(e.on(\"end\",o=>this[h_]()),r=!1)):(this[qf]=null,r=!1),r}[h_](){do;while(this[JAe](this[jf].shift()));if(!this[jf].length){let e=this[qf];!e||e.flowing||e.size===e.remain?this[h2]||this.emit(\"drain\"):e.once(\"drain\",o=>this.emit(\"drain\"))}}[g_](e,r){let o=this[_g],a=o.blockRemain,n=a>=e.length&&r===0?e:e.slice(r,r+a);return o.write(n),o.blockRemain||(this[$l]=\"header\",this[_g]=null,o.end()),n.length}[$Ae](e,r){let o=this[_g],a=this[g_](e,r);return this[_g]||this[XAe](o),a}[qg](e,r,o){!this[jf].length&&!this[qf]?this.emit(e,r,o):this[jf].push([e,r,o])}[XAe](e){switch(this[qg](\"meta\",this[Dh]),e.type){case\"ExtendedHeader\":case\"OldExtendedHeader\":this[ec]=zAe.parse(this[Dh],this[ec],!1);break;case\"GlobalExtendedHeader\":this[p2]=zAe.parse(this[Dh],this[p2],!0);break;case\"NextFileHasLongPath\":case\"OldGnuLongPath\":this[ec]=this[ec]||Object.create(null),this[ec].path=this[Dh].replace(/\\0.*/,\"\");break;case\"NextFileHasLongLinkpath\":this[ec]=this[ec]||Object.create(null),this[ec].linkpath=this[Dh].replace(/\\0.*/,\"\");break;default:throw new Error(\"unknown meta: \"+e.type)}}abort(e){this[Ph]=!0,this.emit(\"abort\",e),this.warn(\"TAR_ABORT\",e,{recoverable:!1})}write(e){if(this[Ph])return;if(this[La]===null&&e){if(this[yi]&&(e=Buffer.concat([this[yi],e]),this[yi]=null),e.length<p_.length)return this[yi]=e,!0;for(let o=0;this[La]===null&&o<p_.length;o++)e[o]!==p_[o]&&(this[La]=!1);if(this[La]===null){let o=this[Hg];this[Hg]=!1,this[La]=new Clt.Unzip,this[La].on(\"data\",n=>this[ok](n)),this[La].on(\"error\",n=>this.abort(n)),this[La].on(\"end\",n=>{this[Hg]=!0,this[ok]()}),this[h2]=!0;let a=this[La][o?\"end\":\"write\"](e);return this[h2]=!1,a}}this[h2]=!0,this[La]?this[La].write(e):this[ok](e),this[h2]=!1;let r=this[jf].length?!1:this[qf]?this[qf].flowing:!0;return!r&&!this[jf].length&&this[qf].once(\"drain\",o=>this.emit(\"drain\")),r}[d_](e){e&&!this[Ph]&&(this[yi]=this[yi]?Buffer.concat([this[yi],e]):e)}[m_](){if(this[Hg]&&!this[ZAe]&&!this[Ph]&&!this[lk]){this[ZAe]=!0;let e=this[_g];if(e&&e.blockRemain){let r=this[yi]?this[yi].length:0;this.warn(\"TAR_BAD_ARCHIVE\",`Truncated input (needed ${e.blockRemain} more bytes, only ${r} available)`,{entry:e}),this[yi]&&e.write(this[yi]),e.end()}this[qg](ck)}}[ok](e){if(this[lk])this[d_](e);else if(!e&&!this[yi])this[m_]();else{if(this[lk]=!0,this[yi]){this[d_](e);let r=this[yi];this[yi]=null,this[ak](r)}else this[ak](e);for(;this[yi]&&this[yi].length>=512&&!this[Ph]&&!this[Ak];){let r=this[yi];this[yi]=null,this[ak](r)}this[lk]=!1}(!this[yi]||this[Hg])&&this[m_]()}[ak](e){let r=0,o=e.length;for(;r+512<=o&&!this[Ph]&&!this[Ak];)switch(this[$l]){case\"begin\":case\"header\":this[efe](e,r),r+=512;break;case\"ignore\":case\"body\":r+=this[g_](e,r);break;case\"meta\":r+=this[$Ae](e,r);break;default:throw new Error(\"invalid state: \"+this[$l])}r<o&&(this[yi]?this[yi]=Buffer.concat([e.slice(r),this[yi]]):this[yi]=e.slice(r))}end(e){this[Ph]||(this[La]?this[La].end(e):(this[Hg]=!0,this.write(e)))}})});var pk=_((W4t,sfe)=>{\"use strict\";var wlt=Fy(),nfe=fk(),Jy=ve(\"fs\"),Blt=zy(),rfe=ve(\"path\"),y_=_y();sfe.exports=(t,e,r)=>{typeof t==\"function\"?(r=t,e=null,t={}):Array.isArray(t)&&(e=t,t={}),typeof e==\"function\"&&(r=e,e=null),e?e=Array.from(e):e=[];let o=wlt(t);if(o.sync&&typeof r==\"function\")throw new TypeError(\"callback not supported for sync tar functions\");if(!o.file&&typeof r==\"function\")throw new TypeError(\"callback only supported with file option\");return e.length&&Dlt(o,e),o.noResume||vlt(o),o.file&&o.sync?Plt(o):o.file?Slt(o,r):ife(o)};var vlt=t=>{let e=t.onentry;t.onentry=e?r=>{e(r),r.resume()}:r=>r.resume()},Dlt=(t,e)=>{let r=new Map(e.map(n=>[y_(n),!0])),o=t.filter,a=(n,u)=>{let A=u||rfe.parse(n).root||\".\",p=n===A?!1:r.has(n)?r.get(n):a(rfe.dirname(n),A);return r.set(n,p),p};t.filter=o?(n,u)=>o(n,u)&&a(y_(n)):n=>a(y_(n))},Plt=t=>{let e=ife(t),r=t.file,o=!0,a;try{let n=Jy.statSync(r),u=t.maxReadSize||16*1024*1024;if(n.size<u)e.end(Jy.readFileSync(r));else{let A=0,p=Buffer.allocUnsafe(u);for(a=Jy.openSync(r,\"r\");A<n.size;){let h=Jy.readSync(a,p,0,u,A);A+=h,e.write(p.slice(0,h))}e.end()}o=!1}finally{if(o&&a)try{Jy.closeSync(a)}catch{}}},Slt=(t,e)=>{let r=new nfe(t),o=t.maxReadSize||16*1024*1024,a=t.file,n=new Promise((u,A)=>{r.on(\"error\",A),r.on(\"end\",u),Jy.stat(a,(p,h)=>{if(p)A(p);else{let E=new Blt.ReadStream(a,{readSize:o,size:h.size});E.on(\"error\",A),E.pipe(r)}})});return e?n.then(e,e):n},ife=t=>new nfe(t)});var Afe=_((Y4t,ufe)=>{\"use strict\";var xlt=Fy(),hk=Zb(),ofe=zy(),afe=pk(),lfe=ve(\"path\");ufe.exports=(t,e,r)=>{if(typeof e==\"function\"&&(r=e),Array.isArray(t)&&(e=t,t={}),!e||!Array.isArray(e)||!e.length)throw new TypeError(\"no files or directories specified\");e=Array.from(e);let o=xlt(t);if(o.sync&&typeof r==\"function\")throw new TypeError(\"callback not supported for sync tar functions\");if(!o.file&&typeof r==\"function\")throw new TypeError(\"callback only supported with file option\");return o.file&&o.sync?blt(o,e):o.file?klt(o,e,r):o.sync?Qlt(o,e):Flt(o,e)};var blt=(t,e)=>{let r=new hk.Sync(t),o=new ofe.WriteStreamSync(t.file,{mode:t.mode||438});r.pipe(o),cfe(r,e)},klt=(t,e,r)=>{let o=new hk(t),a=new ofe.WriteStream(t.file,{mode:t.mode||438});o.pipe(a);let n=new Promise((u,A)=>{a.on(\"error\",A),a.on(\"close\",u),o.on(\"error\",A)});return E_(o,e),r?n.then(r,r):n},cfe=(t,e)=>{e.forEach(r=>{r.charAt(0)===\"@\"?afe({file:lfe.resolve(t.cwd,r.substr(1)),sync:!0,noResume:!0,onentry:o=>t.add(o)}):t.add(r)}),t.end()},E_=(t,e)=>{for(;e.length;){let r=e.shift();if(r.charAt(0)===\"@\")return afe({file:lfe.resolve(t.cwd,r.substr(1)),noResume:!0,onentry:o=>t.add(o)}).then(o=>E_(t,e));t.add(r)}t.end()},Qlt=(t,e)=>{let r=new hk.Sync(t);return cfe(r,e),r},Flt=(t,e)=>{let r=new hk(t);return E_(r,e),r}});var C_=_((K4t,yfe)=>{\"use strict\";var Rlt=Fy(),ffe=Zb(),dl=ve(\"fs\"),pfe=zy(),hfe=pk(),gfe=ve(\"path\"),dfe=Uy();yfe.exports=(t,e,r)=>{let o=Rlt(t);if(!o.file)throw new TypeError(\"file is required\");if(o.gzip)throw new TypeError(\"cannot append to compressed archives\");if(!e||!Array.isArray(e)||!e.length)throw new TypeError(\"no files or directories specified\");return e=Array.from(e),o.sync?Tlt(o,e):Nlt(o,e,r)};var Tlt=(t,e)=>{let r=new ffe.Sync(t),o=!0,a,n;try{try{a=dl.openSync(t.file,\"r+\")}catch(p){if(p.code===\"ENOENT\")a=dl.openSync(t.file,\"w+\");else throw p}let u=dl.fstatSync(a),A=Buffer.alloc(512);e:for(n=0;n<u.size;n+=512){for(let E=0,w=0;E<512;E+=w){if(w=dl.readSync(a,A,E,A.length-E,n+E),n===0&&A[0]===31&&A[1]===139)throw new Error(\"cannot append to compressed archives\");if(!w)break e}let p=new dfe(A);if(!p.cksumValid)break;let h=512*Math.ceil(p.size/512);if(n+h+512>u.size)break;n+=h,t.mtimeCache&&t.mtimeCache.set(p.path,p.mtime)}o=!1,Llt(t,r,n,a,e)}finally{if(o)try{dl.closeSync(a)}catch{}}},Llt=(t,e,r,o,a)=>{let n=new pfe.WriteStreamSync(t.file,{fd:o,start:r});e.pipe(n),Olt(e,a)},Nlt=(t,e,r)=>{e=Array.from(e);let o=new ffe(t),a=(u,A,p)=>{let h=(C,T)=>{C?dl.close(u,N=>p(C)):p(null,T)},E=0;if(A===0)return h(null,0);let w=0,D=Buffer.alloc(512),b=(C,T)=>{if(C)return h(C);if(w+=T,w<512&&T)return dl.read(u,D,w,D.length-w,E+w,b);if(E===0&&D[0]===31&&D[1]===139)return h(new Error(\"cannot append to compressed archives\"));if(w<512)return h(null,E);let N=new dfe(D);if(!N.cksumValid)return h(null,E);let U=512*Math.ceil(N.size/512);if(E+U+512>A||(E+=U+512,E>=A))return h(null,E);t.mtimeCache&&t.mtimeCache.set(N.path,N.mtime),w=0,dl.read(u,D,0,512,E,b)};dl.read(u,D,0,512,E,b)},n=new Promise((u,A)=>{o.on(\"error\",A);let p=\"r+\",h=(E,w)=>{if(E&&E.code===\"ENOENT\"&&p===\"r+\")return p=\"w+\",dl.open(t.file,p,h);if(E)return A(E);dl.fstat(w,(D,b)=>{if(D)return dl.close(w,()=>A(D));a(w,b.size,(C,T)=>{if(C)return A(C);let N=new pfe.WriteStream(t.file,{fd:w,start:T});o.pipe(N),N.on(\"error\",A),N.on(\"close\",u),mfe(o,e)})})};dl.open(t.file,p,h)});return r?n.then(r,r):n},Olt=(t,e)=>{e.forEach(r=>{r.charAt(0)===\"@\"?hfe({file:gfe.resolve(t.cwd,r.substr(1)),sync:!0,noResume:!0,onentry:o=>t.add(o)}):t.add(r)}),t.end()},mfe=(t,e)=>{for(;e.length;){let r=e.shift();if(r.charAt(0)===\"@\")return hfe({file:gfe.resolve(t.cwd,r.substr(1)),noResume:!0,onentry:o=>t.add(o)}).then(o=>mfe(t,e));t.add(r)}t.end()}});var Cfe=_((V4t,Efe)=>{\"use strict\";var Mlt=Fy(),Ult=C_();Efe.exports=(t,e,r)=>{let o=Mlt(t);if(!o.file)throw new TypeError(\"file is required\");if(o.gzip)throw new TypeError(\"cannot append to compressed archives\");if(!e||!Array.isArray(e)||!e.length)throw new TypeError(\"no files or directories specified\");return e=Array.from(e),_lt(o),Ult(o,e,r)};var _lt=t=>{let e=t.filter;t.mtimeCache||(t.mtimeCache=new Map),t.filter=e?(r,o)=>e(r,o)&&!(t.mtimeCache.get(r)>o.mtime):(r,o)=>!(t.mtimeCache.get(r)>o.mtime)}});var Bfe=_((z4t,wfe)=>{var{promisify:Ife}=ve(\"util\"),Sh=ve(\"fs\"),Hlt=t=>{if(!t)t={mode:511,fs:Sh};else if(typeof t==\"object\")t={mode:511,fs:Sh,...t};else if(typeof t==\"number\")t={mode:t,fs:Sh};else if(typeof t==\"string\")t={mode:parseInt(t,8),fs:Sh};else throw new TypeError(\"invalid options argument\");return t.mkdir=t.mkdir||t.fs.mkdir||Sh.mkdir,t.mkdirAsync=Ife(t.mkdir),t.stat=t.stat||t.fs.stat||Sh.stat,t.statAsync=Ife(t.stat),t.statSync=t.statSync||t.fs.statSync||Sh.statSync,t.mkdirSync=t.mkdirSync||t.fs.mkdirSync||Sh.mkdirSync,t};wfe.exports=Hlt});var Dfe=_((J4t,vfe)=>{var qlt=process.platform,{resolve:jlt,parse:Glt}=ve(\"path\"),Wlt=t=>{if(/\\0/.test(t))throw Object.assign(new TypeError(\"path must be a string without null bytes\"),{path:t,code:\"ERR_INVALID_ARG_VALUE\"});if(t=jlt(t),qlt===\"win32\"){let e=/[*|\"<>?:]/,{root:r}=Glt(t);if(e.test(t.substr(r.length)))throw Object.assign(new Error(\"Illegal characters in path.\"),{path:t,code:\"EINVAL\"})}return t};vfe.exports=Wlt});var kfe=_((X4t,bfe)=>{var{dirname:Pfe}=ve(\"path\"),Sfe=(t,e,r=void 0)=>r===e?Promise.resolve():t.statAsync(e).then(o=>o.isDirectory()?r:void 0,o=>o.code===\"ENOENT\"?Sfe(t,Pfe(e),e):void 0),xfe=(t,e,r=void 0)=>{if(r!==e)try{return t.statSync(e).isDirectory()?r:void 0}catch(o){return o.code===\"ENOENT\"?xfe(t,Pfe(e),e):void 0}};bfe.exports={findMade:Sfe,findMadeSync:xfe}});var B_=_((Z4t,Ffe)=>{var{dirname:Qfe}=ve(\"path\"),I_=(t,e,r)=>{e.recursive=!1;let o=Qfe(t);return o===t?e.mkdirAsync(t,e).catch(a=>{if(a.code!==\"EISDIR\")throw a}):e.mkdirAsync(t,e).then(()=>r||t,a=>{if(a.code===\"ENOENT\")return I_(o,e).then(n=>I_(t,e,n));if(a.code!==\"EEXIST\"&&a.code!==\"EROFS\")throw a;return e.statAsync(t).then(n=>{if(n.isDirectory())return r;throw a},()=>{throw a})})},w_=(t,e,r)=>{let o=Qfe(t);if(e.recursive=!1,o===t)try{return e.mkdirSync(t,e)}catch(a){if(a.code!==\"EISDIR\")throw a;return}try{return e.mkdirSync(t,e),r||t}catch(a){if(a.code===\"ENOENT\")return w_(t,e,w_(o,e,r));if(a.code!==\"EEXIST\"&&a.code!==\"EROFS\")throw a;try{if(!e.statSync(t).isDirectory())throw a}catch{throw a}}};Ffe.exports={mkdirpManual:I_,mkdirpManualSync:w_}});var Lfe=_(($4t,Tfe)=>{var{dirname:Rfe}=ve(\"path\"),{findMade:Ylt,findMadeSync:Klt}=kfe(),{mkdirpManual:Vlt,mkdirpManualSync:zlt}=B_(),Jlt=(t,e)=>(e.recursive=!0,Rfe(t)===t?e.mkdirAsync(t,e):Ylt(e,t).then(o=>e.mkdirAsync(t,e).then(()=>o).catch(a=>{if(a.code===\"ENOENT\")return Vlt(t,e);throw a}))),Xlt=(t,e)=>{if(e.recursive=!0,Rfe(t)===t)return e.mkdirSync(t,e);let o=Klt(e,t);try{return e.mkdirSync(t,e),o}catch(a){if(a.code===\"ENOENT\")return zlt(t,e);throw a}};Tfe.exports={mkdirpNative:Jlt,mkdirpNativeSync:Xlt}});var Ufe=_((eUt,Mfe)=>{var Nfe=ve(\"fs\"),Zlt=process.version,v_=Zlt.replace(/^v/,\"\").split(\".\"),Ofe=+v_[0]>10||+v_[0]==10&&+v_[1]>=12,$lt=Ofe?t=>t.mkdir===Nfe.mkdir:()=>!1,ect=Ofe?t=>t.mkdirSync===Nfe.mkdirSync:()=>!1;Mfe.exports={useNative:$lt,useNativeSync:ect}});var Wfe=_((tUt,Gfe)=>{var Xy=Bfe(),Zy=Dfe(),{mkdirpNative:_fe,mkdirpNativeSync:Hfe}=Lfe(),{mkdirpManual:qfe,mkdirpManualSync:jfe}=B_(),{useNative:tct,useNativeSync:rct}=Ufe(),$y=(t,e)=>(t=Zy(t),e=Xy(e),tct(e)?_fe(t,e):qfe(t,e)),nct=(t,e)=>(t=Zy(t),e=Xy(e),rct(e)?Hfe(t,e):jfe(t,e));$y.sync=nct;$y.native=(t,e)=>_fe(Zy(t),Xy(e));$y.manual=(t,e)=>qfe(Zy(t),Xy(e));$y.nativeSync=(t,e)=>Hfe(Zy(t),Xy(e));$y.manualSync=(t,e)=>jfe(Zy(t),Xy(e));Gfe.exports=$y});var Zfe=_((rUt,Xfe)=>{\"use strict\";var tc=ve(\"fs\"),Gg=ve(\"path\"),ict=tc.lchown?\"lchown\":\"chown\",sct=tc.lchownSync?\"lchownSync\":\"chownSync\",Kfe=tc.lchown&&!process.version.match(/v1[1-9]+\\./)&&!process.version.match(/v10\\.[6-9]/),Yfe=(t,e,r)=>{try{return tc[sct](t,e,r)}catch(o){if(o.code!==\"ENOENT\")throw o}},oct=(t,e,r)=>{try{return tc.chownSync(t,e,r)}catch(o){if(o.code!==\"ENOENT\")throw o}},act=Kfe?(t,e,r,o)=>a=>{!a||a.code!==\"EISDIR\"?o(a):tc.chown(t,e,r,o)}:(t,e,r,o)=>o,D_=Kfe?(t,e,r)=>{try{return Yfe(t,e,r)}catch(o){if(o.code!==\"EISDIR\")throw o;oct(t,e,r)}}:(t,e,r)=>Yfe(t,e,r),lct=process.version,Vfe=(t,e,r)=>tc.readdir(t,e,r),cct=(t,e)=>tc.readdirSync(t,e);/^v4\\./.test(lct)&&(Vfe=(t,e,r)=>tc.readdir(t,r));var gk=(t,e,r,o)=>{tc[ict](t,e,r,act(t,e,r,a=>{o(a&&a.code!==\"ENOENT\"?a:null)}))},zfe=(t,e,r,o,a)=>{if(typeof e==\"string\")return tc.lstat(Gg.resolve(t,e),(n,u)=>{if(n)return a(n.code!==\"ENOENT\"?n:null);u.name=e,zfe(t,u,r,o,a)});if(e.isDirectory())P_(Gg.resolve(t,e.name),r,o,n=>{if(n)return a(n);let u=Gg.resolve(t,e.name);gk(u,r,o,a)});else{let n=Gg.resolve(t,e.name);gk(n,r,o,a)}},P_=(t,e,r,o)=>{Vfe(t,{withFileTypes:!0},(a,n)=>{if(a){if(a.code===\"ENOENT\")return o();if(a.code!==\"ENOTDIR\"&&a.code!==\"ENOTSUP\")return o(a)}if(a||!n.length)return gk(t,e,r,o);let u=n.length,A=null,p=h=>{if(!A){if(h)return o(A=h);if(--u===0)return gk(t,e,r,o)}};n.forEach(h=>zfe(t,h,e,r,p))})},uct=(t,e,r,o)=>{if(typeof e==\"string\")try{let a=tc.lstatSync(Gg.resolve(t,e));a.name=e,e=a}catch(a){if(a.code===\"ENOENT\")return;throw a}e.isDirectory()&&Jfe(Gg.resolve(t,e.name),r,o),D_(Gg.resolve(t,e.name),r,o)},Jfe=(t,e,r)=>{let o;try{o=cct(t,{withFileTypes:!0})}catch(a){if(a.code===\"ENOENT\")return;if(a.code===\"ENOTDIR\"||a.code===\"ENOTSUP\")return D_(t,e,r);throw a}return o&&o.length&&o.forEach(a=>uct(t,a,e,r)),D_(t,e,r)};Xfe.exports=P_;P_.sync=Jfe});var rpe=_((nUt,S_)=>{\"use strict\";var $fe=Wfe(),rc=ve(\"fs\"),dk=ve(\"path\"),epe=Zfe(),$c=Oy(),mk=class extends Error{constructor(e,r){super(\"Cannot extract through symbolic link\"),this.path=r,this.symlink=e}get name(){return\"SylinkError\"}},yk=class extends Error{constructor(e,r){super(r+\": Cannot cd into '\"+e+\"'\"),this.path=e,this.code=r}get name(){return\"CwdError\"}},Ek=(t,e)=>t.get($c(e)),g2=(t,e,r)=>t.set($c(e),r),Act=(t,e)=>{rc.stat(t,(r,o)=>{(r||!o.isDirectory())&&(r=new yk(t,r&&r.code||\"ENOTDIR\")),e(r)})};S_.exports=(t,e,r)=>{t=$c(t);let o=e.umask,a=e.mode|448,n=(a&o)!==0,u=e.uid,A=e.gid,p=typeof u==\"number\"&&typeof A==\"number\"&&(u!==e.processUid||A!==e.processGid),h=e.preserve,E=e.unlink,w=e.cache,D=$c(e.cwd),b=(N,U)=>{N?r(N):(g2(w,t,!0),U&&p?epe(U,u,A,z=>b(z)):n?rc.chmod(t,a,r):r())};if(w&&Ek(w,t)===!0)return b();if(t===D)return Act(t,b);if(h)return $fe(t,{mode:a}).then(N=>b(null,N),b);let T=$c(dk.relative(D,t)).split(\"/\");Ck(D,T,a,w,E,D,null,b)};var Ck=(t,e,r,o,a,n,u,A)=>{if(!e.length)return A(null,u);let p=e.shift(),h=$c(dk.resolve(t+\"/\"+p));if(Ek(o,h))return Ck(h,e,r,o,a,n,u,A);rc.mkdir(h,r,tpe(h,e,r,o,a,n,u,A))},tpe=(t,e,r,o,a,n,u,A)=>p=>{p?rc.lstat(t,(h,E)=>{if(h)h.path=h.path&&$c(h.path),A(h);else if(E.isDirectory())Ck(t,e,r,o,a,n,u,A);else if(a)rc.unlink(t,w=>{if(w)return A(w);rc.mkdir(t,r,tpe(t,e,r,o,a,n,u,A))});else{if(E.isSymbolicLink())return A(new mk(t,t+\"/\"+e.join(\"/\")));A(p)}}):(u=u||t,Ck(t,e,r,o,a,n,u,A))},fct=t=>{let e=!1,r=\"ENOTDIR\";try{e=rc.statSync(t).isDirectory()}catch(o){r=o.code}finally{if(!e)throw new yk(t,r)}};S_.exports.sync=(t,e)=>{t=$c(t);let r=e.umask,o=e.mode|448,a=(o&r)!==0,n=e.uid,u=e.gid,A=typeof n==\"number\"&&typeof u==\"number\"&&(n!==e.processUid||u!==e.processGid),p=e.preserve,h=e.unlink,E=e.cache,w=$c(e.cwd),D=N=>{g2(E,t,!0),N&&A&&epe.sync(N,n,u),a&&rc.chmodSync(t,o)};if(E&&Ek(E,t)===!0)return D();if(t===w)return fct(w),D();if(p)return D($fe.sync(t,o));let C=$c(dk.relative(w,t)).split(\"/\"),T=null;for(let N=C.shift(),U=w;N&&(U+=\"/\"+N);N=C.shift())if(U=$c(dk.resolve(U)),!Ek(E,U))try{rc.mkdirSync(U,o),T=T||U,g2(E,U,!0)}catch{let te=rc.lstatSync(U);if(te.isDirectory()){g2(E,U,!0);continue}else if(h){rc.unlinkSync(U),rc.mkdirSync(U,o),T=T||U,g2(E,U,!0);continue}else if(te.isSymbolicLink())return new mk(U,U+\"/\"+C.join(\"/\"))}return D(T)}});var b_=_((iUt,npe)=>{var x_=Object.create(null),{hasOwnProperty:pct}=Object.prototype;npe.exports=t=>(pct.call(x_,t)||(x_[t]=t.normalize(\"NFKD\")),x_[t])});var ape=_((sUt,ope)=>{var ipe=ve(\"assert\"),hct=b_(),gct=_y(),{join:spe}=ve(\"path\"),dct=process.env.TESTING_TAR_FAKE_PLATFORM||process.platform,mct=dct===\"win32\";ope.exports=()=>{let t=new Map,e=new Map,r=h=>h.split(\"/\").slice(0,-1).reduce((w,D)=>(w.length&&(D=spe(w[w.length-1],D)),w.push(D||\"/\"),w),[]),o=new Set,a=h=>{let E=e.get(h);if(!E)throw new Error(\"function does not have any path reservations\");return{paths:E.paths.map(w=>t.get(w)),dirs:[...E.dirs].map(w=>t.get(w))}},n=h=>{let{paths:E,dirs:w}=a(h);return E.every(D=>D[0]===h)&&w.every(D=>D[0]instanceof Set&&D[0].has(h))},u=h=>o.has(h)||!n(h)?!1:(o.add(h),h(()=>A(h)),!0),A=h=>{if(!o.has(h))return!1;let{paths:E,dirs:w}=e.get(h),D=new Set;return E.forEach(b=>{let C=t.get(b);ipe.equal(C[0],h),C.length===1?t.delete(b):(C.shift(),typeof C[0]==\"function\"?D.add(C[0]):C[0].forEach(T=>D.add(T)))}),w.forEach(b=>{let C=t.get(b);ipe(C[0]instanceof Set),C[0].size===1&&C.length===1?t.delete(b):C[0].size===1?(C.shift(),D.add(C[0])):C[0].delete(h)}),o.delete(h),D.forEach(b=>u(b)),!0};return{check:n,reserve:(h,E)=>{h=mct?[\"win32 parallelization disabled\"]:h.map(D=>hct(gct(spe(D))).toLowerCase());let w=new Set(h.map(D=>r(D)).reduce((D,b)=>D.concat(b)));return e.set(E,{dirs:w,paths:h}),h.forEach(D=>{let b=t.get(D);b?b.push(E):t.set(D,[E])}),w.forEach(D=>{let b=t.get(D);b?b[b.length-1]instanceof Set?b[b.length-1].add(E):b.push(new Set([E])):t.set(D,[new Set([E])])}),u(E)}}}});var upe=_((oUt,cpe)=>{var yct=process.platform,Ect=yct===\"win32\",Cct=global.__FAKE_TESTING_FS__||ve(\"fs\"),{O_CREAT:Ict,O_TRUNC:wct,O_WRONLY:Bct,UV_FS_O_FILEMAP:lpe=0}=Cct.constants,vct=Ect&&!!lpe,Dct=512*1024,Pct=lpe|wct|Ict|Bct;cpe.exports=vct?t=>t<Dct?Pct:\"w\":()=>\"w\"});var M_=_((aUt,vpe)=>{\"use strict\";var Sct=ve(\"assert\"),xct=fk(),Fn=ve(\"fs\"),bct=zy(),Gf=ve(\"path\"),Ipe=rpe(),Ape=M3(),kct=ape(),Qct=U3(),ml=Oy(),Fct=_y(),Rct=b_(),fpe=Symbol(\"onEntry\"),F_=Symbol(\"checkFs\"),ppe=Symbol(\"checkFs2\"),Bk=Symbol(\"pruneCache\"),R_=Symbol(\"isReusable\"),nc=Symbol(\"makeFs\"),T_=Symbol(\"file\"),L_=Symbol(\"directory\"),vk=Symbol(\"link\"),hpe=Symbol(\"symlink\"),gpe=Symbol(\"hardlink\"),dpe=Symbol(\"unsupported\"),mpe=Symbol(\"checkPath\"),xh=Symbol(\"mkdir\"),So=Symbol(\"onError\"),Ik=Symbol(\"pending\"),ype=Symbol(\"pend\"),eE=Symbol(\"unpend\"),k_=Symbol(\"ended\"),Q_=Symbol(\"maybeClose\"),N_=Symbol(\"skip\"),d2=Symbol(\"doChown\"),m2=Symbol(\"uid\"),y2=Symbol(\"gid\"),E2=Symbol(\"checkedCwd\"),wpe=ve(\"crypto\"),Bpe=upe(),Tct=process.env.TESTING_TAR_FAKE_PLATFORM||process.platform,C2=Tct===\"win32\",Lct=(t,e)=>{if(!C2)return Fn.unlink(t,e);let r=t+\".DELETE.\"+wpe.randomBytes(16).toString(\"hex\");Fn.rename(t,r,o=>{if(o)return e(o);Fn.unlink(r,e)})},Nct=t=>{if(!C2)return Fn.unlinkSync(t);let e=t+\".DELETE.\"+wpe.randomBytes(16).toString(\"hex\");Fn.renameSync(t,e),Fn.unlinkSync(e)},Epe=(t,e,r)=>t===t>>>0?t:e===e>>>0?e:r,Cpe=t=>Rct(Fct(ml(t))).toLowerCase(),Oct=(t,e)=>{e=Cpe(e);for(let r of t.keys()){let o=Cpe(r);(o===e||o.indexOf(e+\"/\")===0)&&t.delete(r)}},Mct=t=>{for(let e of t.keys())t.delete(e)},I2=class extends xct{constructor(e){if(e||(e={}),e.ondone=r=>{this[k_]=!0,this[Q_]()},super(e),this[E2]=!1,this.reservations=kct(),this.transform=typeof e.transform==\"function\"?e.transform:null,this.writable=!0,this.readable=!1,this[Ik]=0,this[k_]=!1,this.dirCache=e.dirCache||new Map,typeof e.uid==\"number\"||typeof e.gid==\"number\"){if(typeof e.uid!=\"number\"||typeof e.gid!=\"number\")throw new TypeError(\"cannot set owner without number uid and gid\");if(e.preserveOwner)throw new TypeError(\"cannot preserve owner in archive and also set owner explicitly\");this.uid=e.uid,this.gid=e.gid,this.setOwner=!0}else this.uid=null,this.gid=null,this.setOwner=!1;e.preserveOwner===void 0&&typeof e.uid!=\"number\"?this.preserveOwner=process.getuid&&process.getuid()===0:this.preserveOwner=!!e.preserveOwner,this.processUid=(this.preserveOwner||this.setOwner)&&process.getuid?process.getuid():null,this.processGid=(this.preserveOwner||this.setOwner)&&process.getgid?process.getgid():null,this.forceChown=e.forceChown===!0,this.win32=!!e.win32||C2,this.newer=!!e.newer,this.keep=!!e.keep,this.noMtime=!!e.noMtime,this.preservePaths=!!e.preservePaths,this.unlink=!!e.unlink,this.cwd=ml(Gf.resolve(e.cwd||process.cwd())),this.strip=+e.strip||0,this.processUmask=e.noChmod?0:process.umask(),this.umask=typeof e.umask==\"number\"?e.umask:this.processUmask,this.dmode=e.dmode||511&~this.umask,this.fmode=e.fmode||438&~this.umask,this.on(\"entry\",r=>this[fpe](r))}warn(e,r,o={}){return(e===\"TAR_BAD_ARCHIVE\"||e===\"TAR_ABORT\")&&(o.recoverable=!1),super.warn(e,r,o)}[Q_](){this[k_]&&this[Ik]===0&&(this.emit(\"prefinish\"),this.emit(\"finish\"),this.emit(\"end\"),this.emit(\"close\"))}[mpe](e){if(this.strip){let r=ml(e.path).split(\"/\");if(r.length<this.strip)return!1;if(e.path=r.slice(this.strip).join(\"/\"),e.type===\"Link\"){let o=ml(e.linkpath).split(\"/\");if(o.length>=this.strip)e.linkpath=o.slice(this.strip).join(\"/\");else return!1}}if(!this.preservePaths){let r=ml(e.path),o=r.split(\"/\");if(o.includes(\"..\")||C2&&/^[a-z]:\\.\\.$/i.test(o[0]))return this.warn(\"TAR_ENTRY_ERROR\",\"path contains '..'\",{entry:e,path:r}),!1;let[a,n]=Qct(r);a&&(e.path=n,this.warn(\"TAR_ENTRY_INFO\",`stripping ${a} from absolute path`,{entry:e,path:r}))}if(Gf.isAbsolute(e.path)?e.absolute=ml(Gf.resolve(e.path)):e.absolute=ml(Gf.resolve(this.cwd,e.path)),!this.preservePaths&&e.absolute.indexOf(this.cwd+\"/\")!==0&&e.absolute!==this.cwd)return this.warn(\"TAR_ENTRY_ERROR\",\"path escaped extraction target\",{entry:e,path:ml(e.path),resolvedPath:e.absolute,cwd:this.cwd}),!1;if(e.absolute===this.cwd&&e.type!==\"Directory\"&&e.type!==\"GNUDumpDir\")return!1;if(this.win32){let{root:r}=Gf.win32.parse(e.absolute);e.absolute=r+Ape.encode(e.absolute.substr(r.length));let{root:o}=Gf.win32.parse(e.path);e.path=o+Ape.encode(e.path.substr(o.length))}return!0}[fpe](e){if(!this[mpe](e))return e.resume();switch(Sct.equal(typeof e.absolute,\"string\"),e.type){case\"Directory\":case\"GNUDumpDir\":e.mode&&(e.mode=e.mode|448);case\"File\":case\"OldFile\":case\"ContiguousFile\":case\"Link\":case\"SymbolicLink\":return this[F_](e);case\"CharacterDevice\":case\"BlockDevice\":case\"FIFO\":default:return this[dpe](e)}}[So](e,r){e.name===\"CwdError\"?this.emit(\"error\",e):(this.warn(\"TAR_ENTRY_ERROR\",e,{entry:r}),this[eE](),r.resume())}[xh](e,r,o){Ipe(ml(e),{uid:this.uid,gid:this.gid,processUid:this.processUid,processGid:this.processGid,umask:this.processUmask,preserve:this.preservePaths,unlink:this.unlink,cache:this.dirCache,cwd:this.cwd,mode:r,noChmod:this.noChmod},o)}[d2](e){return this.forceChown||this.preserveOwner&&(typeof e.uid==\"number\"&&e.uid!==this.processUid||typeof e.gid==\"number\"&&e.gid!==this.processGid)||typeof this.uid==\"number\"&&this.uid!==this.processUid||typeof this.gid==\"number\"&&this.gid!==this.processGid}[m2](e){return Epe(this.uid,e.uid,this.processUid)}[y2](e){return Epe(this.gid,e.gid,this.processGid)}[T_](e,r){let o=e.mode&4095||this.fmode,a=new bct.WriteStream(e.absolute,{flags:Bpe(e.size),mode:o,autoClose:!1});a.on(\"error\",p=>{a.fd&&Fn.close(a.fd,()=>{}),a.write=()=>!0,this[So](p,e),r()});let n=1,u=p=>{if(p){a.fd&&Fn.close(a.fd,()=>{}),this[So](p,e),r();return}--n===0&&Fn.close(a.fd,h=>{h?this[So](h,e):this[eE](),r()})};a.on(\"finish\",p=>{let h=e.absolute,E=a.fd;if(e.mtime&&!this.noMtime){n++;let w=e.atime||new Date,D=e.mtime;Fn.futimes(E,w,D,b=>b?Fn.utimes(h,w,D,C=>u(C&&b)):u())}if(this[d2](e)){n++;let w=this[m2](e),D=this[y2](e);Fn.fchown(E,w,D,b=>b?Fn.chown(h,w,D,C=>u(C&&b)):u())}u()});let A=this.transform&&this.transform(e)||e;A!==e&&(A.on(\"error\",p=>{this[So](p,e),r()}),e.pipe(A)),A.pipe(a)}[L_](e,r){let o=e.mode&4095||this.dmode;this[xh](e.absolute,o,a=>{if(a){this[So](a,e),r();return}let n=1,u=A=>{--n===0&&(r(),this[eE](),e.resume())};e.mtime&&!this.noMtime&&(n++,Fn.utimes(e.absolute,e.atime||new Date,e.mtime,u)),this[d2](e)&&(n++,Fn.chown(e.absolute,this[m2](e),this[y2](e),u)),u()})}[dpe](e){e.unsupported=!0,this.warn(\"TAR_ENTRY_UNSUPPORTED\",`unsupported entry type: ${e.type}`,{entry:e}),e.resume()}[hpe](e,r){this[vk](e,e.linkpath,\"symlink\",r)}[gpe](e,r){let o=ml(Gf.resolve(this.cwd,e.linkpath));this[vk](e,o,\"link\",r)}[ype](){this[Ik]++}[eE](){this[Ik]--,this[Q_]()}[N_](e){this[eE](),e.resume()}[R_](e,r){return e.type===\"File\"&&!this.unlink&&r.isFile()&&r.nlink<=1&&!C2}[F_](e){this[ype]();let r=[e.path];e.linkpath&&r.push(e.linkpath),this.reservations.reserve(r,o=>this[ppe](e,o))}[Bk](e){e.type===\"SymbolicLink\"?Mct(this.dirCache):e.type!==\"Directory\"&&Oct(this.dirCache,e.absolute)}[ppe](e,r){this[Bk](e);let o=A=>{this[Bk](e),r(A)},a=()=>{this[xh](this.cwd,this.dmode,A=>{if(A){this[So](A,e),o();return}this[E2]=!0,n()})},n=()=>{if(e.absolute!==this.cwd){let A=ml(Gf.dirname(e.absolute));if(A!==this.cwd)return this[xh](A,this.dmode,p=>{if(p){this[So](p,e),o();return}u()})}u()},u=()=>{Fn.lstat(e.absolute,(A,p)=>{if(p&&(this.keep||this.newer&&p.mtime>e.mtime)){this[N_](e),o();return}if(A||this[R_](e,p))return this[nc](null,e,o);if(p.isDirectory()){if(e.type===\"Directory\"){let h=!this.noChmod&&e.mode&&(p.mode&4095)!==e.mode,E=w=>this[nc](w,e,o);return h?Fn.chmod(e.absolute,e.mode,E):E()}if(e.absolute!==this.cwd)return Fn.rmdir(e.absolute,h=>this[nc](h,e,o))}if(e.absolute===this.cwd)return this[nc](null,e,o);Lct(e.absolute,h=>this[nc](h,e,o))})};this[E2]?n():a()}[nc](e,r,o){if(e){this[So](e,r),o();return}switch(r.type){case\"File\":case\"OldFile\":case\"ContiguousFile\":return this[T_](r,o);case\"Link\":return this[gpe](r,o);case\"SymbolicLink\":return this[hpe](r,o);case\"Directory\":case\"GNUDumpDir\":return this[L_](r,o)}}[vk](e,r,o,a){Fn[o](r,e.absolute,n=>{n?this[So](n,e):(this[eE](),e.resume()),a()})}},wk=t=>{try{return[null,t()]}catch(e){return[e,null]}},O_=class extends I2{[nc](e,r){return super[nc](e,r,()=>{})}[F_](e){if(this[Bk](e),!this[E2]){let n=this[xh](this.cwd,this.dmode);if(n)return this[So](n,e);this[E2]=!0}if(e.absolute!==this.cwd){let n=ml(Gf.dirname(e.absolute));if(n!==this.cwd){let u=this[xh](n,this.dmode);if(u)return this[So](u,e)}}let[r,o]=wk(()=>Fn.lstatSync(e.absolute));if(o&&(this.keep||this.newer&&o.mtime>e.mtime))return this[N_](e);if(r||this[R_](e,o))return this[nc](null,e);if(o.isDirectory()){if(e.type===\"Directory\"){let u=!this.noChmod&&e.mode&&(o.mode&4095)!==e.mode,[A]=u?wk(()=>{Fn.chmodSync(e.absolute,e.mode)}):[];return this[nc](A,e)}let[n]=wk(()=>Fn.rmdirSync(e.absolute));this[nc](n,e)}let[a]=e.absolute===this.cwd?[]:wk(()=>Nct(e.absolute));this[nc](a,e)}[T_](e,r){let o=e.mode&4095||this.fmode,a=A=>{let p;try{Fn.closeSync(n)}catch(h){p=h}(A||p)&&this[So](A||p,e),r()},n;try{n=Fn.openSync(e.absolute,Bpe(e.size),o)}catch(A){return a(A)}let u=this.transform&&this.transform(e)||e;u!==e&&(u.on(\"error\",A=>this[So](A,e)),e.pipe(u)),u.on(\"data\",A=>{try{Fn.writeSync(n,A,0,A.length)}catch(p){a(p)}}),u.on(\"end\",A=>{let p=null;if(e.mtime&&!this.noMtime){let h=e.atime||new Date,E=e.mtime;try{Fn.futimesSync(n,h,E)}catch(w){try{Fn.utimesSync(e.absolute,h,E)}catch{p=w}}}if(this[d2](e)){let h=this[m2](e),E=this[y2](e);try{Fn.fchownSync(n,h,E)}catch(w){try{Fn.chownSync(e.absolute,h,E)}catch{p=p||w}}}a(p)})}[L_](e,r){let o=e.mode&4095||this.dmode,a=this[xh](e.absolute,o);if(a){this[So](a,e),r();return}if(e.mtime&&!this.noMtime)try{Fn.utimesSync(e.absolute,e.atime||new Date,e.mtime)}catch{}if(this[d2](e))try{Fn.chownSync(e.absolute,this[m2](e),this[y2](e))}catch{}r(),e.resume()}[xh](e,r){try{return Ipe.sync(ml(e),{uid:this.uid,gid:this.gid,processUid:this.processUid,processGid:this.processGid,umask:this.processUmask,preserve:this.preservePaths,unlink:this.unlink,cache:this.dirCache,cwd:this.cwd,mode:r})}catch(o){return o}}[vk](e,r,o,a){try{Fn[o+\"Sync\"](r,e.absolute),a(),e.resume()}catch(n){return this[So](n,e)}}};I2.Sync=O_;vpe.exports=I2});var bpe=_((lUt,xpe)=>{\"use strict\";var Uct=Fy(),Dk=M_(),Ppe=ve(\"fs\"),Spe=zy(),Dpe=ve(\"path\"),U_=_y();xpe.exports=(t,e,r)=>{typeof t==\"function\"?(r=t,e=null,t={}):Array.isArray(t)&&(e=t,t={}),typeof e==\"function\"&&(r=e,e=null),e?e=Array.from(e):e=[];let o=Uct(t);if(o.sync&&typeof r==\"function\")throw new TypeError(\"callback not supported for sync tar functions\");if(!o.file&&typeof r==\"function\")throw new TypeError(\"callback only supported with file option\");return e.length&&_ct(o,e),o.file&&o.sync?Hct(o):o.file?qct(o,r):o.sync?jct(o):Gct(o)};var _ct=(t,e)=>{let r=new Map(e.map(n=>[U_(n),!0])),o=t.filter,a=(n,u)=>{let A=u||Dpe.parse(n).root||\".\",p=n===A?!1:r.has(n)?r.get(n):a(Dpe.dirname(n),A);return r.set(n,p),p};t.filter=o?(n,u)=>o(n,u)&&a(U_(n)):n=>a(U_(n))},Hct=t=>{let e=new Dk.Sync(t),r=t.file,o=Ppe.statSync(r),a=t.maxReadSize||16*1024*1024;new Spe.ReadStreamSync(r,{readSize:a,size:o.size}).pipe(e)},qct=(t,e)=>{let r=new Dk(t),o=t.maxReadSize||16*1024*1024,a=t.file,n=new Promise((u,A)=>{r.on(\"error\",A),r.on(\"close\",u),Ppe.stat(a,(p,h)=>{if(p)A(p);else{let E=new Spe.ReadStream(a,{readSize:o,size:h.size});E.on(\"error\",A),E.pipe(r)}})});return e?n.then(e,e):n},jct=t=>new Dk.Sync(t),Gct=t=>new Dk(t)});var kpe=_(us=>{\"use strict\";us.c=us.create=Afe();us.r=us.replace=C_();us.t=us.list=pk();us.u=us.update=Cfe();us.x=us.extract=bpe();us.Pack=Zb();us.Unpack=M_();us.Parse=fk();us.ReadEntry=Lb();us.WriteEntry=z3();us.Header=Uy();us.Pax=Ob();us.types=Q3()});var __,Qpe,bh,w2,B2,Fpe=It(()=>{__=et(lg()),Qpe=ve(\"worker_threads\"),bh=Symbol(\"kTaskInfo\"),w2=class{constructor(e,r){this.fn=e;this.limit=(0,__.default)(r.poolSize)}run(e){return this.limit(()=>this.fn(e))}},B2=class{constructor(e,r){this.source=e;this.workers=[];this.limit=(0,__.default)(r.poolSize),this.cleanupInterval=setInterval(()=>{if(this.limit.pendingCount===0&&this.limit.activeCount===0){let o=this.workers.pop();o?o.terminate():clearInterval(this.cleanupInterval)}},5e3).unref()}createWorker(){this.cleanupInterval.refresh();let e=new Qpe.Worker(this.source,{eval:!0,execArgv:[...process.execArgv,\"--unhandled-rejections=strict\"]});return e.on(\"message\",r=>{if(!e[bh])throw new Error(\"Assertion failed: Worker sent a result without having a task assigned\");e[bh].resolve(r),e[bh]=null,e.unref(),this.workers.push(e)}),e.on(\"error\",r=>{e[bh]?.reject(r),e[bh]=null}),e.on(\"exit\",r=>{r!==0&&e[bh]?.reject(new Error(`Worker exited with code ${r}`)),e[bh]=null}),e}run(e){return this.limit(()=>{let r=this.workers.pop()??this.createWorker();return r.ref(),new Promise((o,a)=>{r[bh]={resolve:o,reject:a},r.postMessage(e)})})}}});var Tpe=_((fUt,Rpe)=>{var H_;Rpe.exports.getContent=()=>(typeof H_>\"u\"&&(H_=ve(\"zlib\").brotliDecompressSync(Buffer.from(\"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\",\"base64\")).toString()),H_)});var $i={};Kt($i,{convertToZip:()=>Vct,convertToZipWorker:()=>G_,extractArchiveTo:()=>Upe,getDefaultTaskPool:()=>Ope,getTaskPoolForConfiguration:()=>Mpe,makeArchiveFromDirectory:()=>Kct});function Wct(t,e){switch(t){case\"async\":return new w2(G_,{poolSize:e});case\"workers\":return new B2((0,j_.getContent)(),{poolSize:e});default:throw new Error(`Assertion failed: Unknown value ${t} for taskPoolMode`)}}function Ope(){return typeof q_>\"u\"&&(q_=Wct(\"workers\",Xi.availableParallelism())),q_}function Mpe(t){return typeof t>\"u\"?Ope():Al(Yct,t,()=>{let e=t.get(\"taskPoolMode\"),r=t.get(\"taskPoolConcurrency\");switch(e){case\"async\":return new w2(G_,{poolSize:r});case\"workers\":return new B2((0,j_.getContent)(),{poolSize:r});default:throw new Error(`Assertion failed: Unknown value ${e} for taskPoolMode`)}})}async function G_(t){let{tmpFile:e,tgz:r,compressionLevel:o,extractBufferOpts:a}=t,n=new Zi(e,{create:!0,level:o,stats:wa.makeDefaultStats()}),u=Buffer.from(r.buffer,r.byteOffset,r.byteLength);return await Upe(u,n,a),n.saveAndClose(),e}async function Kct(t,{baseFs:e=new _n,prefixPath:r=Bt.root,compressionLevel:o,inMemory:a=!1}={}){let n;if(a)n=new Zi(null,{level:o});else{let A=await ae.mktempPromise(),p=K.join(A,\"archive.zip\");n=new Zi(p,{create:!0,level:o})}let u=K.resolve(Bt.root,r);return await n.copyPromise(u,t,{baseFs:e,stableTime:!0,stableSort:!0}),n}async function Vct(t,e={}){let r=await ae.mktempPromise(),o=K.join(r,\"archive.zip\"),a=e.compressionLevel??e.configuration?.get(\"compressionLevel\")??\"mixed\",n={prefixPath:e.prefixPath,stripComponents:e.stripComponents};return await(e.taskPool??Mpe(e.configuration)).run({tmpFile:o,tgz:t,compressionLevel:a,extractBufferOpts:n}),new Zi(o,{level:e.compressionLevel})}async function*zct(t){let e=new Npe.default.Parse,r=new Lpe.PassThrough({objectMode:!0,autoDestroy:!0,emitClose:!0});e.on(\"entry\",o=>{r.write(o)}),e.on(\"error\",o=>{r.destroy(o)}),e.on(\"close\",()=>{r.destroyed||r.end()}),e.end(t);for await(let o of r){let a=o;yield a,a.resume()}}async function Upe(t,e,{stripComponents:r=0,prefixPath:o=Bt.dot}={}){function a(n){if(n.path[0]===\"/\")return!0;let u=n.path.split(/\\//g);return!!(u.some(A=>A===\"..\")||u.length<=r)}for await(let n of zct(t)){if(a(n))continue;let u=K.normalize(Ae.toPortablePath(n.path)).replace(/\\/$/,\"\").split(/\\//g);if(u.length<=r)continue;let A=u.slice(r).join(\"/\"),p=K.join(o,A),h=420;switch((n.type===\"Directory\"||(n.mode??0)&73)&&(h|=73),n.type){case\"Directory\":e.mkdirpSync(K.dirname(p),{chmod:493,utimes:[Pi.SAFE_TIME,Pi.SAFE_TIME]}),e.mkdirSync(p,{mode:h}),e.utimesSync(p,Pi.SAFE_TIME,Pi.SAFE_TIME);break;case\"OldFile\":case\"File\":e.mkdirpSync(K.dirname(p),{chmod:493,utimes:[Pi.SAFE_TIME,Pi.SAFE_TIME]}),e.writeFileSync(p,await Xm(n),{mode:h}),e.utimesSync(p,Pi.SAFE_TIME,Pi.SAFE_TIME);break;case\"SymbolicLink\":e.mkdirpSync(K.dirname(p),{chmod:493,utimes:[Pi.SAFE_TIME,Pi.SAFE_TIME]}),e.symlinkSync(n.linkpath,p),e.lutimesSync(p,Pi.SAFE_TIME,Pi.SAFE_TIME);break}}return e}var Lpe,Npe,j_,q_,Yct,_pe=It(()=>{Ke();Pt();sA();Lpe=ve(\"stream\"),Npe=et(kpe());Fpe();Gl();j_=et(Tpe());Yct=new WeakMap});var qpe=_((W_,Hpe)=>{(function(t,e){typeof W_==\"object\"?Hpe.exports=e():typeof define==\"function\"&&define.amd?define(e):t.treeify=e()})(W_,function(){function t(a,n){var u=n?\"\\u2514\":\"\\u251C\";return a?u+=\"\\u2500 \":u+=\"\\u2500\\u2500\\u2510\",u}function e(a,n){var u=[];for(var A in a)a.hasOwnProperty(A)&&(n&&typeof a[A]==\"function\"||u.push(A));return u}function r(a,n,u,A,p,h,E){var w=\"\",D=0,b,C,T=A.slice(0);if(T.push([n,u])&&A.length>0&&(A.forEach(function(U,z){z>0&&(w+=(U[1]?\" \":\"\\u2502\")+\"  \"),!C&&U[0]===n&&(C=!0)}),w+=t(a,u)+a,p&&(typeof n!=\"object\"||n instanceof Date)&&(w+=\": \"+n),C&&(w+=\" (circular ref.)\"),E(w)),!C&&typeof n==\"object\"){var N=e(n,h);N.forEach(function(U){b=++D===N.length,r(U,n[U],b,T,p,h,E)})}}var o={};return o.asLines=function(a,n,u,A){var p=typeof u!=\"function\"?u:!1;r(\".\",a,!1,[],n,p,A||u)},o.asTree=function(a,n,u){var A=\"\";return r(\".\",a,!1,[],n,u,function(p){A+=p+`\n`}),A},o})});var As={};Kt(As,{emitList:()=>Jct,emitTree:()=>Ype,treeNodeToJson:()=>Wpe,treeNodeToTreeify:()=>Gpe});function Gpe(t,{configuration:e}){let r={},o=0,a=(n,u)=>{let A=Array.isArray(n)?n.entries():Object.entries(n);for(let[p,h]of A){if(!h)continue;let{label:E,value:w,children:D}=h,b=[];typeof E<\"u\"&&b.push(Cg(e,E,2)),typeof w<\"u\"&&b.push(Ut(e,w[0],w[1])),b.length===0&&b.push(Cg(e,`${p}`,2));let C=b.join(\": \").trim(),T=`\\0${o++}\\0`,N=u[`${T}${C}`]={};typeof D<\"u\"&&a(D,N)}};if(typeof t.children>\"u\")throw new Error(\"The root node must only contain children\");return a(t.children,r),r}function Wpe(t){let e=r=>{if(typeof r.children>\"u\"){if(typeof r.value>\"u\")throw new Error(\"Assertion failed: Expected a value to be set if the children are missing\");return Ig(r.value[0],r.value[1])}let o=Array.isArray(r.children)?r.children.entries():Object.entries(r.children??{}),a=Array.isArray(r.children)?[]:{};for(let[n,u]of o)u&&(a[Xct(n)]=e(u));return typeof r.value>\"u\"?a:{value:Ig(r.value[0],r.value[1]),children:a}};return e(t)}function Jct(t,{configuration:e,stdout:r,json:o}){let a=t.map(n=>({value:n}));Ype({children:a},{configuration:e,stdout:r,json:o})}function Ype(t,{configuration:e,stdout:r,json:o,separators:a=0}){if(o){let u=Array.isArray(t.children)?t.children.values():Object.values(t.children??{});for(let A of u)A&&r.write(`${JSON.stringify(Wpe(A))}\n`);return}let n=(0,jpe.asTree)(Gpe(t,{configuration:e}),!1,!1);if(n=n.replace(/\\0[0-9]+\\0/g,\"\"),a>=1&&(n=n.replace(/^([├└]─)/gm,`\\u2502\n$1`).replace(/^│\\n/,\"\")),a>=2)for(let u=0;u<2;++u)n=n.replace(/^([│ ].{2}[├│ ].{2}[^\\n]+\\n)(([│ ]).{2}[├└].{2}[^\\n]*\\n[│ ].{2}[│ ].{2}[├└]─)/gm,`$1$3  \\u2502 \n$2`).replace(/^│\\n/,\"\");if(a>=3)throw new Error(\"Only the first two levels are accepted by treeUtils.emitTree\");r.write(n)}function Xct(t){return typeof t==\"string\"?t.replace(/^\\0[0-9]+\\0/,\"\"):t}var jpe,Kpe=It(()=>{jpe=et(qpe());Wl()});function v2(t){let e=t.match(Zct);if(!e?.groups)throw new Error(\"Assertion failed: Expected the checksum to match the requested pattern\");let r=e.groups.cacheVersion?parseInt(e.groups.cacheVersion):null;return{cacheKey:e.groups.cacheKey??null,cacheVersion:r,cacheSpec:e.groups.cacheSpec??null,hash:e.groups.hash}}var Vpe,Y_,K_,Pk,Wr,Zct,V_=It(()=>{Ke();Pt();Pt();sA();Vpe=ve(\"crypto\"),Y_=et(ve(\"fs\"));Vl();ah();Gl();Io();K_=Zm(process.env.YARN_CACHE_CHECKPOINT_OVERRIDE??process.env.YARN_CACHE_VERSION_OVERRIDE??9),Pk=Zm(process.env.YARN_CACHE_VERSION_OVERRIDE??10),Wr=class t{constructor(e,{configuration:r,immutable:o=r.get(\"enableImmutableCache\"),check:a=!1}){this.markedFiles=new Set;this.mutexes=new Map;this.cacheId=`-${(0,Vpe.randomBytes)(8).toString(\"hex\")}.tmp`;this.configuration=r,this.cwd=e,this.immutable=o,this.check=a;let{cacheSpec:n,cacheKey:u}=t.getCacheKey(r);this.cacheSpec=n,this.cacheKey=u}static async find(e,{immutable:r,check:o}={}){let a=new t(e.get(\"cacheFolder\"),{configuration:e,immutable:r,check:o});return await a.setup(),a}static getCacheKey(e){let r=e.get(\"compressionLevel\"),o=r!==\"mixed\"?`c${r}`:\"\";return{cacheKey:[Pk,o].join(\"\"),cacheSpec:o}}get mirrorCwd(){if(!this.configuration.get(\"enableMirror\"))return null;let e=`${this.configuration.get(\"globalFolder\")}/cache`;return e!==this.cwd?e:null}getVersionFilename(e){return`${ly(e)}-${this.cacheKey}.zip`}getChecksumFilename(e,r){let a=v2(r).hash.slice(0,10);return`${ly(e)}-${a}.zip`}isChecksumCompatible(e){if(e===null)return!1;let{cacheVersion:r,cacheSpec:o}=v2(e);if(r===null||r<K_)return!1;let a=this.configuration.get(\"cacheMigrationMode\");return!(r<Pk&&a===\"always\"||o!==this.cacheSpec&&a!==\"required-only\")}getLocatorPath(e,r){return this.mirrorCwd===null?K.resolve(this.cwd,this.getVersionFilename(e)):r===null?K.resolve(this.cwd,this.getVersionFilename(e)):K.resolve(this.cwd,this.getChecksumFilename(e,r))}getLocatorMirrorPath(e){let r=this.mirrorCwd;return r!==null?K.resolve(r,this.getVersionFilename(e)):null}async setup(){if(!this.configuration.get(\"enableGlobalCache\"))if(this.immutable){if(!await ae.existsPromise(this.cwd))throw new zt(56,\"Cache path does not exist.\")}else{await ae.mkdirPromise(this.cwd,{recursive:!0});let e=K.resolve(this.cwd,\".gitignore\");await ae.changeFilePromise(e,`/.gitignore\n*.flock\n*.tmp\n`)}(this.mirrorCwd||!this.immutable)&&await ae.mkdirPromise(this.mirrorCwd||this.cwd,{recursive:!0})}async fetchPackageFromCache(e,r,{onHit:o,onMiss:a,loader:n,...u}){let A=this.getLocatorMirrorPath(e),p=new _n,h=()=>{let he=new Zi,De=K.join(Bt.root,_M(e));return he.mkdirSync(De,{recursive:!0}),he.writeJsonSync(K.join(De,mr.manifest),{name:rn(e),mocked:!0}),he},E=async(he,{isColdHit:De,controlPath:Ee=null})=>{if(Ee===null&&u.unstablePackages?.has(e.locatorHash))return{isValid:!0,hash:null};let g=r&&!De?v2(r).cacheKey:this.cacheKey,me=!u.skipIntegrityCheck||!r?`${g}/${await fx(he)}`:r;if(Ee!==null){let fe=!u.skipIntegrityCheck||!r?`${this.cacheKey}/${await fx(Ee)}`:r;if(me!==fe)throw new zt(18,\"The remote archive doesn't match the local checksum - has the local cache been corrupted?\")}let Ce=null;switch(r!==null&&me!==r&&(this.check?Ce=\"throw\":v2(r).cacheKey!==v2(me).cacheKey?Ce=\"update\":Ce=this.configuration.get(\"checksumBehavior\")),Ce){case null:case\"update\":return{isValid:!0,hash:me};case\"ignore\":return{isValid:!0,hash:r};case\"reset\":return{isValid:!1,hash:r};default:case\"throw\":throw new zt(18,\"The remote archive doesn't match the expected checksum\")}},w=async he=>{if(!n)throw new Error(`Cache check required but no loader configured for ${jr(this.configuration,e)}`);let De=await n(),Ee=De.getRealPath();De.saveAndClose(),await ae.chmodPromise(Ee,420);let g=await E(he,{controlPath:Ee,isColdHit:!1});if(!g.isValid)throw new Error(\"Assertion failed: Expected a valid checksum\");return g.hash},D=async()=>{if(A===null||!await ae.existsPromise(A)){let he=await n(),De=he.getRealPath();return he.saveAndClose(),{source:\"loader\",path:De}}return{source:\"mirror\",path:A}},b=async()=>{if(!n)throw new Error(`Cache entry required but missing for ${jr(this.configuration,e)}`);if(this.immutable)throw new zt(56,`Cache entry required but missing for ${jr(this.configuration,e)}`);let{path:he,source:De}=await D(),{hash:Ee}=await E(he,{isColdHit:!0}),g=this.getLocatorPath(e,Ee),me=[];De!==\"mirror\"&&A!==null&&me.push(async()=>{let fe=`${A}${this.cacheId}`;await ae.copyFilePromise(he,fe,Y_.default.constants.COPYFILE_FICLONE),await ae.chmodPromise(fe,420),await ae.renamePromise(fe,A)}),(!u.mirrorWriteOnly||A===null)&&me.push(async()=>{let fe=`${g}${this.cacheId}`;await ae.copyFilePromise(he,fe,Y_.default.constants.COPYFILE_FICLONE),await ae.chmodPromise(fe,420),await ae.renamePromise(fe,g)});let Ce=u.mirrorWriteOnly?A??g:g;return await Promise.all(me.map(fe=>fe())),[!1,Ce,Ee]},C=async()=>{let De=(async()=>{let Ee=u.unstablePackages?.has(e.locatorHash),g=Ee||!r||this.isChecksumCompatible(r)?this.getLocatorPath(e,r):null,me=g!==null?this.markedFiles.has(g)||await p.existsPromise(g):!1,Ce=!!u.mockedPackages?.has(e.locatorHash)&&(!this.check||!me),fe=Ce||me,ie=fe?o:a;if(ie&&ie(),fe){let Z=null,Pe=g;if(!Ce)if(this.check)Z=await w(Pe);else{let Re=await E(Pe,{isColdHit:!1});if(Re.isValid)Z=Re.hash;else return b()}return[Ce,Pe,Z]}else{if(this.immutable&&Ee)throw new zt(56,`Cache entry required but missing for ${jr(this.configuration,e)}; consider defining ${pe.pretty(this.configuration,\"supportedArchitectures\",pe.Type.CODE)} to cache packages for multiple systems`);return b()}})();this.mutexes.set(e.locatorHash,De);try{return await De}finally{this.mutexes.delete(e.locatorHash)}};for(let he;he=this.mutexes.get(e.locatorHash);)await he;let[T,N,U]=await C();T||this.markedFiles.add(N);let z,te=T?()=>h():()=>new Zi(N,{baseFs:p,readOnly:!0}),le=new Am(()=>rO(()=>z=te(),he=>`Failed to open the cache entry for ${jr(this.configuration,e)}: ${he}`),K),ce=new ju(N,{baseFs:le,pathUtils:K}),ue=()=>{z?.discardAndClose()},Ie=u.unstablePackages?.has(e.locatorHash)?null:U;return[ce,ue,Ie]}},Zct=/^(?:(?<cacheKey>(?<cacheVersion>[0-9]+)(?<cacheSpec>.*))\\/)?(?<hash>.*)$/});var Sk,zpe=It(()=>{Sk=(r=>(r[r.SCRIPT=0]=\"SCRIPT\",r[r.SHELLCODE=1]=\"SHELLCODE\",r))(Sk||{})});var $ct,tE,z_=It(()=>{Pt();Ol();bf();Io();$ct=[[/^(git(?:\\+(?:https|ssh))?:\\/\\/.*(?:\\.git)?)#(.*)$/,(t,e,r,o)=>`${r}#commit=${o}`],[/^https:\\/\\/((?:[^/]+?)@)?codeload\\.github\\.com\\/([^/]+\\/[^/]+)\\/tar\\.gz\\/([0-9a-f]+)$/,(t,e,r=\"\",o,a)=>`https://${r}github.com/${o}.git#commit=${a}`],[/^https:\\/\\/((?:[^/]+?)@)?github\\.com\\/([^/]+\\/[^/]+?)(?:\\.git)?#([0-9a-f]+)$/,(t,e,r=\"\",o,a)=>`https://${r}github.com/${o}.git#commit=${a}`],[/^https?:\\/\\/[^/]+\\/(?:[^/]+\\/)*(?:@.+(?:\\/|(?:%2f)))?([^/]+)\\/(?:-|download)\\/\\1-[^/]+\\.tgz(?:#|$)/,t=>`npm:${t}`],[/^https:\\/\\/npm\\.pkg\\.github\\.com\\/download\\/(?:@[^/]+)\\/(?:[^/]+)\\/(?:[^/]+)\\/(?:[0-9a-f]+)(?:#|$)/,t=>`npm:${t}`],[/^https:\\/\\/npm\\.fontawesome\\.com\\/(?:@[^/]+)\\/([^/]+)\\/-\\/([^/]+)\\/\\1-\\2.tgz(?:#|$)/,t=>`npm:${t}`],[/^https?:\\/\\/[^/]+\\/.*\\/(@[^/]+)\\/([^/]+)\\/-\\/\\1\\/\\2-(?:[.\\d\\w-]+)\\.tgz(?:#|$)/,(t,e)=>mx({protocol:\"npm:\",source:null,selector:t,params:{__archiveUrl:e}})],[/^[^/]+\\.tgz#[0-9a-f]+$/,t=>`npm:${t}`]],tE=class{constructor(e){this.resolver=e;this.resolutions=null}async setup(e,{report:r}){let o=K.join(e.cwd,mr.lockfile);if(!ae.existsSync(o))return;let a=await ae.readFilePromise(o,\"utf8\"),n=Ki(a);if(Object.hasOwn(n,\"__metadata\"))return;let u=this.resolutions=new Map;for(let A of Object.keys(n)){let p=v1(A);if(!p){r.reportWarning(14,`Failed to parse the string \"${A}\" into a proper descriptor`);continue}let h=Fa(p.range)?kn(p,`npm:${p.range}`):p,{version:E,resolved:w}=n[A];if(!w)continue;let D;for(let[C,T]of $ct){let N=w.match(C);if(N){D=T(E,...N);break}}if(!D){r.reportWarning(14,`${zn(e.configuration,h)}: Only some patterns can be imported from legacy lockfiles (not \"${w}\")`);continue}let b=h;try{let C=vg(h.range),T=v1(C.selector,!0);T&&(b=T)}catch{}u.set(h.descriptorHash,Ss(b,D))}}supportsDescriptor(e,r){return this.resolutions?this.resolutions.has(e.descriptorHash):!1}supportsLocator(e,r){return!1}shouldPersistResolution(e,r){throw new Error(\"Assertion failed: This resolver doesn't support resolving locators to packages\")}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){if(!this.resolutions)throw new Error(\"Assertion failed: The resolution store should have been setup\");let a=this.resolutions.get(e.descriptorHash);if(!a)throw new Error(\"Assertion failed: The resolution should have been registered\");let n=NM(a),u=o.project.configuration.normalizeDependency(n);return await this.resolver.getCandidates(u,r,o)}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){throw new Error(\"Assertion failed: This resolver doesn't support resolving locators to packages\")}}});var pA,Jpe=It(()=>{Vl();n2();Wl();pA=class extends Ws{constructor({configuration:r,stdout:o,suggestInstall:a=!0}){super();this.errorCount=0;g1(this,{configuration:r}),this.configuration=r,this.stdout=o,this.suggestInstall=a}static async start(r,o){let a=new this(r);try{await o(a)}catch(n){a.reportExceptionOnce(n)}finally{await a.finalize()}return a}hasErrors(){return this.errorCount>0}exitCode(){return this.hasErrors()?1:0}reportCacheHit(r){}reportCacheMiss(r){}startSectionSync(r,o){return o()}async startSectionPromise(r,o){return await o()}startTimerSync(r,o,a){return(typeof o==\"function\"?o:a)()}async startTimerPromise(r,o,a){return await(typeof o==\"function\"?o:a)()}reportSeparator(){}reportInfo(r,o){}reportWarning(r,o){}reportError(r,o){this.errorCount+=1,this.stdout.write(`${Ut(this.configuration,\"\\u27A4\",\"redBright\")} ${this.formatNameWithHyperlink(r)}: ${o}\n`)}reportProgress(r){return{...Promise.resolve().then(async()=>{for await(let{}of r);}),stop:()=>{}}}reportJson(r){}reportFold(r,o){}async finalize(){this.errorCount>0&&(this.stdout.write(`\n`),this.stdout.write(`${Ut(this.configuration,\"\\u27A4\",\"redBright\")} Errors happened when preparing the environment required to run this command.\n`),this.suggestInstall&&this.stdout.write(`${Ut(this.configuration,\"\\u27A4\",\"redBright\")} This might be caused by packages being missing from the lockfile, in which case running \"yarn install\" might help.\n`))}formatNameWithHyperlink(r){return r3(r,{configuration:this.configuration,json:!1})}}});var rE,J_=It(()=>{Io();rE=class{constructor(e){this.resolver=e}supportsDescriptor(e,r){return!!(r.project.storedResolutions.get(e.descriptorHash)||r.project.originalPackages.has(hx(e).locatorHash))}supportsLocator(e,r){return!!(r.project.originalPackages.has(e.locatorHash)&&!r.project.lockfileNeedsRefresh)}shouldPersistResolution(e,r){throw new Error(\"The shouldPersistResolution method shouldn't be called on the lockfile resolver, which would always answer yes\")}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return this.resolver.getResolutionDependencies(e,r)}async getCandidates(e,r,o){let a=o.project.storedResolutions.get(e.descriptorHash);if(a){let u=o.project.originalPackages.get(a);if(u)return[u]}let n=o.project.originalPackages.get(hx(e).locatorHash);if(n)return[n];throw new Error(\"Resolution expected from the lockfile data\")}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){let o=r.project.originalPackages.get(e.locatorHash);if(!o)throw new Error(\"The lockfile resolver isn't meant to resolve packages - they should already have been stored into a cache\");return o}}});function Wf(){}function eut(t,e,r,o,a){for(var n=0,u=e.length,A=0,p=0;n<u;n++){var h=e[n];if(h.removed){if(h.value=t.join(o.slice(p,p+h.count)),p+=h.count,n&&e[n-1].added){var w=e[n-1];e[n-1]=e[n],e[n]=w}}else{if(!h.added&&a){var E=r.slice(A,A+h.count);E=E.map(function(b,C){var T=o[p+C];return T.length>b.length?T:b}),h.value=t.join(E)}else h.value=t.join(r.slice(A,A+h.count));A+=h.count,h.added||(p+=h.count)}}var D=e[u-1];return u>1&&typeof D.value==\"string\"&&(D.added||D.removed)&&t.equals(\"\",D.value)&&(e[u-2].value+=D.value,e.pop()),e}function tut(t){return{newPos:t.newPos,components:t.components.slice(0)}}function rut(t,e){if(typeof t==\"function\")e.callback=t;else if(t)for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);return e}function $pe(t,e,r){return r=rut(r,{ignoreWhitespace:!0}),t8.diff(t,e,r)}function nut(t,e,r){return r8.diff(t,e,r)}function xk(t){\"@babel/helpers - typeof\";return typeof Symbol==\"function\"&&typeof Symbol.iterator==\"symbol\"?xk=function(e){return typeof e}:xk=function(e){return e&&typeof Symbol==\"function\"&&e.constructor===Symbol&&e!==Symbol.prototype?\"symbol\":typeof e},xk(t)}function X_(t){return out(t)||aut(t)||lut(t)||cut()}function out(t){if(Array.isArray(t))return Z_(t)}function aut(t){if(typeof Symbol<\"u\"&&Symbol.iterator in Object(t))return Array.from(t)}function lut(t,e){if(t){if(typeof t==\"string\")return Z_(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);if(r===\"Object\"&&t.constructor&&(r=t.constructor.name),r===\"Map\"||r===\"Set\")return Array.from(t);if(r===\"Arguments\"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return Z_(t,e)}}function Z_(t,e){(e==null||e>t.length)&&(e=t.length);for(var r=0,o=new Array(e);r<e;r++)o[r]=t[r];return o}function cut(){throw new TypeError(`Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function $_(t,e,r,o,a){e=e||[],r=r||[],o&&(t=o(a,t));var n;for(n=0;n<e.length;n+=1)if(e[n]===t)return r[n];var u;if(uut.call(t)===\"[object Array]\"){for(e.push(t),u=new Array(t.length),r.push(u),n=0;n<t.length;n+=1)u[n]=$_(t[n],e,r,o,a);return e.pop(),r.pop(),u}if(t&&t.toJSON&&(t=t.toJSON()),xk(t)===\"object\"&&t!==null){e.push(t),u={},r.push(u);var A=[],p;for(p in t)t.hasOwnProperty(p)&&A.push(p);for(A.sort(),n=0;n<A.length;n+=1)p=A[n],u[p]=$_(t[p],e,r,o,p);e.pop(),r.pop()}else u=t;return u}function ehe(t,e,r,o,a,n,u){u||(u={}),typeof u.context>\"u\"&&(u.context=4);var A=nut(r,o,u);if(!A)return;A.push({value:\"\",lines:[]});function p(U){return U.map(function(z){return\" \"+z})}for(var h=[],E=0,w=0,D=[],b=1,C=1,T=function(z){var te=A[z],le=te.lines||te.value.replace(/\\n$/,\"\").split(`\n`);if(te.lines=le,te.added||te.removed){var ce;if(!E){var ue=A[z-1];E=b,w=C,ue&&(D=u.context>0?p(ue.lines.slice(-u.context)):[],E-=D.length,w-=D.length)}(ce=D).push.apply(ce,X_(le.map(function(fe){return(te.added?\"+\":\"-\")+fe}))),te.added?C+=le.length:b+=le.length}else{if(E)if(le.length<=u.context*2&&z<A.length-2){var Ie;(Ie=D).push.apply(Ie,X_(p(le)))}else{var he,De=Math.min(le.length,u.context);(he=D).push.apply(he,X_(p(le.slice(0,De))));var Ee={oldStart:E,oldLines:b-E+De,newStart:w,newLines:C-w+De,lines:D};if(z>=A.length-2&&le.length<=u.context){var g=/\\n$/.test(r),me=/\\n$/.test(o),Ce=le.length==0&&D.length>Ee.oldLines;!g&&Ce&&r.length>0&&D.splice(Ee.oldLines,0,\"\\\\ No newline at end of file\"),(!g&&!Ce||!me)&&D.push(\"\\\\ No newline at end of file\")}h.push(Ee),E=0,w=0,D=[]}b+=le.length,C+=le.length}},N=0;N<A.length;N++)T(N);return{oldFileName:t,newFileName:e,oldHeader:a,newHeader:n,hunks:h}}var UUt,Xpe,Zpe,t8,r8,iut,sut,uut,D2,e8,n8=It(()=>{Wf.prototype={diff:function(e,r){var o=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},a=o.callback;typeof o==\"function\"&&(a=o,o={}),this.options=o;var n=this;function u(T){return a?(setTimeout(function(){a(void 0,T)},0),!0):T}e=this.castInput(e),r=this.castInput(r),e=this.removeEmpty(this.tokenize(e)),r=this.removeEmpty(this.tokenize(r));var A=r.length,p=e.length,h=1,E=A+p;o.maxEditLength&&(E=Math.min(E,o.maxEditLength));var w=[{newPos:-1,components:[]}],D=this.extractCommon(w[0],r,e,0);if(w[0].newPos+1>=A&&D+1>=p)return u([{value:this.join(r),count:r.length}]);function b(){for(var T=-1*h;T<=h;T+=2){var N=void 0,U=w[T-1],z=w[T+1],te=(z?z.newPos:0)-T;U&&(w[T-1]=void 0);var le=U&&U.newPos+1<A,ce=z&&0<=te&&te<p;if(!le&&!ce){w[T]=void 0;continue}if(!le||ce&&U.newPos<z.newPos?(N=tut(z),n.pushComponent(N.components,void 0,!0)):(N=U,N.newPos++,n.pushComponent(N.components,!0,void 0)),te=n.extractCommon(N,r,e,T),N.newPos+1>=A&&te+1>=p)return u(eut(n,N.components,r,e,n.useLongestToken));w[T]=N}h++}if(a)(function T(){setTimeout(function(){if(h>E)return a();b()||T()},0)})();else for(;h<=E;){var C=b();if(C)return C}},pushComponent:function(e,r,o){var a=e[e.length-1];a&&a.added===r&&a.removed===o?e[e.length-1]={count:a.count+1,added:r,removed:o}:e.push({count:1,added:r,removed:o})},extractCommon:function(e,r,o,a){for(var n=r.length,u=o.length,A=e.newPos,p=A-a,h=0;A+1<n&&p+1<u&&this.equals(r[A+1],o[p+1]);)A++,p++,h++;return h&&e.components.push({count:h}),e.newPos=A,p},equals:function(e,r){return this.options.comparator?this.options.comparator(e,r):e===r||this.options.ignoreCase&&e.toLowerCase()===r.toLowerCase()},removeEmpty:function(e){for(var r=[],o=0;o<e.length;o++)e[o]&&r.push(e[o]);return r},castInput:function(e){return e},tokenize:function(e){return e.split(\"\")},join:function(e){return e.join(\"\")}};UUt=new Wf;Xpe=/^[A-Za-z\\xC0-\\u02C6\\u02C8-\\u02D7\\u02DE-\\u02FF\\u1E00-\\u1EFF]+$/,Zpe=/\\S/,t8=new Wf;t8.equals=function(t,e){return this.options.ignoreCase&&(t=t.toLowerCase(),e=e.toLowerCase()),t===e||this.options.ignoreWhitespace&&!Zpe.test(t)&&!Zpe.test(e)};t8.tokenize=function(t){for(var e=t.split(/([^\\S\\r\\n]+|[()[\\]{}'\"\\r\\n]|\\b)/),r=0;r<e.length-1;r++)!e[r+1]&&e[r+2]&&Xpe.test(e[r])&&Xpe.test(e[r+2])&&(e[r]+=e[r+2],e.splice(r+1,2),r--);return e};r8=new Wf;r8.tokenize=function(t){var e=[],r=t.split(/(\\n|\\r\\n)/);r[r.length-1]||r.pop();for(var o=0;o<r.length;o++){var a=r[o];o%2&&!this.options.newlineIsToken?e[e.length-1]+=a:(this.options.ignoreWhitespace&&(a=a.trim()),e.push(a))}return e};iut=new Wf;iut.tokenize=function(t){return t.split(/(\\S.+?[.!?])(?=\\s+|$)/)};sut=new Wf;sut.tokenize=function(t){return t.split(/([{}:;,]|\\s+)/)};uut=Object.prototype.toString,D2=new Wf;D2.useLongestToken=!0;D2.tokenize=r8.tokenize;D2.castInput=function(t){var e=this.options,r=e.undefinedReplacement,o=e.stringifyReplacer,a=o===void 0?function(n,u){return typeof u>\"u\"?r:u}:o;return typeof t==\"string\"?t:JSON.stringify($_(t,null,null,a),a,\"  \")};D2.equals=function(t,e){return Wf.prototype.equals.call(D2,t.replace(/,([\\r\\n])/g,\"$1\"),e.replace(/,([\\r\\n])/g,\"$1\"))};e8=new Wf;e8.tokenize=function(t){return t.slice()};e8.join=e8.removeEmpty=function(t){return t}});var rhe=_((HUt,the)=>{var Aut=jl(),fut=fy(),put=/\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\\\]|\\\\.)*?\\1)\\]/,hut=/^\\w*$/;function gut(t,e){if(Aut(t))return!1;var r=typeof t;return r==\"number\"||r==\"symbol\"||r==\"boolean\"||t==null||fut(t)?!0:hut.test(t)||!put.test(t)||e!=null&&t in Object(e)}the.exports=gut});var she=_((qUt,ihe)=>{var nhe=dS(),dut=\"Expected a function\";function i8(t,e){if(typeof t!=\"function\"||e!=null&&typeof e!=\"function\")throw new TypeError(dut);var r=function(){var o=arguments,a=e?e.apply(this,o):o[0],n=r.cache;if(n.has(a))return n.get(a);var u=t.apply(this,o);return r.cache=n.set(a,u)||n,u};return r.cache=new(i8.Cache||nhe),r}i8.Cache=nhe;ihe.exports=i8});var ahe=_((jUt,ohe)=>{var mut=she(),yut=500;function Eut(t){var e=mut(t,function(o){return r.size===yut&&r.clear(),o}),r=e.cache;return e}ohe.exports=Eut});var s8=_((GUt,lhe)=>{var Cut=ahe(),Iut=/[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2)\\]|(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))/g,wut=/\\\\(\\\\)?/g,But=Cut(function(t){var e=[];return t.charCodeAt(0)===46&&e.push(\"\"),t.replace(Iut,function(r,o,a,n){e.push(a?n.replace(wut,\"$1\"):o||r)}),e});lhe.exports=But});var Wg=_((WUt,che)=>{var vut=jl(),Dut=rhe(),Put=s8(),Sut=t2();function xut(t,e){return vut(t)?t:Dut(t,e)?[t]:Put(Sut(t))}che.exports=xut});var nE=_((YUt,uhe)=>{var but=fy(),kut=1/0;function Qut(t){if(typeof t==\"string\"||but(t))return t;var e=t+\"\";return e==\"0\"&&1/t==-kut?\"-0\":e}uhe.exports=Qut});var bk=_((KUt,Ahe)=>{var Fut=Wg(),Rut=nE();function Tut(t,e){e=Fut(e,t);for(var r=0,o=e.length;t!=null&&r<o;)t=t[Rut(e[r++])];return r&&r==o?t:void 0}Ahe.exports=Tut});var o8=_((VUt,phe)=>{var Lut=RS(),Nut=Wg(),Out=n1(),fhe=cl(),Mut=nE();function Uut(t,e,r,o){if(!fhe(t))return t;e=Nut(e,t);for(var a=-1,n=e.length,u=n-1,A=t;A!=null&&++a<n;){var p=Mut(e[a]),h=r;if(p===\"__proto__\"||p===\"constructor\"||p===\"prototype\")return t;if(a!=u){var E=A[p];h=o?o(E,p,A):void 0,h===void 0&&(h=fhe(E)?E:Out(e[a+1])?[]:{})}Lut(A,p,h),A=A[p]}return t}phe.exports=Uut});var ghe=_((zUt,hhe)=>{var _ut=bk(),Hut=o8(),qut=Wg();function jut(t,e,r){for(var o=-1,a=e.length,n={};++o<a;){var u=e[o],A=_ut(t,u);r(A,u)&&Hut(n,qut(u,t),A)}return n}hhe.exports=jut});var mhe=_((JUt,dhe)=>{function Gut(t,e){return t!=null&&e in Object(t)}dhe.exports=Gut});var a8=_((XUt,yhe)=>{var Wut=Wg(),Yut=e1(),Kut=jl(),Vut=n1(),zut=IS(),Jut=nE();function Xut(t,e,r){e=Wut(e,t);for(var o=-1,a=e.length,n=!1;++o<a;){var u=Jut(e[o]);if(!(n=t!=null&&r(t,u)))break;t=t[u]}return n||++o!=a?n:(a=t==null?0:t.length,!!a&&zut(a)&&Vut(u,a)&&(Kut(t)||Yut(t)))}yhe.exports=Xut});var Che=_((ZUt,Ehe)=>{var Zut=mhe(),$ut=a8();function eAt(t,e){return t!=null&&$ut(t,e,Zut)}Ehe.exports=eAt});var whe=_(($Ut,Ihe)=>{var tAt=ghe(),rAt=Che();function nAt(t,e){return tAt(t,e,function(r,o){return rAt(t,o)})}Ihe.exports=nAt});var Phe=_((e3t,Dhe)=>{var Bhe=dg(),iAt=e1(),sAt=jl(),vhe=Bhe?Bhe.isConcatSpreadable:void 0;function oAt(t){return sAt(t)||iAt(t)||!!(vhe&&t&&t[vhe])}Dhe.exports=oAt});var bhe=_((t3t,xhe)=>{var aAt=ES(),lAt=Phe();function She(t,e,r,o,a){var n=-1,u=t.length;for(r||(r=lAt),a||(a=[]);++n<u;){var A=t[n];e>0&&r(A)?e>1?She(A,e-1,r,o,a):aAt(a,A):o||(a[a.length]=A)}return a}xhe.exports=She});var Qhe=_((r3t,khe)=>{var cAt=bhe();function uAt(t){var e=t==null?0:t.length;return e?cAt(t,1):[]}khe.exports=uAt});var l8=_((n3t,Fhe)=>{var AAt=Qhe(),fAt=VN(),pAt=zN();function hAt(t){return pAt(fAt(t,void 0,AAt),t+\"\")}Fhe.exports=hAt});var c8=_((i3t,Rhe)=>{var gAt=whe(),dAt=l8(),mAt=dAt(function(t,e){return t==null?{}:gAt(t,e)});Rhe.exports=mAt});var kk,The=It(()=>{Vl();kk=class{constructor(e){this.resolver=e}supportsDescriptor(e,r){return this.resolver.supportsDescriptor(e,r)}supportsLocator(e,r){return this.resolver.supportsLocator(e,r)}shouldPersistResolution(e,r){return this.resolver.shouldPersistResolution(e,r)}bindDescriptor(e,r,o){return this.resolver.bindDescriptor(e,r,o)}getResolutionDependencies(e,r){return this.resolver.getResolutionDependencies(e,r)}async getCandidates(e,r,o){throw new zt(20,`This package doesn't seem to be present in your lockfile; run \"yarn install\" to update the lockfile`)}async getSatisfying(e,r,o,a){throw new zt(20,`This package doesn't seem to be present in your lockfile; run \"yarn install\" to update the lockfile`)}async resolve(e,r){throw new zt(20,`This package doesn't seem to be present in your lockfile; run \"yarn install\" to update the lockfile`)}}});var Ri,u8=It(()=>{Vl();Ri=class extends Ws{reportCacheHit(e){}reportCacheMiss(e){}startSectionSync(e,r){return r()}async startSectionPromise(e,r){return await r()}startTimerSync(e,r,o){return(typeof r==\"function\"?r:o)()}async startTimerPromise(e,r,o){return await(typeof r==\"function\"?r:o)()}reportSeparator(){}reportInfo(e,r){}reportWarning(e,r){}reportError(e,r){}reportProgress(e){return{...Promise.resolve().then(async()=>{for await(let{}of e);}),stop:()=>{}}}reportJson(e){}reportFold(e,r){}async finalize(){}}});var Lhe,iE,A8=It(()=>{Pt();Lhe=et(ux());Ay();Dg();Wl();ah();bf();Io();iE=class{constructor(e,{project:r}){this.workspacesCwds=new Set;this.project=r,this.cwd=e}async setup(){this.manifest=await _t.tryFind(this.cwd)??new _t,this.relativeCwd=K.relative(this.project.cwd,this.cwd)||Bt.dot;let e=this.manifest.name?this.manifest.name:rA(null,`${this.computeCandidateName()}-${zi(this.relativeCwd).substring(0,6)}`);this.anchoredDescriptor=kn(e,`${ci.protocol}${this.relativeCwd}`),this.anchoredLocator=Ss(e,`${ci.protocol}${this.relativeCwd}`);let r=this.manifest.workspaceDefinitions.map(({pattern:a})=>a);if(r.length===0)return;let o=await(0,Lhe.default)(r,{cwd:Ae.fromPortablePath(this.cwd),onlyDirectories:!0,ignore:[\"**/node_modules\",\"**/.git\",\"**/.yarn\"]});o.sort(),await o.reduce(async(a,n)=>{let u=K.resolve(this.cwd,Ae.toPortablePath(n)),A=await ae.existsPromise(K.join(u,\"package.json\"));await a,A&&this.workspacesCwds.add(u)},Promise.resolve())}get anchoredPackage(){let e=this.project.storedPackages.get(this.anchoredLocator.locatorHash);if(!e)throw new Error(`Assertion failed: Expected workspace ${P1(this.project.configuration,this)} (${Ut(this.project.configuration,K.join(this.cwd,mr.manifest),Ct.PATH)}) to have been resolved. Run \"yarn install\" to update the lockfile`);return e}accepts(e){let r=e.indexOf(\":\"),o=r!==-1?e.slice(0,r+1):null,a=r!==-1?e.slice(r+1):e;if(o===ci.protocol&&K.normalize(a)===this.relativeCwd||o===ci.protocol&&(a===\"*\"||a===\"^\"||a===\"~\"))return!0;let n=Fa(a);return n?o===ci.protocol?n.test(this.manifest.version??\"0.0.0\"):this.project.configuration.get(\"enableTransparentWorkspaces\")&&this.manifest.version!==null?n.test(this.manifest.version):!1:!1}computeCandidateName(){return this.cwd===this.project.cwd?\"root-workspace\":`${K.basename(this.cwd)}`||\"unnamed-workspace\"}getRecursiveWorkspaceDependencies({dependencies:e=_t.hardDependencies}={}){let r=new Set,o=a=>{for(let n of e)for(let u of a.manifest[n].values()){let A=this.project.tryWorkspaceByDescriptor(u);A===null||r.has(A)||(r.add(A),o(A))}};return o(this),r}getRecursiveWorkspaceDependents({dependencies:e=_t.hardDependencies}={}){let r=new Set,o=a=>{for(let n of this.project.workspaces)e.some(A=>[...n.manifest[A].values()].some(p=>{let h=this.project.tryWorkspaceByDescriptor(p);return h!==null&&B1(h.anchoredLocator,a.anchoredLocator)}))&&!r.has(n)&&(r.add(n),o(n))};return o(this),r}getRecursiveWorkspaceChildren(){let e=new Set([this]);for(let r of e)for(let o of r.workspacesCwds){let a=this.project.workspacesByCwd.get(o);a&&e.add(a)}return e.delete(this),Array.from(e)}async persistManifest(){let e={};this.manifest.exportTo(e);let r=K.join(this.cwd,_t.fileName),o=`${JSON.stringify(e,null,this.manifest.indent)}\n`;await ae.changeFilePromise(r,o,{automaticNewlines:!0}),this.manifest.raw=e}}});function BAt({project:t,allDescriptors:e,allResolutions:r,allPackages:o,accessibleLocators:a=new Set,optionalBuilds:n=new Set,peerRequirements:u=new Map,peerWarnings:A=[],peerRequirementNodes:p=new Map,volatileDescriptors:h=new Set}){let E=new Map,w=[],D=new Map,b=new Map,C=new Map,T=new Map,N=new Map(t.workspaces.map(ce=>{let ue=ce.anchoredLocator.locatorHash,Ie=o.get(ue);if(typeof Ie>\"u\")throw new Error(\"Assertion failed: The workspace should have an associated package\");return[ue,E1(Ie)]})),U=()=>{let ce=ae.mktempSync(),ue=K.join(ce,\"stacktrace.log\"),Ie=String(w.length+1).length,he=w.map((De,Ee)=>`${`${Ee+1}.`.padStart(Ie,\" \")} ${Qa(De)}\n`).join(\"\");throw ae.writeFileSync(ue,he),ae.detachTemp(ce),new zt(45,`Encountered a stack overflow when resolving peer dependencies; cf ${Ae.fromPortablePath(ue)}`)},z=ce=>{let ue=r.get(ce.descriptorHash);if(typeof ue>\"u\")throw new Error(\"Assertion failed: The resolution should have been registered\");let Ie=o.get(ue);if(!Ie)throw new Error(\"Assertion failed: The package could not be found\");return Ie},te=(ce,ue,Ie,{top:he,optional:De})=>{w.length>1e3&&U(),w.push(ue);let Ee=le(ce,ue,Ie,{top:he,optional:De});return w.pop(),Ee},le=(ce,ue,Ie,{top:he,optional:De})=>{if(De||n.delete(ue.locatorHash),a.has(ue.locatorHash))return;a.add(ue.locatorHash);let Ee=o.get(ue.locatorHash);if(!Ee)throw new Error(`Assertion failed: The package (${jr(t.configuration,ue)}) should have been registered`);let g=[],me=new Map,Ce=[],fe=[],ie=[],Z=[];for(let Re of Array.from(Ee.dependencies.values())){if(Ee.peerDependencies.has(Re.identHash)&&Ee.locatorHash!==he)continue;if(Pf(Re))throw new Error(\"Assertion failed: Virtual packages shouldn't be encountered when virtualizing a branch\");h.delete(Re.descriptorHash);let ht=De;if(!ht){let xe=Ee.dependenciesMeta.get(rn(Re));if(typeof xe<\"u\"){let tt=xe.get(null);typeof tt<\"u\"&&tt.optional&&(ht=!0)}}let q=r.get(Re.descriptorHash);if(!q)throw new Error(`Assertion failed: The resolution (${zn(t.configuration,Re)}) should have been registered`);let nt=N.get(q)||o.get(q);if(!nt)throw new Error(`Assertion failed: The package (${q}, resolved from ${zn(t.configuration,Re)}) should have been registered`);if(nt.peerDependencies.size===0){te(Re,nt,new Map,{top:he,optional:ht});continue}let Le,Te,ke=new Set,Ve=new Map;Ce.push(()=>{Le=MM(Re,ue.locatorHash),Te=UM(nt,ue.locatorHash),Ee.dependencies.delete(Re.identHash),Ee.dependencies.set(Le.identHash,Le),r.set(Le.descriptorHash,Te.locatorHash),e.set(Le.descriptorHash,Le),o.set(Te.locatorHash,Te),g.push([nt,Le,Te])}),fe.push(()=>{T.set(Te.locatorHash,Ve);for(let xe of Te.peerDependencies.values()){let He=Al(me,xe.identHash,()=>{let x=Ie.get(xe.identHash)??null,I=Ee.dependencies.get(xe.identHash);return!I&&w1(ue,xe)&&(ce.identHash===ue.identHash?I=ce:(I=kn(ue,ce.range),e.set(I.descriptorHash,I),r.set(I.descriptorHash,ue.locatorHash),h.delete(I.descriptorHash),x=null)),I||(I=kn(xe,\"missing:\")),{subject:ue,ident:xe,provided:I,root:!x,requests:new Map,hash:`p${zi(ue.locatorHash,xe.identHash).slice(0,5)}`}}).provided;if(He.range===\"missing:\"&&Te.dependencies.has(xe.identHash)){Te.peerDependencies.delete(xe.identHash);continue}Ve.set(xe.identHash,{requester:Te,descriptor:xe,meta:Te.peerDependenciesMeta.get(rn(xe)),children:new Map}),Te.dependencies.set(xe.identHash,He),Pf(He)&&zm(C,He.descriptorHash).add(Te.locatorHash),D.set(He.identHash,He),He.range===\"missing:\"&&ke.add(He.identHash)}Te.dependencies=new Map(Ps(Te.dependencies,([xe,tt])=>rn(tt)))}),ie.push(()=>{if(!o.has(Te.locatorHash))return;let xe=E.get(nt.locatorHash);typeof xe==\"number\"&&xe>=2&&U();let tt=E.get(nt.locatorHash),He=typeof tt<\"u\"?tt+1:1;E.set(nt.locatorHash,He),te(Le,Te,Ve,{top:he,optional:ht}),E.set(nt.locatorHash,He-1)}),Z.push(()=>{let xe=Ee.dependencies.get(Re.identHash);if(typeof xe>\"u\")throw new Error(\"Assertion failed: Expected the peer dependency to have been turned into a dependency\");let tt=r.get(xe.descriptorHash);if(typeof tt>\"u\")throw new Error(\"Assertion failed: Expected the descriptor to be registered\");let He=T.get(tt);if(typeof He>\"u\")throw new Error(\"Assertion failed: Expected the peer requests to be registered\");for(let x of me.values()){let I=He.get(x.ident.identHash);I&&(x.requests.set(xe.descriptorHash,I),p.set(x.hash,x),x.root||Ie.get(x.ident.identHash)?.children.set(xe.descriptorHash,I))}if(o.has(Te.locatorHash))for(let x of ke)Te.dependencies.delete(x)})}for(let Re of[...Ce,...fe])Re();let Pe;do{Pe=!0;for(let[Re,ht,q]of g){let nt=A1(b,Re.locatorHash),Le=zi(...[...q.dependencies.values()].map(xe=>{let tt=xe.range!==\"missing:\"?r.get(xe.descriptorHash):\"missing:\";if(typeof tt>\"u\")throw new Error(`Assertion failed: Expected the resolution for ${zn(t.configuration,xe)} to have been registered`);return tt===he?`${tt} (top)`:tt}),ht.identHash),Te=nt.get(Le);if(typeof Te>\"u\"){nt.set(Le,ht);continue}if(Te===ht)continue;o.delete(q.locatorHash),e.delete(ht.descriptorHash),r.delete(ht.descriptorHash),a.delete(q.locatorHash);let ke=C.get(ht.descriptorHash)||[],Ve=[Ee.locatorHash,...ke];C.delete(ht.descriptorHash);for(let xe of Ve){let tt=o.get(xe);typeof tt>\"u\"||(tt.dependencies.get(ht.identHash).descriptorHash!==Te.descriptorHash&&(Pe=!1),tt.dependencies.set(ht.identHash,Te))}for(let xe of me.values())xe.provided.descriptorHash===ht.descriptorHash&&(xe.provided=Te)}}while(!Pe);for(let Re of[...ie,...Z])Re()};for(let ce of t.workspaces){let ue=ce.anchoredLocator;h.delete(ce.anchoredDescriptor.descriptorHash),te(ce.anchoredDescriptor,ue,new Map,{top:ue.locatorHash,optional:!1})}for(let ce of p.values()){if(!ce.root)continue;let ue=o.get(ce.subject.locatorHash);if(typeof ue>\"u\")continue;for(let he of ce.requests.values()){let De=`p${zi(ce.subject.locatorHash,rn(ce.ident),he.requester.locatorHash).slice(0,5)}`;u.set(De,{subject:ce.subject.locatorHash,requested:ce.ident,rootRequester:he.requester.locatorHash,allRequesters:Array.from(S1(he),Ee=>Ee.requester.locatorHash)})}let Ie=[...S1(ce)];if(ce.provided.range!==\"missing:\"){let he=z(ce.provided),De=he.version??\"0.0.0\",Ee=me=>{if(me.startsWith(ci.protocol)){if(!t.tryWorkspaceByLocator(he))return null;me=me.slice(ci.protocol.length),(me===\"^\"||me===\"~\")&&(me=\"*\")}return me},g=!0;for(let me of Ie){let Ce=Ee(me.descriptor.range);if(Ce===null){g=!1;continue}if(!nA(De,Ce)){g=!1;let fe=`p${zi(ce.subject.locatorHash,rn(ce.ident),me.requester.locatorHash).slice(0,5)}`;A.push({type:1,subject:ue,requested:ce.ident,requester:me.requester,version:De,hash:fe,requirementCount:Ie.length})}}if(!g){let me=Ie.map(Ce=>Ee(Ce.descriptor.range));A.push({type:3,node:ce,range:me.includes(null)?null:qM(me),hash:ce.hash})}}else{let he=!0;for(let De of Ie)if(!De.meta?.optional){he=!1;let Ee=`p${zi(ce.subject.locatorHash,rn(ce.ident),De.requester.locatorHash).slice(0,5)}`;A.push({type:0,subject:ue,requested:ce.ident,requester:De.requester,hash:Ee})}he||A.push({type:2,node:ce,hash:ce.hash})}}}function*vAt(t){let e=new Map;if(\"children\"in t)e.set(t,t);else for(let r of t.requests.values())e.set(r,r);for(let[r,o]of e){yield{request:r,root:o};for(let a of r.children.values())e.has(a)||e.set(a,o)}}function DAt(t,e){let r=[],o=[],a=!1;for(let n of t.peerWarnings)if(!(n.type===1||n.type===0)){if(!t.tryWorkspaceByLocator(n.node.subject)){a=!0;continue}if(n.type===3){let u=t.storedResolutions.get(n.node.provided.descriptorHash);if(typeof u>\"u\")throw new Error(\"Assertion failed: Expected the descriptor to be registered\");let A=t.storedPackages.get(u);if(typeof A>\"u\")throw new Error(\"Assertion failed: Expected the package to be registered\");let p=eh(vAt(n.node),({request:w,root:D})=>nA(A.version??\"0.0.0\",w.descriptor.range)?eh.skip:w===D?Ui(t.configuration,w.requester):`${Ui(t.configuration,w.requester)} (via ${Ui(t.configuration,D.requester)})`),h=[...S1(n.node)].length>1?\"and other dependencies request\":\"requests\",E=n.range?cy(t.configuration,n.range):Ut(t.configuration,\"but they have non-overlapping ranges!\",\"redBright\");r.push(`${Ui(t.configuration,n.node.ident)} is listed by your project with version ${D1(t.configuration,A.version??\"0.0.0\")} (${Ut(t.configuration,n.hash,Ct.CODE)}), which doesn't satisfy what ${p} ${h} (${E}).`)}if(n.type===2){let u=n.node.requests.size>1?\" and other dependencies\":\"\";o.push(`${jr(t.configuration,n.node.subject)} doesn't provide ${Ui(t.configuration,n.node.ident)} (${Ut(t.configuration,n.hash,Ct.CODE)}), requested by ${Ui(t.configuration,n.node.requests.values().next().value.requester)}${u}.`)}}e.startSectionSync({reportFooter:()=>{e.reportWarning(86,`Some peer dependencies are incorrectly met by your project; run ${Ut(t.configuration,\"yarn explain peer-requirements <hash>\",Ct.CODE)} for details, where ${Ut(t.configuration,\"<hash>\",Ct.CODE)} is the six-letter p-prefixed code.`)},skipIfEmpty:!0},()=>{for(let n of Ps(r,u=>ey.default(u)))e.reportWarning(60,n);for(let n of Ps(o,u=>ey.default(u)))e.reportWarning(2,n)}),a&&e.reportWarning(86,`Some peer dependencies are incorrectly met by dependencies; run ${Ut(t.configuration,\"yarn explain peer-requirements\",Ct.CODE)} for details.`)}var Qk,Fk,Rk,Mhe,h8,p8,g8,Tk,yAt,EAt,Nhe,CAt,IAt,wAt,yl,f8,Lk,Ohe,Qt,Uhe=It(()=>{Pt();Pt();Ol();Gt();Qk=ve(\"crypto\");n8();Fk=et(c8()),Rk=et(lg()),Mhe=et(ni()),h8=ve(\"util\"),p8=et(ve(\"v8\")),g8=et(ve(\"zlib\"));V_();W1();z_();J_();Ay();KM();Vl();The();n2();u8();Dg();A8();vx();Wl();ah();Gl();rb();a3();bf();Io();Tk=Zm(process.env.YARN_LOCKFILE_VERSION_OVERRIDE??8),yAt=3,EAt=/ *, */g,Nhe=/\\/$/,CAt=32,IAt=(0,h8.promisify)(g8.default.gzip),wAt=(0,h8.promisify)(g8.default.gunzip),yl=(r=>(r.UpdateLockfile=\"update-lockfile\",r.SkipBuild=\"skip-build\",r))(yl||{}),f8={restoreLinkersCustomData:[\"linkersCustomData\"],restoreResolutions:[\"accessibleLocators\",\"conditionalLocators\",\"disabledLocators\",\"optionalBuilds\",\"storedDescriptors\",\"storedResolutions\",\"storedPackages\",\"lockFileChecksum\"],restoreBuildState:[\"skippedBuilds\",\"storedBuildState\"]},Lk=(a=>(a[a.NotProvided=0]=\"NotProvided\",a[a.NotCompatible=1]=\"NotCompatible\",a[a.NodeNotProvided=2]=\"NodeNotProvided\",a[a.NodeNotCompatible=3]=\"NodeNotCompatible\",a))(Lk||{}),Ohe=t=>zi(`${yAt}`,t),Qt=class t{constructor(e,{configuration:r}){this.resolutionAliases=new Map;this.workspaces=[];this.workspacesByCwd=new Map;this.workspacesByIdent=new Map;this.storedResolutions=new Map;this.storedDescriptors=new Map;this.storedPackages=new Map;this.storedChecksums=new Map;this.storedBuildState=new Map;this.accessibleLocators=new Set;this.conditionalLocators=new Set;this.disabledLocators=new Set;this.originalPackages=new Map;this.optionalBuilds=new Set;this.skippedBuilds=new Set;this.lockfileLastVersion=null;this.lockfileNeedsRefresh=!1;this.peerRequirements=new Map;this.peerWarnings=[];this.peerRequirementNodes=new Map;this.linkersCustomData=new Map;this.lockFileChecksum=null;this.installStateChecksum=null;this.configuration=r,this.cwd=e}static async find(e,r){if(!e.projectCwd)throw new ot(`No project found in ${r}`);let o=e.projectCwd,a=r,n=null;for(;n!==e.projectCwd;){if(n=a,ae.existsSync(K.join(n,mr.manifest))){o=n;break}a=K.dirname(n)}let u=new t(e.projectCwd,{configuration:e});Je.telemetry?.reportProject(u.cwd),await u.setupResolutions(),await u.setupWorkspaces(),Je.telemetry?.reportWorkspaceCount(u.workspaces.length),Je.telemetry?.reportDependencyCount(u.workspaces.reduce((C,T)=>C+T.manifest.dependencies.size+T.manifest.devDependencies.size,0));let A=u.tryWorkspaceByCwd(o);if(A)return{project:u,workspace:A,locator:A.anchoredLocator};let p=await u.findLocatorForLocation(`${o}/`,{strict:!0});if(p)return{project:u,locator:p,workspace:null};let h=Ut(e,u.cwd,Ct.PATH),E=Ut(e,K.relative(u.cwd,o),Ct.PATH),w=`- If ${h} isn't intended to be a project, remove any yarn.lock and/or package.json file there.`,D=`- If ${h} is intended to be a project, it might be that you forgot to list ${E} in its workspace configuration.`,b=`- Finally, if ${h} is fine and you intend ${E} to be treated as a completely separate project (not even a workspace), create an empty yarn.lock file in it.`;throw new ot(`The nearest package directory (${Ut(e,o,Ct.PATH)}) doesn't seem to be part of the project declared in ${Ut(e,u.cwd,Ct.PATH)}.\n\n${[w,D,b].join(`\n`)}`)}async setupResolutions(){this.storedResolutions=new Map,this.storedDescriptors=new Map,this.storedPackages=new Map,this.lockFileChecksum=null;let e=K.join(this.cwd,mr.lockfile),r=this.configuration.get(\"defaultLanguageName\");if(ae.existsSync(e)){let o=await ae.readFilePromise(e,\"utf8\");this.lockFileChecksum=Ohe(o);let a=Ki(o);if(a.__metadata){let n=a.__metadata.version,u=a.__metadata.cacheKey;this.lockfileLastVersion=n,this.lockfileNeedsRefresh=n<Tk;for(let A of Object.keys(a)){if(A===\"__metadata\")continue;let p=a[A];if(typeof p.resolution>\"u\")throw new Error(`Assertion failed: Expected the lockfile entry to have a resolution field (${A})`);let h=Sf(p.resolution,!0),E=new _t;E.load(p,{yamlCompatibilityMode:!0});let w=E.version,D=E.languageName||r,b=p.linkType.toUpperCase(),C=p.conditions??null,T=E.dependencies,N=E.peerDependencies,U=E.dependenciesMeta,z=E.peerDependenciesMeta,te=E.bin;if(p.checksum!=null){let ce=typeof u<\"u\"&&!p.checksum.includes(\"/\")?`${u}/${p.checksum}`:p.checksum;this.storedChecksums.set(h.locatorHash,ce)}let le={...h,version:w,languageName:D,linkType:b,conditions:C,dependencies:T,peerDependencies:N,dependenciesMeta:U,peerDependenciesMeta:z,bin:te};this.originalPackages.set(le.locatorHash,le);for(let ce of A.split(EAt)){let ue=lh(ce);n<=6&&(ue=this.configuration.normalizeDependency(ue),ue=kn(ue,ue.range.replace(/^patch:[^@]+@(?!npm(:|%3A))/,\"$1npm%3A\"))),this.storedDescriptors.set(ue.descriptorHash,ue),this.storedResolutions.set(ue.descriptorHash,h.locatorHash)}}}else o.includes(\"yarn lockfile v1\")&&(this.lockfileLastVersion=-1)}}async setupWorkspaces(){this.workspaces=[],this.workspacesByCwd=new Map,this.workspacesByIdent=new Map;let e=new Set,r=(0,Rk.default)(4),o=async(a,n)=>{if(e.has(n))return a;e.add(n);let u=new iE(n,{project:this});await r(()=>u.setup());let A=a.then(()=>{this.addWorkspace(u)});return Array.from(u.workspacesCwds).reduce(o,A)};await o(Promise.resolve(),this.cwd)}addWorkspace(e){let r=this.workspacesByIdent.get(e.anchoredLocator.identHash);if(typeof r<\"u\")throw new Error(`Duplicate workspace name ${Ui(this.configuration,e.anchoredLocator)}: ${Ae.fromPortablePath(e.cwd)} conflicts with ${Ae.fromPortablePath(r.cwd)}`);this.workspaces.push(e),this.workspacesByCwd.set(e.cwd,e),this.workspacesByIdent.set(e.anchoredLocator.identHash,e)}get topLevelWorkspace(){return this.getWorkspaceByCwd(this.cwd)}tryWorkspaceByCwd(e){K.isAbsolute(e)||(e=K.resolve(this.cwd,e)),e=K.normalize(e).replace(/\\/+$/,\"\");let r=this.workspacesByCwd.get(e);return r||null}getWorkspaceByCwd(e){let r=this.tryWorkspaceByCwd(e);if(!r)throw new Error(`Workspace not found (${e})`);return r}tryWorkspaceByFilePath(e){let r=null;for(let o of this.workspaces)K.relative(o.cwd,e).startsWith(\"../\")||r&&r.cwd.length>=o.cwd.length||(r=o);return r||null}getWorkspaceByFilePath(e){let r=this.tryWorkspaceByFilePath(e);if(!r)throw new Error(`Workspace not found (${e})`);return r}tryWorkspaceByIdent(e){let r=this.workspacesByIdent.get(e.identHash);return typeof r>\"u\"?null:r}getWorkspaceByIdent(e){let r=this.tryWorkspaceByIdent(e);if(!r)throw new Error(`Workspace not found (${Ui(this.configuration,e)})`);return r}tryWorkspaceByDescriptor(e){if(e.range.startsWith(ci.protocol)){let o=e.range.slice(ci.protocol.length);if(o!==\"^\"&&o!==\"~\"&&o!==\"*\"&&!Fa(o))return this.tryWorkspaceByCwd(o)}let r=this.tryWorkspaceByIdent(e);return r===null||(Pf(e)&&(e=C1(e)),!r.accepts(e.range))?null:r}getWorkspaceByDescriptor(e){let r=this.tryWorkspaceByDescriptor(e);if(r===null)throw new Error(`Workspace not found (${zn(this.configuration,e)})`);return r}tryWorkspaceByLocator(e){let r=this.tryWorkspaceByIdent(e);return r===null||(zc(e)&&(e=I1(e)),r.anchoredLocator.locatorHash!==e.locatorHash)?null:r}getWorkspaceByLocator(e){let r=this.tryWorkspaceByLocator(e);if(!r)throw new Error(`Workspace not found (${jr(this.configuration,e)})`);return r}deleteDescriptor(e){this.storedResolutions.delete(e),this.storedDescriptors.delete(e)}deleteLocator(e){this.originalPackages.delete(e),this.storedPackages.delete(e),this.accessibleLocators.delete(e)}forgetResolution(e){if(\"descriptorHash\"in e){let r=this.storedResolutions.get(e.descriptorHash);this.deleteDescriptor(e.descriptorHash);let o=new Set(this.storedResolutions.values());typeof r<\"u\"&&!o.has(r)&&this.deleteLocator(r)}if(\"locatorHash\"in e){this.deleteLocator(e.locatorHash);for(let[r,o]of this.storedResolutions)o===e.locatorHash&&this.deleteDescriptor(r)}}forgetTransientResolutions(){let e=this.configuration.makeResolver(),r=new Map;for(let[o,a]of this.storedResolutions.entries()){let n=r.get(a);n||r.set(a,n=new Set),n.add(o)}for(let o of this.originalPackages.values()){let a;try{a=e.shouldPersistResolution(o,{project:this,resolver:e})}catch{a=!1}if(!a){this.deleteLocator(o.locatorHash);let n=r.get(o.locatorHash);if(n){r.delete(o.locatorHash);for(let u of n)this.deleteDescriptor(u)}}}}forgetVirtualResolutions(){for(let e of this.storedPackages.values())for(let[r,o]of e.dependencies)Pf(o)&&e.dependencies.set(r,C1(o))}getDependencyMeta(e,r){let o={},n=this.topLevelWorkspace.manifest.dependenciesMeta.get(rn(e));if(!n)return o;let u=n.get(null);if(u&&Object.assign(o,u),r===null||!Mhe.default.valid(r))return o;for(let[A,p]of n)A!==null&&A===r&&Object.assign(o,p);return o}async findLocatorForLocation(e,{strict:r=!1}={}){let o=new Ri,a=this.configuration.getLinkers(),n={project:this,report:o};for(let u of a){let A=await u.findPackageLocator(e,n);if(A){if(r&&(await u.findPackageLocation(A,n)).replace(Nhe,\"\")!==e.replace(Nhe,\"\"))continue;return A}}return null}async loadUserConfig(){let e=K.join(this.cwd,\".pnp.cjs\");await ae.existsPromise(e)&&vf(e).setup();let r=K.join(this.cwd,\"yarn.config.cjs\");return await ae.existsPromise(r)?vf(r):null}async preparePackage(e,{resolver:r,resolveOptions:o}){let a=await this.configuration.getPackageExtensions(),n=this.configuration.normalizePackage(e,{packageExtensions:a});for(let[u,A]of n.dependencies){let p=await this.configuration.reduceHook(E=>E.reduceDependency,A,this,n,A,{resolver:r,resolveOptions:o});if(!w1(A,p))throw new Error(\"Assertion failed: The descriptor ident cannot be changed through aliases\");let h=r.bindDescriptor(p,n,o);n.dependencies.set(u,h)}return n}async resolveEverything(e){if(!this.workspacesByCwd||!this.workspacesByIdent)throw new Error(\"Workspaces must have been setup before calling this function\");this.forgetVirtualResolutions();let r=new Map(this.originalPackages),o=[];e.lockfileOnly||this.forgetTransientResolutions();let a=e.resolver||this.configuration.makeResolver(),n=new tE(a);await n.setup(this,{report:e.report});let u=e.lockfileOnly?[new kk(a)]:[n,a],A=new Pg([new rE(a),...u]),p=new Pg([...u]),h=this.configuration.makeFetcher(),E=e.lockfileOnly?{project:this,report:e.report,resolver:A}:{project:this,report:e.report,resolver:A,fetchOptions:{project:this,cache:e.cache,checksums:this.storedChecksums,report:e.report,fetcher:h,cacheOptions:{mirrorWriteOnly:!0}}},w=new Map,D=new Map,b=new Map,C=new Map,T=new Map,N=new Map,U=this.topLevelWorkspace.anchoredLocator,z=new Set,te=[],le=IU(),ce=this.configuration.getSupportedArchitectures();await e.report.startProgressPromise(Ws.progressViaTitle(),async ie=>{let Z=async nt=>{let Le=await Jm(async()=>await A.resolve(nt,E),xe=>`${jr(this.configuration,nt)}: ${xe}`);if(!B1(nt,Le))throw new Error(`Assertion failed: The locator cannot be changed by the resolver (went from ${jr(this.configuration,nt)} to ${jr(this.configuration,Le)})`);C.set(Le.locatorHash,Le),!r.delete(Le.locatorHash)&&!this.tryWorkspaceByLocator(Le)&&o.push(Le);let ke=await this.preparePackage(Le,{resolver:A,resolveOptions:E}),Ve=Wc([...ke.dependencies.values()].map(xe=>q(xe)));return te.push(Ve),Ve.catch(()=>{}),D.set(ke.locatorHash,ke),ke},Pe=async nt=>{let Le=T.get(nt.locatorHash);if(typeof Le<\"u\")return Le;let Te=Promise.resolve().then(()=>Z(nt));return T.set(nt.locatorHash,Te),Te},Re=async(nt,Le)=>{let Te=await q(Le);return w.set(nt.descriptorHash,nt),b.set(nt.descriptorHash,Te.locatorHash),Te},ht=async nt=>{ie.setTitle(zn(this.configuration,nt));let Le=this.resolutionAliases.get(nt.descriptorHash);if(typeof Le<\"u\")return Re(nt,this.storedDescriptors.get(Le));let Te=A.getResolutionDependencies(nt,E),ke=Object.fromEntries(await Wc(Object.entries(Te).map(async([tt,He])=>{let x=A.bindDescriptor(He,U,E),I=await q(x);return z.add(I.locatorHash),[tt,I]}))),xe=(await Jm(async()=>await A.getCandidates(nt,ke,E),tt=>`${zn(this.configuration,nt)}: ${tt}`))[0];if(typeof xe>\"u\")throw new zt(82,`${zn(this.configuration,nt)}: No candidates found`);if(e.checkResolutions){let{locators:tt}=await p.getSatisfying(nt,ke,[xe],{...E,resolver:p});if(!tt.find(He=>He.locatorHash===xe.locatorHash))throw new zt(78,`Invalid resolution ${d1(this.configuration,nt,xe)}`)}return w.set(nt.descriptorHash,nt),b.set(nt.descriptorHash,xe.locatorHash),Pe(xe)},q=nt=>{let Le=N.get(nt.descriptorHash);if(typeof Le<\"u\")return Le;w.set(nt.descriptorHash,nt);let Te=Promise.resolve().then(()=>ht(nt));return N.set(nt.descriptorHash,Te),Te};for(let nt of this.workspaces){let Le=nt.anchoredDescriptor;te.push(q(Le))}for(;te.length>0;){let nt=[...te];te.length=0,await Wc(nt)}});let ue=ul(r.values(),ie=>this.tryWorkspaceByLocator(ie)?ul.skip:ie);if(o.length>0||ue.length>0){let ie=new Set(this.workspaces.flatMap(nt=>{let Le=D.get(nt.anchoredLocator.locatorHash);if(!Le)throw new Error(\"Assertion failed: The workspace should have been resolved\");return Array.from(Le.dependencies.values(),Te=>{let ke=b.get(Te.descriptorHash);if(!ke)throw new Error(\"Assertion failed: The resolution should have been registered\");return ke})})),Z=nt=>ie.has(nt.locatorHash)?\"0\":\"1\",Pe=nt=>Qa(nt),Re=Ps(o,[Z,Pe]),ht=Ps(ue,[Z,Pe]),q=e.report.getRecommendedLength();Re.length>0&&e.report.reportInfo(85,`${Ut(this.configuration,\"+\",Ct.ADDED)} ${_S(this.configuration,Re,q)}`),ht.length>0&&e.report.reportInfo(85,`${Ut(this.configuration,\"-\",Ct.REMOVED)} ${_S(this.configuration,ht,q)}`)}let Ie=new Set(this.resolutionAliases.values()),he=new Set(D.keys()),De=new Set,Ee=new Map,g=[],me=new Map;BAt({project:this,accessibleLocators:De,volatileDescriptors:Ie,optionalBuilds:he,peerRequirements:Ee,peerWarnings:g,peerRequirementNodes:me,allDescriptors:w,allResolutions:b,allPackages:D});for(let ie of z)he.delete(ie);for(let ie of Ie)w.delete(ie),b.delete(ie);let Ce=new Set,fe=new Set;for(let ie of D.values())ie.conditions!=null&&he.has(ie.locatorHash)&&(Ex(ie,ce)||(Ex(ie,le)&&e.report.reportWarningOnce(77,`${jr(this.configuration,ie)}: Your current architecture (${process.platform}-${process.arch}) is supported by this package, but is missing from the ${Ut(this.configuration,\"supportedArchitectures\",Ct.SETTING)} setting`),fe.add(ie.locatorHash)),Ce.add(ie.locatorHash));this.storedResolutions=b,this.storedDescriptors=w,this.storedPackages=D,this.accessibleLocators=De,this.conditionalLocators=Ce,this.disabledLocators=fe,this.originalPackages=C,this.optionalBuilds=he,this.peerRequirements=Ee,this.peerWarnings=g,this.peerRequirementNodes=me}async fetchEverything({cache:e,report:r,fetcher:o,mode:a,persistProject:n=!0}){let u={mockedPackages:this.disabledLocators,unstablePackages:this.conditionalLocators},A=o||this.configuration.makeFetcher(),p={checksums:this.storedChecksums,project:this,cache:e,fetcher:A,report:r,cacheOptions:u},h=Array.from(new Set(Ps(this.storedResolutions.values(),[C=>{let T=this.storedPackages.get(C);if(!T)throw new Error(\"Assertion failed: The locator should have been registered\");return Qa(T)}])));a===\"update-lockfile\"&&(h=h.filter(C=>!this.storedChecksums.has(C)));let E=!1,w=Ws.progressViaCounter(h.length);await r.reportProgress(w);let D=(0,Rk.default)(CAt);if(await Wc(h.map(C=>D(async()=>{let T=this.storedPackages.get(C);if(!T)throw new Error(\"Assertion failed: The locator should have been registered\");if(zc(T))return;let N;try{N=await A.fetch(T,p)}catch(U){U.message=`${jr(this.configuration,T)}: ${U.message}`,r.reportExceptionOnce(U),E=U;return}N.checksum!=null?this.storedChecksums.set(T.locatorHash,N.checksum):this.storedChecksums.delete(T.locatorHash),N.releaseFs&&N.releaseFs()}).finally(()=>{w.tick()}))),E)throw E;let b=n&&a!==\"update-lockfile\"?await this.cacheCleanup({cache:e,report:r}):null;if(r.cacheMisses.size>0||b){let T=(await Promise.all([...r.cacheMisses].map(async ue=>{let Ie=this.storedPackages.get(ue),he=this.storedChecksums.get(ue)??null,De=e.getLocatorPath(Ie,he);return(await ae.statPromise(De)).size}))).reduce((ue,Ie)=>ue+Ie,0)-(b?.size??0),N=r.cacheMisses.size,U=b?.count??0,z=`${TS(N,{zero:\"No new packages\",one:\"A package was\",more:`${Ut(this.configuration,N,Ct.NUMBER)} packages were`})} added to the project`,te=`${TS(U,{zero:\"none were\",one:\"one was\",more:`${Ut(this.configuration,U,Ct.NUMBER)} were`})} removed`,le=T!==0?` (${Ut(this.configuration,T,Ct.SIZE_DIFF)})`:\"\",ce=U>0?N>0?`${z}, and ${te}${le}.`:`${z}, but ${te}${le}.`:`${z}${le}.`;r.reportInfo(13,ce)}}async linkEverything({cache:e,report:r,fetcher:o,mode:a}){let n={mockedPackages:this.disabledLocators,unstablePackages:this.conditionalLocators,skipIntegrityCheck:!0},u=o||this.configuration.makeFetcher(),A={checksums:this.storedChecksums,project:this,cache:e,fetcher:u,report:r,cacheOptions:n},p=this.configuration.getLinkers(),h={project:this,report:r},E=new Map(p.map(Ce=>{let fe=Ce.makeInstaller(h),ie=Ce.getCustomDataKey(),Z=this.linkersCustomData.get(ie);return typeof Z<\"u\"&&fe.attachCustomData(Z),[Ce,fe]})),w=new Map,D=new Map,b=new Map,C=new Map(await Wc([...this.accessibleLocators].map(async Ce=>{let fe=this.storedPackages.get(Ce);if(!fe)throw new Error(\"Assertion failed: The locator should have been registered\");return[Ce,await u.fetch(fe,A)]}))),T=[],N=new Set,U=[];for(let Ce of this.accessibleLocators){let fe=this.storedPackages.get(Ce);if(typeof fe>\"u\")throw new Error(\"Assertion failed: The locator should have been registered\");let ie=C.get(fe.locatorHash);if(typeof ie>\"u\")throw new Error(\"Assertion failed: The fetch result should have been registered\");let Z=[],Pe=ht=>{Z.push(ht)},Re=this.tryWorkspaceByLocator(fe);if(Re!==null){let ht=[],{scripts:q}=Re.manifest;for(let Le of[\"preinstall\",\"install\",\"postinstall\"])q.has(Le)&&ht.push({type:0,script:Le});try{for(let[Le,Te]of E)if(Le.supportsPackage(fe,h)&&(await Te.installPackage(fe,ie,{holdFetchResult:Pe})).buildRequest!==null)throw new Error(\"Assertion failed: Linkers can't return build directives for workspaces; this responsibility befalls to the Yarn core\")}finally{Z.length===0?ie.releaseFs?.():T.push(Wc(Z).catch(()=>{}).then(()=>{ie.releaseFs?.()}))}let nt=K.join(ie.packageFs.getRealPath(),ie.prefixPath);D.set(fe.locatorHash,nt),!zc(fe)&&ht.length>0&&b.set(fe.locatorHash,{buildDirectives:ht,buildLocations:[nt]})}else{let ht=p.find(Le=>Le.supportsPackage(fe,h));if(!ht)throw new zt(12,`${jr(this.configuration,fe)} isn't supported by any available linker`);let q=E.get(ht);if(!q)throw new Error(\"Assertion failed: The installer should have been registered\");let nt;try{nt=await q.installPackage(fe,ie,{holdFetchResult:Pe})}finally{Z.length===0?ie.releaseFs?.():T.push(Wc(Z).then(()=>{}).then(()=>{ie.releaseFs?.()}))}w.set(fe.locatorHash,ht),D.set(fe.locatorHash,nt.packageLocation),nt.buildRequest&&nt.packageLocation&&(nt.buildRequest.skipped?(N.add(fe.locatorHash),this.skippedBuilds.has(fe.locatorHash)||U.push([fe,nt.buildRequest.explain])):b.set(fe.locatorHash,{buildDirectives:nt.buildRequest.directives,buildLocations:[nt.packageLocation]}))}}let z=new Map;for(let Ce of this.accessibleLocators){let fe=this.storedPackages.get(Ce);if(!fe)throw new Error(\"Assertion failed: The locator should have been registered\");let ie=this.tryWorkspaceByLocator(fe)!==null,Z=async(Pe,Re)=>{let ht=D.get(fe.locatorHash);if(typeof ht>\"u\")throw new Error(`Assertion failed: The package (${jr(this.configuration,fe)}) should have been registered`);let q=[];for(let nt of fe.dependencies.values()){let Le=this.storedResolutions.get(nt.descriptorHash);if(typeof Le>\"u\")throw new Error(`Assertion failed: The resolution (${zn(this.configuration,nt)}, from ${jr(this.configuration,fe)})should have been registered`);let Te=this.storedPackages.get(Le);if(typeof Te>\"u\")throw new Error(`Assertion failed: The package (${Le}, resolved from ${zn(this.configuration,nt)}) should have been registered`);let ke=this.tryWorkspaceByLocator(Te)===null?w.get(Le):null;if(typeof ke>\"u\")throw new Error(`Assertion failed: The package (${Le}, resolved from ${zn(this.configuration,nt)}) should have been registered`);ke===Pe||ke===null?D.get(Te.locatorHash)!==null&&q.push([nt,Te]):!ie&&ht!==null&&u1(z,Le).push(ht)}ht!==null&&await Re.attachInternalDependencies(fe,q)};if(ie)for(let[Pe,Re]of E)Pe.supportsPackage(fe,h)&&await Z(Pe,Re);else{let Pe=w.get(fe.locatorHash);if(!Pe)throw new Error(\"Assertion failed: The linker should have been found\");let Re=E.get(Pe);if(!Re)throw new Error(\"Assertion failed: The installer should have been registered\");await Z(Pe,Re)}}for(let[Ce,fe]of z){let ie=this.storedPackages.get(Ce);if(!ie)throw new Error(\"Assertion failed: The package should have been registered\");let Z=w.get(ie.locatorHash);if(!Z)throw new Error(\"Assertion failed: The linker should have been found\");let Pe=E.get(Z);if(!Pe)throw new Error(\"Assertion failed: The installer should have been registered\");await Pe.attachExternalDependents(ie,fe)}let te=new Map;for(let[Ce,fe]of E){let ie=await fe.finalizeInstall();for(let Z of ie?.records??[])Z.buildRequest.skipped?(N.add(Z.locator.locatorHash),this.skippedBuilds.has(Z.locator.locatorHash)||U.push([Z.locator,Z.buildRequest.explain])):b.set(Z.locator.locatorHash,{buildDirectives:Z.buildRequest.directives,buildLocations:Z.buildLocations});typeof ie?.customData<\"u\"&&te.set(Ce.getCustomDataKey(),ie.customData)}if(this.linkersCustomData=te,await Wc(T),a===\"skip-build\")return;for(let[,Ce]of Ps(U,([fe])=>Qa(fe)))Ce(r);let le=new Set(b.keys()),ce=(0,Qk.createHash)(\"sha512\");ce.update(process.versions.node),await this.configuration.triggerHook(Ce=>Ce.globalHashGeneration,this,Ce=>{ce.update(\"\\0\"),ce.update(Ce)});let ue=ce.digest(\"hex\"),Ie=new Map,he=Ce=>{let fe=Ie.get(Ce.locatorHash);if(typeof fe<\"u\")return fe;let ie=this.storedPackages.get(Ce.locatorHash);if(typeof ie>\"u\")throw new Error(\"Assertion failed: The package should have been registered\");let Z=(0,Qk.createHash)(\"sha512\");Z.update(Ce.locatorHash),Ie.set(Ce.locatorHash,\"<recursive>\");for(let Pe of ie.dependencies.values()){let Re=this.storedResolutions.get(Pe.descriptorHash);if(typeof Re>\"u\")throw new Error(`Assertion failed: The resolution (${zn(this.configuration,Pe)}) should have been registered`);let ht=this.storedPackages.get(Re);if(typeof ht>\"u\")throw new Error(\"Assertion failed: The package should have been registered\");Z.update(he(ht))}return fe=Z.digest(\"hex\"),Ie.set(Ce.locatorHash,fe),fe},De=(Ce,fe)=>{let ie=(0,Qk.createHash)(\"sha512\");ie.update(ue),ie.update(he(Ce));for(let Z of fe)ie.update(Z);return ie.digest(\"hex\")},Ee=new Map,g=!1,me=Ce=>{let fe=new Set([Ce.locatorHash]);for(let ie of fe){let Z=this.storedPackages.get(ie);if(!Z)throw new Error(\"Assertion failed: The package should have been registered\");for(let Pe of Z.dependencies.values()){let Re=this.storedResolutions.get(Pe.descriptorHash);if(!Re)throw new Error(`Assertion failed: The resolution (${zn(this.configuration,Pe)}) should have been registered`);if(Re!==Ce.locatorHash&&le.has(Re))return!1;let ht=this.storedPackages.get(Re);if(!ht)throw new Error(\"Assertion failed: The package should have been registered\");let q=this.tryWorkspaceByLocator(ht);if(q){if(q.anchoredLocator.locatorHash!==Ce.locatorHash&&le.has(q.anchoredLocator.locatorHash))return!1;fe.add(q.anchoredLocator.locatorHash)}fe.add(Re)}}return!0};for(;le.size>0;){let Ce=le.size,fe=[];for(let ie of le){let Z=this.storedPackages.get(ie);if(!Z)throw new Error(\"Assertion failed: The package should have been registered\");if(!me(Z))continue;let Pe=b.get(Z.locatorHash);if(!Pe)throw new Error(\"Assertion failed: The build directive should have been registered\");let Re=De(Z,Pe.buildLocations);if(this.storedBuildState.get(Z.locatorHash)===Re){Ee.set(Z.locatorHash,Re),le.delete(ie);continue}g||(await this.persistInstallStateFile(),g=!0),this.storedBuildState.has(Z.locatorHash)?r.reportInfo(8,`${jr(this.configuration,Z)} must be rebuilt because its dependency tree changed`):r.reportInfo(7,`${jr(this.configuration,Z)} must be built because it never has been before or the last one failed`);let ht=Pe.buildLocations.map(async q=>{if(!K.isAbsolute(q))throw new Error(`Assertion failed: Expected the build location to be absolute (not ${q})`);for(let nt of Pe.buildDirectives){let Le=`# This file contains the result of Yarn building a package (${Qa(Z)})\n`;switch(nt.type){case 0:Le+=`# Script name: ${nt.script}\n`;break;case 1:Le+=`# Script code: ${nt.script}\n`;break}let Te=null;if(!await ae.mktempPromise(async Ve=>{let xe=K.join(Ve,\"build.log\"),{stdout:tt,stderr:He}=this.configuration.getSubprocessStreams(xe,{header:Le,prefix:jr(this.configuration,Z),report:r}),x;try{switch(nt.type){case 0:x=await Db(Z,nt.script,[],{cwd:q,project:this,stdin:Te,stdout:tt,stderr:He});break;case 1:x=await n3(Z,nt.script,[],{cwd:q,project:this,stdin:Te,stdout:tt,stderr:He});break}}catch(y){He.write(y.stack),x=1}if(tt.end(),He.end(),x===0)return!0;ae.detachTemp(Ve);let I=`${jr(this.configuration,Z)} couldn't be built successfully (exit code ${Ut(this.configuration,x,Ct.NUMBER)}, logs can be found here: ${Ut(this.configuration,xe,Ct.PATH)})`,S=this.optionalBuilds.has(Z.locatorHash);return S?r.reportInfo(9,I):r.reportError(9,I),Nue&&r.reportFold(Ae.fromPortablePath(xe),ae.readFileSync(xe,\"utf8\")),S}))return!1}return!0});fe.push(...ht,Promise.allSettled(ht).then(q=>{le.delete(ie),q.every(nt=>nt.status===\"fulfilled\"&&nt.value===!0)&&Ee.set(Z.locatorHash,Re)}))}if(await Wc(fe),Ce===le.size){let ie=Array.from(le).map(Z=>{let Pe=this.storedPackages.get(Z);if(!Pe)throw new Error(\"Assertion failed: The package should have been registered\");return jr(this.configuration,Pe)}).join(\", \");r.reportError(3,`Some packages have circular dependencies that make their build order unsatisfiable - as a result they won't be built (affected packages are: ${ie})`);break}}this.storedBuildState=Ee,this.skippedBuilds=N}async installWithNewReport(e,r){return(await Lt.start({configuration:this.configuration,json:e.json,stdout:e.stdout,forceSectionAlignment:!0,includeLogs:!e.json&&!e.quiet,includeVersion:!0},async a=>{await this.install({...r,report:a})})).exitCode()}async install(e){let r=this.configuration.get(\"nodeLinker\");Je.telemetry?.reportInstall(r);let o=!1;if(await e.report.startTimerPromise(\"Project validation\",{skipIfEmpty:!0},async()=>{this.configuration.get(\"enableOfflineMode\")&&e.report.reportWarning(90,\"Offline work is enabled; Yarn won't fetch packages from the remote registry if it can avoid it\"),await this.configuration.triggerHook(E=>E.validateProject,this,{reportWarning:(E,w)=>{e.report.reportWarning(E,w)},reportError:(E,w)=>{e.report.reportError(E,w),o=!0}})}),o)return;let a=await this.configuration.getPackageExtensions();for(let E of a.values())for(let[,w]of E)for(let D of w)D.status=\"inactive\";let n=K.join(this.cwd,mr.lockfile),u=null;if(e.immutable)try{u=await ae.readFilePromise(n,\"utf8\")}catch(E){throw E.code===\"ENOENT\"?new zt(28,\"The lockfile would have been created by this install, which is explicitly forbidden.\"):E}await e.report.startTimerPromise(\"Resolution step\",async()=>{await this.resolveEverything(e)}),await e.report.startTimerPromise(\"Post-resolution validation\",{skipIfEmpty:!0},async()=>{DAt(this,e.report);for(let[,E]of a)for(let[,w]of E)for(let D of w)if(D.userProvided){let b=Ut(this.configuration,D,Ct.PACKAGE_EXTENSION);switch(D.status){case\"inactive\":e.report.reportWarning(68,`${b}: No matching package in the dependency tree; you may not need this rule anymore.`);break;case\"redundant\":e.report.reportWarning(69,`${b}: This rule seems redundant when applied on the original package; the extension may have been applied upstream.`);break}}if(u!==null){let E=G0(u,this.generateLockfile());if(E!==u){let w=ehe(n,n,u,E,void 0,void 0,{maxEditLength:100});if(w){e.report.reportSeparator();for(let D of w.hunks){e.report.reportInfo(null,`@@ -${D.oldStart},${D.oldLines} +${D.newStart},${D.newLines} @@`);for(let b of D.lines)b.startsWith(\"+\")?e.report.reportError(28,Ut(this.configuration,b,Ct.ADDED)):b.startsWith(\"-\")?e.report.reportError(28,Ut(this.configuration,b,Ct.REMOVED)):e.report.reportInfo(null,Ut(this.configuration,b,\"grey\"))}e.report.reportSeparator()}throw new zt(28,\"The lockfile would have been modified by this install, which is explicitly forbidden.\")}}});for(let E of a.values())for(let[,w]of E)for(let D of w)D.userProvided&&D.status===\"active\"&&Je.telemetry?.reportPackageExtension(Ig(D,Ct.PACKAGE_EXTENSION));await e.report.startTimerPromise(\"Fetch step\",async()=>{await this.fetchEverything(e)});let A=e.immutable?[...new Set(this.configuration.get(\"immutablePatterns\"))].sort():[],p=await Promise.all(A.map(async E=>px(E,{cwd:this.cwd})));(typeof e.persistProject>\"u\"||e.persistProject)&&await this.persist(),await e.report.startTimerPromise(\"Link step\",async()=>{if(e.mode===\"update-lockfile\"){e.report.reportWarning(73,`Skipped due to ${Ut(this.configuration,\"mode=update-lockfile\",Ct.CODE)}`);return}await this.linkEverything(e);let E=await Promise.all(A.map(async w=>px(w,{cwd:this.cwd})));for(let w=0;w<A.length;++w)p[w]!==E[w]&&e.report.reportError(64,`The checksum for ${A[w]} has been modified by this install, which is explicitly forbidden.`)}),await this.persistInstallStateFile();let h=!1;await e.report.startTimerPromise(\"Post-install validation\",{skipIfEmpty:!0},async()=>{await this.configuration.triggerHook(E=>E.validateProjectAfterInstall,this,{reportWarning:(E,w)=>{e.report.reportWarning(E,w)},reportError:(E,w)=>{e.report.reportError(E,w),h=!0}})}),!h&&await this.configuration.triggerHook(E=>E.afterAllInstalled,this,e)}generateLockfile(){let e=new Map;for(let[n,u]of this.storedResolutions.entries()){let A=e.get(u);A||e.set(u,A=new Set),A.add(n)}let r={},{cacheKey:o}=Wr.getCacheKey(this.configuration);r.__metadata={version:Tk,cacheKey:o};for(let[n,u]of e.entries()){let A=this.originalPackages.get(n);if(!A)continue;let p=[];for(let w of u){let D=this.storedDescriptors.get(w);if(!D)throw new Error(\"Assertion failed: The descriptor should have been registered\");p.push(D)}let h=p.map(w=>ka(w)).sort().join(\", \"),E=new _t;E.version=A.linkType===\"HARD\"?A.version:\"0.0.0-use.local\",E.languageName=A.languageName,E.dependencies=new Map(A.dependencies),E.peerDependencies=new Map(A.peerDependencies),E.dependenciesMeta=new Map(A.dependenciesMeta),E.peerDependenciesMeta=new Map(A.peerDependenciesMeta),E.bin=new Map(A.bin),r[h]={...E.exportTo({},{compatibilityMode:!1}),linkType:A.linkType.toLowerCase(),resolution:Qa(A),checksum:this.storedChecksums.get(A.locatorHash),conditions:A.conditions||void 0}}return`${[`# This file is generated by running \"yarn install\" inside your project.\n`,`# Manual changes might be lost - proceed with caution!\n`].join(\"\")}\n`+Pa(r)}async persistLockfile(){let e=K.join(this.cwd,mr.lockfile),r=\"\";try{r=await ae.readFilePromise(e,\"utf8\")}catch{}let o=this.generateLockfile(),a=G0(r,o);a!==r&&(await ae.writeFilePromise(e,a),this.lockFileChecksum=Ohe(a),this.lockfileNeedsRefresh=!1)}async persistInstallStateFile(){let e=[];for(let u of Object.values(f8))e.push(...u);let r=(0,Fk.default)(this,e),o=p8.default.serialize(r),a=zi(o);if(this.installStateChecksum===a)return;let n=this.configuration.get(\"installStatePath\");await ae.mkdirPromise(K.dirname(n),{recursive:!0}),await ae.writeFilePromise(n,await IAt(o)),this.installStateChecksum=a}async restoreInstallState({restoreLinkersCustomData:e=!0,restoreResolutions:r=!0,restoreBuildState:o=!0}={}){let a=this.configuration.get(\"installStatePath\"),n;try{let u=await wAt(await ae.readFilePromise(a));n=p8.default.deserialize(u),this.installStateChecksum=zi(u)}catch{r&&await this.applyLightResolution();return}e&&typeof n.linkersCustomData<\"u\"&&(this.linkersCustomData=n.linkersCustomData),o&&Object.assign(this,(0,Fk.default)(n,f8.restoreBuildState)),r&&(n.lockFileChecksum===this.lockFileChecksum?Object.assign(this,(0,Fk.default)(n,f8.restoreResolutions)):await this.applyLightResolution())}async applyLightResolution(){await this.resolveEverything({lockfileOnly:!0,report:new Ri}),await this.persistInstallStateFile()}async persist(){let e=(0,Rk.default)(4);await Promise.all([this.persistLockfile(),...this.workspaces.map(r=>e(()=>r.persistManifest()))])}async cacheCleanup({cache:e,report:r}){if(this.configuration.get(\"enableGlobalCache\"))return null;let o=new Set([\".gitignore\"]);if(!n4(e.cwd,this.cwd)||!await ae.existsPromise(e.cwd))return null;let a=[];for(let u of await ae.readdirPromise(e.cwd)){if(o.has(u))continue;let A=K.resolve(e.cwd,u);e.markedFiles.has(A)||(e.immutable?r.reportError(56,`${Ut(this.configuration,K.basename(A),\"magenta\")} appears to be unused and would be marked for deletion, but the cache is immutable`):a.push(ae.lstatPromise(A).then(async p=>(await ae.removePromise(A),p.size))))}if(a.length===0)return null;let n=await Promise.all(a);return{count:a.length,size:n.reduce((u,A)=>u+A,0)}}}});function PAt(t){let o=Math.floor(t.timeNow/864e5),a=t.updateInterval*864e5,n=t.state.lastUpdate??t.timeNow+a+Math.floor(a*t.randomInitialInterval),u=n+a,A=t.state.lastTips??o*864e5,p=A+864e5+8*36e5-t.timeZone,h=u<=t.timeNow,E=p<=t.timeNow,w=null;return(h||E||!t.state.lastUpdate||!t.state.lastTips)&&(w={},w.lastUpdate=h?t.timeNow:n,w.lastTips=A,w.blocks=h?{}:t.state.blocks,w.displayedTips=t.state.displayedTips),{nextState:w,triggerUpdate:h,triggerTips:E,nextTips:E?o*864e5:A}}var sE,_he=It(()=>{Pt();r2();ah();eb();Gl();bf();sE=class{constructor(e,r){this.values=new Map;this.hits=new Map;this.enumerators=new Map;this.nextTips=0;this.displayedTips=[];this.shouldCommitTips=!1;this.configuration=e;let o=this.getRegistryPath();this.isNew=!ae.existsSync(o),this.shouldShowTips=!1,this.sendReport(r),this.startBuffer()}commitTips(){this.shouldShowTips&&(this.shouldCommitTips=!0)}selectTip(e){let r=new Set(this.displayedTips),o=A=>A&&nn?nA(nn,A):!1,a=e.map((A,p)=>p).filter(A=>e[A]&&o(e[A]?.selector));if(a.length===0)return null;let n=a.filter(A=>!r.has(A));if(n.length===0){let A=Math.floor(a.length*.2);this.displayedTips=A>0?this.displayedTips.slice(-A):[],n=a.filter(p=>!r.has(p))}let u=n[Math.floor(Math.random()*n.length)];return this.displayedTips.push(u),this.commitTips(),e[u]}reportVersion(e){this.reportValue(\"version\",e.replace(/-git\\..*/,\"-git\"))}reportCommandName(e){this.reportValue(\"commandName\",e||\"<none>\")}reportPluginName(e){this.reportValue(\"pluginName\",e)}reportProject(e){this.reportEnumerator(\"projectCount\",e)}reportInstall(e){this.reportHit(\"installCount\",e)}reportPackageExtension(e){this.reportValue(\"packageExtension\",e)}reportWorkspaceCount(e){this.reportValue(\"workspaceCount\",String(e))}reportDependencyCount(e){this.reportValue(\"dependencyCount\",String(e))}reportValue(e,r){zm(this.values,e).add(r)}reportEnumerator(e,r){zm(this.enumerators,e).add(zi(r))}reportHit(e,r=\"*\"){let o=A1(this.hits,e),a=Al(o,r,()=>0);o.set(r,a+1)}getRegistryPath(){let e=this.configuration.get(\"globalFolder\");return K.join(e,\"telemetry.json\")}sendReport(e){let r=this.getRegistryPath(),o;try{o=ae.readJsonSync(r)}catch{o={}}let{nextState:a,triggerUpdate:n,triggerTips:u,nextTips:A}=PAt({state:o,timeNow:Date.now(),timeZone:new Date().getTimezoneOffset()*60*1e3,randomInitialInterval:Math.random(),updateInterval:this.configuration.get(\"telemetryInterval\")});if(this.nextTips=A,this.displayedTips=o.displayedTips??[],a!==null)try{ae.mkdirSync(K.dirname(r),{recursive:!0}),ae.writeJsonSync(r,a)}catch{return!1}if(u&&this.configuration.get(\"enableTips\")&&(this.shouldShowTips=!0),n){let p=o.blocks??{};if(Object.keys(p).length===0){let h=`https://browser-http-intake.logs.datadoghq.eu/v1/input/${e}?ddsource=yarn`,E=w=>CU(h,w,{configuration:this.configuration}).catch(()=>{});for(let[w,D]of Object.entries(o.blocks??{})){if(Object.keys(D).length===0)continue;let b=D;b.userId=w,b.reportType=\"primary\";for(let N of Object.keys(b.enumerators??{}))b.enumerators[N]=b.enumerators[N].length;E(b);let C=new Map,T=20;for(let[N,U]of Object.entries(b.values))U.length>0&&C.set(N,U.slice(0,T));for(;C.size>0;){let N={};N.userId=w,N.reportType=\"secondary\",N.metrics={};for(let[U,z]of C)N.metrics[U]=z.shift(),z.length===0&&C.delete(U);E(N)}}}}return!0}applyChanges(){let e=this.getRegistryPath(),r;try{r=ae.readJsonSync(e)}catch{r={}}let o=this.configuration.get(\"telemetryUserId\")??\"*\",a=r.blocks=r.blocks??{},n=a[o]=a[o]??{};for(let u of this.hits.keys()){let A=n.hits=n.hits??{},p=A[u]=A[u]??{};for(let[h,E]of this.hits.get(u))p[h]=(p[h]??0)+E}for(let u of[\"values\",\"enumerators\"])for(let A of this[u].keys()){let p=n[u]=n[u]??{};p[A]=[...new Set([...p[A]??[],...this[u].get(A)??[]])]}this.shouldCommitTips&&(r.lastTips=this.nextTips,r.displayedTips=this.displayedTips),ae.mkdirSync(K.dirname(e),{recursive:!0}),ae.writeJsonSync(e,r)}startBuffer(){process.on(\"exit\",()=>{try{this.applyChanges()}catch{}})}}});var P2={};Kt(P2,{BuildDirectiveType:()=>Sk,CACHE_CHECKPOINT:()=>K_,CACHE_VERSION:()=>Pk,Cache:()=>Wr,Configuration:()=>Je,DEFAULT_RC_FILENAME:()=>SU,FormatType:()=>yce,InstallMode:()=>yl,LEGACY_PLUGINS:()=>j1,LOCKFILE_VERSION:()=>Tk,LegacyMigrationResolver:()=>tE,LightReport:()=>pA,LinkType:()=>$m,LockfileResolver:()=>rE,Manifest:()=>_t,MessageName:()=>vr,MultiFetcher:()=>py,PackageExtensionStatus:()=>sO,PackageExtensionType:()=>iO,PeerWarningType:()=>Lk,Project:()=>Qt,Report:()=>Ws,ReportError:()=>zt,SettingsType:()=>G1,StreamReport:()=>Lt,TAG_REGEXP:()=>by,TelemetryManager:()=>sE,ThrowReport:()=>Ri,VirtualFetcher:()=>hy,WindowsLinkType:()=>ab,Workspace:()=>iE,WorkspaceFetcher:()=>gy,WorkspaceResolver:()=>ci,YarnVersion:()=>nn,execUtils:()=>Hr,folderUtils:()=>Bx,formatUtils:()=>pe,hashUtils:()=>bn,httpUtils:()=>on,miscUtils:()=>qe,nodeUtils:()=>Xi,parseMessageName:()=>qP,reportOptionDeprecations:()=>Qy,scriptUtils:()=>hn,semverUtils:()=>Ur,stringifyMessageName:()=>zu,structUtils:()=>G,tgzUtils:()=>$i,treeUtils:()=>As});var Ke=It(()=>{nb();vx();Wl();ah();eb();Gl();rb();a3();bf();Io();_pe();Kpe();V_();W1();W1();zpe();z_();Jpe();J_();Ay();jP();YM();Uhe();Vl();n2();_he();u8();VM();zM();Dg();A8();r2();iie()});var Yhe=_((b_t,x2)=>{\"use strict\";var xAt=process.env.TERM_PROGRAM===\"Hyper\",bAt=process.platform===\"win32\",jhe=process.platform===\"linux\",d8={ballotDisabled:\"\\u2612\",ballotOff:\"\\u2610\",ballotOn:\"\\u2611\",bullet:\"\\u2022\",bulletWhite:\"\\u25E6\",fullBlock:\"\\u2588\",heart:\"\\u2764\",identicalTo:\"\\u2261\",line:\"\\u2500\",mark:\"\\u203B\",middot:\"\\xB7\",minus:\"\\uFF0D\",multiplication:\"\\xD7\",obelus:\"\\xF7\",pencilDownRight:\"\\u270E\",pencilRight:\"\\u270F\",pencilUpRight:\"\\u2710\",percent:\"%\",pilcrow2:\"\\u2761\",pilcrow:\"\\xB6\",plusMinus:\"\\xB1\",section:\"\\xA7\",starsOff:\"\\u2606\",starsOn:\"\\u2605\",upDownArrow:\"\\u2195\"},Ghe=Object.assign({},d8,{check:\"\\u221A\",cross:\"\\xD7\",ellipsisLarge:\"...\",ellipsis:\"...\",info:\"i\",question:\"?\",questionSmall:\"?\",pointer:\">\",pointerSmall:\"\\xBB\",radioOff:\"( )\",radioOn:\"(*)\",warning:\"\\u203C\"}),Whe=Object.assign({},d8,{ballotCross:\"\\u2718\",check:\"\\u2714\",cross:\"\\u2716\",ellipsisLarge:\"\\u22EF\",ellipsis:\"\\u2026\",info:\"\\u2139\",question:\"?\",questionFull:\"\\uFF1F\",questionSmall:\"\\uFE56\",pointer:jhe?\"\\u25B8\":\"\\u276F\",pointerSmall:jhe?\"\\u2023\":\"\\u203A\",radioOff:\"\\u25EF\",radioOn:\"\\u25C9\",warning:\"\\u26A0\"});x2.exports=bAt&&!xAt?Ghe:Whe;Reflect.defineProperty(x2.exports,\"common\",{enumerable:!1,value:d8});Reflect.defineProperty(x2.exports,\"windows\",{enumerable:!1,value:Ghe});Reflect.defineProperty(x2.exports,\"other\",{enumerable:!1,value:Whe})});var eu=_((k_t,m8)=>{\"use strict\";var kAt=t=>t!==null&&typeof t==\"object\"&&!Array.isArray(t),QAt=/[\\u001b\\u009b][[\\]#;?()]*(?:(?:(?:[^\\W_]*;?[^\\W_]*)\\u0007)|(?:(?:[0-9]{1,4}(;[0-9]{0,4})*)?[~0-9=<>cf-nqrtyA-PRZ]))/g,Khe=()=>{let t={enabled:!0,visible:!0,styles:{},keys:{}};\"FORCE_COLOR\"in process.env&&(t.enabled=process.env.FORCE_COLOR!==\"0\");let e=n=>{let u=n.open=`\\x1B[${n.codes[0]}m`,A=n.close=`\\x1B[${n.codes[1]}m`,p=n.regex=new RegExp(`\\\\u001b\\\\[${n.codes[1]}m`,\"g\");return n.wrap=(h,E)=>{h.includes(A)&&(h=h.replace(p,A+u));let w=u+h+A;return E?w.replace(/\\r*\\n/g,`${A}$&${u}`):w},n},r=(n,u,A)=>typeof n==\"function\"?n(u):n.wrap(u,A),o=(n,u)=>{if(n===\"\"||n==null)return\"\";if(t.enabled===!1)return n;if(t.visible===!1)return\"\";let A=\"\"+n,p=A.includes(`\n`),h=u.length;for(h>0&&u.includes(\"unstyle\")&&(u=[...new Set([\"unstyle\",...u])].reverse());h-- >0;)A=r(t.styles[u[h]],A,p);return A},a=(n,u,A)=>{t.styles[n]=e({name:n,codes:u}),(t.keys[A]||(t.keys[A]=[])).push(n),Reflect.defineProperty(t,n,{configurable:!0,enumerable:!0,set(h){t.alias(n,h)},get(){let h=E=>o(E,h.stack);return Reflect.setPrototypeOf(h,t),h.stack=this.stack?this.stack.concat(n):[n],h}})};return a(\"reset\",[0,0],\"modifier\"),a(\"bold\",[1,22],\"modifier\"),a(\"dim\",[2,22],\"modifier\"),a(\"italic\",[3,23],\"modifier\"),a(\"underline\",[4,24],\"modifier\"),a(\"inverse\",[7,27],\"modifier\"),a(\"hidden\",[8,28],\"modifier\"),a(\"strikethrough\",[9,29],\"modifier\"),a(\"black\",[30,39],\"color\"),a(\"red\",[31,39],\"color\"),a(\"green\",[32,39],\"color\"),a(\"yellow\",[33,39],\"color\"),a(\"blue\",[34,39],\"color\"),a(\"magenta\",[35,39],\"color\"),a(\"cyan\",[36,39],\"color\"),a(\"white\",[37,39],\"color\"),a(\"gray\",[90,39],\"color\"),a(\"grey\",[90,39],\"color\"),a(\"bgBlack\",[40,49],\"bg\"),a(\"bgRed\",[41,49],\"bg\"),a(\"bgGreen\",[42,49],\"bg\"),a(\"bgYellow\",[43,49],\"bg\"),a(\"bgBlue\",[44,49],\"bg\"),a(\"bgMagenta\",[45,49],\"bg\"),a(\"bgCyan\",[46,49],\"bg\"),a(\"bgWhite\",[47,49],\"bg\"),a(\"blackBright\",[90,39],\"bright\"),a(\"redBright\",[91,39],\"bright\"),a(\"greenBright\",[92,39],\"bright\"),a(\"yellowBright\",[93,39],\"bright\"),a(\"blueBright\",[94,39],\"bright\"),a(\"magentaBright\",[95,39],\"bright\"),a(\"cyanBright\",[96,39],\"bright\"),a(\"whiteBright\",[97,39],\"bright\"),a(\"bgBlackBright\",[100,49],\"bgBright\"),a(\"bgRedBright\",[101,49],\"bgBright\"),a(\"bgGreenBright\",[102,49],\"bgBright\"),a(\"bgYellowBright\",[103,49],\"bgBright\"),a(\"bgBlueBright\",[104,49],\"bgBright\"),a(\"bgMagentaBright\",[105,49],\"bgBright\"),a(\"bgCyanBright\",[106,49],\"bgBright\"),a(\"bgWhiteBright\",[107,49],\"bgBright\"),t.ansiRegex=QAt,t.hasColor=t.hasAnsi=n=>(t.ansiRegex.lastIndex=0,typeof n==\"string\"&&n!==\"\"&&t.ansiRegex.test(n)),t.alias=(n,u)=>{let A=typeof u==\"string\"?t[u]:u;if(typeof A!=\"function\")throw new TypeError(\"Expected alias to be the name of an existing color (string) or a function\");A.stack||(Reflect.defineProperty(A,\"name\",{value:n}),t.styles[n]=A,A.stack=[n]),Reflect.defineProperty(t,n,{configurable:!0,enumerable:!0,set(p){t.alias(n,p)},get(){let p=h=>o(h,p.stack);return Reflect.setPrototypeOf(p,t),p.stack=this.stack?this.stack.concat(A.stack):A.stack,p}})},t.theme=n=>{if(!kAt(n))throw new TypeError(\"Expected theme to be an object\");for(let u of Object.keys(n))t.alias(u,n[u]);return t},t.alias(\"unstyle\",n=>typeof n==\"string\"&&n!==\"\"?(t.ansiRegex.lastIndex=0,n.replace(t.ansiRegex,\"\")):\"\"),t.alias(\"noop\",n=>n),t.none=t.clear=t.noop,t.stripColor=t.unstyle,t.symbols=Yhe(),t.define=a,t};m8.exports=Khe();m8.exports.create=Khe});var xo=_(an=>{\"use strict\";var FAt=Object.prototype.toString,ic=eu(),Vhe=!1,y8=[],zhe={yellow:\"blue\",cyan:\"red\",green:\"magenta\",black:\"white\",blue:\"yellow\",red:\"cyan\",magenta:\"green\",white:\"black\"};an.longest=(t,e)=>t.reduce((r,o)=>Math.max(r,e?o[e].length:o.length),0);an.hasColor=t=>!!t&&ic.hasColor(t);var Ok=an.isObject=t=>t!==null&&typeof t==\"object\"&&!Array.isArray(t);an.nativeType=t=>FAt.call(t).slice(8,-1).toLowerCase().replace(/\\s/g,\"\");an.isAsyncFn=t=>an.nativeType(t)===\"asyncfunction\";an.isPrimitive=t=>t!=null&&typeof t!=\"object\"&&typeof t!=\"function\";an.resolve=(t,e,...r)=>typeof e==\"function\"?e.call(t,...r):e;an.scrollDown=(t=[])=>[...t.slice(1),t[0]];an.scrollUp=(t=[])=>[t.pop(),...t];an.reorder=(t=[])=>{let e=t.slice();return e.sort((r,o)=>r.index>o.index?1:r.index<o.index?-1:0),e};an.swap=(t,e,r)=>{let o=t.length,a=r===o?0:r<0?o-1:r,n=t[e];t[e]=t[a],t[a]=n};an.width=(t,e=80)=>{let r=t&&t.columns?t.columns:e;return t&&typeof t.getWindowSize==\"function\"&&(r=t.getWindowSize()[0]),process.platform===\"win32\"?r-1:r};an.height=(t,e=20)=>{let r=t&&t.rows?t.rows:e;return t&&typeof t.getWindowSize==\"function\"&&(r=t.getWindowSize()[1]),r};an.wordWrap=(t,e={})=>{if(!t)return t;typeof e==\"number\"&&(e={width:e});let{indent:r=\"\",newline:o=`\n`+r,width:a=80}=e,n=(o+r).match(/[^\\S\\n]/g)||[];a-=n.length;let u=`.{1,${a}}([\\\\s\\\\u200B]+|$)|[^\\\\s\\\\u200B]+?([\\\\s\\\\u200B]+|$)`,A=t.trim(),p=new RegExp(u,\"g\"),h=A.match(p)||[];return h=h.map(E=>E.replace(/\\n$/,\"\")),e.padEnd&&(h=h.map(E=>E.padEnd(a,\" \"))),e.padStart&&(h=h.map(E=>E.padStart(a,\" \"))),r+h.join(o)};an.unmute=t=>{let e=t.stack.find(o=>ic.keys.color.includes(o));return e?ic[e]:t.stack.find(o=>o.slice(2)===\"bg\")?ic[e.slice(2)]:o=>o};an.pascal=t=>t?t[0].toUpperCase()+t.slice(1):\"\";an.inverse=t=>{if(!t||!t.stack)return t;let e=t.stack.find(o=>ic.keys.color.includes(o));if(e){let o=ic[\"bg\"+an.pascal(e)];return o?o.black:t}let r=t.stack.find(o=>o.slice(0,2)===\"bg\");return r?ic[r.slice(2).toLowerCase()]||t:ic.none};an.complement=t=>{if(!t||!t.stack)return t;let e=t.stack.find(o=>ic.keys.color.includes(o)),r=t.stack.find(o=>o.slice(0,2)===\"bg\");if(e&&!r)return ic[zhe[e]||e];if(r){let o=r.slice(2).toLowerCase(),a=zhe[o];return a&&ic[\"bg\"+an.pascal(a)]||t}return ic.none};an.meridiem=t=>{let e=t.getHours(),r=t.getMinutes(),o=e>=12?\"pm\":\"am\";e=e%12;let a=e===0?12:e,n=r<10?\"0\"+r:r;return a+\":\"+n+\" \"+o};an.set=(t={},e=\"\",r)=>e.split(\".\").reduce((o,a,n,u)=>{let A=u.length-1>n?o[a]||{}:r;return!an.isObject(A)&&n<u.length-1&&(A={}),o[a]=A},t);an.get=(t={},e=\"\",r)=>{let o=t[e]==null?e.split(\".\").reduce((a,n)=>a&&a[n],t):t[e];return o??r};an.mixin=(t,e)=>{if(!Ok(t))return e;if(!Ok(e))return t;for(let r of Object.keys(e)){let o=Object.getOwnPropertyDescriptor(e,r);if(o.hasOwnProperty(\"value\"))if(t.hasOwnProperty(r)&&Ok(o.value)){let a=Object.getOwnPropertyDescriptor(t,r);Ok(a.value)?t[r]=an.merge({},t[r],e[r]):Reflect.defineProperty(t,r,o)}else Reflect.defineProperty(t,r,o);else Reflect.defineProperty(t,r,o)}return t};an.merge=(...t)=>{let e={};for(let r of t)an.mixin(e,r);return e};an.mixinEmitter=(t,e)=>{let r=e.constructor.prototype;for(let o of Object.keys(r)){let a=r[o];typeof a==\"function\"?an.define(t,o,a.bind(e)):an.define(t,o,a)}};an.onExit=t=>{let e=(r,o)=>{Vhe||(Vhe=!0,y8.forEach(a=>a()),r===!0&&process.exit(128+o))};y8.length===0&&(process.once(\"SIGTERM\",e.bind(null,!0,15)),process.once(\"SIGINT\",e.bind(null,!0,2)),process.once(\"exit\",e)),y8.push(t)};an.define=(t,e,r)=>{Reflect.defineProperty(t,e,{value:r})};an.defineExport=(t,e,r)=>{let o;Reflect.defineProperty(t,e,{enumerable:!0,configurable:!0,set(a){o=a},get(){return o?o():r()}})}});var Jhe=_(cE=>{\"use strict\";cE.ctrl={a:\"first\",b:\"backward\",c:\"cancel\",d:\"deleteForward\",e:\"last\",f:\"forward\",g:\"reset\",i:\"tab\",k:\"cutForward\",l:\"reset\",n:\"newItem\",m:\"cancel\",j:\"submit\",p:\"search\",r:\"remove\",s:\"save\",u:\"undo\",w:\"cutLeft\",x:\"toggleCursor\",v:\"paste\"};cE.shift={up:\"shiftUp\",down:\"shiftDown\",left:\"shiftLeft\",right:\"shiftRight\",tab:\"prev\"};cE.fn={up:\"pageUp\",down:\"pageDown\",left:\"pageLeft\",right:\"pageRight\",delete:\"deleteForward\"};cE.option={b:\"backward\",f:\"forward\",d:\"cutRight\",left:\"cutLeft\",up:\"altUp\",down:\"altDown\"};cE.keys={pageup:\"pageUp\",pagedown:\"pageDown\",home:\"home\",end:\"end\",cancel:\"cancel\",delete:\"deleteForward\",backspace:\"delete\",down:\"down\",enter:\"submit\",escape:\"cancel\",left:\"left\",space:\"space\",number:\"number\",return:\"submit\",right:\"right\",tab:\"next\",up:\"up\"}});var $he=_((R_t,Zhe)=>{\"use strict\";var Xhe=ve(\"readline\"),RAt=Jhe(),TAt=/^(?:\\x1b)([a-zA-Z0-9])$/,LAt=/^(?:\\x1b+)(O|N|\\[|\\[\\[)(?:(\\d+)(?:;(\\d+))?([~^$])|(?:1;)?(\\d+)?([a-zA-Z]))/,NAt={OP:\"f1\",OQ:\"f2\",OR:\"f3\",OS:\"f4\",\"[11~\":\"f1\",\"[12~\":\"f2\",\"[13~\":\"f3\",\"[14~\":\"f4\",\"[[A\":\"f1\",\"[[B\":\"f2\",\"[[C\":\"f3\",\"[[D\":\"f4\",\"[[E\":\"f5\",\"[15~\":\"f5\",\"[17~\":\"f6\",\"[18~\":\"f7\",\"[19~\":\"f8\",\"[20~\":\"f9\",\"[21~\":\"f10\",\"[23~\":\"f11\",\"[24~\":\"f12\",\"[A\":\"up\",\"[B\":\"down\",\"[C\":\"right\",\"[D\":\"left\",\"[E\":\"clear\",\"[F\":\"end\",\"[H\":\"home\",OA:\"up\",OB:\"down\",OC:\"right\",OD:\"left\",OE:\"clear\",OF:\"end\",OH:\"home\",\"[1~\":\"home\",\"[2~\":\"insert\",\"[3~\":\"delete\",\"[4~\":\"end\",\"[5~\":\"pageup\",\"[6~\":\"pagedown\",\"[[5~\":\"pageup\",\"[[6~\":\"pagedown\",\"[7~\":\"home\",\"[8~\":\"end\",\"[a\":\"up\",\"[b\":\"down\",\"[c\":\"right\",\"[d\":\"left\",\"[e\":\"clear\",\"[2$\":\"insert\",\"[3$\":\"delete\",\"[5$\":\"pageup\",\"[6$\":\"pagedown\",\"[7$\":\"home\",\"[8$\":\"end\",Oa:\"up\",Ob:\"down\",Oc:\"right\",Od:\"left\",Oe:\"clear\",\"[2^\":\"insert\",\"[3^\":\"delete\",\"[5^\":\"pageup\",\"[6^\":\"pagedown\",\"[7^\":\"home\",\"[8^\":\"end\",\"[Z\":\"tab\"};function OAt(t){return[\"[a\",\"[b\",\"[c\",\"[d\",\"[e\",\"[2$\",\"[3$\",\"[5$\",\"[6$\",\"[7$\",\"[8$\",\"[Z\"].includes(t)}function MAt(t){return[\"Oa\",\"Ob\",\"Oc\",\"Od\",\"Oe\",\"[2^\",\"[3^\",\"[5^\",\"[6^\",\"[7^\",\"[8^\"].includes(t)}var Mk=(t=\"\",e={})=>{let r,o={name:e.name,ctrl:!1,meta:!1,shift:!1,option:!1,sequence:t,raw:t,...e};if(Buffer.isBuffer(t)?t[0]>127&&t[1]===void 0?(t[0]-=128,t=\"\\x1B\"+String(t)):t=String(t):t!==void 0&&typeof t!=\"string\"?t=String(t):t||(t=o.sequence||\"\"),o.sequence=o.sequence||t||o.name,t===\"\\r\")o.raw=void 0,o.name=\"return\";else if(t===`\n`)o.name=\"enter\";else if(t===\"\t\")o.name=\"tab\";else if(t===\"\\b\"||t===\"\\x7F\"||t===\"\\x1B\\x7F\"||t===\"\\x1B\\b\")o.name=\"backspace\",o.meta=t.charAt(0)===\"\\x1B\";else if(t===\"\\x1B\"||t===\"\\x1B\\x1B\")o.name=\"escape\",o.meta=t.length===2;else if(t===\" \"||t===\"\\x1B \")o.name=\"space\",o.meta=t.length===2;else if(t<=\"\u001a\")o.name=String.fromCharCode(t.charCodeAt(0)+97-1),o.ctrl=!0;else if(t.length===1&&t>=\"0\"&&t<=\"9\")o.name=\"number\";else if(t.length===1&&t>=\"a\"&&t<=\"z\")o.name=t;else if(t.length===1&&t>=\"A\"&&t<=\"Z\")o.name=t.toLowerCase(),o.shift=!0;else if(r=TAt.exec(t))o.meta=!0,o.shift=/^[A-Z]$/.test(r[1]);else if(r=LAt.exec(t)){let a=[...t];a[0]===\"\\x1B\"&&a[1]===\"\\x1B\"&&(o.option=!0);let n=[r[1],r[2],r[4],r[6]].filter(Boolean).join(\"\"),u=(r[3]||r[5]||1)-1;o.ctrl=!!(u&4),o.meta=!!(u&10),o.shift=!!(u&1),o.code=n,o.name=NAt[n],o.shift=OAt(n)||o.shift,o.ctrl=MAt(n)||o.ctrl}return o};Mk.listen=(t={},e)=>{let{stdin:r}=t;if(!r||r!==process.stdin&&!r.isTTY)throw new Error(\"Invalid stream passed\");let o=Xhe.createInterface({terminal:!0,input:r});Xhe.emitKeypressEvents(r,o);let a=(A,p)=>e(A,Mk(A,p),o),n=r.isRaw;return r.isTTY&&r.setRawMode(!0),r.on(\"keypress\",a),o.resume(),()=>{r.isTTY&&r.setRawMode(n),r.removeListener(\"keypress\",a),o.pause(),o.close()}};Mk.action=(t,e,r)=>{let o={...RAt,...r};return e.ctrl?(e.action=o.ctrl[e.name],e):e.option&&o.option?(e.action=o.option[e.name],e):e.shift?(e.action=o.shift[e.name],e):(e.action=o.keys[e.name],e)};Zhe.exports=Mk});var t0e=_((T_t,e0e)=>{\"use strict\";e0e.exports=t=>{t.timers=t.timers||{};let e=t.options.timers;if(e)for(let r of Object.keys(e)){let o=e[r];typeof o==\"number\"&&(o={interval:o}),UAt(t,r,o)}};function UAt(t,e,r={}){let o=t.timers[e]={name:e,start:Date.now(),ms:0,tick:0},a=r.interval||120;o.frames=r.frames||[],o.loading=!0;let n=setInterval(()=>{o.ms=Date.now()-o.start,o.tick++,t.render()},a);return o.stop=()=>{o.loading=!1,clearInterval(n)},Reflect.defineProperty(o,\"interval\",{value:n}),t.once(\"close\",()=>o.stop()),o.stop}});var n0e=_((L_t,r0e)=>{\"use strict\";var{define:_At,width:HAt}=xo(),E8=class{constructor(e){let r=e.options;_At(this,\"_prompt\",e),this.type=e.type,this.name=e.name,this.message=\"\",this.header=\"\",this.footer=\"\",this.error=\"\",this.hint=\"\",this.input=\"\",this.cursor=0,this.index=0,this.lines=0,this.tick=0,this.prompt=\"\",this.buffer=\"\",this.width=HAt(r.stdout||process.stdout),Object.assign(this,r),this.name=this.name||this.message,this.message=this.message||this.name,this.symbols=e.symbols,this.styles=e.styles,this.required=new Set,this.cancelled=!1,this.submitted=!1}clone(){let e={...this};return e.status=this.status,e.buffer=Buffer.from(e.buffer),delete e.clone,e}set color(e){this._color=e}get color(){let e=this.prompt.styles;if(this.cancelled)return e.cancelled;if(this.submitted)return e.submitted;let r=this._color||e[this.status];return typeof r==\"function\"?r:e.pending}set loading(e){this._loading=e}get loading(){return typeof this._loading==\"boolean\"?this._loading:this.loadingChoices?\"choices\":!1}get status(){return this.cancelled?\"cancelled\":this.submitted?\"submitted\":\"pending\"}};r0e.exports=E8});var s0e=_((N_t,i0e)=>{\"use strict\";var C8=xo(),Ks=eu(),I8={default:Ks.noop,noop:Ks.noop,set inverse(t){this._inverse=t},get inverse(){return this._inverse||C8.inverse(this.primary)},set complement(t){this._complement=t},get complement(){return this._complement||C8.complement(this.primary)},primary:Ks.cyan,success:Ks.green,danger:Ks.magenta,strong:Ks.bold,warning:Ks.yellow,muted:Ks.dim,disabled:Ks.gray,dark:Ks.dim.gray,underline:Ks.underline,set info(t){this._info=t},get info(){return this._info||this.primary},set em(t){this._em=t},get em(){return this._em||this.primary.underline},set heading(t){this._heading=t},get heading(){return this._heading||this.muted.underline},set pending(t){this._pending=t},get pending(){return this._pending||this.primary},set submitted(t){this._submitted=t},get submitted(){return this._submitted||this.success},set cancelled(t){this._cancelled=t},get cancelled(){return this._cancelled||this.danger},set typing(t){this._typing=t},get typing(){return this._typing||this.dim},set placeholder(t){this._placeholder=t},get placeholder(){return this._placeholder||this.primary.dim},set highlight(t){this._highlight=t},get highlight(){return this._highlight||this.inverse}};I8.merge=(t={})=>{t.styles&&typeof t.styles.enabled==\"boolean\"&&(Ks.enabled=t.styles.enabled),t.styles&&typeof t.styles.visible==\"boolean\"&&(Ks.visible=t.styles.visible);let e=C8.merge({},I8,t.styles);delete e.merge;for(let r of Object.keys(Ks))e.hasOwnProperty(r)||Reflect.defineProperty(e,r,{get:()=>Ks[r]});for(let r of Object.keys(Ks.styles))e.hasOwnProperty(r)||Reflect.defineProperty(e,r,{get:()=>Ks[r]});return e};i0e.exports=I8});var a0e=_((O_t,o0e)=>{\"use strict\";var w8=process.platform===\"win32\",Yf=eu(),qAt=xo(),B8={...Yf.symbols,upDownDoubleArrow:\"\\u21D5\",upDownDoubleArrow2:\"\\u2B0D\",upDownArrow:\"\\u2195\",asterisk:\"*\",asterism:\"\\u2042\",bulletWhite:\"\\u25E6\",electricArrow:\"\\u2301\",ellipsisLarge:\"\\u22EF\",ellipsisSmall:\"\\u2026\",fullBlock:\"\\u2588\",identicalTo:\"\\u2261\",indicator:Yf.symbols.check,leftAngle:\"\\u2039\",mark:\"\\u203B\",minus:\"\\u2212\",multiplication:\"\\xD7\",obelus:\"\\xF7\",percent:\"%\",pilcrow:\"\\xB6\",pilcrow2:\"\\u2761\",pencilUpRight:\"\\u2710\",pencilDownRight:\"\\u270E\",pencilRight:\"\\u270F\",plus:\"+\",plusMinus:\"\\xB1\",pointRight:\"\\u261E\",rightAngle:\"\\u203A\",section:\"\\xA7\",hexagon:{off:\"\\u2B21\",on:\"\\u2B22\",disabled:\"\\u2B22\"},ballot:{on:\"\\u2611\",off:\"\\u2610\",disabled:\"\\u2612\"},stars:{on:\"\\u2605\",off:\"\\u2606\",disabled:\"\\u2606\"},folder:{on:\"\\u25BC\",off:\"\\u25B6\",disabled:\"\\u25B6\"},prefix:{pending:Yf.symbols.question,submitted:Yf.symbols.check,cancelled:Yf.symbols.cross},separator:{pending:Yf.symbols.pointerSmall,submitted:Yf.symbols.middot,cancelled:Yf.symbols.middot},radio:{off:w8?\"( )\":\"\\u25EF\",on:w8?\"(*)\":\"\\u25C9\",disabled:w8?\"(|)\":\"\\u24BE\"},numbers:[\"\\u24EA\",\"\\u2460\",\"\\u2461\",\"\\u2462\",\"\\u2463\",\"\\u2464\",\"\\u2465\",\"\\u2466\",\"\\u2467\",\"\\u2468\",\"\\u2469\",\"\\u246A\",\"\\u246B\",\"\\u246C\",\"\\u246D\",\"\\u246E\",\"\\u246F\",\"\\u2470\",\"\\u2471\",\"\\u2472\",\"\\u2473\",\"\\u3251\",\"\\u3252\",\"\\u3253\",\"\\u3254\",\"\\u3255\",\"\\u3256\",\"\\u3257\",\"\\u3258\",\"\\u3259\",\"\\u325A\",\"\\u325B\",\"\\u325C\",\"\\u325D\",\"\\u325E\",\"\\u325F\",\"\\u32B1\",\"\\u32B2\",\"\\u32B3\",\"\\u32B4\",\"\\u32B5\",\"\\u32B6\",\"\\u32B7\",\"\\u32B8\",\"\\u32B9\",\"\\u32BA\",\"\\u32BB\",\"\\u32BC\",\"\\u32BD\",\"\\u32BE\",\"\\u32BF\"]};B8.merge=t=>{let e=qAt.merge({},Yf.symbols,B8,t.symbols);return delete e.merge,e};o0e.exports=B8});var c0e=_((M_t,l0e)=>{\"use strict\";var jAt=s0e(),GAt=a0e(),WAt=xo();l0e.exports=t=>{t.options=WAt.merge({},t.options.theme,t.options),t.symbols=GAt.merge(t.options),t.styles=jAt.merge(t.options)}});var h0e=_((f0e,p0e)=>{\"use strict\";var u0e=process.env.TERM_PROGRAM===\"Apple_Terminal\",YAt=eu(),v8=xo(),tu=p0e.exports=f0e,Si=\"\\x1B[\",A0e=\"\\x07\",D8=!1,kh=tu.code={bell:A0e,beep:A0e,beginning:`${Si}G`,down:`${Si}J`,esc:Si,getPosition:`${Si}6n`,hide:`${Si}?25l`,line:`${Si}2K`,lineEnd:`${Si}K`,lineStart:`${Si}1K`,restorePosition:Si+(u0e?\"8\":\"u\"),savePosition:Si+(u0e?\"7\":\"s\"),screen:`${Si}2J`,show:`${Si}?25h`,up:`${Si}1J`},Yg=tu.cursor={get hidden(){return D8},hide(){return D8=!0,kh.hide},show(){return D8=!1,kh.show},forward:(t=1)=>`${Si}${t}C`,backward:(t=1)=>`${Si}${t}D`,nextLine:(t=1)=>`${Si}E`.repeat(t),prevLine:(t=1)=>`${Si}F`.repeat(t),up:(t=1)=>t?`${Si}${t}A`:\"\",down:(t=1)=>t?`${Si}${t}B`:\"\",right:(t=1)=>t?`${Si}${t}C`:\"\",left:(t=1)=>t?`${Si}${t}D`:\"\",to(t,e){return e?`${Si}${e+1};${t+1}H`:`${Si}${t+1}G`},move(t=0,e=0){let r=\"\";return r+=t<0?Yg.left(-t):t>0?Yg.right(t):\"\",r+=e<0?Yg.up(-e):e>0?Yg.down(e):\"\",r},restore(t={}){let{after:e,cursor:r,initial:o,input:a,prompt:n,size:u,value:A}=t;if(o=v8.isPrimitive(o)?String(o):\"\",a=v8.isPrimitive(a)?String(a):\"\",A=v8.isPrimitive(A)?String(A):\"\",u){let p=tu.cursor.up(u)+tu.cursor.to(n.length),h=a.length-r;return h>0&&(p+=tu.cursor.left(h)),p}if(A||e){let p=!a&&o?-o.length:-a.length+r;return e&&(p-=e.length),a===\"\"&&o&&!n.includes(o)&&(p+=o.length),tu.cursor.move(p)}}},P8=tu.erase={screen:kh.screen,up:kh.up,down:kh.down,line:kh.line,lineEnd:kh.lineEnd,lineStart:kh.lineStart,lines(t){let e=\"\";for(let r=0;r<t;r++)e+=tu.erase.line+(r<t-1?tu.cursor.up(1):\"\");return t&&(e+=tu.code.beginning),e}};tu.clear=(t=\"\",e=process.stdout.columns)=>{if(!e)return P8.line+Yg.to(0);let r=n=>[...YAt.unstyle(n)].length,o=t.split(/\\r?\\n/),a=0;for(let n of o)a+=1+Math.floor(Math.max(r(n)-1,0)/e);return(P8.line+Yg.prevLine()).repeat(a-1)+P8.line+Yg.to(0)}});var uE=_((U_t,d0e)=>{\"use strict\";var KAt=ve(\"events\"),g0e=eu(),S8=$he(),VAt=t0e(),zAt=n0e(),JAt=c0e(),Na=xo(),Kg=h0e(),x8=class t extends KAt{constructor(e={}){super(),this.name=e.name,this.type=e.type,this.options=e,JAt(this),VAt(this),this.state=new zAt(this),this.initial=[e.initial,e.default].find(r=>r!=null),this.stdout=e.stdout||process.stdout,this.stdin=e.stdin||process.stdin,this.scale=e.scale||1,this.term=this.options.term||process.env.TERM_PROGRAM,this.margin=ZAt(this.options.margin),this.setMaxListeners(0),XAt(this)}async keypress(e,r={}){this.keypressed=!0;let o=S8.action(e,S8(e,r),this.options.actions);this.state.keypress=o,this.emit(\"keypress\",e,o),this.emit(\"state\",this.state.clone());let a=this.options[o.action]||this[o.action]||this.dispatch;if(typeof a==\"function\")return await a.call(this,e,o);this.alert()}alert(){delete this.state.alert,this.options.show===!1?this.emit(\"alert\"):this.stdout.write(Kg.code.beep)}cursorHide(){this.stdout.write(Kg.cursor.hide()),Na.onExit(()=>this.cursorShow())}cursorShow(){this.stdout.write(Kg.cursor.show())}write(e){e&&(this.stdout&&this.state.show!==!1&&this.stdout.write(e),this.state.buffer+=e)}clear(e=0){let r=this.state.buffer;this.state.buffer=\"\",!(!r&&!e||this.options.show===!1)&&this.stdout.write(Kg.cursor.down(e)+Kg.clear(r,this.width))}restore(){if(this.state.closed||this.options.show===!1)return;let{prompt:e,after:r,rest:o}=this.sections(),{cursor:a,initial:n=\"\",input:u=\"\",value:A=\"\"}=this,p=this.state.size=o.length,h={after:r,cursor:a,initial:n,input:u,prompt:e,size:p,value:A},E=Kg.cursor.restore(h);E&&this.stdout.write(E)}sections(){let{buffer:e,input:r,prompt:o}=this.state;o=g0e.unstyle(o);let a=g0e.unstyle(e),n=a.indexOf(o),u=a.slice(0,n),p=a.slice(n).split(`\n`),h=p[0],E=p[p.length-1],D=(o+(r?\" \"+r:\"\")).length,b=D<h.length?h.slice(D+1):\"\";return{header:u,prompt:h,after:b,rest:p.slice(1),last:E}}async submit(){this.state.submitted=!0,this.state.validating=!0,this.options.onSubmit&&await this.options.onSubmit.call(this,this.name,this.value,this);let e=this.state.error||await this.validate(this.value,this.state);if(e!==!0){let r=`\n`+this.symbols.pointer+\" \";typeof e==\"string\"?r+=e.trim():r+=\"Invalid input\",this.state.error=`\n`+this.styles.danger(r),this.state.submitted=!1,await this.render(),await this.alert(),this.state.validating=!1,this.state.error=void 0;return}this.state.validating=!1,await this.render(),await this.close(),this.value=await this.result(this.value),this.emit(\"submit\",this.value)}async cancel(e){this.state.cancelled=this.state.submitted=!0,await this.render(),await this.close(),typeof this.options.onCancel==\"function\"&&await this.options.onCancel.call(this,this.name,this.value,this),this.emit(\"cancel\",await this.error(e))}async close(){this.state.closed=!0;try{let e=this.sections(),r=Math.ceil(e.prompt.length/this.width);e.rest&&this.write(Kg.cursor.down(e.rest.length)),this.write(`\n`.repeat(r))}catch{}this.emit(\"close\")}start(){!this.stop&&this.options.show!==!1&&(this.stop=S8.listen(this,this.keypress.bind(this)),this.once(\"close\",this.stop))}async skip(){return this.skipped=this.options.skip===!0,typeof this.options.skip==\"function\"&&(this.skipped=await this.options.skip.call(this,this.name,this.value)),this.skipped}async initialize(){let{format:e,options:r,result:o}=this;if(this.format=()=>e.call(this,this.value),this.result=()=>o.call(this,this.value),typeof r.initial==\"function\"&&(this.initial=await r.initial.call(this,this)),typeof r.onRun==\"function\"&&await r.onRun.call(this,this),typeof r.onSubmit==\"function\"){let a=r.onSubmit.bind(this),n=this.submit.bind(this);delete this.options.onSubmit,this.submit=async()=>(await a(this.name,this.value,this),n())}await this.start(),await this.render()}render(){throw new Error(\"expected prompt to have a custom render method\")}run(){return new Promise(async(e,r)=>{if(this.once(\"submit\",e),this.once(\"cancel\",r),await this.skip())return this.render=()=>{},this.submit();await this.initialize(),this.emit(\"run\")})}async element(e,r,o){let{options:a,state:n,symbols:u,timers:A}=this,p=A&&A[e];n.timer=p;let h=a[e]||n[e]||u[e],E=r&&r[e]!=null?r[e]:await h;if(E===\"\")return E;let w=await this.resolve(E,n,r,o);return!w&&r&&r[e]?this.resolve(h,n,r,o):w}async prefix(){let e=await this.element(\"prefix\")||this.symbols,r=this.timers&&this.timers.prefix,o=this.state;return o.timer=r,Na.isObject(e)&&(e=e[o.status]||e.pending),Na.hasColor(e)?e:(this.styles[o.status]||this.styles.pending)(e)}async message(){let e=await this.element(\"message\");return Na.hasColor(e)?e:this.styles.strong(e)}async separator(){let e=await this.element(\"separator\")||this.symbols,r=this.timers&&this.timers.separator,o=this.state;o.timer=r;let a=e[o.status]||e.pending||o.separator,n=await this.resolve(a,o);return Na.isObject(n)&&(n=n[o.status]||n.pending),Na.hasColor(n)?n:this.styles.muted(n)}async pointer(e,r){let o=await this.element(\"pointer\",e,r);if(typeof o==\"string\"&&Na.hasColor(o))return o;if(o){let a=this.styles,n=this.index===r,u=n?a.primary:h=>h,A=await this.resolve(o[n?\"on\":\"off\"]||o,this.state),p=Na.hasColor(A)?A:u(A);return n?p:\" \".repeat(A.length)}}async indicator(e,r){let o=await this.element(\"indicator\",e,r);if(typeof o==\"string\"&&Na.hasColor(o))return o;if(o){let a=this.styles,n=e.enabled===!0,u=n?a.success:a.dark,A=o[n?\"on\":\"off\"]||o;return Na.hasColor(A)?A:u(A)}return\"\"}body(){return null}footer(){if(this.state.status===\"pending\")return this.element(\"footer\")}header(){if(this.state.status===\"pending\")return this.element(\"header\")}async hint(){if(this.state.status===\"pending\"&&!this.isValue(this.state.input)){let e=await this.element(\"hint\");return Na.hasColor(e)?e:this.styles.muted(e)}}error(e){return this.state.submitted?\"\":e||this.state.error}format(e){return e}result(e){return e}validate(e){return this.options.required===!0?this.isValue(e):!0}isValue(e){return e!=null&&e!==\"\"}resolve(e,...r){return Na.resolve(this,e,...r)}get base(){return t.prototype}get style(){return this.styles[this.state.status]}get height(){return this.options.rows||Na.height(this.stdout,25)}get width(){return this.options.columns||Na.width(this.stdout,80)}get size(){return{width:this.width,height:this.height}}set cursor(e){this.state.cursor=e}get cursor(){return this.state.cursor}set input(e){this.state.input=e}get input(){return this.state.input}set value(e){this.state.value=e}get value(){let{input:e,value:r}=this.state,o=[r,e].find(this.isValue.bind(this));return this.isValue(o)?o:this.initial}static get prompt(){return e=>new this(e).run()}};function XAt(t){let e=a=>t[a]===void 0||typeof t[a]==\"function\",r=[\"actions\",\"choices\",\"initial\",\"margin\",\"roles\",\"styles\",\"symbols\",\"theme\",\"timers\",\"value\"],o=[\"body\",\"footer\",\"error\",\"header\",\"hint\",\"indicator\",\"message\",\"prefix\",\"separator\",\"skip\"];for(let a of Object.keys(t.options)){if(r.includes(a)||/^on[A-Z]/.test(a))continue;let n=t.options[a];typeof n==\"function\"&&e(a)?o.includes(a)||(t[a]=n.bind(t)):typeof t[a]!=\"function\"&&(t[a]=n)}}function ZAt(t){typeof t==\"number\"&&(t=[t,t,t,t]);let e=[].concat(t||[]),r=a=>a%2===0?`\n`:\" \",o=[];for(let a=0;a<4;a++){let n=r(a);e[a]?o.push(n.repeat(e[a])):o.push(\"\")}return o}d0e.exports=x8});var E0e=_((__t,y0e)=>{\"use strict\";var $At=xo(),m0e={default(t,e){return e},checkbox(t,e){throw new Error(\"checkbox role is not implemented yet\")},editable(t,e){throw new Error(\"editable role is not implemented yet\")},expandable(t,e){throw new Error(\"expandable role is not implemented yet\")},heading(t,e){return e.disabled=\"\",e.indicator=[e.indicator,\" \"].find(r=>r!=null),e.message=e.message||\"\",e},input(t,e){throw new Error(\"input role is not implemented yet\")},option(t,e){return m0e.default(t,e)},radio(t,e){throw new Error(\"radio role is not implemented yet\")},separator(t,e){return e.disabled=\"\",e.indicator=[e.indicator,\" \"].find(r=>r!=null),e.message=e.message||t.symbols.line.repeat(5),e},spacer(t,e){return e}};y0e.exports=(t,e={})=>{let r=$At.merge({},m0e,e.roles);return r[t]||r.default}});var b2=_((H_t,w0e)=>{\"use strict\";var eft=eu(),tft=uE(),rft=E0e(),Uk=xo(),{reorder:b8,scrollUp:nft,scrollDown:ift,isObject:C0e,swap:sft}=Uk,k8=class extends tft{constructor(e){super(e),this.cursorHide(),this.maxSelected=e.maxSelected||1/0,this.multiple=e.multiple||!1,this.initial=e.initial||0,this.delay=e.delay||0,this.longest=0,this.num=\"\"}async initialize(){typeof this.options.initial==\"function\"&&(this.initial=await this.options.initial.call(this)),await this.reset(!0),await super.initialize()}async reset(){let{choices:e,initial:r,autofocus:o,suggest:a}=this.options;if(this.state._choices=[],this.state.choices=[],this.choices=await Promise.all(await this.toChoices(e)),this.choices.forEach(n=>n.enabled=!1),typeof a!=\"function\"&&this.selectable.length===0)throw new Error(\"At least one choice must be selectable\");C0e(r)&&(r=Object.keys(r)),Array.isArray(r)?(o!=null&&(this.index=this.findIndex(o)),r.forEach(n=>this.enable(this.find(n))),await this.render()):(o!=null&&(r=o),typeof r==\"string\"&&(r=this.findIndex(r)),typeof r==\"number\"&&r>-1&&(this.index=Math.max(0,Math.min(r,this.choices.length)),this.enable(this.find(this.index)))),this.isDisabled(this.focused)&&await this.down()}async toChoices(e,r){this.state.loadingChoices=!0;let o=[],a=0,n=async(u,A)=>{typeof u==\"function\"&&(u=await u.call(this)),u instanceof Promise&&(u=await u);for(let p=0;p<u.length;p++){let h=u[p]=await this.toChoice(u[p],a++,A);o.push(h),h.choices&&await n(h.choices,h)}return o};return n(e,r).then(u=>(this.state.loadingChoices=!1,u))}async toChoice(e,r,o){if(typeof e==\"function\"&&(e=await e.call(this,this)),e instanceof Promise&&(e=await e),typeof e==\"string\"&&(e={name:e}),e.normalized)return e;e.normalized=!0;let a=e.value;if(e=rft(e.role,this.options)(this,e),typeof e.disabled==\"string\"&&!e.hint&&(e.hint=e.disabled,e.disabled=!0),e.disabled===!0&&e.hint==null&&(e.hint=\"(disabled)\"),e.index!=null)return e;e.name=e.name||e.key||e.title||e.value||e.message,e.message=e.message||e.name||\"\",e.value=[e.value,e.name].find(this.isValue.bind(this)),e.input=\"\",e.index=r,e.cursor=0,Uk.define(e,\"parent\",o),e.level=o?o.level+1:1,e.indent==null&&(e.indent=o?o.indent+\"  \":e.indent||\"\"),e.path=o?o.path+\".\"+e.name:e.name,e.enabled=!!(this.multiple&&!this.isDisabled(e)&&(e.enabled||this.isSelected(e))),this.isDisabled(e)||(this.longest=Math.max(this.longest,eft.unstyle(e.message).length));let u={...e};return e.reset=(A=u.input,p=u.value)=>{for(let h of Object.keys(u))e[h]=u[h];e.input=A,e.value=p},a==null&&typeof e.initial==\"function\"&&(e.input=await e.initial.call(this,this.state,e,r)),e}async onChoice(e,r){this.emit(\"choice\",e,r,this),typeof e.onChoice==\"function\"&&await e.onChoice.call(this,this.state,e,r)}async addChoice(e,r,o){let a=await this.toChoice(e,r,o);return this.choices.push(a),this.index=this.choices.length-1,this.limit=this.choices.length,a}async newItem(e,r,o){let a={name:\"New choice name?\",editable:!0,newChoice:!0,...e},n=await this.addChoice(a,r,o);return n.updateChoice=()=>{delete n.newChoice,n.name=n.message=n.input,n.input=\"\",n.cursor=0},this.render()}indent(e){return e.indent==null?e.level>1?\"  \".repeat(e.level-1):\"\":e.indent}dispatch(e,r){if(this.multiple&&this[r.name])return this[r.name]();this.alert()}focus(e,r){return typeof r!=\"boolean\"&&(r=e.enabled),r&&!e.enabled&&this.selected.length>=this.maxSelected?this.alert():(this.index=e.index,e.enabled=r&&!this.isDisabled(e),e)}space(){return this.multiple?(this.toggle(this.focused),this.render()):this.alert()}a(){if(this.maxSelected<this.choices.length)return this.alert();let e=this.selectable.every(r=>r.enabled);return this.choices.forEach(r=>r.enabled=!e),this.render()}i(){return this.choices.length-this.selected.length>this.maxSelected?this.alert():(this.choices.forEach(e=>e.enabled=!e.enabled),this.render())}g(e=this.focused){return this.choices.some(r=>!!r.parent)?(this.toggle(e.parent&&!e.choices?e.parent:e),this.render()):this.a()}toggle(e,r){if(!e.enabled&&this.selected.length>=this.maxSelected)return this.alert();typeof r!=\"boolean\"&&(r=!e.enabled),e.enabled=r,e.choices&&e.choices.forEach(a=>this.toggle(a,r));let o=e.parent;for(;o;){let a=o.choices.filter(n=>this.isDisabled(n));o.enabled=a.every(n=>n.enabled===!0),o=o.parent}return I0e(this,this.choices),this.emit(\"toggle\",e,this),e}enable(e){return this.selected.length>=this.maxSelected?this.alert():(e.enabled=!this.isDisabled(e),e.choices&&e.choices.forEach(this.enable.bind(this)),e)}disable(e){return e.enabled=!1,e.choices&&e.choices.forEach(this.disable.bind(this)),e}number(e){this.num+=e;let r=o=>{let a=Number(o);if(a>this.choices.length-1)return this.alert();let n=this.focused,u=this.choices.find(A=>a===A.index);if(!u.enabled&&this.selected.length>=this.maxSelected)return this.alert();if(this.visible.indexOf(u)===-1){let A=b8(this.choices),p=A.indexOf(u);if(n.index>p){let h=A.slice(p,p+this.limit),E=A.filter(w=>!h.includes(w));this.choices=h.concat(E)}else{let h=p-this.limit+1;this.choices=A.slice(h).concat(A.slice(0,h))}}return this.index=this.choices.indexOf(u),this.toggle(this.focused),this.render()};return clearTimeout(this.numberTimeout),new Promise(o=>{let a=this.choices.length,n=this.num,u=(A=!1,p)=>{clearTimeout(this.numberTimeout),A&&(p=r(n)),this.num=\"\",o(p)};if(n===\"0\"||n.length===1&&+(n+\"0\")>a)return u(!0);if(Number(n)>a)return u(!1,this.alert());this.numberTimeout=setTimeout(()=>u(!0),this.delay)})}home(){return this.choices=b8(this.choices),this.index=0,this.render()}end(){let e=this.choices.length-this.limit,r=b8(this.choices);return this.choices=r.slice(e).concat(r.slice(0,e)),this.index=this.limit-1,this.render()}first(){return this.index=0,this.render()}last(){return this.index=this.visible.length-1,this.render()}prev(){return this.visible.length<=1?this.alert():this.up()}next(){return this.visible.length<=1?this.alert():this.down()}right(){return this.cursor>=this.input.length?this.alert():(this.cursor++,this.render())}left(){return this.cursor<=0?this.alert():(this.cursor--,this.render())}up(){let e=this.choices.length,r=this.visible.length,o=this.index;return this.options.scroll===!1&&o===0?this.alert():e>r&&o===0?this.scrollUp():(this.index=(o-1%e+e)%e,this.isDisabled()?this.up():this.render())}down(){let e=this.choices.length,r=this.visible.length,o=this.index;return this.options.scroll===!1&&o===r-1?this.alert():e>r&&o===r-1?this.scrollDown():(this.index=(o+1)%e,this.isDisabled()?this.down():this.render())}scrollUp(e=0){return this.choices=nft(this.choices),this.index=e,this.isDisabled()?this.up():this.render()}scrollDown(e=this.visible.length-1){return this.choices=ift(this.choices),this.index=e,this.isDisabled()?this.down():this.render()}async shiftUp(){if(this.options.sort===!0){this.sorting=!0,this.swap(this.index-1),await this.up(),this.sorting=!1;return}return this.scrollUp(this.index)}async shiftDown(){if(this.options.sort===!0){this.sorting=!0,this.swap(this.index+1),await this.down(),this.sorting=!1;return}return this.scrollDown(this.index)}pageUp(){return this.visible.length<=1?this.alert():(this.limit=Math.max(this.limit-1,0),this.index=Math.min(this.limit-1,this.index),this._limit=this.limit,this.isDisabled()?this.up():this.render())}pageDown(){return this.visible.length>=this.choices.length?this.alert():(this.index=Math.max(0,this.index),this.limit=Math.min(this.limit+1,this.choices.length),this._limit=this.limit,this.isDisabled()?this.down():this.render())}swap(e){sft(this.choices,this.index,e)}isDisabled(e=this.focused){return e&&[\"disabled\",\"collapsed\",\"hidden\",\"completing\",\"readonly\"].some(o=>e[o]===!0)?!0:e&&e.role===\"heading\"}isEnabled(e=this.focused){if(Array.isArray(e))return e.every(r=>this.isEnabled(r));if(e.choices){let r=e.choices.filter(o=>!this.isDisabled(o));return e.enabled&&r.every(o=>this.isEnabled(o))}return e.enabled&&!this.isDisabled(e)}isChoice(e,r){return e.name===r||e.index===Number(r)}isSelected(e){return Array.isArray(this.initial)?this.initial.some(r=>this.isChoice(e,r)):this.isChoice(e,this.initial)}map(e=[],r=\"value\"){return[].concat(e||[]).reduce((o,a)=>(o[a]=this.find(a,r),o),{})}filter(e,r){let a=typeof e==\"function\"?e:(A,p)=>[A.name,p].includes(e),u=(this.options.multiple?this.state._choices:this.choices).filter(a);return r?u.map(A=>A[r]):u}find(e,r){if(C0e(e))return r?e[r]:e;let a=typeof e==\"function\"?e:(u,A)=>[u.name,A].includes(e),n=this.choices.find(a);if(n)return r?n[r]:n}findIndex(e){return this.choices.indexOf(this.find(e))}async submit(){let e=this.focused;if(!e)return this.alert();if(e.newChoice)return e.input?(e.updateChoice(),this.render()):this.alert();if(this.choices.some(u=>u.newChoice))return this.alert();let{reorder:r,sort:o}=this.options,a=this.multiple===!0,n=this.selected;return n===void 0?this.alert():(Array.isArray(n)&&r!==!1&&o!==!0&&(n=Uk.reorder(n)),this.value=a?n.map(u=>u.name):n.name,super.submit())}set choices(e=[]){this.state._choices=this.state._choices||[],this.state.choices=e;for(let r of e)this.state._choices.some(o=>o.name===r.name)||this.state._choices.push(r);if(!this._initial&&this.options.initial){this._initial=!0;let r=this.initial;if(typeof r==\"string\"||typeof r==\"number\"){let o=this.find(r);o&&(this.initial=o.index,this.focus(o,!0))}}}get choices(){return I0e(this,this.state.choices||[])}set visible(e){this.state.visible=e}get visible(){return(this.state.visible||this.choices).slice(0,this.limit)}set limit(e){this.state.limit=e}get limit(){let{state:e,options:r,choices:o}=this,a=e.limit||this._limit||r.limit||o.length;return Math.min(a,this.height)}set value(e){super.value=e}get value(){return typeof super.value!=\"string\"&&super.value===this.initial?this.input:super.value}set index(e){this.state.index=e}get index(){return Math.max(0,this.state?this.state.index:0)}get enabled(){return this.filter(this.isEnabled.bind(this))}get focused(){let e=this.choices[this.index];return e&&this.state.submitted&&this.multiple!==!0&&(e.enabled=!0),e}get selectable(){return this.choices.filter(e=>!this.isDisabled(e))}get selected(){return this.multiple?this.enabled:this.focused}};function I0e(t,e){if(e instanceof Promise)return e;if(typeof e==\"function\"){if(Uk.isAsyncFn(e))return e;e=e.call(t,t)}for(let r of e){if(Array.isArray(r.choices)){let o=r.choices.filter(a=>!t.isDisabled(a));r.enabled=o.every(a=>a.enabled===!0)}t.isDisabled(r)===!0&&delete r.enabled}return e}w0e.exports=k8});var Qh=_((q_t,B0e)=>{\"use strict\";var oft=b2(),Q8=xo(),F8=class extends oft{constructor(e){super(e),this.emptyError=this.options.emptyError||\"No items were selected\"}async dispatch(e,r){if(this.multiple)return this[r.name]?await this[r.name](e,r):await super.dispatch(e,r);this.alert()}separator(){if(this.options.separator)return super.separator();let e=this.styles.muted(this.symbols.ellipsis);return this.state.submitted?super.separator():e}pointer(e,r){return!this.multiple||this.options.pointer?super.pointer(e,r):\"\"}indicator(e,r){return this.multiple?super.indicator(e,r):\"\"}choiceMessage(e,r){let o=this.resolve(e.message,this.state,e,r);return e.role===\"heading\"&&!Q8.hasColor(o)&&(o=this.styles.strong(o)),this.resolve(o,this.state,e,r)}choiceSeparator(){return\":\"}async renderChoice(e,r){await this.onChoice(e,r);let o=this.index===r,a=await this.pointer(e,r),n=await this.indicator(e,r)+(e.pad||\"\"),u=await this.resolve(e.hint,this.state,e,r);u&&!Q8.hasColor(u)&&(u=this.styles.muted(u));let A=this.indent(e),p=await this.choiceMessage(e,r),h=()=>[this.margin[3],A+a+n,p,this.margin[1],u].filter(Boolean).join(\" \");return e.role===\"heading\"?h():e.disabled?(Q8.hasColor(p)||(p=this.styles.disabled(p)),h()):(o&&(p=this.styles.em(p)),h())}async renderChoices(){if(this.state.loading===\"choices\")return this.styles.warning(\"Loading choices\");if(this.state.submitted)return\"\";let e=this.visible.map(async(n,u)=>await this.renderChoice(n,u)),r=await Promise.all(e);r.length||r.push(this.styles.danger(\"No matching choices\"));let o=this.margin[0]+r.join(`\n`),a;return this.options.choicesHeader&&(a=await this.resolve(this.options.choicesHeader,this.state)),[a,o].filter(Boolean).join(`\n`)}format(){return!this.state.submitted||this.state.cancelled?\"\":Array.isArray(this.selected)?this.selected.map(e=>this.styles.primary(e.name)).join(\", \"):this.styles.primary(this.selected.name)}async render(){let{submitted:e,size:r}=this.state,o=\"\",a=await this.header(),n=await this.prefix(),u=await this.separator(),A=await this.message();this.options.promptLine!==!1&&(o=[n,A,u,\"\"].join(\" \"),this.state.prompt=o);let p=await this.format(),h=await this.error()||await this.hint(),E=await this.renderChoices(),w=await this.footer();p&&(o+=p),h&&!o.includes(h)&&(o+=\" \"+h),e&&!p&&!E.trim()&&this.multiple&&this.emptyError!=null&&(o+=this.styles.danger(this.emptyError)),this.clear(r),this.write([a,o,E,w].filter(Boolean).join(`\n`)),this.write(this.margin[2]),this.restore()}};B0e.exports=F8});var D0e=_((j_t,v0e)=>{\"use strict\";var aft=Qh(),lft=(t,e)=>{let r=t.toLowerCase();return o=>{let n=o.toLowerCase().indexOf(r),u=e(o.slice(n,n+r.length));return n>=0?o.slice(0,n)+u+o.slice(n+r.length):o}},R8=class extends aft{constructor(e){super(e),this.cursorShow()}moveCursor(e){this.state.cursor+=e}dispatch(e){return this.append(e)}space(e){return this.options.multiple?super.space(e):this.append(e)}append(e){let{cursor:r,input:o}=this.state;return this.input=o.slice(0,r)+e+o.slice(r),this.moveCursor(1),this.complete()}delete(){let{cursor:e,input:r}=this.state;return r?(this.input=r.slice(0,e-1)+r.slice(e),this.moveCursor(-1),this.complete()):this.alert()}deleteForward(){let{cursor:e,input:r}=this.state;return r[e]===void 0?this.alert():(this.input=`${r}`.slice(0,e)+`${r}`.slice(e+1),this.complete())}number(e){return this.append(e)}async complete(){this.completing=!0,this.choices=await this.suggest(this.input,this.state._choices),this.state.limit=void 0,this.index=Math.min(Math.max(this.visible.length-1,0),this.index),await this.render(),this.completing=!1}suggest(e=this.input,r=this.state._choices){if(typeof this.options.suggest==\"function\")return this.options.suggest.call(this,e,r);let o=e.toLowerCase();return r.filter(a=>a.message.toLowerCase().includes(o))}pointer(){return\"\"}format(){if(!this.focused)return this.input;if(this.options.multiple&&this.state.submitted)return this.selected.map(e=>this.styles.primary(e.message)).join(\", \");if(this.state.submitted){let e=this.value=this.input=this.focused.value;return this.styles.primary(e)}return this.input}async render(){if(this.state.status!==\"pending\")return super.render();let e=this.options.highlight?this.options.highlight.bind(this):this.styles.placeholder,r=lft(this.input,e),o=this.choices;this.choices=o.map(a=>({...a,message:r(a.message)})),await super.render(),this.choices=o}submit(){return this.options.multiple&&(this.value=this.selected.map(e=>e.name)),super.submit()}};v0e.exports=R8});var L8=_((G_t,P0e)=>{\"use strict\";var T8=xo();P0e.exports=(t,e={})=>{t.cursorHide();let{input:r=\"\",initial:o=\"\",pos:a,showCursor:n=!0,color:u}=e,A=u||t.styles.placeholder,p=T8.inverse(t.styles.primary),h=T=>p(t.styles.black(T)),E=r,w=\" \",D=h(w);if(t.blink&&t.blink.off===!0&&(h=T=>T,D=\"\"),n&&a===0&&o===\"\"&&r===\"\")return h(w);if(n&&a===0&&(r===o||r===\"\"))return h(o[0])+A(o.slice(1));o=T8.isPrimitive(o)?`${o}`:\"\",r=T8.isPrimitive(r)?`${r}`:\"\";let b=o&&o.startsWith(r)&&o!==r,C=b?h(o[r.length]):D;if(a!==r.length&&n===!0&&(E=r.slice(0,a)+h(r[a])+r.slice(a+1),C=\"\"),n===!1&&(C=\"\"),b){let T=t.styles.unstyle(E+C);return E+C+A(o.slice(T.length))}return E+C}});var _k=_((W_t,S0e)=>{\"use strict\";var cft=eu(),uft=Qh(),Aft=L8(),N8=class extends uft{constructor(e){super({...e,multiple:!0}),this.type=\"form\",this.initial=this.options.initial,this.align=[this.options.align,\"right\"].find(r=>r!=null),this.emptyError=\"\",this.values={}}async reset(e){return await super.reset(),e===!0&&(this._index=this.index),this.index=this._index,this.values={},this.choices.forEach(r=>r.reset&&r.reset()),this.render()}dispatch(e){return!!e&&this.append(e)}append(e){let r=this.focused;if(!r)return this.alert();let{cursor:o,input:a}=r;return r.value=r.input=a.slice(0,o)+e+a.slice(o),r.cursor++,this.render()}delete(){let e=this.focused;if(!e||e.cursor<=0)return this.alert();let{cursor:r,input:o}=e;return e.value=e.input=o.slice(0,r-1)+o.slice(r),e.cursor--,this.render()}deleteForward(){let e=this.focused;if(!e)return this.alert();let{cursor:r,input:o}=e;if(o[r]===void 0)return this.alert();let a=`${o}`.slice(0,r)+`${o}`.slice(r+1);return e.value=e.input=a,this.render()}right(){let e=this.focused;return e?e.cursor>=e.input.length?this.alert():(e.cursor++,this.render()):this.alert()}left(){let e=this.focused;return e?e.cursor<=0?this.alert():(e.cursor--,this.render()):this.alert()}space(e,r){return this.dispatch(e,r)}number(e,r){return this.dispatch(e,r)}next(){let e=this.focused;if(!e)return this.alert();let{initial:r,input:o}=e;return r&&r.startsWith(o)&&o!==r?(e.value=e.input=r,e.cursor=e.value.length,this.render()):super.next()}prev(){let e=this.focused;return e?e.cursor===0?super.prev():(e.value=e.input=\"\",e.cursor=0,this.render()):this.alert()}separator(){return\"\"}format(e){return this.state.submitted?\"\":super.format(e)}pointer(){return\"\"}indicator(e){return e.input?\"\\u29BF\":\"\\u2299\"}async choiceSeparator(e,r){let o=await this.resolve(e.separator,this.state,e,r)||\":\";return o?\" \"+this.styles.disabled(o):\"\"}async renderChoice(e,r){await this.onChoice(e,r);let{state:o,styles:a}=this,{cursor:n,initial:u=\"\",name:A,hint:p,input:h=\"\"}=e,{muted:E,submitted:w,primary:D,danger:b}=a,C=p,T=this.index===r,N=e.validate||(()=>!0),U=await this.choiceSeparator(e,r),z=e.message;this.align===\"right\"&&(z=z.padStart(this.longest+1,\" \")),this.align===\"left\"&&(z=z.padEnd(this.longest+1,\" \"));let te=this.values[A]=h||u,le=h?\"success\":\"dark\";await N.call(e,te,this.state)!==!0&&(le=\"danger\");let ce=a[le],ue=ce(await this.indicator(e,r))+(e.pad||\"\"),Ie=this.indent(e),he=()=>[Ie,ue,z+U,h,C].filter(Boolean).join(\" \");if(o.submitted)return z=cft.unstyle(z),h=w(h),C=\"\",he();if(e.format)h=await e.format.call(this,h,e,r);else{let De=this.styles.muted;h=Aft(this,{input:h,initial:u,pos:n,showCursor:T,color:De})}return this.isValue(h)||(h=this.styles.muted(this.symbols.ellipsis)),e.result&&(this.values[A]=await e.result.call(this,te,e,r)),T&&(z=D(z)),e.error?h+=(h?\" \":\"\")+b(e.error.trim()):e.hint&&(h+=(h?\" \":\"\")+E(e.hint.trim())),he()}async submit(){return this.value=this.values,super.base.submit.call(this)}};S0e.exports=N8});var O8=_((Y_t,b0e)=>{\"use strict\";var fft=_k(),pft=()=>{throw new Error(\"expected prompt to have a custom authenticate method\")},x0e=(t=pft)=>{class e extends fft{constructor(o){super(o)}async submit(){this.value=await t.call(this,this.values,this.state),super.base.submit.call(this)}static create(o){return x0e(o)}}return e};b0e.exports=x0e()});var F0e=_((K_t,Q0e)=>{\"use strict\";var hft=O8();function gft(t,e){return t.username===this.options.username&&t.password===this.options.password}var k0e=(t=gft)=>{let e=[{name:\"username\",message:\"username\"},{name:\"password\",message:\"password\",format(o){return this.options.showPassword?o:(this.state.submitted?this.styles.primary:this.styles.muted)(this.symbols.asterisk.repeat(o.length))}}];class r extends hft.create(t){constructor(a){super({...a,choices:e})}static create(a){return k0e(a)}}return r};Q0e.exports=k0e()});var Hk=_((V_t,R0e)=>{\"use strict\";var dft=uE(),{isPrimitive:mft,hasColor:yft}=xo(),M8=class extends dft{constructor(e){super(e),this.cursorHide()}async initialize(){let e=await this.resolve(this.initial,this.state);this.input=await this.cast(e),await super.initialize()}dispatch(e){return this.isValue(e)?(this.input=e,this.submit()):this.alert()}format(e){let{styles:r,state:o}=this;return o.submitted?r.success(e):r.primary(e)}cast(e){return this.isTrue(e)}isTrue(e){return/^[ty1]/i.test(e)}isFalse(e){return/^[fn0]/i.test(e)}isValue(e){return mft(e)&&(this.isTrue(e)||this.isFalse(e))}async hint(){if(this.state.status===\"pending\"){let e=await this.element(\"hint\");return yft(e)?e:this.styles.muted(e)}}async render(){let{input:e,size:r}=this.state,o=await this.prefix(),a=await this.separator(),n=await this.message(),u=this.styles.muted(this.default),A=[o,n,u,a].filter(Boolean).join(\" \");this.state.prompt=A;let p=await this.header(),h=this.value=this.cast(e),E=await this.format(h),w=await this.error()||await this.hint(),D=await this.footer();w&&!A.includes(w)&&(E+=\" \"+w),A+=\" \"+E,this.clear(r),this.write([p,A,D].filter(Boolean).join(`\n`)),this.restore()}set value(e){super.value=e}get value(){return this.cast(super.value)}};R0e.exports=M8});var L0e=_((z_t,T0e)=>{\"use strict\";var Eft=Hk(),U8=class extends Eft{constructor(e){super(e),this.default=this.options.default||(this.initial?\"(Y/n)\":\"(y/N)\")}};T0e.exports=U8});var O0e=_((J_t,N0e)=>{\"use strict\";var Cft=Qh(),Ift=_k(),AE=Ift.prototype,_8=class extends Cft{constructor(e){super({...e,multiple:!0}),this.align=[this.options.align,\"left\"].find(r=>r!=null),this.emptyError=\"\",this.values={}}dispatch(e,r){let o=this.focused,a=o.parent||{};return!o.editable&&!a.editable&&(e===\"a\"||e===\"i\")?super[e]():AE.dispatch.call(this,e,r)}append(e,r){return AE.append.call(this,e,r)}delete(e,r){return AE.delete.call(this,e,r)}space(e){return this.focused.editable?this.append(e):super.space()}number(e){return this.focused.editable?this.append(e):super.number(e)}next(){return this.focused.editable?AE.next.call(this):super.next()}prev(){return this.focused.editable?AE.prev.call(this):super.prev()}async indicator(e,r){let o=e.indicator||\"\",a=e.editable?o:super.indicator(e,r);return await this.resolve(a,this.state,e,r)||\"\"}indent(e){return e.role===\"heading\"?\"\":e.editable?\" \":\"  \"}async renderChoice(e,r){return e.indent=\"\",e.editable?AE.renderChoice.call(this,e,r):super.renderChoice(e,r)}error(){return\"\"}footer(){return this.state.error}async validate(){let e=!0;for(let r of this.choices){if(typeof r.validate!=\"function\"||r.role===\"heading\")continue;let o=r.parent?this.value[r.parent.name]:this.value;if(r.editable?o=r.value===r.name?r.initial||\"\":r.value:this.isDisabled(r)||(o=r.enabled===!0),e=await r.validate(o,this.state),e!==!0)break}return e!==!0&&(this.state.error=typeof e==\"string\"?e:\"Invalid Input\"),e}submit(){if(this.focused.newChoice===!0)return super.submit();if(this.choices.some(e=>e.newChoice))return this.alert();this.value={};for(let e of this.choices){let r=e.parent?this.value[e.parent.name]:this.value;if(e.role===\"heading\"){this.value[e.name]={};continue}e.editable?r[e.name]=e.value===e.name?e.initial||\"\":e.value:this.isDisabled(e)||(r[e.name]=e.enabled===!0)}return this.base.submit.call(this)}};N0e.exports=_8});var Vg=_((X_t,M0e)=>{\"use strict\";var wft=uE(),Bft=L8(),{isPrimitive:vft}=xo(),H8=class extends wft{constructor(e){super(e),this.initial=vft(this.initial)?String(this.initial):\"\",this.initial&&this.cursorHide(),this.state.prevCursor=0,this.state.clipboard=[]}async keypress(e,r={}){let o=this.state.prevKeypress;return this.state.prevKeypress=r,this.options.multiline===!0&&r.name===\"return\"&&(!o||o.name!==\"return\")?this.append(`\n`,r):super.keypress(e,r)}moveCursor(e){this.cursor+=e}reset(){return this.input=this.value=\"\",this.cursor=0,this.render()}dispatch(e,r){if(!e||r.ctrl||r.code)return this.alert();this.append(e)}append(e){let{cursor:r,input:o}=this.state;this.input=`${o}`.slice(0,r)+e+`${o}`.slice(r),this.moveCursor(String(e).length),this.render()}insert(e){this.append(e)}delete(){let{cursor:e,input:r}=this.state;if(e<=0)return this.alert();this.input=`${r}`.slice(0,e-1)+`${r}`.slice(e),this.moveCursor(-1),this.render()}deleteForward(){let{cursor:e,input:r}=this.state;if(r[e]===void 0)return this.alert();this.input=`${r}`.slice(0,e)+`${r}`.slice(e+1),this.render()}cutForward(){let e=this.cursor;if(this.input.length<=e)return this.alert();this.state.clipboard.push(this.input.slice(e)),this.input=this.input.slice(0,e),this.render()}cutLeft(){let e=this.cursor;if(e===0)return this.alert();let r=this.input.slice(0,e),o=this.input.slice(e),a=r.split(\" \");this.state.clipboard.push(a.pop()),this.input=a.join(\" \"),this.cursor=this.input.length,this.input+=o,this.render()}paste(){if(!this.state.clipboard.length)return this.alert();this.insert(this.state.clipboard.pop()),this.render()}toggleCursor(){this.state.prevCursor?(this.cursor=this.state.prevCursor,this.state.prevCursor=0):(this.state.prevCursor=this.cursor,this.cursor=0),this.render()}first(){this.cursor=0,this.render()}last(){this.cursor=this.input.length-1,this.render()}next(){let e=this.initial!=null?String(this.initial):\"\";if(!e||!e.startsWith(this.input))return this.alert();this.input=this.initial,this.cursor=this.initial.length,this.render()}prev(){if(!this.input)return this.alert();this.reset()}backward(){return this.left()}forward(){return this.right()}right(){return this.cursor>=this.input.length?this.alert():(this.moveCursor(1),this.render())}left(){return this.cursor<=0?this.alert():(this.moveCursor(-1),this.render())}isValue(e){return!!e}async format(e=this.value){let r=await this.resolve(this.initial,this.state);return this.state.submitted?this.styles.submitted(e||r):Bft(this,{input:e,initial:r,pos:this.cursor})}async render(){let e=this.state.size,r=await this.prefix(),o=await this.separator(),a=await this.message(),n=[r,a,o].filter(Boolean).join(\" \");this.state.prompt=n;let u=await this.header(),A=await this.format(),p=await this.error()||await this.hint(),h=await this.footer();p&&!A.includes(p)&&(A+=\" \"+p),n+=\" \"+A,this.clear(e),this.write([u,n,h].filter(Boolean).join(`\n`)),this.restore()}};M0e.exports=H8});var _0e=_((Z_t,U0e)=>{\"use strict\";var Dft=t=>t.filter((e,r)=>t.lastIndexOf(e)===r),qk=t=>Dft(t).filter(Boolean);U0e.exports=(t,e={},r=\"\")=>{let{past:o=[],present:a=\"\"}=e,n,u;switch(t){case\"prev\":case\"undo\":return n=o.slice(0,o.length-1),u=o[o.length-1]||\"\",{past:qk([r,...n]),present:u};case\"next\":case\"redo\":return n=o.slice(1),u=o[0]||\"\",{past:qk([...n,r]),present:u};case\"save\":return{past:qk([...o,r]),present:\"\"};case\"remove\":return u=qk(o.filter(A=>A!==r)),a=\"\",u.length&&(a=u.pop()),{past:u,present:a};default:throw new Error(`Invalid action: \"${t}\"`)}}});var j8=_(($_t,q0e)=>{\"use strict\";var Pft=Vg(),H0e=_0e(),q8=class extends Pft{constructor(e){super(e);let r=this.options.history;if(r&&r.store){let o=r.values||this.initial;this.autosave=!!r.autosave,this.store=r.store,this.data=this.store.get(\"values\")||{past:[],present:o},this.initial=this.data.present||this.data.past[this.data.past.length-1]}}completion(e){return this.store?(this.data=H0e(e,this.data,this.input),this.data.present?(this.input=this.data.present,this.cursor=this.input.length,this.render()):this.alert()):this.alert()}altUp(){return this.completion(\"prev\")}altDown(){return this.completion(\"next\")}prev(){return this.save(),super.prev()}save(){this.store&&(this.data=H0e(\"save\",this.data,this.input),this.store.set(\"values\",this.data))}submit(){return this.store&&this.autosave===!0&&this.save(),super.submit()}};q0e.exports=q8});var G0e=_((e8t,j0e)=>{\"use strict\";var Sft=Vg(),G8=class extends Sft{format(){return\"\"}};j0e.exports=G8});var Y0e=_((t8t,W0e)=>{\"use strict\";var xft=Vg(),W8=class extends xft{constructor(e={}){super(e),this.sep=this.options.separator||/, */,this.initial=e.initial||\"\"}split(e=this.value){return e?String(e).split(this.sep):[]}format(){let e=this.state.submitted?this.styles.primary:r=>r;return this.list.map(e).join(\", \")}async submit(e){let r=this.state.error||await this.validate(this.list,this.state);return r!==!0?(this.state.error=r,super.submit()):(this.value=this.list,super.submit())}get list(){return this.split()}};W0e.exports=W8});var V0e=_((r8t,K0e)=>{\"use strict\";var bft=Qh(),Y8=class extends bft{constructor(e){super({...e,multiple:!0})}};K0e.exports=Y8});var V8=_((n8t,z0e)=>{\"use strict\";var kft=Vg(),K8=class extends kft{constructor(e={}){super({style:\"number\",...e}),this.min=this.isValue(e.min)?this.toNumber(e.min):-1/0,this.max=this.isValue(e.max)?this.toNumber(e.max):1/0,this.delay=e.delay!=null?e.delay:1e3,this.float=e.float!==!1,this.round=e.round===!0||e.float===!1,this.major=e.major||10,this.minor=e.minor||1,this.initial=e.initial!=null?e.initial:\"\",this.input=String(this.initial),this.cursor=this.input.length,this.cursorShow()}append(e){return!/[-+.]/.test(e)||e===\".\"&&this.input.includes(\".\")?this.alert(\"invalid number\"):super.append(e)}number(e){return super.append(e)}next(){return this.input&&this.input!==this.initial?this.alert():this.isValue(this.initial)?(this.input=this.initial,this.cursor=String(this.initial).length,this.render()):this.alert()}up(e){let r=e||this.minor,o=this.toNumber(this.input);return o>this.max+r?this.alert():(this.input=`${o+r}`,this.render())}down(e){let r=e||this.minor,o=this.toNumber(this.input);return o<this.min-r?this.alert():(this.input=`${o-r}`,this.render())}shiftDown(){return this.down(this.major)}shiftUp(){return this.up(this.major)}format(e=this.input){return typeof this.options.format==\"function\"?this.options.format.call(this,e):this.styles.info(e)}toNumber(e=\"\"){return this.float?+e:Math.round(+e)}isValue(e){return/^[-+]?[0-9]+((\\.)|(\\.[0-9]+))?$/.test(e)}submit(){let e=[this.input,this.initial].find(r=>this.isValue(r));return this.value=this.toNumber(e||0),super.submit()}};z0e.exports=K8});var X0e=_((i8t,J0e)=>{J0e.exports=V8()});var $0e=_((s8t,Z0e)=>{\"use strict\";var Qft=Vg(),z8=class extends Qft{constructor(e){super(e),this.cursorShow()}format(e=this.input){return this.keypressed?(this.state.submitted?this.styles.primary:this.styles.muted)(this.symbols.asterisk.repeat(e.length)):\"\"}};Z0e.exports=z8});var rge=_((o8t,tge)=>{\"use strict\";var Fft=eu(),Rft=b2(),ege=xo(),J8=class extends Rft{constructor(e={}){super(e),this.widths=[].concat(e.messageWidth||50),this.align=[].concat(e.align||\"left\"),this.linebreak=e.linebreak||!1,this.edgeLength=e.edgeLength||3,this.newline=e.newline||`\n   `;let r=e.startNumber||1;typeof this.scale==\"number\"&&(this.scaleKey=!1,this.scale=Array(this.scale).fill(0).map((o,a)=>({name:a+r})))}async reset(){return this.tableized=!1,await super.reset(),this.render()}tableize(){if(this.tableized===!0)return;this.tableized=!0;let e=0;for(let r of this.choices){e=Math.max(e,r.message.length),r.scaleIndex=r.initial||2,r.scale=[];for(let o=0;o<this.scale.length;o++)r.scale.push({index:o})}this.widths[0]=Math.min(this.widths[0],e+3)}async dispatch(e,r){if(this.multiple)return this[r.name]?await this[r.name](e,r):await super.dispatch(e,r);this.alert()}heading(e,r,o){return this.styles.strong(e)}separator(){return this.styles.muted(this.symbols.ellipsis)}right(){let e=this.focused;return e.scaleIndex>=this.scale.length-1?this.alert():(e.scaleIndex++,this.render())}left(){let e=this.focused;return e.scaleIndex<=0?this.alert():(e.scaleIndex--,this.render())}indent(){return\"\"}format(){return this.state.submitted?this.choices.map(r=>this.styles.info(r.index)).join(\", \"):\"\"}pointer(){return\"\"}renderScaleKey(){return this.scaleKey===!1||this.state.submitted?\"\":[\"\",...this.scale.map(o=>`   ${o.name} - ${o.message}`)].map(o=>this.styles.muted(o)).join(`\n`)}renderScaleHeading(e){let r=this.scale.map(p=>p.name);typeof this.options.renderScaleHeading==\"function\"&&(r=this.options.renderScaleHeading.call(this,e));let o=this.scaleLength-r.join(\"\").length,a=Math.round(o/(r.length-1)),u=r.map(p=>this.styles.strong(p)).join(\" \".repeat(a)),A=\" \".repeat(this.widths[0]);return this.margin[3]+A+this.margin[1]+u}scaleIndicator(e,r,o){if(typeof this.options.scaleIndicator==\"function\")return this.options.scaleIndicator.call(this,e,r,o);let a=e.scaleIndex===r.index;return r.disabled?this.styles.hint(this.symbols.radio.disabled):a?this.styles.success(this.symbols.radio.on):this.symbols.radio.off}renderScale(e,r){let o=e.scale.map(n=>this.scaleIndicator(e,n,r)),a=this.term===\"Hyper\"?\"\":\" \";return o.join(a+this.symbols.line.repeat(this.edgeLength))}async renderChoice(e,r){await this.onChoice(e,r);let o=this.index===r,a=await this.pointer(e,r),n=await e.hint;n&&!ege.hasColor(n)&&(n=this.styles.muted(n));let u=C=>this.margin[3]+C.replace(/\\s+$/,\"\").padEnd(this.widths[0],\" \"),A=this.newline,p=this.indent(e),h=await this.resolve(e.message,this.state,e,r),E=await this.renderScale(e,r),w=this.margin[1]+this.margin[3];this.scaleLength=Fft.unstyle(E).length,this.widths[0]=Math.min(this.widths[0],this.width-this.scaleLength-w.length);let b=ege.wordWrap(h,{width:this.widths[0],newline:A}).split(`\n`).map(C=>u(C)+this.margin[1]);return o&&(E=this.styles.info(E),b=b.map(C=>this.styles.info(C))),b[0]+=E,this.linebreak&&b.push(\"\"),[p+a,b.join(`\n`)].filter(Boolean)}async renderChoices(){if(this.state.submitted)return\"\";this.tableize();let e=this.visible.map(async(a,n)=>await this.renderChoice(a,n)),r=await Promise.all(e),o=await this.renderScaleHeading();return this.margin[0]+[o,...r.map(a=>a.join(\" \"))].join(`\n`)}async render(){let{submitted:e,size:r}=this.state,o=await this.prefix(),a=await this.separator(),n=await this.message(),u=\"\";this.options.promptLine!==!1&&(u=[o,n,a,\"\"].join(\" \"),this.state.prompt=u);let A=await this.header(),p=await this.format(),h=await this.renderScaleKey(),E=await this.error()||await this.hint(),w=await this.renderChoices(),D=await this.footer(),b=this.emptyError;p&&(u+=p),E&&!u.includes(E)&&(u+=\" \"+E),e&&!p&&!w.trim()&&this.multiple&&b!=null&&(u+=this.styles.danger(b)),this.clear(r),this.write([A,u,h,w,D].filter(Boolean).join(`\n`)),this.state.submitted||this.write(this.margin[2]),this.restore()}submit(){this.value={};for(let e of this.choices)this.value[e.name]=e.scaleIndex;return this.base.submit.call(this)}};tge.exports=J8});var sge=_((a8t,ige)=>{\"use strict\";var nge=eu(),Tft=(t=\"\")=>typeof t==\"string\"?t.replace(/^['\"]|['\"]$/g,\"\"):\"\",Z8=class{constructor(e){this.name=e.key,this.field=e.field||{},this.value=Tft(e.initial||this.field.initial||\"\"),this.message=e.message||this.name,this.cursor=0,this.input=\"\",this.lines=[]}},Lft=async(t={},e={},r=o=>o)=>{let o=new Set,a=t.fields||[],n=t.template,u=[],A=[],p=[],h=1;typeof n==\"function\"&&(n=await n());let E=-1,w=()=>n[++E],D=()=>n[E+1],b=C=>{C.line=h,u.push(C)};for(b({type:\"bos\",value:\"\"});E<n.length-1;){let C=w();if(/^[^\\S\\n ]$/.test(C)){b({type:\"text\",value:C});continue}if(C===`\n`){b({type:\"newline\",value:C}),h++;continue}if(C===\"\\\\\"){C+=w(),b({type:\"text\",value:C});continue}if((C===\"$\"||C===\"#\"||C===\"{\")&&D()===\"{\"){let N=w();C+=N;let U={type:\"template\",open:C,inner:\"\",close:\"\",value:C},z;for(;z=w();){if(z===\"}\"){D()===\"}\"&&(z+=w()),U.value+=z,U.close=z;break}z===\":\"?(U.initial=\"\",U.key=U.inner):U.initial!==void 0&&(U.initial+=z),U.value+=z,U.inner+=z}U.template=U.open+(U.initial||U.inner)+U.close,U.key=U.key||U.inner,e.hasOwnProperty(U.key)&&(U.initial=e[U.key]),U=r(U),b(U),p.push(U.key),o.add(U.key);let te=A.find(le=>le.name===U.key);U.field=a.find(le=>le.name===U.key),te||(te=new Z8(U),A.push(te)),te.lines.push(U.line-1);continue}let T=u[u.length-1];T.type===\"text\"&&T.line===h?T.value+=C:b({type:\"text\",value:C})}return b({type:\"eos\",value:\"\"}),{input:n,tabstops:u,unique:o,keys:p,items:A}};ige.exports=async t=>{let e=t.options,r=new Set(e.required===!0?[]:e.required||[]),o={...e.values,...e.initial},{tabstops:a,items:n,keys:u}=await Lft(e,o),A=X8(\"result\",t,e),p=X8(\"format\",t,e),h=X8(\"validate\",t,e,!0),E=t.isValue.bind(t);return async(w={},D=!1)=>{let b=0;w.required=r,w.items=n,w.keys=u,w.output=\"\";let C=async(z,te,le,ce)=>{let ue=await h(z,te,le,ce);return ue===!1?\"Invalid field \"+le.name:ue};for(let z of a){let te=z.value,le=z.key;if(z.type!==\"template\"){te&&(w.output+=te);continue}if(z.type===\"template\"){let ce=n.find(Ee=>Ee.name===le);e.required===!0&&w.required.add(ce.name);let ue=[ce.input,w.values[ce.value],ce.value,te].find(E),he=(ce.field||{}).message||z.inner;if(D){let Ee=await C(w.values[le],w,ce,b);if(Ee&&typeof Ee==\"string\"||Ee===!1){w.invalid.set(le,Ee);continue}w.invalid.delete(le);let g=await A(w.values[le],w,ce,b);w.output+=nge.unstyle(g);continue}ce.placeholder=!1;let De=te;te=await p(te,w,ce,b),ue!==te?(w.values[le]=ue,te=t.styles.typing(ue),w.missing.delete(he)):(w.values[le]=void 0,ue=`<${he}>`,te=t.styles.primary(ue),ce.placeholder=!0,w.required.has(le)&&w.missing.add(he)),w.missing.has(he)&&w.validating&&(te=t.styles.warning(ue)),w.invalid.has(le)&&w.validating&&(te=t.styles.danger(ue)),b===w.index&&(De!==te?te=t.styles.underline(te):te=t.styles.heading(nge.unstyle(te))),b++}te&&(w.output+=te)}let T=w.output.split(`\n`).map(z=>\" \"+z),N=n.length,U=0;for(let z of n)w.invalid.has(z.name)&&z.lines.forEach(te=>{T[te][0]===\" \"&&(T[te]=w.styles.danger(w.symbols.bullet)+T[te].slice(1))}),t.isValue(w.values[z.name])&&U++;return w.completed=(U/N*100).toFixed(0),w.output=T.join(`\n`),w.output}};function X8(t,e,r,o){return(a,n,u,A)=>typeof u.field[t]==\"function\"?u.field[t].call(e,a,n,u,A):[o,a].find(p=>e.isValue(p))}});var age=_((l8t,oge)=>{\"use strict\";var Nft=eu(),Oft=sge(),Mft=uE(),$8=class extends Mft{constructor(e){super(e),this.cursorHide(),this.reset(!0)}async initialize(){this.interpolate=await Oft(this),await super.initialize()}async reset(e){this.state.keys=[],this.state.invalid=new Map,this.state.missing=new Set,this.state.completed=0,this.state.values={},e!==!0&&(await this.initialize(),await this.render())}moveCursor(e){let r=this.getItem();this.cursor+=e,r.cursor+=e}dispatch(e,r){if(!r.code&&!r.ctrl&&e!=null&&this.getItem()){this.append(e,r);return}this.alert()}append(e,r){let o=this.getItem(),a=o.input.slice(0,this.cursor),n=o.input.slice(this.cursor);this.input=o.input=`${a}${e}${n}`,this.moveCursor(1),this.render()}delete(){let e=this.getItem();if(this.cursor<=0||!e.input)return this.alert();let r=e.input.slice(this.cursor),o=e.input.slice(0,this.cursor-1);this.input=e.input=`${o}${r}`,this.moveCursor(-1),this.render()}increment(e){return e>=this.state.keys.length-1?0:e+1}decrement(e){return e<=0?this.state.keys.length-1:e-1}first(){this.state.index=0,this.render()}last(){this.state.index=this.state.keys.length-1,this.render()}right(){if(this.cursor>=this.input.length)return this.alert();this.moveCursor(1),this.render()}left(){if(this.cursor<=0)return this.alert();this.moveCursor(-1),this.render()}prev(){this.state.index=this.decrement(this.state.index),this.getItem(),this.render()}next(){this.state.index=this.increment(this.state.index),this.getItem(),this.render()}up(){this.prev()}down(){this.next()}format(e){let r=this.state.completed<100?this.styles.warning:this.styles.success;return this.state.submitted===!0&&this.state.completed!==100&&(r=this.styles.danger),r(`${this.state.completed}% completed`)}async render(){let{index:e,keys:r=[],submitted:o,size:a}=this.state,n=[this.options.newline,`\n`].find(z=>z!=null),u=await this.prefix(),A=await this.separator(),p=await this.message(),h=[u,p,A].filter(Boolean).join(\" \");this.state.prompt=h;let E=await this.header(),w=await this.error()||\"\",D=await this.hint()||\"\",b=o?\"\":await this.interpolate(this.state),C=this.state.key=r[e]||\"\",T=await this.format(C),N=await this.footer();T&&(h+=\" \"+T),D&&!T&&this.state.completed===0&&(h+=\" \"+D),this.clear(a);let U=[E,h,b,N,w.trim()];this.write(U.filter(Boolean).join(n)),this.restore()}getItem(e){let{items:r,keys:o,index:a}=this.state,n=r.find(u=>u.name===o[a]);return n&&n.input!=null&&(this.input=n.input,this.cursor=n.cursor),n}async submit(){typeof this.interpolate!=\"function\"&&await this.initialize(),await this.interpolate(this.state,!0);let{invalid:e,missing:r,output:o,values:a}=this.state;if(e.size){let A=\"\";for(let[p,h]of e)A+=`Invalid ${p}: ${h}\n`;return this.state.error=A,super.submit()}if(r.size)return this.state.error=\"Required: \"+[...r.keys()].join(\", \"),super.submit();let u=Nft.unstyle(o).split(`\n`).map(A=>A.slice(1)).join(`\n`);return this.value={values:a,result:u},super.submit()}};oge.exports=$8});var cge=_((c8t,lge)=>{\"use strict\";var Uft=\"(Use <shift>+<up/down> to sort)\",_ft=Qh(),eH=class extends _ft{constructor(e){super({...e,reorder:!1,sort:!0,multiple:!0}),this.state.hint=[this.options.hint,Uft].find(this.isValue.bind(this))}indicator(){return\"\"}async renderChoice(e,r){let o=await super.renderChoice(e,r),a=this.symbols.identicalTo+\" \",n=this.index===r&&this.sorting?this.styles.muted(a):\"  \";return this.options.drag===!1&&(n=\"\"),this.options.numbered===!0?n+`${r+1} - `+o:n+o}get selected(){return this.choices}submit(){return this.value=this.choices.map(e=>e.value),super.submit()}};lge.exports=eH});var Age=_((u8t,uge)=>{\"use strict\";var Hft=b2(),tH=class extends Hft{constructor(e={}){if(super(e),this.emptyError=e.emptyError||\"No items were selected\",this.term=process.env.TERM_PROGRAM,!this.options.header){let r=[\"\",\"4 - Strongly Agree\",\"3 - Agree\",\"2 - Neutral\",\"1 - Disagree\",\"0 - Strongly Disagree\",\"\"];r=r.map(o=>this.styles.muted(o)),this.state.header=r.join(`\n   `)}}async toChoices(...e){if(this.createdScales)return!1;this.createdScales=!0;let r=await super.toChoices(...e);for(let o of r)o.scale=qft(5,this.options),o.scaleIdx=2;return r}dispatch(){this.alert()}space(){let e=this.focused,r=e.scale[e.scaleIdx],o=r.selected;return e.scale.forEach(a=>a.selected=!1),r.selected=!o,this.render()}indicator(){return\"\"}pointer(){return\"\"}separator(){return this.styles.muted(this.symbols.ellipsis)}right(){let e=this.focused;return e.scaleIdx>=e.scale.length-1?this.alert():(e.scaleIdx++,this.render())}left(){let e=this.focused;return e.scaleIdx<=0?this.alert():(e.scaleIdx--,this.render())}indent(){return\"   \"}async renderChoice(e,r){await this.onChoice(e,r);let o=this.index===r,a=this.term===\"Hyper\",n=a?9:8,u=a?\"\":\" \",A=this.symbols.line.repeat(n),p=\" \".repeat(n+(a?0:1)),h=te=>(te?this.styles.success(\"\\u25C9\"):\"\\u25EF\")+u,E=r+1+\".\",w=o?this.styles.heading:this.styles.noop,D=await this.resolve(e.message,this.state,e,r),b=this.indent(e),C=b+e.scale.map((te,le)=>h(le===e.scaleIdx)).join(A),T=te=>te===e.scaleIdx?w(te):te,N=b+e.scale.map((te,le)=>T(le)).join(p),U=()=>[E,D].filter(Boolean).join(\" \"),z=()=>[U(),C,N,\" \"].filter(Boolean).join(`\n`);return o&&(C=this.styles.cyan(C),N=this.styles.cyan(N)),z()}async renderChoices(){if(this.state.submitted)return\"\";let e=this.visible.map(async(o,a)=>await this.renderChoice(o,a)),r=await Promise.all(e);return r.length||r.push(this.styles.danger(\"No matching choices\")),r.join(`\n`)}format(){return this.state.submitted?this.choices.map(r=>this.styles.info(r.scaleIdx)).join(\", \"):\"\"}async render(){let{submitted:e,size:r}=this.state,o=await this.prefix(),a=await this.separator(),n=await this.message(),u=[o,n,a].filter(Boolean).join(\" \");this.state.prompt=u;let A=await this.header(),p=await this.format(),h=await this.error()||await this.hint(),E=await this.renderChoices(),w=await this.footer();(p||!h)&&(u+=\" \"+p),h&&!u.includes(h)&&(u+=\" \"+h),e&&!p&&!E&&this.multiple&&this.type!==\"form\"&&(u+=this.styles.danger(this.emptyError)),this.clear(r),this.write([u,A,E,w].filter(Boolean).join(`\n`)),this.restore()}submit(){this.value={};for(let e of this.choices)this.value[e.name]=e.scaleIdx;return this.base.submit.call(this)}};function qft(t,e={}){if(Array.isArray(e.scale))return e.scale.map(o=>({...o}));let r=[];for(let o=1;o<t+1;o++)r.push({i:o,selected:!1});return r}uge.exports=tH});var pge=_((A8t,fge)=>{fge.exports=j8()});var gge=_((f8t,hge)=>{\"use strict\";var jft=Hk(),rH=class extends jft{async initialize(){await super.initialize(),this.value=this.initial=!!this.options.initial,this.disabled=this.options.disabled||\"no\",this.enabled=this.options.enabled||\"yes\",await this.render()}reset(){this.value=this.initial,this.render()}delete(){this.alert()}toggle(){this.value=!this.value,this.render()}enable(){if(this.value===!0)return this.alert();this.value=!0,this.render()}disable(){if(this.value===!1)return this.alert();this.value=!1,this.render()}up(){this.toggle()}down(){this.toggle()}right(){this.toggle()}left(){this.toggle()}next(){this.toggle()}prev(){this.toggle()}dispatch(e=\"\",r){switch(e.toLowerCase()){case\" \":return this.toggle();case\"1\":case\"y\":case\"t\":return this.enable();case\"0\":case\"n\":case\"f\":return this.disable();default:return this.alert()}}format(){let e=o=>this.styles.primary.underline(o);return[this.value?this.disabled:e(this.disabled),this.value?e(this.enabled):this.enabled].join(this.styles.muted(\" / \"))}async render(){let{size:e}=this.state,r=await this.header(),o=await this.prefix(),a=await this.separator(),n=await this.message(),u=await this.format(),A=await this.error()||await this.hint(),p=await this.footer(),h=[o,n,a,u].join(\" \");this.state.prompt=h,A&&!h.includes(A)&&(h+=\" \"+A),this.clear(e),this.write([r,h,p].filter(Boolean).join(`\n`)),this.write(this.margin[2]),this.restore()}};hge.exports=rH});var mge=_((p8t,dge)=>{\"use strict\";var Gft=Qh(),nH=class extends Gft{constructor(e){if(super(e),typeof this.options.correctChoice!=\"number\"||this.options.correctChoice<0)throw new Error(\"Please specify the index of the correct answer from the list of choices\")}async toChoices(e,r){let o=await super.toChoices(e,r);if(o.length<2)throw new Error(\"Please give at least two choices to the user\");if(this.options.correctChoice>o.length)throw new Error(\"Please specify the index of the correct answer from the list of choices\");return o}check(e){return e.index===this.options.correctChoice}async result(e){return{selectedAnswer:e,correctAnswer:this.options.choices[this.options.correctChoice].value,correct:await this.check(this.state)}}};dge.exports=nH});var Ege=_(iH=>{\"use strict\";var yge=xo(),fs=(t,e)=>{yge.defineExport(iH,t,e),yge.defineExport(iH,t.toLowerCase(),e)};fs(\"AutoComplete\",()=>D0e());fs(\"BasicAuth\",()=>F0e());fs(\"Confirm\",()=>L0e());fs(\"Editable\",()=>O0e());fs(\"Form\",()=>_k());fs(\"Input\",()=>j8());fs(\"Invisible\",()=>G0e());fs(\"List\",()=>Y0e());fs(\"MultiSelect\",()=>V0e());fs(\"Numeral\",()=>X0e());fs(\"Password\",()=>$0e());fs(\"Scale\",()=>rge());fs(\"Select\",()=>Qh());fs(\"Snippet\",()=>age());fs(\"Sort\",()=>cge());fs(\"Survey\",()=>Age());fs(\"Text\",()=>pge());fs(\"Toggle\",()=>gge());fs(\"Quiz\",()=>mge())});var Ige=_((g8t,Cge)=>{Cge.exports={ArrayPrompt:b2(),AuthPrompt:O8(),BooleanPrompt:Hk(),NumberPrompt:V8(),StringPrompt:Vg()}});var Q2=_((d8t,Bge)=>{\"use strict\";var wge=ve(\"assert\"),oH=ve(\"events\"),Fh=xo(),ru=class extends oH{constructor(e,r){super(),this.options=Fh.merge({},e),this.answers={...r}}register(e,r){if(Fh.isObject(e)){for(let a of Object.keys(e))this.register(a,e[a]);return this}wge.equal(typeof r,\"function\",\"expected a function\");let o=e.toLowerCase();return r.prototype instanceof this.Prompt?this.prompts[o]=r:this.prompts[o]=r(this.Prompt,this),this}async prompt(e=[]){for(let r of[].concat(e))try{typeof r==\"function\"&&(r=await r.call(this)),await this.ask(Fh.merge({},this.options,r))}catch(o){return Promise.reject(o)}return this.answers}async ask(e){typeof e==\"function\"&&(e=await e.call(this));let r=Fh.merge({},this.options,e),{type:o,name:a}=e,{set:n,get:u}=Fh;if(typeof o==\"function\"&&(o=await o.call(this,e,this.answers)),!o)return this.answers[a];wge(this.prompts[o],`Prompt \"${o}\" is not registered`);let A=new this.prompts[o](r),p=u(this.answers,a);A.state.answers=this.answers,A.enquirer=this,a&&A.on(\"submit\",E=>{this.emit(\"answer\",a,E,A),n(this.answers,a,E)});let h=A.emit.bind(A);return A.emit=(...E)=>(this.emit.call(this,...E),h(...E)),this.emit(\"prompt\",A,this),r.autofill&&p!=null?(A.value=A.input=p,r.autofill===\"show\"&&await A.submit()):p=A.value=await A.run(),p}use(e){return e.call(this,this),this}set Prompt(e){this._Prompt=e}get Prompt(){return this._Prompt||this.constructor.Prompt}get prompts(){return this.constructor.prompts}static set Prompt(e){this._Prompt=e}static get Prompt(){return this._Prompt||uE()}static get prompts(){return Ege()}static get types(){return Ige()}static get prompt(){let e=(r,...o)=>{let a=new this(...o),n=a.emit.bind(a);return a.emit=(...u)=>(e.emit(...u),n(...u)),a.prompt(r)};return Fh.mixinEmitter(e,new oH),e}};Fh.mixinEmitter(ru,new oH);var sH=ru.prompts;for(let t of Object.keys(sH)){let e=t.toLowerCase(),r=o=>new sH[t](o).run();ru.prompt[e]=r,ru[e]=r,ru[t]||Reflect.defineProperty(ru,t,{get:()=>sH[t]})}var k2=t=>{Fh.defineExport(ru,t,()=>ru.types[t])};k2(\"ArrayPrompt\");k2(\"AuthPrompt\");k2(\"BooleanPrompt\");k2(\"NumberPrompt\");k2(\"StringPrompt\");Bge.exports=ru});var L2=_((Z8t,kge)=>{var Jft=bk();function Xft(t,e,r){var o=t==null?void 0:Jft(t,e);return o===void 0?r:o}kge.exports=Xft});var Rge=_((iHt,Fge)=>{function Zft(t,e){for(var r=-1,o=t==null?0:t.length;++r<o&&e(t[r],r,t)!==!1;);return t}Fge.exports=Zft});var Lge=_((sHt,Tge)=>{var $ft=Eg(),ept=PS();function tpt(t,e){return t&&$ft(e,ept(e),t)}Tge.exports=tpt});var Oge=_((oHt,Nge)=>{var rpt=Eg(),npt=Vm();function ipt(t,e){return t&&rpt(e,npt(e),t)}Nge.exports=ipt});var Uge=_((aHt,Mge)=>{var spt=Eg(),opt=CS();function apt(t,e){return spt(t,opt(t),e)}Mge.exports=apt});var fH=_((lHt,_ge)=>{var lpt=ES(),cpt=QS(),upt=CS(),Apt=bN(),fpt=Object.getOwnPropertySymbols,ppt=fpt?function(t){for(var e=[];t;)lpt(e,upt(t)),t=cpt(t);return e}:Apt;_ge.exports=ppt});var qge=_((cHt,Hge)=>{var hpt=Eg(),gpt=fH();function dpt(t,e){return hpt(t,gpt(t),e)}Hge.exports=dpt});var pH=_((uHt,jge)=>{var mpt=xN(),ypt=fH(),Ept=Vm();function Cpt(t){return mpt(t,Ept,ypt)}jge.exports=Cpt});var Wge=_((AHt,Gge)=>{var Ipt=Object.prototype,wpt=Ipt.hasOwnProperty;function Bpt(t){var e=t.length,r=new t.constructor(e);return e&&typeof t[0]==\"string\"&&wpt.call(t,\"index\")&&(r.index=t.index,r.input=t.input),r}Gge.exports=Bpt});var Kge=_((fHt,Yge)=>{var vpt=bS();function Dpt(t,e){var r=e?vpt(t.buffer):t.buffer;return new t.constructor(r,t.byteOffset,t.byteLength)}Yge.exports=Dpt});var zge=_((pHt,Vge)=>{var Ppt=/\\w*$/;function Spt(t){var e=new t.constructor(t.source,Ppt.exec(t));return e.lastIndex=t.lastIndex,e}Vge.exports=Spt});var ede=_((hHt,$ge)=>{var Jge=dg(),Xge=Jge?Jge.prototype:void 0,Zge=Xge?Xge.valueOf:void 0;function xpt(t){return Zge?Object(Zge.call(t)):{}}$ge.exports=xpt});var rde=_((gHt,tde)=>{var bpt=bS(),kpt=Kge(),Qpt=zge(),Fpt=ede(),Rpt=jN(),Tpt=\"[object Boolean]\",Lpt=\"[object Date]\",Npt=\"[object Map]\",Opt=\"[object Number]\",Mpt=\"[object RegExp]\",Upt=\"[object Set]\",_pt=\"[object String]\",Hpt=\"[object Symbol]\",qpt=\"[object ArrayBuffer]\",jpt=\"[object DataView]\",Gpt=\"[object Float32Array]\",Wpt=\"[object Float64Array]\",Ypt=\"[object Int8Array]\",Kpt=\"[object Int16Array]\",Vpt=\"[object Int32Array]\",zpt=\"[object Uint8Array]\",Jpt=\"[object Uint8ClampedArray]\",Xpt=\"[object Uint16Array]\",Zpt=\"[object Uint32Array]\";function $pt(t,e,r){var o=t.constructor;switch(e){case qpt:return bpt(t);case Tpt:case Lpt:return new o(+t);case jpt:return kpt(t,r);case Gpt:case Wpt:case Ypt:case Kpt:case Vpt:case zpt:case Jpt:case Xpt:case Zpt:return Rpt(t,r);case Npt:return new o;case Opt:case _pt:return new o(t);case Mpt:return Qpt(t);case Upt:return new o;case Hpt:return Fpt(t)}}tde.exports=$pt});var ide=_((dHt,nde)=>{var eht=a1(),tht=Zu(),rht=\"[object Map]\";function nht(t){return tht(t)&&eht(t)==rht}nde.exports=nht});var lde=_((mHt,ade)=>{var iht=ide(),sht=wS(),sde=BS(),ode=sde&&sde.isMap,oht=ode?sht(ode):iht;ade.exports=oht});var ude=_((yHt,cde)=>{var aht=a1(),lht=Zu(),cht=\"[object Set]\";function uht(t){return lht(t)&&aht(t)==cht}cde.exports=uht});var hde=_((EHt,pde)=>{var Aht=ude(),fht=wS(),Ade=BS(),fde=Ade&&Ade.isSet,pht=fde?fht(fde):Aht;pde.exports=pht});var hH=_((CHt,yde)=>{var hht=mS(),ght=Rge(),dht=RS(),mht=Lge(),yht=Oge(),Eht=qN(),Cht=kS(),Iht=Uge(),wht=qge(),Bht=RN(),vht=pH(),Dht=a1(),Pht=Wge(),Sht=rde(),xht=GN(),bht=jl(),kht=r1(),Qht=lde(),Fht=cl(),Rht=hde(),Tht=PS(),Lht=Vm(),Nht=1,Oht=2,Mht=4,gde=\"[object Arguments]\",Uht=\"[object Array]\",_ht=\"[object Boolean]\",Hht=\"[object Date]\",qht=\"[object Error]\",dde=\"[object Function]\",jht=\"[object GeneratorFunction]\",Ght=\"[object Map]\",Wht=\"[object Number]\",mde=\"[object Object]\",Yht=\"[object RegExp]\",Kht=\"[object Set]\",Vht=\"[object String]\",zht=\"[object Symbol]\",Jht=\"[object WeakMap]\",Xht=\"[object ArrayBuffer]\",Zht=\"[object DataView]\",$ht=\"[object Float32Array]\",e0t=\"[object Float64Array]\",t0t=\"[object Int8Array]\",r0t=\"[object Int16Array]\",n0t=\"[object Int32Array]\",i0t=\"[object Uint8Array]\",s0t=\"[object Uint8ClampedArray]\",o0t=\"[object Uint16Array]\",a0t=\"[object Uint32Array]\",Ai={};Ai[gde]=Ai[Uht]=Ai[Xht]=Ai[Zht]=Ai[_ht]=Ai[Hht]=Ai[$ht]=Ai[e0t]=Ai[t0t]=Ai[r0t]=Ai[n0t]=Ai[Ght]=Ai[Wht]=Ai[mde]=Ai[Yht]=Ai[Kht]=Ai[Vht]=Ai[zht]=Ai[i0t]=Ai[s0t]=Ai[o0t]=Ai[a0t]=!0;Ai[qht]=Ai[dde]=Ai[Jht]=!1;function Gk(t,e,r,o,a,n){var u,A=e&Nht,p=e&Oht,h=e&Mht;if(r&&(u=a?r(t,o,a,n):r(t)),u!==void 0)return u;if(!Fht(t))return t;var E=bht(t);if(E){if(u=Pht(t),!A)return Cht(t,u)}else{var w=Dht(t),D=w==dde||w==jht;if(kht(t))return Eht(t,A);if(w==mde||w==gde||D&&!a){if(u=p||D?{}:xht(t),!A)return p?wht(t,yht(u,t)):Iht(t,mht(u,t))}else{if(!Ai[w])return a?t:{};u=Sht(t,w,A)}}n||(n=new hht);var b=n.get(t);if(b)return b;n.set(t,u),Rht(t)?t.forEach(function(N){u.add(Gk(N,e,r,N,t,n))}):Qht(t)&&t.forEach(function(N,U){u.set(U,Gk(N,e,r,U,t,n))});var C=h?p?vht:Bht:p?Lht:Tht,T=E?void 0:C(t);return ght(T||t,function(N,U){T&&(U=N,N=t[U]),dht(u,U,Gk(N,e,r,U,t,n))}),u}yde.exports=Gk});var gH=_((IHt,Ede)=>{var l0t=hH(),c0t=1,u0t=4;function A0t(t){return l0t(t,c0t|u0t)}Ede.exports=A0t});var dH=_((wHt,Cde)=>{var f0t=o8();function p0t(t,e,r){return t==null?t:f0t(t,e,r)}Cde.exports=p0t});var Dde=_((xHt,vde)=>{var h0t=Object.prototype,g0t=h0t.hasOwnProperty;function d0t(t,e){return t!=null&&g0t.call(t,e)}vde.exports=d0t});var Sde=_((bHt,Pde)=>{var m0t=Dde(),y0t=a8();function E0t(t,e){return t!=null&&y0t(t,e,m0t)}Pde.exports=E0t});var bde=_((kHt,xde)=>{function C0t(t){var e=t==null?0:t.length;return e?t[e-1]:void 0}xde.exports=C0t});var Qde=_((QHt,kde)=>{var I0t=bk(),w0t=XU();function B0t(t,e){return e.length<2?t:I0t(t,w0t(e,0,-1))}kde.exports=B0t});var yH=_((FHt,Fde)=>{var v0t=Wg(),D0t=bde(),P0t=Qde(),S0t=nE();function x0t(t,e){return e=v0t(e,t),t=P0t(t,e),t==null||delete t[S0t(D0t(e))]}Fde.exports=x0t});var EH=_((RHt,Rde)=>{var b0t=yH();function k0t(t,e){return t==null?!0:b0t(t,e)}Rde.exports=k0t});var Mde=_((l6t,R0t)=>{R0t.exports={name:\"@yarnpkg/cli\",version:\"4.5.3\",license:\"BSD-2-Clause\",main:\"./sources/index.ts\",exports:{\".\":\"./sources/index.ts\",\"./polyfills\":\"./sources/polyfills.ts\",\"./package.json\":\"./package.json\"},dependencies:{\"@yarnpkg/core\":\"workspace:^\",\"@yarnpkg/fslib\":\"workspace:^\",\"@yarnpkg/libzip\":\"workspace:^\",\"@yarnpkg/parsers\":\"workspace:^\",\"@yarnpkg/plugin-compat\":\"workspace:^\",\"@yarnpkg/plugin-constraints\":\"workspace:^\",\"@yarnpkg/plugin-dlx\":\"workspace:^\",\"@yarnpkg/plugin-essentials\":\"workspace:^\",\"@yarnpkg/plugin-exec\":\"workspace:^\",\"@yarnpkg/plugin-file\":\"workspace:^\",\"@yarnpkg/plugin-git\":\"workspace:^\",\"@yarnpkg/plugin-github\":\"workspace:^\",\"@yarnpkg/plugin-http\":\"workspace:^\",\"@yarnpkg/plugin-init\":\"workspace:^\",\"@yarnpkg/plugin-interactive-tools\":\"workspace:^\",\"@yarnpkg/plugin-link\":\"workspace:^\",\"@yarnpkg/plugin-nm\":\"workspace:^\",\"@yarnpkg/plugin-npm\":\"workspace:^\",\"@yarnpkg/plugin-npm-cli\":\"workspace:^\",\"@yarnpkg/plugin-pack\":\"workspace:^\",\"@yarnpkg/plugin-patch\":\"workspace:^\",\"@yarnpkg/plugin-pnp\":\"workspace:^\",\"@yarnpkg/plugin-pnpm\":\"workspace:^\",\"@yarnpkg/plugin-stage\":\"workspace:^\",\"@yarnpkg/plugin-typescript\":\"workspace:^\",\"@yarnpkg/plugin-version\":\"workspace:^\",\"@yarnpkg/plugin-workspace-tools\":\"workspace:^\",\"@yarnpkg/shell\":\"workspace:^\",\"ci-info\":\"^4.0.0\",clipanion:\"^4.0.0-rc.2\",semver:\"^7.1.2\",tslib:\"^2.4.0\",typanion:\"^3.14.0\"},devDependencies:{\"@types/semver\":\"^7.1.0\",\"@yarnpkg/builder\":\"workspace:^\",\"@yarnpkg/monorepo\":\"workspace:^\",\"@yarnpkg/pnpify\":\"workspace:^\"},peerDependencies:{\"@yarnpkg/core\":\"workspace:^\"},scripts:{postpack:\"rm -rf lib\",prepack:'run build:compile \"$(pwd)\"',\"build:cli+hook\":\"run build:pnp:hook && builder build bundle\",\"build:cli\":\"builder build bundle\",\"run:cli\":\"builder run\",\"update-local\":\"run build:cli --no-git-hash && rsync -a --delete bundles/ bin/\"},publishConfig:{main:\"./lib/index.js\",bin:null,exports:{\".\":\"./lib/index.js\",\"./package.json\":\"./package.json\"}},files:[\"/lib/**/*\",\"!/lib/pluginConfiguration.*\",\"!/lib/cli.*\"],\"@yarnpkg/builder\":{bundles:{standard:[\"@yarnpkg/plugin-essentials\",\"@yarnpkg/plugin-compat\",\"@yarnpkg/plugin-constraints\",\"@yarnpkg/plugin-dlx\",\"@yarnpkg/plugin-exec\",\"@yarnpkg/plugin-file\",\"@yarnpkg/plugin-git\",\"@yarnpkg/plugin-github\",\"@yarnpkg/plugin-http\",\"@yarnpkg/plugin-init\",\"@yarnpkg/plugin-interactive-tools\",\"@yarnpkg/plugin-link\",\"@yarnpkg/plugin-nm\",\"@yarnpkg/plugin-npm\",\"@yarnpkg/plugin-npm-cli\",\"@yarnpkg/plugin-pack\",\"@yarnpkg/plugin-patch\",\"@yarnpkg/plugin-pnp\",\"@yarnpkg/plugin-pnpm\",\"@yarnpkg/plugin-stage\",\"@yarnpkg/plugin-typescript\",\"@yarnpkg/plugin-version\",\"@yarnpkg/plugin-workspace-tools\"]}},repository:{type:\"git\",url:\"ssh://git@github.com/yarnpkg/berry.git\",directory:\"packages/yarnpkg-cli\"},engines:{node:\">=18.12.0\"}}});var xH=_((U9t,Jde)=>{\"use strict\";Jde.exports=function(e,r){r===!0&&(r=0);var o=\"\";if(typeof e==\"string\")try{o=new URL(e).protocol}catch{}else e&&e.constructor===URL&&(o=e.protocol);var a=o.split(/\\:|\\+/).filter(Boolean);return typeof r==\"number\"?a[r]:a}});var Zde=_((_9t,Xde)=>{\"use strict\";var $0t=xH();function egt(t){var e={protocols:[],protocol:null,port:null,resource:\"\",host:\"\",user:\"\",password:\"\",pathname:\"\",hash:\"\",search:\"\",href:t,query:{},parse_failed:!1};try{var r=new URL(t);e.protocols=$0t(r),e.protocol=e.protocols[0],e.port=r.port,e.resource=r.hostname,e.host=r.host,e.user=r.username||\"\",e.password=r.password||\"\",e.pathname=r.pathname,e.hash=r.hash.slice(1),e.search=r.search.slice(1),e.href=r.href,e.query=Object.fromEntries(r.searchParams)}catch{e.protocols=[\"file\"],e.protocol=e.protocols[0],e.port=\"\",e.resource=\"\",e.user=\"\",e.pathname=\"\",e.hash=\"\",e.search=\"\",e.href=t,e.query={},e.parse_failed=!0}return e}Xde.exports=egt});var tme=_((H9t,eme)=>{\"use strict\";var tgt=Zde();function rgt(t){return t&&typeof t==\"object\"&&\"default\"in t?t:{default:t}}var ngt=rgt(tgt),igt=\"text/plain\",sgt=\"us-ascii\",$de=(t,e)=>e.some(r=>r instanceof RegExp?r.test(t):r===t),ogt=(t,{stripHash:e})=>{let r=/^data:(?<type>[^,]*?),(?<data>[^#]*?)(?:#(?<hash>.*))?$/.exec(t);if(!r)throw new Error(`Invalid URL: ${t}`);let{type:o,data:a,hash:n}=r.groups,u=o.split(\";\");n=e?\"\":n;let A=!1;u[u.length-1]===\"base64\"&&(u.pop(),A=!0);let p=(u.shift()||\"\").toLowerCase(),E=[...u.map(w=>{let[D,b=\"\"]=w.split(\"=\").map(C=>C.trim());return D===\"charset\"&&(b=b.toLowerCase(),b===sgt)?\"\":`${D}${b?`=${b}`:\"\"}`}).filter(Boolean)];return A&&E.push(\"base64\"),(E.length>0||p&&p!==igt)&&E.unshift(p),`data:${E.join(\";\")},${A?a.trim():a}${n?`#${n}`:\"\"}`};function agt(t,e){if(e={defaultProtocol:\"http:\",normalizeProtocol:!0,forceHttp:!1,forceHttps:!1,stripAuthentication:!0,stripHash:!1,stripTextFragment:!0,stripWWW:!0,removeQueryParameters:[/^utm_\\w+/i],removeTrailingSlash:!0,removeSingleSlash:!0,removeDirectoryIndex:!1,sortQueryParameters:!0,...e},t=t.trim(),/^data:/i.test(t))return ogt(t,e);if(/^view-source:/i.test(t))throw new Error(\"`view-source:` is not supported as it is a non-standard protocol\");let r=t.startsWith(\"//\");!r&&/^\\.*\\//.test(t)||(t=t.replace(/^(?!(?:\\w+:)?\\/\\/)|^\\/\\//,e.defaultProtocol));let a=new URL(t);if(e.forceHttp&&e.forceHttps)throw new Error(\"The `forceHttp` and `forceHttps` options cannot be used together\");if(e.forceHttp&&a.protocol===\"https:\"&&(a.protocol=\"http:\"),e.forceHttps&&a.protocol===\"http:\"&&(a.protocol=\"https:\"),e.stripAuthentication&&(a.username=\"\",a.password=\"\"),e.stripHash?a.hash=\"\":e.stripTextFragment&&(a.hash=a.hash.replace(/#?:~:text.*?$/i,\"\")),a.pathname){let u=/\\b[a-z][a-z\\d+\\-.]{1,50}:\\/\\//g,A=0,p=\"\";for(;;){let E=u.exec(a.pathname);if(!E)break;let w=E[0],D=E.index,b=a.pathname.slice(A,D);p+=b.replace(/\\/{2,}/g,\"/\"),p+=w,A=D+w.length}let h=a.pathname.slice(A,a.pathname.length);p+=h.replace(/\\/{2,}/g,\"/\"),a.pathname=p}if(a.pathname)try{a.pathname=decodeURI(a.pathname)}catch{}if(e.removeDirectoryIndex===!0&&(e.removeDirectoryIndex=[/^index\\.[a-z]+$/]),Array.isArray(e.removeDirectoryIndex)&&e.removeDirectoryIndex.length>0){let u=a.pathname.split(\"/\"),A=u[u.length-1];$de(A,e.removeDirectoryIndex)&&(u=u.slice(0,-1),a.pathname=u.slice(1).join(\"/\")+\"/\")}if(a.hostname&&(a.hostname=a.hostname.replace(/\\.$/,\"\"),e.stripWWW&&/^www\\.(?!www\\.)[a-z\\-\\d]{1,63}\\.[a-z.\\-\\d]{2,63}$/.test(a.hostname)&&(a.hostname=a.hostname.replace(/^www\\./,\"\"))),Array.isArray(e.removeQueryParameters))for(let u of[...a.searchParams.keys()])$de(u,e.removeQueryParameters)&&a.searchParams.delete(u);if(e.removeQueryParameters===!0&&(a.search=\"\"),e.sortQueryParameters){a.searchParams.sort();try{a.search=decodeURIComponent(a.search)}catch{}}e.removeTrailingSlash&&(a.pathname=a.pathname.replace(/\\/$/,\"\"));let n=t;return t=a.toString(),!e.removeSingleSlash&&a.pathname===\"/\"&&!n.endsWith(\"/\")&&a.hash===\"\"&&(t=t.replace(/\\/$/,\"\")),(e.removeTrailingSlash||a.pathname===\"/\")&&a.hash===\"\"&&e.removeSingleSlash&&(t=t.replace(/\\/$/,\"\")),r&&!e.normalizeProtocol&&(t=t.replace(/^http:\\/\\//,\"//\")),e.stripProtocol&&(t=t.replace(/^(?:https?:)?\\/\\//,\"\")),t}var bH=(t,e=!1)=>{let r=/^(?:([a-z_][a-z0-9_-]{0,31})@|https?:\\/\\/)([\\w\\.\\-@]+)[\\/:]([\\~,\\.\\w,\\-,\\_,\\/]+?(?:\\.git|\\/)?)$/,o=n=>{let u=new Error(n);throw u.subject_url=t,u};(typeof t!=\"string\"||!t.trim())&&o(\"Invalid url.\"),t.length>bH.MAX_INPUT_LENGTH&&o(\"Input exceeds maximum length. If needed, change the value of parseUrl.MAX_INPUT_LENGTH.\"),e&&(typeof e!=\"object\"&&(e={stripHash:!1}),t=agt(t,e));let a=ngt.default(t);if(a.parse_failed){let n=a.href.match(r);n?(a.protocols=[\"ssh\"],a.protocol=\"ssh\",a.resource=n[2],a.host=n[2],a.user=n[1],a.pathname=`/${n[3]}`,a.parse_failed=!1):o(\"URL parsing failed.\")}return a};bH.MAX_INPUT_LENGTH=2048;eme.exports=bH});var ime=_((q9t,nme)=>{\"use strict\";var lgt=xH();function rme(t){if(Array.isArray(t))return t.indexOf(\"ssh\")!==-1||t.indexOf(\"rsync\")!==-1;if(typeof t!=\"string\")return!1;var e=lgt(t);if(t=t.substring(t.indexOf(\"://\")+3),rme(e))return!0;var r=new RegExp(\".([a-zA-Z\\\\d]+):(\\\\d+)/\");return!t.match(r)&&t.indexOf(\"@\")<t.indexOf(\":\")}nme.exports=rme});var ame=_((j9t,ome)=>{\"use strict\";var cgt=tme(),sme=ime();function ugt(t){var e=cgt(t);return e.token=\"\",e.password===\"x-oauth-basic\"?e.token=e.user:e.user===\"x-token-auth\"&&(e.token=e.password),sme(e.protocols)||e.protocols.length===0&&sme(t)?e.protocol=\"ssh\":e.protocols.length?e.protocol=e.protocols[0]:(e.protocol=\"file\",e.protocols=[\"file\"]),e.href=e.href.replace(/\\/$/,\"\"),e}ome.exports=ugt});var cme=_((G9t,lme)=>{\"use strict\";var Agt=ame();function kH(t){if(typeof t!=\"string\")throw new Error(\"The url must be a string.\");var e=/^([a-z\\d-]{1,39})\\/([-\\.\\w]{1,100})$/i;e.test(t)&&(t=\"https://github.com/\"+t);var r=Agt(t),o=r.resource.split(\".\"),a=null;switch(r.toString=function(N){return kH.stringify(this,N)},r.source=o.length>2?o.slice(1-o.length).join(\".\"):r.source=r.resource,r.git_suffix=/\\.git$/.test(r.pathname),r.name=decodeURIComponent((r.pathname||r.href).replace(/(^\\/)|(\\/$)/g,\"\").replace(/\\.git$/,\"\")),r.owner=decodeURIComponent(r.user),r.source){case\"git.cloudforge.com\":r.owner=r.user,r.organization=o[0],r.source=\"cloudforge.com\";break;case\"visualstudio.com\":if(r.resource===\"vs-ssh.visualstudio.com\"){a=r.name.split(\"/\"),a.length===4&&(r.organization=a[1],r.owner=a[2],r.name=a[3],r.full_name=a[2]+\"/\"+a[3]);break}else{a=r.name.split(\"/\"),a.length===2?(r.owner=a[1],r.name=a[1],r.full_name=\"_git/\"+r.name):a.length===3?(r.name=a[2],a[0]===\"DefaultCollection\"?(r.owner=a[2],r.organization=a[0],r.full_name=r.organization+\"/_git/\"+r.name):(r.owner=a[0],r.full_name=r.owner+\"/_git/\"+r.name)):a.length===4&&(r.organization=a[0],r.owner=a[1],r.name=a[3],r.full_name=r.organization+\"/\"+r.owner+\"/_git/\"+r.name);break}case\"dev.azure.com\":case\"azure.com\":if(r.resource===\"ssh.dev.azure.com\"){a=r.name.split(\"/\"),a.length===4&&(r.organization=a[1],r.owner=a[2],r.name=a[3]);break}else{a=r.name.split(\"/\"),a.length===5?(r.organization=a[0],r.owner=a[1],r.name=a[4],r.full_name=\"_git/\"+r.name):a.length===3?(r.name=a[2],a[0]===\"DefaultCollection\"?(r.owner=a[2],r.organization=a[0],r.full_name=r.organization+\"/_git/\"+r.name):(r.owner=a[0],r.full_name=r.owner+\"/_git/\"+r.name)):a.length===4&&(r.organization=a[0],r.owner=a[1],r.name=a[3],r.full_name=r.organization+\"/\"+r.owner+\"/_git/\"+r.name),r.query&&r.query.path&&(r.filepath=r.query.path.replace(/^\\/+/g,\"\")),r.query&&r.query.version&&(r.ref=r.query.version.replace(/^GB/,\"\"));break}default:a=r.name.split(\"/\");var n=a.length-1;if(a.length>=2){var u=a.indexOf(\"-\",2),A=a.indexOf(\"blob\",2),p=a.indexOf(\"tree\",2),h=a.indexOf(\"commit\",2),E=a.indexOf(\"src\",2),w=a.indexOf(\"raw\",2),D=a.indexOf(\"edit\",2);n=u>0?u-1:A>0?A-1:p>0?p-1:h>0?h-1:E>0?E-1:w>0?w-1:D>0?D-1:n,r.owner=a.slice(0,n).join(\"/\"),r.name=a[n],h&&(r.commit=a[n+2])}r.ref=\"\",r.filepathtype=\"\",r.filepath=\"\";var b=a.length>n&&a[n+1]===\"-\"?n+1:n;a.length>b+2&&[\"raw\",\"src\",\"blob\",\"tree\",\"edit\"].indexOf(a[b+1])>=0&&(r.filepathtype=a[b+1],r.ref=a[b+2],a.length>b+3&&(r.filepath=a.slice(b+3).join(\"/\"))),r.organization=r.owner;break}r.full_name||(r.full_name=r.owner,r.name&&(r.full_name&&(r.full_name+=\"/\"),r.full_name+=r.name)),r.owner.startsWith(\"scm/\")&&(r.source=\"bitbucket-server\",r.owner=r.owner.replace(\"scm/\",\"\"),r.organization=r.owner,r.full_name=r.owner+\"/\"+r.name);var C=/(projects|users)\\/(.*?)\\/repos\\/(.*?)((\\/.*$)|$)/,T=C.exec(r.pathname);return T!=null&&(r.source=\"bitbucket-server\",T[1]===\"users\"?r.owner=\"~\"+T[2]:r.owner=T[2],r.organization=r.owner,r.name=T[3],a=T[4].split(\"/\"),a.length>1&&([\"raw\",\"browse\"].indexOf(a[1])>=0?(r.filepathtype=a[1],a.length>2&&(r.filepath=a.slice(2).join(\"/\"))):a[1]===\"commits\"&&a.length>2&&(r.commit=a[2])),r.full_name=r.owner+\"/\"+r.name,r.query.at?r.ref=r.query.at:r.ref=\"\"),r}kH.stringify=function(t,e){e=e||(t.protocols&&t.protocols.length?t.protocols.join(\"+\"):t.protocol);var r=t.port?\":\"+t.port:\"\",o=t.user||\"git\",a=t.git_suffix?\".git\":\"\";switch(e){case\"ssh\":return r?\"ssh://\"+o+\"@\"+t.resource+r+\"/\"+t.full_name+a:o+\"@\"+t.resource+\":\"+t.full_name+a;case\"git+ssh\":case\"ssh+git\":case\"ftp\":case\"ftps\":return e+\"://\"+o+\"@\"+t.resource+r+\"/\"+t.full_name+a;case\"http\":case\"https\":var n=t.token?fgt(t):t.user&&(t.protocols.includes(\"http\")||t.protocols.includes(\"https\"))?t.user+\"@\":\"\";return e+\"://\"+n+t.resource+r+\"/\"+pgt(t)+a;default:return t.href}};function fgt(t){switch(t.source){case\"bitbucket.org\":return\"x-token-auth:\"+t.token+\"@\";default:return t.token+\"@\"}}function pgt(t){switch(t.source){case\"bitbucket-server\":return\"scm/\"+t.full_name;default:return\"\"+t.full_name}}lme.exports=kH});var Dme=_((B5t,vme)=>{var vgt=Cb(),Dgt=kS(),Pgt=jl(),Sgt=fy(),xgt=s8(),bgt=nE(),kgt=t2();function Qgt(t){return Pgt(t)?vgt(t,bgt):Sgt(t)?[t]:Dgt(xgt(kgt(t)))}vme.exports=Qgt});function Lgt(t,e){return e===1&&Tgt.has(t[0])}function q2(t){let e=Array.isArray(t)?t:(0,xme.default)(t);return e.map((o,a)=>Fgt.test(o)?`[${o}]`:Rgt.test(o)&&!Lgt(e,a)?`.${o}`:`[${JSON.stringify(o)}]`).join(\"\").replace(/^\\./,\"\")}function Ngt(t,e){let r=[];if(e.methodName!==null&&r.push(pe.pretty(t,e.methodName,pe.Type.CODE)),e.file!==null){let o=[];o.push(pe.pretty(t,e.file,pe.Type.PATH)),e.line!==null&&(o.push(pe.pretty(t,e.line,pe.Type.NUMBER)),e.column!==null&&o.push(pe.pretty(t,e.column,pe.Type.NUMBER))),r.push(`(${o.join(pe.pretty(t,\":\",\"grey\"))})`)}return r.join(\" \")}function Vk(t,{manifestUpdates:e,reportedErrors:r},{fix:o}={}){let a=new Map,n=new Map,u=[...r.keys()].map(A=>[A,new Map]);for(let[A,p]of[...u,...e]){let h=r.get(A)?.map(b=>({text:b,fixable:!1}))??[],E=!1,w=t.getWorkspaceByCwd(A),D=w.manifest.exportTo({});for(let[b,C]of p){if(C.size>1){let T=[...C].map(([N,U])=>{let z=pe.pretty(t.configuration,N,pe.Type.INSPECT),te=U.size>0?Ngt(t.configuration,U.values().next().value):null;return te!==null?`\n${z} at ${te}`:`\n${z}`}).join(\"\");h.push({text:`Conflict detected in constraint targeting ${pe.pretty(t.configuration,b,pe.Type.CODE)}; conflicting values are:${T}`,fixable:!1})}else{let[[T]]=C,N=(0,Pme.default)(D,b);if(JSON.stringify(N)===JSON.stringify(T))continue;if(!o){let U=typeof N>\"u\"?`Missing field ${pe.pretty(t.configuration,b,pe.Type.CODE)}; expected ${pe.pretty(t.configuration,T,pe.Type.INSPECT)}`:typeof T>\"u\"?`Extraneous field ${pe.pretty(t.configuration,b,pe.Type.CODE)} currently set to ${pe.pretty(t.configuration,N,pe.Type.INSPECT)}`:`Invalid field ${pe.pretty(t.configuration,b,pe.Type.CODE)}; expected ${pe.pretty(t.configuration,T,pe.Type.INSPECT)}, found ${pe.pretty(t.configuration,N,pe.Type.INSPECT)}`;h.push({text:U,fixable:!0});continue}typeof T>\"u\"?(0,bme.default)(D,b):(0,Sme.default)(D,b,T),E=!0}E&&a.set(w,D)}h.length>0&&n.set(w,h)}return{changedWorkspaces:a,remainingErrors:n}}function kme(t,{configuration:e}){let r={children:[]};for(let[o,a]of t){let n=[];for(let A of a){let p=A.text.split(/\\n/);A.fixable&&(p[0]=`${pe.pretty(e,\"\\u2699\",\"gray\")} ${p[0]}`),n.push({value:pe.tuple(pe.Type.NO_HINT,p[0]),children:p.slice(1).map(h=>({value:pe.tuple(pe.Type.NO_HINT,h)}))})}let u={value:pe.tuple(pe.Type.LOCATOR,o.anchoredLocator),children:qe.sortMap(n,A=>A.value[1])};r.children.push(u)}return r.children=qe.sortMap(r.children,o=>o.value[1]),r}var Pme,Sme,xme,bme,ZE,Fgt,Rgt,Tgt,j2=It(()=>{Ke();Pme=et(L2()),Sme=et(dH()),xme=et(Dme()),bme=et(EH()),ZE=class{constructor(e){this.indexedFields=e;this.items=[];this.indexes={};this.clear()}clear(){this.items=[];for(let e of this.indexedFields)this.indexes[e]=new Map}insert(e){this.items.push(e);for(let r of this.indexedFields){let o=Object.hasOwn(e,r)?e[r]:void 0;if(typeof o>\"u\")continue;qe.getArrayWithDefault(this.indexes[r],o).push(e)}return e}find(e){if(typeof e>\"u\")return this.items;let r=Object.entries(e);if(r.length===0)return this.items;let o=[],a;for(let[u,A]of r){let p=u,h=Object.hasOwn(this.indexes,p)?this.indexes[p]:void 0;if(typeof h>\"u\"){o.push([p,A]);continue}let E=new Set(h.get(A)??[]);if(E.size===0)return[];if(typeof a>\"u\")a=E;else for(let w of a)E.has(w)||a.delete(w);if(a.size===0)break}let n=[...a??[]];return o.length>0&&(n=n.filter(u=>{for(let[A,p]of o)if(!(typeof p<\"u\"?Object.hasOwn(u,A)&&u[A]===p:Object.hasOwn(u,A)===!1))return!1;return!0})),n}},Fgt=/^[0-9]+$/,Rgt=/^[a-zA-Z0-9_]+$/,Tgt=new Set([\"scripts\",..._t.allDependencies])});var Qme=_((L5t,GH)=>{var Ogt;(function(t){var e=function(){return{\"append/2\":[new t.type.Rule(new t.type.Term(\"append\",[new t.type.Var(\"X\"),new t.type.Var(\"L\")]),new t.type.Term(\"foldl\",[new t.type.Term(\"append\",[]),new t.type.Var(\"X\"),new t.type.Term(\"[]\",[]),new t.type.Var(\"L\")]))],\"append/3\":[new t.type.Rule(new t.type.Term(\"append\",[new t.type.Term(\"[]\",[]),new t.type.Var(\"X\"),new t.type.Var(\"X\")]),null),new t.type.Rule(new t.type.Term(\"append\",[new t.type.Term(\".\",[new t.type.Var(\"H\"),new t.type.Var(\"T\")]),new t.type.Var(\"X\"),new t.type.Term(\".\",[new t.type.Var(\"H\"),new t.type.Var(\"S\")])]),new t.type.Term(\"append\",[new t.type.Var(\"T\"),new t.type.Var(\"X\"),new t.type.Var(\"S\")]))],\"member/2\":[new t.type.Rule(new t.type.Term(\"member\",[new t.type.Var(\"X\"),new t.type.Term(\".\",[new t.type.Var(\"X\"),new t.type.Var(\"_\")])]),null),new t.type.Rule(new t.type.Term(\"member\",[new t.type.Var(\"X\"),new t.type.Term(\".\",[new t.type.Var(\"_\"),new t.type.Var(\"Xs\")])]),new t.type.Term(\"member\",[new t.type.Var(\"X\"),new t.type.Var(\"Xs\")]))],\"permutation/2\":[new t.type.Rule(new t.type.Term(\"permutation\",[new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[])]),null),new t.type.Rule(new t.type.Term(\"permutation\",[new t.type.Term(\".\",[new t.type.Var(\"H\"),new t.type.Var(\"T\")]),new t.type.Var(\"S\")]),new t.type.Term(\",\",[new t.type.Term(\"permutation\",[new t.type.Var(\"T\"),new t.type.Var(\"P\")]),new t.type.Term(\",\",[new t.type.Term(\"append\",[new t.type.Var(\"X\"),new t.type.Var(\"Y\"),new t.type.Var(\"P\")]),new t.type.Term(\"append\",[new t.type.Var(\"X\"),new t.type.Term(\".\",[new t.type.Var(\"H\"),new t.type.Var(\"Y\")]),new t.type.Var(\"S\")])])]))],\"maplist/2\":[new t.type.Rule(new t.type.Term(\"maplist\",[new t.type.Var(\"_\"),new t.type.Term(\"[]\",[])]),null),new t.type.Rule(new t.type.Term(\"maplist\",[new t.type.Var(\"P\"),new t.type.Term(\".\",[new t.type.Var(\"X\"),new t.type.Var(\"Xs\")])]),new t.type.Term(\",\",[new t.type.Term(\"call\",[new t.type.Var(\"P\"),new t.type.Var(\"X\")]),new t.type.Term(\"maplist\",[new t.type.Var(\"P\"),new t.type.Var(\"Xs\")])]))],\"maplist/3\":[new t.type.Rule(new t.type.Term(\"maplist\",[new t.type.Var(\"_\"),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[])]),null),new t.type.Rule(new t.type.Term(\"maplist\",[new t.type.Var(\"P\"),new t.type.Term(\".\",[new t.type.Var(\"A\"),new t.type.Var(\"As\")]),new t.type.Term(\".\",[new t.type.Var(\"B\"),new t.type.Var(\"Bs\")])]),new t.type.Term(\",\",[new t.type.Term(\"call\",[new t.type.Var(\"P\"),new t.type.Var(\"A\"),new t.type.Var(\"B\")]),new t.type.Term(\"maplist\",[new t.type.Var(\"P\"),new t.type.Var(\"As\"),new t.type.Var(\"Bs\")])]))],\"maplist/4\":[new t.type.Rule(new t.type.Term(\"maplist\",[new t.type.Var(\"_\"),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[])]),null),new t.type.Rule(new t.type.Term(\"maplist\",[new t.type.Var(\"P\"),new t.type.Term(\".\",[new t.type.Var(\"A\"),new t.type.Var(\"As\")]),new t.type.Term(\".\",[new t.type.Var(\"B\"),new t.type.Var(\"Bs\")]),new t.type.Term(\".\",[new t.type.Var(\"C\"),new t.type.Var(\"Cs\")])]),new t.type.Term(\",\",[new t.type.Term(\"call\",[new t.type.Var(\"P\"),new t.type.Var(\"A\"),new t.type.Var(\"B\"),new t.type.Var(\"C\")]),new t.type.Term(\"maplist\",[new t.type.Var(\"P\"),new t.type.Var(\"As\"),new t.type.Var(\"Bs\"),new t.type.Var(\"Cs\")])]))],\"maplist/5\":[new t.type.Rule(new t.type.Term(\"maplist\",[new t.type.Var(\"_\"),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[])]),null),new t.type.Rule(new t.type.Term(\"maplist\",[new t.type.Var(\"P\"),new t.type.Term(\".\",[new t.type.Var(\"A\"),new t.type.Var(\"As\")]),new t.type.Term(\".\",[new t.type.Var(\"B\"),new t.type.Var(\"Bs\")]),new t.type.Term(\".\",[new t.type.Var(\"C\"),new t.type.Var(\"Cs\")]),new t.type.Term(\".\",[new t.type.Var(\"D\"),new t.type.Var(\"Ds\")])]),new t.type.Term(\",\",[new t.type.Term(\"call\",[new t.type.Var(\"P\"),new t.type.Var(\"A\"),new t.type.Var(\"B\"),new t.type.Var(\"C\"),new t.type.Var(\"D\")]),new t.type.Term(\"maplist\",[new t.type.Var(\"P\"),new t.type.Var(\"As\"),new t.type.Var(\"Bs\"),new t.type.Var(\"Cs\"),new t.type.Var(\"Ds\")])]))],\"maplist/6\":[new t.type.Rule(new t.type.Term(\"maplist\",[new t.type.Var(\"_\"),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[])]),null),new t.type.Rule(new t.type.Term(\"maplist\",[new t.type.Var(\"P\"),new t.type.Term(\".\",[new t.type.Var(\"A\"),new t.type.Var(\"As\")]),new t.type.Term(\".\",[new t.type.Var(\"B\"),new t.type.Var(\"Bs\")]),new t.type.Term(\".\",[new t.type.Var(\"C\"),new t.type.Var(\"Cs\")]),new t.type.Term(\".\",[new t.type.Var(\"D\"),new t.type.Var(\"Ds\")]),new t.type.Term(\".\",[new t.type.Var(\"E\"),new t.type.Var(\"Es\")])]),new t.type.Term(\",\",[new t.type.Term(\"call\",[new t.type.Var(\"P\"),new t.type.Var(\"A\"),new t.type.Var(\"B\"),new t.type.Var(\"C\"),new t.type.Var(\"D\"),new t.type.Var(\"E\")]),new t.type.Term(\"maplist\",[new t.type.Var(\"P\"),new t.type.Var(\"As\"),new t.type.Var(\"Bs\"),new t.type.Var(\"Cs\"),new t.type.Var(\"Ds\"),new t.type.Var(\"Es\")])]))],\"maplist/7\":[new t.type.Rule(new t.type.Term(\"maplist\",[new t.type.Var(\"_\"),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[])]),null),new t.type.Rule(new t.type.Term(\"maplist\",[new t.type.Var(\"P\"),new t.type.Term(\".\",[new t.type.Var(\"A\"),new t.type.Var(\"As\")]),new t.type.Term(\".\",[new t.type.Var(\"B\"),new t.type.Var(\"Bs\")]),new t.type.Term(\".\",[new t.type.Var(\"C\"),new t.type.Var(\"Cs\")]),new t.type.Term(\".\",[new t.type.Var(\"D\"),new t.type.Var(\"Ds\")]),new t.type.Term(\".\",[new t.type.Var(\"E\"),new t.type.Var(\"Es\")]),new t.type.Term(\".\",[new t.type.Var(\"F\"),new t.type.Var(\"Fs\")])]),new t.type.Term(\",\",[new t.type.Term(\"call\",[new t.type.Var(\"P\"),new t.type.Var(\"A\"),new t.type.Var(\"B\"),new t.type.Var(\"C\"),new t.type.Var(\"D\"),new t.type.Var(\"E\"),new t.type.Var(\"F\")]),new t.type.Term(\"maplist\",[new t.type.Var(\"P\"),new t.type.Var(\"As\"),new t.type.Var(\"Bs\"),new t.type.Var(\"Cs\"),new t.type.Var(\"Ds\"),new t.type.Var(\"Es\"),new t.type.Var(\"Fs\")])]))],\"maplist/8\":[new t.type.Rule(new t.type.Term(\"maplist\",[new t.type.Var(\"_\"),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[])]),null),new t.type.Rule(new t.type.Term(\"maplist\",[new t.type.Var(\"P\"),new t.type.Term(\".\",[new t.type.Var(\"A\"),new t.type.Var(\"As\")]),new t.type.Term(\".\",[new t.type.Var(\"B\"),new t.type.Var(\"Bs\")]),new t.type.Term(\".\",[new t.type.Var(\"C\"),new t.type.Var(\"Cs\")]),new t.type.Term(\".\",[new t.type.Var(\"D\"),new t.type.Var(\"Ds\")]),new t.type.Term(\".\",[new t.type.Var(\"E\"),new t.type.Var(\"Es\")]),new t.type.Term(\".\",[new t.type.Var(\"F\"),new t.type.Var(\"Fs\")]),new t.type.Term(\".\",[new t.type.Var(\"G\"),new t.type.Var(\"Gs\")])]),new t.type.Term(\",\",[new t.type.Term(\"call\",[new t.type.Var(\"P\"),new t.type.Var(\"A\"),new t.type.Var(\"B\"),new t.type.Var(\"C\"),new t.type.Var(\"D\"),new t.type.Var(\"E\"),new t.type.Var(\"F\"),new t.type.Var(\"G\")]),new t.type.Term(\"maplist\",[new t.type.Var(\"P\"),new t.type.Var(\"As\"),new t.type.Var(\"Bs\"),new t.type.Var(\"Cs\"),new t.type.Var(\"Ds\"),new t.type.Var(\"Es\"),new t.type.Var(\"Fs\"),new t.type.Var(\"Gs\")])]))],\"include/3\":[new t.type.Rule(new t.type.Term(\"include\",[new t.type.Var(\"_\"),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[])]),null),new t.type.Rule(new t.type.Term(\"include\",[new t.type.Var(\"P\"),new t.type.Term(\".\",[new t.type.Var(\"H\"),new t.type.Var(\"T\")]),new t.type.Var(\"L\")]),new t.type.Term(\",\",[new t.type.Term(\"=..\",[new t.type.Var(\"P\"),new t.type.Var(\"A\")]),new t.type.Term(\",\",[new t.type.Term(\"append\",[new t.type.Var(\"A\"),new t.type.Term(\".\",[new t.type.Var(\"H\"),new t.type.Term(\"[]\",[])]),new t.type.Var(\"B\")]),new t.type.Term(\",\",[new t.type.Term(\"=..\",[new t.type.Var(\"F\"),new t.type.Var(\"B\")]),new t.type.Term(\",\",[new t.type.Term(\";\",[new t.type.Term(\",\",[new t.type.Term(\"call\",[new t.type.Var(\"F\")]),new t.type.Term(\",\",[new t.type.Term(\"=\",[new t.type.Var(\"L\"),new t.type.Term(\".\",[new t.type.Var(\"H\"),new t.type.Var(\"S\")])]),new t.type.Term(\"!\",[])])]),new t.type.Term(\"=\",[new t.type.Var(\"L\"),new t.type.Var(\"S\")])]),new t.type.Term(\"include\",[new t.type.Var(\"P\"),new t.type.Var(\"T\"),new t.type.Var(\"S\")])])])])]))],\"exclude/3\":[new t.type.Rule(new t.type.Term(\"exclude\",[new t.type.Var(\"_\"),new t.type.Term(\"[]\",[]),new t.type.Term(\"[]\",[])]),null),new t.type.Rule(new t.type.Term(\"exclude\",[new t.type.Var(\"P\"),new t.type.Term(\".\",[new t.type.Var(\"H\"),new t.type.Var(\"T\")]),new t.type.Var(\"S\")]),new t.type.Term(\",\",[new t.type.Term(\"exclude\",[new t.type.Var(\"P\"),new t.type.Var(\"T\"),new t.type.Var(\"E\")]),new t.type.Term(\",\",[new t.type.Term(\"=..\",[new t.type.Var(\"P\"),new t.type.Var(\"L\")]),new t.type.Term(\",\",[new t.type.Term(\"append\",[new t.type.Var(\"L\"),new t.type.Term(\".\",[new t.type.Var(\"H\"),new t.type.Term(\"[]\",[])]),new t.type.Var(\"Q\")]),new t.type.Term(\",\",[new t.type.Term(\"=..\",[new t.type.Var(\"R\"),new t.type.Var(\"Q\")]),new t.type.Term(\";\",[new t.type.Term(\",\",[new t.type.Term(\"call\",[new t.type.Var(\"R\")]),new t.type.Term(\",\",[new t.type.Term(\"!\",[]),new t.type.Term(\"=\",[new t.type.Var(\"S\"),new t.type.Var(\"E\")])])]),new t.type.Term(\"=\",[new t.type.Var(\"S\"),new t.type.Term(\".\",[new t.type.Var(\"H\"),new t.type.Var(\"E\")])])])])])])]))],\"foldl/4\":[new t.type.Rule(new t.type.Term(\"foldl\",[new t.type.Var(\"_\"),new t.type.Term(\"[]\",[]),new t.type.Var(\"I\"),new t.type.Var(\"I\")]),null),new t.type.Rule(new t.type.Term(\"foldl\",[new t.type.Var(\"P\"),new t.type.Term(\".\",[new t.type.Var(\"H\"),new t.type.Var(\"T\")]),new t.type.Var(\"I\"),new t.type.Var(\"R\")]),new t.type.Term(\",\",[new t.type.Term(\"=..\",[new t.type.Var(\"P\"),new t.type.Var(\"L\")]),new t.type.Term(\",\",[new t.type.Term(\"append\",[new t.type.Var(\"L\"),new t.type.Term(\".\",[new t.type.Var(\"I\"),new t.type.Term(\".\",[new t.type.Var(\"H\"),new t.type.Term(\".\",[new t.type.Var(\"X\"),new t.type.Term(\"[]\",[])])])]),new t.type.Var(\"L2\")]),new t.type.Term(\",\",[new t.type.Term(\"=..\",[new t.type.Var(\"P2\"),new t.type.Var(\"L2\")]),new t.type.Term(\",\",[new t.type.Term(\"call\",[new t.type.Var(\"P2\")]),new t.type.Term(\"foldl\",[new t.type.Var(\"P\"),new t.type.Var(\"T\"),new t.type.Var(\"X\"),new t.type.Var(\"R\")])])])])]))],\"select/3\":[new t.type.Rule(new t.type.Term(\"select\",[new t.type.Var(\"E\"),new t.type.Term(\".\",[new t.type.Var(\"E\"),new t.type.Var(\"Xs\")]),new t.type.Var(\"Xs\")]),null),new t.type.Rule(new t.type.Term(\"select\",[new t.type.Var(\"E\"),new t.type.Term(\".\",[new t.type.Var(\"X\"),new t.type.Var(\"Xs\")]),new t.type.Term(\".\",[new t.type.Var(\"X\"),new t.type.Var(\"Ys\")])]),new t.type.Term(\"select\",[new t.type.Var(\"E\"),new t.type.Var(\"Xs\"),new t.type.Var(\"Ys\")]))],\"sum_list/2\":[new t.type.Rule(new t.type.Term(\"sum_list\",[new t.type.Term(\"[]\",[]),new t.type.Num(0,!1)]),null),new t.type.Rule(new t.type.Term(\"sum_list\",[new t.type.Term(\".\",[new t.type.Var(\"X\"),new t.type.Var(\"Xs\")]),new t.type.Var(\"S\")]),new t.type.Term(\",\",[new t.type.Term(\"sum_list\",[new t.type.Var(\"Xs\"),new t.type.Var(\"Y\")]),new t.type.Term(\"is\",[new t.type.Var(\"S\"),new t.type.Term(\"+\",[new t.type.Var(\"X\"),new t.type.Var(\"Y\")])])]))],\"max_list/2\":[new t.type.Rule(new t.type.Term(\"max_list\",[new t.type.Term(\".\",[new t.type.Var(\"X\"),new t.type.Term(\"[]\",[])]),new t.type.Var(\"X\")]),null),new t.type.Rule(new t.type.Term(\"max_list\",[new t.type.Term(\".\",[new t.type.Var(\"X\"),new t.type.Var(\"Xs\")]),new t.type.Var(\"S\")]),new t.type.Term(\",\",[new t.type.Term(\"max_list\",[new t.type.Var(\"Xs\"),new t.type.Var(\"Y\")]),new t.type.Term(\";\",[new t.type.Term(\",\",[new t.type.Term(\">=\",[new t.type.Var(\"X\"),new t.type.Var(\"Y\")]),new t.type.Term(\",\",[new t.type.Term(\"=\",[new t.type.Var(\"S\"),new t.type.Var(\"X\")]),new t.type.Term(\"!\",[])])]),new t.type.Term(\"=\",[new t.type.Var(\"S\"),new t.type.Var(\"Y\")])])]))],\"min_list/2\":[new t.type.Rule(new t.type.Term(\"min_list\",[new t.type.Term(\".\",[new t.type.Var(\"X\"),new t.type.Term(\"[]\",[])]),new t.type.Var(\"X\")]),null),new t.type.Rule(new t.type.Term(\"min_list\",[new t.type.Term(\".\",[new t.type.Var(\"X\"),new t.type.Var(\"Xs\")]),new t.type.Var(\"S\")]),new t.type.Term(\",\",[new t.type.Term(\"min_list\",[new t.type.Var(\"Xs\"),new t.type.Var(\"Y\")]),new t.type.Term(\";\",[new t.type.Term(\",\",[new t.type.Term(\"=<\",[new t.type.Var(\"X\"),new t.type.Var(\"Y\")]),new t.type.Term(\",\",[new t.type.Term(\"=\",[new t.type.Var(\"S\"),new t.type.Var(\"X\")]),new t.type.Term(\"!\",[])])]),new t.type.Term(\"=\",[new t.type.Var(\"S\"),new t.type.Var(\"Y\")])])]))],\"prod_list/2\":[new t.type.Rule(new t.type.Term(\"prod_list\",[new t.type.Term(\"[]\",[]),new t.type.Num(1,!1)]),null),new t.type.Rule(new t.type.Term(\"prod_list\",[new t.type.Term(\".\",[new t.type.Var(\"X\"),new t.type.Var(\"Xs\")]),new t.type.Var(\"S\")]),new t.type.Term(\",\",[new t.type.Term(\"prod_list\",[new t.type.Var(\"Xs\"),new t.type.Var(\"Y\")]),new t.type.Term(\"is\",[new t.type.Var(\"S\"),new t.type.Term(\"*\",[new t.type.Var(\"X\"),new t.type.Var(\"Y\")])])]))],\"last/2\":[new t.type.Rule(new t.type.Term(\"last\",[new t.type.Term(\".\",[new t.type.Var(\"X\"),new t.type.Term(\"[]\",[])]),new t.type.Var(\"X\")]),null),new t.type.Rule(new t.type.Term(\"last\",[new t.type.Term(\".\",[new t.type.Var(\"_\"),new t.type.Var(\"Xs\")]),new t.type.Var(\"X\")]),new t.type.Term(\"last\",[new t.type.Var(\"Xs\"),new t.type.Var(\"X\")]))],\"prefix/2\":[new t.type.Rule(new t.type.Term(\"prefix\",[new t.type.Var(\"Part\"),new t.type.Var(\"Whole\")]),new t.type.Term(\"append\",[new t.type.Var(\"Part\"),new t.type.Var(\"_\"),new t.type.Var(\"Whole\")]))],\"nth0/3\":[new t.type.Rule(new t.type.Term(\"nth0\",[new t.type.Var(\"X\"),new t.type.Var(\"Y\"),new t.type.Var(\"Z\")]),new t.type.Term(\";\",[new t.type.Term(\"->\",[new t.type.Term(\"var\",[new t.type.Var(\"X\")]),new t.type.Term(\"nth\",[new t.type.Num(0,!1),new t.type.Var(\"X\"),new t.type.Var(\"Y\"),new t.type.Var(\"Z\"),new t.type.Var(\"_\")])]),new t.type.Term(\",\",[new t.type.Term(\">=\",[new t.type.Var(\"X\"),new t.type.Num(0,!1)]),new t.type.Term(\",\",[new t.type.Term(\"nth\",[new t.type.Num(0,!1),new t.type.Var(\"X\"),new t.type.Var(\"Y\"),new t.type.Var(\"Z\"),new t.type.Var(\"_\")]),new t.type.Term(\"!\",[])])])]))],\"nth1/3\":[new t.type.Rule(new t.type.Term(\"nth1\",[new t.type.Var(\"X\"),new t.type.Var(\"Y\"),new t.type.Var(\"Z\")]),new t.type.Term(\";\",[new t.type.Term(\"->\",[new t.type.Term(\"var\",[new t.type.Var(\"X\")]),new t.type.Term(\"nth\",[new t.type.Num(1,!1),new t.type.Var(\"X\"),new t.type.Var(\"Y\"),new t.type.Var(\"Z\"),new t.type.Var(\"_\")])]),new t.type.Term(\",\",[new t.type.Term(\">\",[new t.type.Var(\"X\"),new t.type.Num(0,!1)]),new t.type.Term(\",\",[new t.type.Term(\"nth\",[new t.type.Num(1,!1),new t.type.Var(\"X\"),new t.type.Var(\"Y\"),new t.type.Var(\"Z\"),new t.type.Var(\"_\")]),new t.type.Term(\"!\",[])])])]))],\"nth0/4\":[new t.type.Rule(new t.type.Term(\"nth0\",[new t.type.Var(\"X\"),new t.type.Var(\"Y\"),new t.type.Var(\"Z\"),new t.type.Var(\"W\")]),new t.type.Term(\";\",[new t.type.Term(\"->\",[new t.type.Term(\"var\",[new t.type.Var(\"X\")]),new t.type.Term(\"nth\",[new t.type.Num(0,!1),new t.type.Var(\"X\"),new t.type.Var(\"Y\"),new t.type.Var(\"Z\"),new t.type.Var(\"W\")])]),new t.type.Term(\",\",[new t.type.Term(\">=\",[new t.type.Var(\"X\"),new t.type.Num(0,!1)]),new t.type.Term(\",\",[new t.type.Term(\"nth\",[new t.type.Num(0,!1),new t.type.Var(\"X\"),new t.type.Var(\"Y\"),new t.type.Var(\"Z\"),new t.type.Var(\"W\")]),new t.type.Term(\"!\",[])])])]))],\"nth1/4\":[new t.type.Rule(new t.type.Term(\"nth1\",[new t.type.Var(\"X\"),new t.type.Var(\"Y\"),new t.type.Var(\"Z\"),new t.type.Var(\"W\")]),new t.type.Term(\";\",[new t.type.Term(\"->\",[new t.type.Term(\"var\",[new t.type.Var(\"X\")]),new t.type.Term(\"nth\",[new t.type.Num(1,!1),new t.type.Var(\"X\"),new t.type.Var(\"Y\"),new t.type.Var(\"Z\"),new t.type.Var(\"W\")])]),new t.type.Term(\",\",[new t.type.Term(\">\",[new t.type.Var(\"X\"),new t.type.Num(0,!1)]),new t.type.Term(\",\",[new t.type.Term(\"nth\",[new t.type.Num(1,!1),new t.type.Var(\"X\"),new t.type.Var(\"Y\"),new t.type.Var(\"Z\"),new t.type.Var(\"W\")]),new t.type.Term(\"!\",[])])])]))],\"nth/5\":[new t.type.Rule(new t.type.Term(\"nth\",[new t.type.Var(\"N\"),new t.type.Var(\"N\"),new t.type.Term(\".\",[new t.type.Var(\"X\"),new t.type.Var(\"Xs\")]),new t.type.Var(\"X\"),new t.type.Var(\"Xs\")]),null),new t.type.Rule(new t.type.Term(\"nth\",[new t.type.Var(\"N\"),new t.type.Var(\"O\"),new t.type.Term(\".\",[new t.type.Var(\"X\"),new t.type.Var(\"Xs\")]),new t.type.Var(\"Y\"),new t.type.Term(\".\",[new t.type.Var(\"X\"),new t.type.Var(\"Ys\")])]),new t.type.Term(\",\",[new t.type.Term(\"is\",[new t.type.Var(\"M\"),new t.type.Term(\"+\",[new t.type.Var(\"N\"),new t.type.Num(1,!1)])]),new t.type.Term(\"nth\",[new t.type.Var(\"M\"),new t.type.Var(\"O\"),new t.type.Var(\"Xs\"),new t.type.Var(\"Y\"),new t.type.Var(\"Ys\")])]))],\"length/2\":function(o,a,n){var u=n.args[0],A=n.args[1];if(!t.type.is_variable(A)&&!t.type.is_integer(A))o.throw_error(t.error.type(\"integer\",A,n.indicator));else if(t.type.is_integer(A)&&A.value<0)o.throw_error(t.error.domain(\"not_less_than_zero\",A,n.indicator));else{var p=new t.type.Term(\"length\",[u,new t.type.Num(0,!1),A]);t.type.is_integer(A)&&(p=new t.type.Term(\",\",[p,new t.type.Term(\"!\",[])])),o.prepend([new t.type.State(a.goal.replace(p),a.substitution,a)])}},\"length/3\":[new t.type.Rule(new t.type.Term(\"length\",[new t.type.Term(\"[]\",[]),new t.type.Var(\"N\"),new t.type.Var(\"N\")]),null),new t.type.Rule(new t.type.Term(\"length\",[new t.type.Term(\".\",[new t.type.Var(\"_\"),new t.type.Var(\"X\")]),new t.type.Var(\"A\"),new t.type.Var(\"N\")]),new t.type.Term(\",\",[new t.type.Term(\"succ\",[new t.type.Var(\"A\"),new t.type.Var(\"B\")]),new t.type.Term(\"length\",[new t.type.Var(\"X\"),new t.type.Var(\"B\"),new t.type.Var(\"N\")])]))],\"replicate/3\":function(o,a,n){var u=n.args[0],A=n.args[1],p=n.args[2];if(t.type.is_variable(A))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_integer(A))o.throw_error(t.error.type(\"integer\",A,n.indicator));else if(A.value<0)o.throw_error(t.error.domain(\"not_less_than_zero\",A,n.indicator));else if(!t.type.is_variable(p)&&!t.type.is_list(p))o.throw_error(t.error.type(\"list\",p,n.indicator));else{for(var h=new t.type.Term(\"[]\"),E=0;E<A.value;E++)h=new t.type.Term(\".\",[u,h]);o.prepend([new t.type.State(a.goal.replace(new t.type.Term(\"=\",[h,p])),a.substitution,a)])}},\"sort/2\":function(o,a,n){var u=n.args[0],A=n.args[1];if(t.type.is_variable(u))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_variable(A)&&!t.type.is_fully_list(A))o.throw_error(t.error.type(\"list\",A,n.indicator));else{for(var p=[],h=u;h.indicator===\"./2\";)p.push(h.args[0]),h=h.args[1];if(t.type.is_variable(h))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_empty_list(h))o.throw_error(t.error.type(\"list\",u,n.indicator));else{for(var E=p.sort(t.compare),w=E.length-1;w>0;w--)E[w].equals(E[w-1])&&E.splice(w,1);for(var D=new t.type.Term(\"[]\"),w=E.length-1;w>=0;w--)D=new t.type.Term(\".\",[E[w],D]);o.prepend([new t.type.State(a.goal.replace(new t.type.Term(\"=\",[D,A])),a.substitution,a)])}}},\"msort/2\":function(o,a,n){var u=n.args[0],A=n.args[1];if(t.type.is_variable(u))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_variable(A)&&!t.type.is_fully_list(A))o.throw_error(t.error.type(\"list\",A,n.indicator));else{for(var p=[],h=u;h.indicator===\"./2\";)p.push(h.args[0]),h=h.args[1];if(t.type.is_variable(h))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_empty_list(h))o.throw_error(t.error.type(\"list\",u,n.indicator));else{for(var E=p.sort(t.compare),w=new t.type.Term(\"[]\"),D=E.length-1;D>=0;D--)w=new t.type.Term(\".\",[E[D],w]);o.prepend([new t.type.State(a.goal.replace(new t.type.Term(\"=\",[w,A])),a.substitution,a)])}}},\"keysort/2\":function(o,a,n){var u=n.args[0],A=n.args[1];if(t.type.is_variable(u))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_variable(A)&&!t.type.is_fully_list(A))o.throw_error(t.error.type(\"list\",A,n.indicator));else{for(var p=[],h,E=u;E.indicator===\"./2\";){if(h=E.args[0],t.type.is_variable(h)){o.throw_error(t.error.instantiation(n.indicator));return}else if(!t.type.is_term(h)||h.indicator!==\"-/2\"){o.throw_error(t.error.type(\"pair\",h,n.indicator));return}h.args[0].pair=h.args[1],p.push(h.args[0]),E=E.args[1]}if(t.type.is_variable(E))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_empty_list(E))o.throw_error(t.error.type(\"list\",u,n.indicator));else{for(var w=p.sort(t.compare),D=new t.type.Term(\"[]\"),b=w.length-1;b>=0;b--)D=new t.type.Term(\".\",[new t.type.Term(\"-\",[w[b],w[b].pair]),D]),delete w[b].pair;o.prepend([new t.type.State(a.goal.replace(new t.type.Term(\"=\",[D,A])),a.substitution,a)])}}},\"take/3\":function(o,a,n){var u=n.args[0],A=n.args[1],p=n.args[2];if(t.type.is_variable(A)||t.type.is_variable(u))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_list(A))o.throw_error(t.error.type(\"list\",A,n.indicator));else if(!t.type.is_integer(u))o.throw_error(t.error.type(\"integer\",u,n.indicator));else if(!t.type.is_variable(p)&&!t.type.is_list(p))o.throw_error(t.error.type(\"list\",p,n.indicator));else{for(var h=u.value,E=[],w=A;h>0&&w.indicator===\"./2\";)E.push(w.args[0]),w=w.args[1],h--;if(h===0){for(var D=new t.type.Term(\"[]\"),h=E.length-1;h>=0;h--)D=new t.type.Term(\".\",[E[h],D]);o.prepend([new t.type.State(a.goal.replace(new t.type.Term(\"=\",[D,p])),a.substitution,a)])}}},\"drop/3\":function(o,a,n){var u=n.args[0],A=n.args[1],p=n.args[2];if(t.type.is_variable(A)||t.type.is_variable(u))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_list(A))o.throw_error(t.error.type(\"list\",A,n.indicator));else if(!t.type.is_integer(u))o.throw_error(t.error.type(\"integer\",u,n.indicator));else if(!t.type.is_variable(p)&&!t.type.is_list(p))o.throw_error(t.error.type(\"list\",p,n.indicator));else{for(var h=u.value,E=[],w=A;h>0&&w.indicator===\"./2\";)E.push(w.args[0]),w=w.args[1],h--;h===0&&o.prepend([new t.type.State(a.goal.replace(new t.type.Term(\"=\",[w,p])),a.substitution,a)])}},\"reverse/2\":function(o,a,n){var u=n.args[0],A=n.args[1],p=t.type.is_instantiated_list(u),h=t.type.is_instantiated_list(A);if(t.type.is_variable(u)&&t.type.is_variable(A))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_variable(u)&&!t.type.is_fully_list(u))o.throw_error(t.error.type(\"list\",u,n.indicator));else if(!t.type.is_variable(A)&&!t.type.is_fully_list(A))o.throw_error(t.error.type(\"list\",A,n.indicator));else if(!p&&!h)o.throw_error(t.error.instantiation(n.indicator));else{for(var E=p?u:A,w=new t.type.Term(\"[]\",[]);E.indicator===\"./2\";)w=new t.type.Term(\".\",[E.args[0],w]),E=E.args[1];o.prepend([new t.type.State(a.goal.replace(new t.type.Term(\"=\",[w,p?A:u])),a.substitution,a)])}},\"list_to_set/2\":function(o,a,n){var u=n.args[0],A=n.args[1];if(t.type.is_variable(u))o.throw_error(t.error.instantiation(n.indicator));else{for(var p=u,h=[];p.indicator===\"./2\";)h.push(p.args[0]),p=p.args[1];if(t.type.is_variable(p))o.throw_error(t.error.instantiation(n.indicator));else if(!t.type.is_term(p)||p.indicator!==\"[]/0\")o.throw_error(t.error.type(\"list\",u,n.indicator));else{for(var E=[],w=new t.type.Term(\"[]\",[]),D,b=0;b<h.length;b++){D=!1;for(var C=0;C<E.length&&!D;C++)D=t.compare(h[b],E[C])===0;D||E.push(h[b])}for(b=E.length-1;b>=0;b--)w=new t.type.Term(\".\",[E[b],w]);o.prepend([new t.type.State(a.goal.replace(new t.type.Term(\"=\",[A,w])),a.substitution,a)])}}}}},r=[\"append/2\",\"append/3\",\"member/2\",\"permutation/2\",\"maplist/2\",\"maplist/3\",\"maplist/4\",\"maplist/5\",\"maplist/6\",\"maplist/7\",\"maplist/8\",\"include/3\",\"exclude/3\",\"foldl/4\",\"sum_list/2\",\"max_list/2\",\"min_list/2\",\"prod_list/2\",\"last/2\",\"prefix/2\",\"nth0/3\",\"nth1/3\",\"nth0/4\",\"nth1/4\",\"length/2\",\"replicate/3\",\"select/3\",\"sort/2\",\"msort/2\",\"keysort/2\",\"take/3\",\"drop/3\",\"reverse/2\",\"list_to_set/2\"];typeof GH<\"u\"?GH.exports=function(o){t=o,new t.type.Module(\"lists\",e(),r)}:new t.type.Module(\"lists\",e(),r)})(Ogt)});var Yme=_(Vr=>{\"use strict\";var Xg=process.platform===\"win32\",WH=\"aes-256-cbc\",Mgt=\"sha256\",Tme=\"The current environment doesn't support interactive reading from TTY.\",Xn=ve(\"fs\"),Fme=process.binding(\"tty_wrap\").TTY,KH=ve(\"child_process\"),Lh=ve(\"path\"),VH={prompt:\"> \",hideEchoBack:!1,mask:\"*\",limit:[],limitMessage:\"Input another, please.$<( [)limit(])>\",defaultInput:\"\",trueValue:[],falseValue:[],caseSensitive:!1,keepWhitespace:!1,encoding:\"utf8\",bufferSize:1024,print:void 0,history:!0,cd:!1,phContent:void 0,preCheck:void 0},Kf=\"none\",iu,eC,Rme=!1,Th,Jk,YH,Ugt=0,$H=\"\",Jg=[],Xk,Lme=!1,zH=!1,G2=!1;function Nme(t){function e(r){return r.replace(/[^\\w\\u0080-\\uFFFF]/g,function(o){return\"#\"+o.charCodeAt(0)+\";\"})}return Jk.concat(function(r){var o=[];return Object.keys(r).forEach(function(a){r[a]===\"boolean\"?t[a]&&o.push(\"--\"+a):r[a]===\"string\"&&t[a]&&o.push(\"--\"+a,e(t[a]))}),o}({display:\"string\",displayOnly:\"boolean\",keyIn:\"boolean\",hideEchoBack:\"boolean\",mask:\"string\",limit:\"string\",caseSensitive:\"boolean\"}))}function _gt(t,e){function r(U){var z,te=\"\",le;for(YH=YH||ve(\"os\").tmpdir();;){z=Lh.join(YH,U+te);try{le=Xn.openSync(z,\"wx\")}catch(ce){if(ce.code===\"EEXIST\"){te++;continue}else throw ce}Xn.closeSync(le);break}return z}var o,a,n,u={},A,p,h=r(\"readline-sync.stdout\"),E=r(\"readline-sync.stderr\"),w=r(\"readline-sync.exit\"),D=r(\"readline-sync.done\"),b=ve(\"crypto\"),C,T,N;C=b.createHash(Mgt),C.update(\"\"+process.pid+Ugt+++Math.random()),N=C.digest(\"hex\"),T=b.createDecipher(WH,N),o=Nme(t),Xg?(a=process.env.ComSpec||\"cmd.exe\",process.env.Q='\"',n=[\"/V:ON\",\"/S\",\"/C\",\"(%Q%\"+a+\"%Q% /V:ON /S /C %Q%%Q%\"+Th+\"%Q%\"+o.map(function(U){return\" %Q%\"+U+\"%Q%\"}).join(\"\")+\" & (echo !ERRORLEVEL!)>%Q%\"+w+\"%Q%%Q%) 2>%Q%\"+E+\"%Q% |%Q%\"+process.execPath+\"%Q% %Q%\"+__dirname+\"\\\\encrypt.js%Q% %Q%\"+WH+\"%Q% %Q%\"+N+\"%Q% >%Q%\"+h+\"%Q% & (echo 1)>%Q%\"+D+\"%Q%\"]):(a=\"/bin/sh\",n=[\"-c\",'(\"'+Th+'\"'+o.map(function(U){return\" '\"+U.replace(/'/g,\"'\\\\''\")+\"'\"}).join(\"\")+'; echo $?>\"'+w+'\") 2>\"'+E+'\" |\"'+process.execPath+'\" \"'+__dirname+'/encrypt.js\" \"'+WH+'\" \"'+N+'\" >\"'+h+'\"; echo 1 >\"'+D+'\"']),G2&&G2(\"_execFileSync\",o);try{KH.spawn(a,n,e)}catch(U){u.error=new Error(U.message),u.error.method=\"_execFileSync - spawn\",u.error.program=a,u.error.args=n}for(;Xn.readFileSync(D,{encoding:t.encoding}).trim()!==\"1\";);return(A=Xn.readFileSync(w,{encoding:t.encoding}).trim())===\"0\"?u.input=T.update(Xn.readFileSync(h,{encoding:\"binary\"}),\"hex\",t.encoding)+T.final(t.encoding):(p=Xn.readFileSync(E,{encoding:t.encoding}).trim(),u.error=new Error(Tme+(p?`\n`+p:\"\")),u.error.method=\"_execFileSync\",u.error.program=a,u.error.args=n,u.error.extMessage=p,u.error.exitCode=+A),Xn.unlinkSync(h),Xn.unlinkSync(E),Xn.unlinkSync(w),Xn.unlinkSync(D),u}function Hgt(t){var e,r={},o,a={env:process.env,encoding:t.encoding};if(Th||(Xg?process.env.PSModulePath?(Th=\"powershell.exe\",Jk=[\"-ExecutionPolicy\",\"Bypass\",\"-File\",__dirname+\"\\\\read.ps1\"]):(Th=\"cscript.exe\",Jk=[\"//nologo\",__dirname+\"\\\\read.cs.js\"]):(Th=\"/bin/sh\",Jk=[__dirname+\"/read.sh\"])),Xg&&!process.env.PSModulePath&&(a.stdio=[process.stdin]),KH.execFileSync){e=Nme(t),G2&&G2(\"execFileSync\",e);try{r.input=KH.execFileSync(Th,e,a)}catch(n){o=n.stderr?(n.stderr+\"\").trim():\"\",r.error=new Error(Tme+(o?`\n`+o:\"\")),r.error.method=\"execFileSync\",r.error.program=Th,r.error.args=e,r.error.extMessage=o,r.error.exitCode=n.status,r.error.code=n.code,r.error.signal=n.signal}}else r=_gt(t,a);return r.error||(r.input=r.input.replace(/^\\s*'|'\\s*$/g,\"\"),t.display=\"\"),r}function JH(t){var e=\"\",r=t.display,o=!t.display&&t.keyIn&&t.hideEchoBack&&!t.mask;function a(){var n=Hgt(t);if(n.error)throw n.error;return n.input}return zH&&zH(t),function(){var n,u,A;function p(){return n||(n=process.binding(\"fs\"),u=process.binding(\"constants\")),n}if(typeof Kf==\"string\")if(Kf=null,Xg){if(A=function(h){var E=h.replace(/^\\D+/,\"\").split(\".\"),w=0;return(E[0]=+E[0])&&(w+=E[0]*1e4),(E[1]=+E[1])&&(w+=E[1]*100),(E[2]=+E[2])&&(w+=E[2]),w}(process.version),!(A>=20302&&A<40204||A>=5e4&&A<50100||A>=50600&&A<60200)&&process.stdin.isTTY)process.stdin.pause(),Kf=process.stdin.fd,eC=process.stdin._handle;else try{Kf=p().open(\"CONIN$\",u.O_RDWR,parseInt(\"0666\",8)),eC=new Fme(Kf,!0)}catch{}if(process.stdout.isTTY)iu=process.stdout.fd;else{try{iu=Xn.openSync(\"\\\\\\\\.\\\\CON\",\"w\")}catch{}if(typeof iu!=\"number\")try{iu=p().open(\"CONOUT$\",u.O_RDWR,parseInt(\"0666\",8))}catch{}}}else{if(process.stdin.isTTY){process.stdin.pause();try{Kf=Xn.openSync(\"/dev/tty\",\"r\"),eC=process.stdin._handle}catch{}}else try{Kf=Xn.openSync(\"/dev/tty\",\"r\"),eC=new Fme(Kf,!1)}catch{}if(process.stdout.isTTY)iu=process.stdout.fd;else try{iu=Xn.openSync(\"/dev/tty\",\"w\")}catch{}}}(),function(){var n,u,A=!t.hideEchoBack&&!t.keyIn,p,h,E,w,D;Xk=\"\";function b(C){return C===Rme?!0:eC.setRawMode(C)!==0?!1:(Rme=C,!0)}if(Lme||!eC||typeof iu!=\"number\"&&(t.display||!A)){e=a();return}if(t.display&&(Xn.writeSync(iu,t.display),t.display=\"\"),!t.displayOnly){if(!b(!A)){e=a();return}for(h=t.keyIn?1:t.bufferSize,p=Buffer.allocUnsafe&&Buffer.alloc?Buffer.alloc(h):new Buffer(h),t.keyIn&&t.limit&&(u=new RegExp(\"[^\"+t.limit+\"]\",\"g\"+(t.caseSensitive?\"\":\"i\")));;){E=0;try{E=Xn.readSync(Kf,p,0,h)}catch(C){if(C.code!==\"EOF\"){b(!1),e+=a();return}}if(E>0?(w=p.toString(t.encoding,0,E),Xk+=w):(w=`\n`,Xk+=\"\\0\"),w&&typeof(D=(w.match(/^(.*?)[\\r\\n]/)||[])[1])==\"string\"&&(w=D,n=!0),w&&(w=w.replace(/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]/g,\"\")),w&&u&&(w=w.replace(u,\"\")),w&&(A||(t.hideEchoBack?t.mask&&Xn.writeSync(iu,new Array(w.length+1).join(t.mask)):Xn.writeSync(iu,w)),e+=w),!t.keyIn&&n||t.keyIn&&e.length>=h)break}!A&&!o&&Xn.writeSync(iu,`\n`),b(!1)}}(),t.print&&!o&&t.print(r+(t.displayOnly?\"\":(t.hideEchoBack?new Array(e.length+1).join(t.mask):e)+`\n`),t.encoding),t.displayOnly?\"\":$H=t.keepWhitespace||t.keyIn?e:e.trim()}function qgt(t,e){var r=[];function o(a){a!=null&&(Array.isArray(a)?a.forEach(o):(!e||e(a))&&r.push(a))}return o(t),r}function e6(t){return t.replace(/[\\x00-\\x7f]/g,function(e){return\"\\\\x\"+(\"00\"+e.charCodeAt().toString(16)).substr(-2)})}function bs(){var t=Array.prototype.slice.call(arguments),e,r;return t.length&&typeof t[0]==\"boolean\"&&(r=t.shift(),r&&(e=Object.keys(VH),t.unshift(VH))),t.reduce(function(o,a){return a==null||(a.hasOwnProperty(\"noEchoBack\")&&!a.hasOwnProperty(\"hideEchoBack\")&&(a.hideEchoBack=a.noEchoBack,delete a.noEchoBack),a.hasOwnProperty(\"noTrim\")&&!a.hasOwnProperty(\"keepWhitespace\")&&(a.keepWhitespace=a.noTrim,delete a.noTrim),r||(e=Object.keys(a)),e.forEach(function(n){var u;if(a.hasOwnProperty(n))switch(u=a[n],n){case\"mask\":case\"limitMessage\":case\"defaultInput\":case\"encoding\":u=u!=null?u+\"\":\"\",u&&n!==\"limitMessage\"&&(u=u.replace(/[\\r\\n]/g,\"\")),o[n]=u;break;case\"bufferSize\":!isNaN(u=parseInt(u,10))&&typeof u==\"number\"&&(o[n]=u);break;case\"displayOnly\":case\"keyIn\":case\"hideEchoBack\":case\"caseSensitive\":case\"keepWhitespace\":case\"history\":case\"cd\":o[n]=!!u;break;case\"limit\":case\"trueValue\":case\"falseValue\":o[n]=qgt(u,function(A){var p=typeof A;return p===\"string\"||p===\"number\"||p===\"function\"||A instanceof RegExp}).map(function(A){return typeof A==\"string\"?A.replace(/[\\r\\n]/g,\"\"):A});break;case\"print\":case\"phContent\":case\"preCheck\":o[n]=typeof u==\"function\"?u:void 0;break;case\"prompt\":case\"display\":o[n]=u??\"\";break}})),o},{})}function XH(t,e,r){return e.some(function(o){var a=typeof o;return a===\"string\"?r?t===o:t.toLowerCase()===o.toLowerCase():a===\"number\"?parseFloat(t)===o:a===\"function\"?o(t):o instanceof RegExp?o.test(t):!1})}function t6(t,e){var r=Lh.normalize(Xg?(process.env.HOMEDRIVE||\"\")+(process.env.HOMEPATH||\"\"):process.env.HOME||\"\").replace(/[\\/\\\\]+$/,\"\");return t=Lh.normalize(t),e?t.replace(/^~(?=\\/|\\\\|$)/,r):t.replace(new RegExp(\"^\"+e6(r)+\"(?=\\\\/|\\\\\\\\|$)\",Xg?\"i\":\"\"),\"~\")}function tC(t,e){var r=\"(?:\\\\(([\\\\s\\\\S]*?)\\\\))?(\\\\w+|.-.)(?:\\\\(([\\\\s\\\\S]*?)\\\\))?\",o=new RegExp(\"(\\\\$)?(\\\\$<\"+r+\">)\",\"g\"),a=new RegExp(\"(\\\\$)?(\\\\$\\\\{\"+r+\"\\\\})\",\"g\");function n(u,A,p,h,E,w){var D;return A||typeof(D=e(E))!=\"string\"?p:D?(h||\"\")+D+(w||\"\"):\"\"}return t.replace(o,n).replace(a,n)}function Ome(t,e,r){var o,a=[],n=-1,u=0,A=\"\",p;function h(E,w){return w.length>3?(E.push(w[0]+\"...\"+w[w.length-1]),p=!0):w.length&&(E=E.concat(w)),E}return o=t.reduce(function(E,w){return E.concat((w+\"\").split(\"\"))},[]).reduce(function(E,w){var D,b;return e||(w=w.toLowerCase()),D=/^\\d$/.test(w)?1:/^[A-Z]$/.test(w)?2:/^[a-z]$/.test(w)?3:0,r&&D===0?A+=w:(b=w.charCodeAt(0),D&&D===n&&b===u+1?a.push(w):(E=h(E,a),a=[w],n=D),u=b),E},[]),o=h(o,a),A&&(o.push(A),p=!0),{values:o,suppressed:p}}function Mme(t,e){return t.join(t.length>2?\", \":e?\" / \":\"/\")}function Ume(t,e){var r,o,a={},n;if(e.phContent&&(r=e.phContent(t,e)),typeof r!=\"string\")switch(t){case\"hideEchoBack\":case\"mask\":case\"defaultInput\":case\"caseSensitive\":case\"keepWhitespace\":case\"encoding\":case\"bufferSize\":case\"history\":case\"cd\":r=e.hasOwnProperty(t)?typeof e[t]==\"boolean\"?e[t]?\"on\":\"off\":e[t]+\"\":\"\";break;case\"limit\":case\"trueValue\":case\"falseValue\":o=e[e.hasOwnProperty(t+\"Src\")?t+\"Src\":t],e.keyIn?(a=Ome(o,e.caseSensitive),o=a.values):o=o.filter(function(u){var A=typeof u;return A===\"string\"||A===\"number\"}),r=Mme(o,a.suppressed);break;case\"limitCount\":case\"limitCountNotZero\":r=e[e.hasOwnProperty(\"limitSrc\")?\"limitSrc\":\"limit\"].length,r=r||t!==\"limitCountNotZero\"?r+\"\":\"\";break;case\"lastInput\":r=$H;break;case\"cwd\":case\"CWD\":case\"cwdHome\":r=process.cwd(),t===\"CWD\"?r=Lh.basename(r):t===\"cwdHome\"&&(r=t6(r));break;case\"date\":case\"time\":case\"localeDate\":case\"localeTime\":r=new Date()[\"to\"+t.replace(/^./,function(u){return u.toUpperCase()})+\"String\"]();break;default:typeof(n=(t.match(/^history_m(\\d+)$/)||[])[1])==\"string\"&&(r=Jg[Jg.length-n]||\"\")}return r}function _me(t){var e=/^(.)-(.)$/.exec(t),r=\"\",o,a,n,u;if(!e)return null;for(o=e[1].charCodeAt(0),a=e[2].charCodeAt(0),u=o<a?1:-1,n=o;n!==a+u;n+=u)r+=String.fromCharCode(n);return r}function ZH(t){var e=new RegExp(/(\\s*)(?:(\"|')(.*?)(?:\\2|$)|(\\S+))/g),r,o=\"\",a=[],n;for(t=t.trim();r=e.exec(t);)n=r[3]||r[4]||\"\",r[1]&&(a.push(o),o=\"\"),o+=n;return o&&a.push(o),a}function Hme(t,e){return e.trueValue.length&&XH(t,e.trueValue,e.caseSensitive)?!0:e.falseValue.length&&XH(t,e.falseValue,e.caseSensitive)?!1:t}function qme(t){var e,r,o,a,n,u,A;function p(E){return Ume(E,t)}function h(E){t.display+=(/[^\\r\\n]$/.test(t.display)?`\n`:\"\")+E}for(t.limitSrc=t.limit,t.displaySrc=t.display,t.limit=\"\",t.display=tC(t.display+\"\",p);;){if(e=JH(t),r=!1,o=\"\",t.defaultInput&&!e&&(e=t.defaultInput),t.history&&((a=/^\\s*\\!(?:\\!|-1)(:p)?\\s*$/.exec(e))?(n=Jg[0]||\"\",a[1]?r=!0:e=n,h(n+`\n`),r||(t.displayOnly=!0,JH(t),t.displayOnly=!1)):e&&e!==Jg[Jg.length-1]&&(Jg=[e])),!r&&t.cd&&e)switch(u=ZH(e),u[0].toLowerCase()){case\"cd\":if(u[1])try{process.chdir(t6(u[1],!0))}catch(E){h(E+\"\")}r=!0;break;case\"pwd\":h(process.cwd()),r=!0;break}if(!r&&t.preCheck&&(A=t.preCheck(e,t),e=A.res,A.forceNext&&(r=!0)),!r){if(!t.limitSrc.length||XH(e,t.limitSrc,t.caseSensitive))break;t.limitMessage&&(o=tC(t.limitMessage,p))}h((o?o+`\n`:\"\")+tC(t.displaySrc+\"\",p))}return Hme(e,t)}Vr._DBG_set_useExt=function(t){Lme=t};Vr._DBG_set_checkOptions=function(t){zH=t};Vr._DBG_set_checkMethod=function(t){G2=t};Vr._DBG_clearHistory=function(){$H=\"\",Jg=[]};Vr.setDefaultOptions=function(t){return VH=bs(!0,t),bs(!0)};Vr.question=function(t,e){return qme(bs(bs(!0,e),{display:t}))};Vr.prompt=function(t){var e=bs(!0,t);return e.display=e.prompt,qme(e)};Vr.keyIn=function(t,e){var r=bs(bs(!0,e),{display:t,keyIn:!0,keepWhitespace:!0});return r.limitSrc=r.limit.filter(function(o){var a=typeof o;return a===\"string\"||a===\"number\"}).map(function(o){return tC(o+\"\",_me)}),r.limit=e6(r.limitSrc.join(\"\")),[\"trueValue\",\"falseValue\"].forEach(function(o){r[o]=r[o].reduce(function(a,n){var u=typeof n;return u===\"string\"||u===\"number\"?a=a.concat((n+\"\").split(\"\")):a.push(n),a},[])}),r.display=tC(r.display+\"\",function(o){return Ume(o,r)}),Hme(JH(r),r)};Vr.questionEMail=function(t,e){return t==null&&(t=\"Input e-mail address: \"),Vr.question(t,bs({hideEchoBack:!1,limit:/^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/,limitMessage:\"Input valid e-mail address, please.\",trueValue:null,falseValue:null},e,{keepWhitespace:!1,cd:!1}))};Vr.questionNewPassword=function(t,e){var r,o,a,n=bs({hideEchoBack:!0,mask:\"*\",limitMessage:`It can include: $<charlist>\nAnd the length must be: $<length>`,trueValue:null,falseValue:null,caseSensitive:!0},e,{history:!1,cd:!1,phContent:function(b){return b===\"charlist\"?r.text:b===\"length\"?o+\"...\"+a:null}}),u,A,p,h,E,w,D;for(e=e||{},u=tC(e.charlist?e.charlist+\"\":\"$<!-~>\",_me),(isNaN(o=parseInt(e.min,10))||typeof o!=\"number\")&&(o=12),(isNaN(a=parseInt(e.max,10))||typeof a!=\"number\")&&(a=24),h=new RegExp(\"^[\"+e6(u)+\"]{\"+o+\",\"+a+\"}$\"),r=Ome([u],n.caseSensitive,!0),r.text=Mme(r.values,r.suppressed),A=e.confirmMessage!=null?e.confirmMessage:\"Reinput a same one to confirm it: \",p=e.unmatchMessage!=null?e.unmatchMessage:\"It differs from first one. Hit only the Enter key if you want to retry from first one.\",t==null&&(t=\"Input new password: \"),E=n.limitMessage;!D;)n.limit=h,n.limitMessage=E,w=Vr.question(t,n),n.limit=[w,\"\"],n.limitMessage=p,D=Vr.question(A,n);return w};function jme(t,e,r){var o;function a(n){return o=r(n),!isNaN(o)&&typeof o==\"number\"}return Vr.question(t,bs({limitMessage:\"Input valid number, please.\"},e,{limit:a,cd:!1})),o}Vr.questionInt=function(t,e){return jme(t,e,function(r){return parseInt(r,10)})};Vr.questionFloat=function(t,e){return jme(t,e,parseFloat)};Vr.questionPath=function(t,e){var r,o=\"\",a=bs({hideEchoBack:!1,limitMessage:`$<error(\n)>Input valid path, please.$<( Min:)min>$<( Max:)max>`,history:!0,cd:!0},e,{keepWhitespace:!1,limit:function(n){var u,A,p;n=t6(n,!0),o=\"\";function h(E){E.split(/\\/|\\\\/).reduce(function(w,D){var b=Lh.resolve(w+=D+Lh.sep);if(!Xn.existsSync(b))Xn.mkdirSync(b);else if(!Xn.statSync(b).isDirectory())throw new Error(\"Non directory already exists: \"+b);return w},\"\")}try{if(u=Xn.existsSync(n),r=u?Xn.realpathSync(n):Lh.resolve(n),!e.hasOwnProperty(\"exists\")&&!u||typeof e.exists==\"boolean\"&&e.exists!==u)return o=(u?\"Already exists\":\"No such file or directory\")+\": \"+r,!1;if(!u&&e.create&&(e.isDirectory?h(r):(h(Lh.dirname(r)),Xn.closeSync(Xn.openSync(r,\"w\"))),r=Xn.realpathSync(r)),u&&(e.min||e.max||e.isFile||e.isDirectory)){if(A=Xn.statSync(r),e.isFile&&!A.isFile())return o=\"Not file: \"+r,!1;if(e.isDirectory&&!A.isDirectory())return o=\"Not directory: \"+r,!1;if(e.min&&A.size<+e.min||e.max&&A.size>+e.max)return o=\"Size \"+A.size+\" is out of range: \"+r,!1}if(typeof e.validate==\"function\"&&(p=e.validate(r))!==!0)return typeof p==\"string\"&&(o=p),!1}catch(E){return o=E+\"\",!1}return!0},phContent:function(n){return n===\"error\"?o:n!==\"min\"&&n!==\"max\"?null:e.hasOwnProperty(n)?e[n]+\"\":\"\"}});return e=e||{},t==null&&(t='Input path (you can \"cd\" and \"pwd\"): '),Vr.question(t,a),r};function Gme(t,e){var r={},o={};return typeof t==\"object\"?(Object.keys(t).forEach(function(a){typeof t[a]==\"function\"&&(o[e.caseSensitive?a:a.toLowerCase()]=t[a])}),r.preCheck=function(a){var n;return r.args=ZH(a),n=r.args[0]||\"\",e.caseSensitive||(n=n.toLowerCase()),r.hRes=n!==\"_\"&&o.hasOwnProperty(n)?o[n].apply(a,r.args.slice(1)):o.hasOwnProperty(\"_\")?o._.apply(a,r.args):null,{res:a,forceNext:!1}},o.hasOwnProperty(\"_\")||(r.limit=function(){var a=r.args[0]||\"\";return e.caseSensitive||(a=a.toLowerCase()),o.hasOwnProperty(a)})):r.preCheck=function(a){return r.args=ZH(a),r.hRes=typeof t==\"function\"?t.apply(a,r.args):!0,{res:a,forceNext:!1}},r}Vr.promptCL=function(t,e){var r=bs({hideEchoBack:!1,limitMessage:\"Requested command is not available.\",caseSensitive:!1,history:!0},e),o=Gme(t,r);return r.limit=o.limit,r.preCheck=o.preCheck,Vr.prompt(r),o.args};Vr.promptLoop=function(t,e){for(var r=bs({hideEchoBack:!1,trueValue:null,falseValue:null,caseSensitive:!1,history:!0},e);!t(Vr.prompt(r)););};Vr.promptCLLoop=function(t,e){var r=bs({hideEchoBack:!1,limitMessage:\"Requested command is not available.\",caseSensitive:!1,history:!0},e),o=Gme(t,r);for(r.limit=o.limit,r.preCheck=o.preCheck;Vr.prompt(r),!o.hRes;);};Vr.promptSimShell=function(t){return Vr.prompt(bs({hideEchoBack:!1,history:!0},t,{prompt:function(){return Xg?\"$<cwd>>\":(process.env.USER||\"\")+(process.env.HOSTNAME?\"@\"+process.env.HOSTNAME.replace(/\\..*$/,\"\"):\"\")+\":$<cwdHome>$ \"}()}))};function Wme(t,e,r){var o;return t==null&&(t=\"Are you sure? \"),(!e||e.guide!==!1)&&(t+=\"\")&&(t=t.replace(/\\s*:?\\s*$/,\"\")+\" [y/n]: \"),o=Vr.keyIn(t,bs(e,{hideEchoBack:!1,limit:r,trueValue:\"y\",falseValue:\"n\",caseSensitive:!1})),typeof o==\"boolean\"?o:\"\"}Vr.keyInYN=function(t,e){return Wme(t,e)};Vr.keyInYNStrict=function(t,e){return Wme(t,e,\"yn\")};Vr.keyInPause=function(t,e){t==null&&(t=\"Continue...\"),(!e||e.guide!==!1)&&(t+=\"\")&&(t=t.replace(/\\s+$/,\"\")+\" (Hit any key)\"),Vr.keyIn(t,bs({limit:null},e,{hideEchoBack:!0,mask:\"\"}))};Vr.keyInSelect=function(t,e,r){var o=bs({hideEchoBack:!1},r,{trueValue:null,falseValue:null,caseSensitive:!1,phContent:function(p){return p===\"itemsCount\"?t.length+\"\":p===\"firstItem\"?(t[0]+\"\").trim():p===\"lastItem\"?(t[t.length-1]+\"\").trim():null}}),a=\"\",n={},u=49,A=`\n`;if(!Array.isArray(t)||!t.length||t.length>35)throw\"`items` must be Array (max length: 35).\";return t.forEach(function(p,h){var E=String.fromCharCode(u);a+=E,n[E]=h,A+=\"[\"+E+\"] \"+(p+\"\").trim()+`\n`,u=u===57?97:u+1}),(!r||r.cancel!==!1)&&(a+=\"0\",n[0]=-1,A+=\"[0] \"+(r&&r.cancel!=null&&typeof r.cancel!=\"boolean\"?(r.cancel+\"\").trim():\"CANCEL\")+`\n`),o.limit=a,A+=`\n`,e==null&&(e=\"Choose one from list: \"),(e+=\"\")&&((!r||r.guide!==!1)&&(e=e.replace(/\\s*:?\\s*$/,\"\")+\" [$<limit>]: \"),A+=e),n[Vr.keyIn(A,o).toLowerCase()]};Vr.getRawInput=function(){return Xk};function W2(t,e){var r;return e.length&&(r={},r[t]=e[0]),Vr.setDefaultOptions(r)[t]}Vr.setPrint=function(){return W2(\"print\",arguments)};Vr.setPrompt=function(){return W2(\"prompt\",arguments)};Vr.setEncoding=function(){return W2(\"encoding\",arguments)};Vr.setMask=function(){return W2(\"mask\",arguments)};Vr.setBufferSize=function(){return W2(\"bufferSize\",arguments)}});var r6=_((O5t,El)=>{(function(){var t={major:0,minor:2,patch:66,status:\"beta\"};tau_file_system={files:{},open:function(I,S,y){var R=tau_file_system.files[I];if(!R){if(y===\"read\")return null;R={path:I,text:\"\",type:S,get:function(J,X){return X===this.text.length||X>this.text.length?\"end_of_file\":this.text.substring(X,X+J)},put:function(J,X){return X===\"end_of_file\"?(this.text+=J,!0):X===\"past_end_of_file\"?null:(this.text=this.text.substring(0,X)+J+this.text.substring(X+J.length),!0)},get_byte:function(J){if(J===\"end_of_stream\")return-1;var X=Math.floor(J/2);if(this.text.length<=X)return-1;var $=n(this.text[Math.floor(J/2)],0);return J%2===0?$&255:$/256>>>0},put_byte:function(J,X){var $=X===\"end_of_stream\"?this.text.length:Math.floor(X/2);if(this.text.length<$)return null;var se=this.text.length===$?-1:n(this.text[Math.floor(X/2)],0);return X%2===0?(se=se/256>>>0,se=(se&255)<<8|J&255):(se=se&255,se=(J&255)<<8|se&255),this.text.length===$?this.text+=u(se):this.text=this.text.substring(0,$)+u(se)+this.text.substring($+1),!0},flush:function(){return!0},close:function(){var J=tau_file_system.files[this.path];return J?!0:null}},tau_file_system.files[I]=R}return y===\"write\"&&(R.text=\"\"),R}},tau_user_input={buffer:\"\",get:function(I,S){for(var y;tau_user_input.buffer.length<I;)y=window.prompt(),y&&(tau_user_input.buffer+=y);return y=tau_user_input.buffer.substr(0,I),tau_user_input.buffer=tau_user_input.buffer.substr(I),y}},tau_user_output={put:function(I,S){return console.log(I),!0},flush:function(){return!0}},nodejs_file_system={open:function(I,S,y){var R=ve(\"fs\"),J=R.openSync(I,y[0]);return y===\"read\"&&!R.existsSync(I)?null:{get:function(X,$){var se=new Buffer(X);return R.readSync(J,se,0,X,$),se.toString()},put:function(X,$){var se=Buffer.from(X);if($===\"end_of_file\")R.writeSync(J,se);else{if($===\"past_end_of_file\")return null;R.writeSync(J,se,0,se.length,$)}return!0},get_byte:function(X){return null},put_byte:function(X,$){return null},flush:function(){return!0},close:function(){return R.closeSync(J),!0}}}},nodejs_user_input={buffer:\"\",get:function(I,S){for(var y,R=Yme();nodejs_user_input.buffer.length<I;)nodejs_user_input.buffer+=R.question();return y=nodejs_user_input.buffer.substr(0,I),nodejs_user_input.buffer=nodejs_user_input.buffer.substr(I),y}},nodejs_user_output={put:function(I,S){return process.stdout.write(I),!0},flush:function(){return!0}};var e;Array.prototype.indexOf?e=function(I,S){return I.indexOf(S)}:e=function(I,S){for(var y=I.length,R=0;R<y;R++)if(S===I[R])return R;return-1};var r=function(I,S){if(I.length!==0){for(var y=I[0],R=I.length,J=1;J<R;J++)y=S(y,I[J]);return y}},o;Array.prototype.map?o=function(I,S){return I.map(S)}:o=function(I,S){for(var y=[],R=I.length,J=0;J<R;J++)y.push(S(I[J]));return y};var a;Array.prototype.filter?a=function(I,S){return I.filter(S)}:a=function(I,S){for(var y=[],R=I.length,J=0;J<R;J++)S(I[J])&&y.push(I[J]);return y};var n;String.prototype.codePointAt?n=function(I,S){return I.codePointAt(S)}:n=function(I,S){return I.charCodeAt(S)};var u;String.fromCodePoint?u=function(){return String.fromCodePoint.apply(null,arguments)}:u=function(){return String.fromCharCode.apply(null,arguments)};var A=0,p=1,h=/(\\\\a)|(\\\\b)|(\\\\f)|(\\\\n)|(\\\\r)|(\\\\t)|(\\\\v)|\\\\x([0-9a-fA-F]+)\\\\|\\\\([0-7]+)\\\\|(\\\\\\\\)|(\\\\')|('')|(\\\\\")|(\\\\`)|(\\\\.)|(.)/g,E={\"\\\\a\":7,\"\\\\b\":8,\"\\\\f\":12,\"\\\\n\":10,\"\\\\r\":13,\"\\\\t\":9,\"\\\\v\":11};function w(I){var S=[],y=!1;return I.replace(h,function(R,J,X,$,se,be,Fe,lt,Et,qt,nr,St,cn,Pr,yr,Rr,Xr){switch(!0){case Et!==void 0:return S.push(parseInt(Et,16)),\"\";case qt!==void 0:return S.push(parseInt(qt,8)),\"\";case nr!==void 0:case St!==void 0:case cn!==void 0:case Pr!==void 0:case yr!==void 0:return S.push(n(R.substr(1),0)),\"\";case Xr!==void 0:return S.push(n(Xr,0)),\"\";case Rr!==void 0:y=!0;default:return S.push(E[R]),\"\"}}),y?null:S}function D(I,S){var y=\"\";if(I.length<2)return I;try{I=I.replace(/\\\\([0-7]+)\\\\/g,function($,se){return u(parseInt(se,8))}),I=I.replace(/\\\\x([0-9a-fA-F]+)\\\\/g,function($,se){return u(parseInt(se,16))})}catch{return null}for(var R=0;R<I.length;R++){var J=I.charAt(R),X=I.charAt(R+1);if(J===S&&X===S)R++,y+=S;else if(J===\"\\\\\")if([\"a\",\"b\",\"f\",\"n\",\"r\",\"t\",\"v\",\"'\",'\"',\"\\\\\",\"a\",\"\\b\",\"\\f\",`\n`,\"\\r\",\"\t\",\"\\v\"].indexOf(X)!==-1)switch(R+=1,X){case\"a\":y+=\"a\";break;case\"b\":y+=\"\\b\";break;case\"f\":y+=\"\\f\";break;case\"n\":y+=`\n`;break;case\"r\":y+=\"\\r\";break;case\"t\":y+=\"\t\";break;case\"v\":y+=\"\\v\";break;case\"'\":y+=\"'\";break;case'\"':y+='\"';break;case\"\\\\\":y+=\"\\\\\";break}else return null;else y+=J}return y}function b(I){for(var S=\"\",y=0;y<I.length;y++)switch(I.charAt(y)){case\"'\":S+=\"\\\\'\";break;case\"\\\\\":S+=\"\\\\\\\\\";break;case\"\\b\":S+=\"\\\\b\";break;case\"\\f\":S+=\"\\\\f\";break;case`\n`:S+=\"\\\\n\";break;case\"\\r\":S+=\"\\\\r\";break;case\"\t\":S+=\"\\\\t\";break;case\"\\v\":S+=\"\\\\v\";break;default:S+=I.charAt(y);break}return S}function C(I){var S=I.substr(2);switch(I.substr(0,2).toLowerCase()){case\"0x\":return parseInt(S,16);case\"0b\":return parseInt(S,2);case\"0o\":return parseInt(S,8);case\"0'\":return w(S)[0];default:return parseFloat(I)}}var T={whitespace:/^\\s*(?:(?:%.*)|(?:\\/\\*(?:\\n|\\r|.)*?\\*\\/)|(?:\\s+))\\s*/,variable:/^(?:[A-Z_][a-zA-Z0-9_]*)/,atom:/^(\\!|,|;|[a-z][0-9a-zA-Z_]*|[#\\$\\&\\*\\+\\-\\.\\/\\:\\<\\=\\>\\?\\@\\^\\~\\\\]+|'(?:[^']*?(?:\\\\(?:x?\\d+)?\\\\)*(?:'')*(?:\\\\')*)*')/,number:/^(?:0o[0-7]+|0x[0-9a-fA-F]+|0b[01]+|0'(?:''|\\\\[abfnrtv\\\\'\"`]|\\\\x?\\d+\\\\|[^\\\\])|\\d+(?:\\.\\d+(?:[eE][+-]?\\d+)?)?)/,string:/^(?:\"([^\"]|\"\"|\\\\\")*\"|`([^`]|``|\\\\`)*`)/,l_brace:/^(?:\\[)/,r_brace:/^(?:\\])/,l_bracket:/^(?:\\{)/,r_bracket:/^(?:\\})/,bar:/^(?:\\|)/,l_paren:/^(?:\\()/,r_paren:/^(?:\\))/};function N(I,S){return I.get_flag(\"char_conversion\").id===\"on\"?S.replace(/./g,function(y){return I.get_char_conversion(y)}):S}function U(I){this.thread=I,this.text=\"\",this.tokens=[]}U.prototype.set_last_tokens=function(I){return this.tokens=I},U.prototype.new_text=function(I){this.text=I,this.tokens=[]},U.prototype.get_tokens=function(I){var S,y=0,R=0,J=0,X=[],$=!1;if(I){var se=this.tokens[I-1];y=se.len,S=N(this.thread,this.text.substr(se.len)),R=se.line,J=se.start}else S=this.text;if(/^\\s*$/.test(S))return null;for(;S!==\"\";){var be=[],Fe=!1;if(/^\\n/.exec(S)!==null){R++,J=0,y++,S=S.replace(/\\n/,\"\"),$=!0;continue}for(var lt in T)if(T.hasOwnProperty(lt)){var Et=T[lt].exec(S);Et&&be.push({value:Et[0],name:lt,matches:Et})}if(!be.length)return this.set_last_tokens([{value:S,matches:[],name:\"lexical\",line:R,start:J}]);var se=r(be,function(Pr,yr){return Pr.value.length>=yr.value.length?Pr:yr});switch(se.start=J,se.line=R,S=S.replace(se.value,\"\"),J+=se.value.length,y+=se.value.length,se.name){case\"atom\":se.raw=se.value,se.value.charAt(0)===\"'\"&&(se.value=D(se.value.substr(1,se.value.length-2),\"'\"),se.value===null&&(se.name=\"lexical\",se.value=\"unknown escape sequence\"));break;case\"number\":se.float=se.value.substring(0,2)!==\"0x\"&&se.value.match(/[.eE]/)!==null&&se.value!==\"0'.\",se.value=C(se.value),se.blank=Fe;break;case\"string\":var qt=se.value.charAt(0);se.value=D(se.value.substr(1,se.value.length-2),qt),se.value===null&&(se.name=\"lexical\",se.value=\"unknown escape sequence\");break;case\"whitespace\":var nr=X[X.length-1];nr&&(nr.space=!0),Fe=!0;continue;case\"r_bracket\":X.length>0&&X[X.length-1].name===\"l_bracket\"&&(se=X.pop(),se.name=\"atom\",se.value=\"{}\",se.raw=\"{}\",se.space=!1);break;case\"r_brace\":X.length>0&&X[X.length-1].name===\"l_brace\"&&(se=X.pop(),se.name=\"atom\",se.value=\"[]\",se.raw=\"[]\",se.space=!1);break}se.len=y,X.push(se),Fe=!1}var St=this.set_last_tokens(X);return St.length===0?null:St};function z(I,S,y,R,J){if(!S[y])return{type:A,value:x.error.syntax(S[y-1],\"expression expected\",!0)};var X;if(R===\"0\"){var $=S[y];switch($.name){case\"number\":return{type:p,len:y+1,value:new x.type.Num($.value,$.float)};case\"variable\":return{type:p,len:y+1,value:new x.type.Var($.value)};case\"string\":var se;switch(I.get_flag(\"double_quotes\").id){case\"atom\":se=new q($.value,[]);break;case\"codes\":se=new q(\"[]\",[]);for(var be=$.value.length-1;be>=0;be--)se=new q(\".\",[new x.type.Num(n($.value,be),!1),se]);break;case\"chars\":se=new q(\"[]\",[]);for(var be=$.value.length-1;be>=0;be--)se=new q(\".\",[new x.type.Term($.value.charAt(be),[]),se]);break}return{type:p,len:y+1,value:se};case\"l_paren\":var St=z(I,S,y+1,I.__get_max_priority(),!0);return St.type!==p?St:S[St.len]&&S[St.len].name===\"r_paren\"?(St.len++,St):{type:A,derived:!0,value:x.error.syntax(S[St.len]?S[St.len]:S[St.len-1],\") or operator expected\",!S[St.len])};case\"l_bracket\":var St=z(I,S,y+1,I.__get_max_priority(),!0);return St.type!==p?St:S[St.len]&&S[St.len].name===\"r_bracket\"?(St.len++,St.value=new q(\"{}\",[St.value]),St):{type:A,derived:!0,value:x.error.syntax(S[St.len]?S[St.len]:S[St.len-1],\"} or operator expected\",!S[St.len])}}var Fe=te(I,S,y,J);return Fe.type===p||Fe.derived||(Fe=le(I,S,y),Fe.type===p||Fe.derived)?Fe:{type:A,derived:!1,value:x.error.syntax(S[y],\"unexpected token\")}}var lt=I.__get_max_priority(),Et=I.__get_next_priority(R),qt=y;if(S[y].name===\"atom\"&&S[y+1]&&(S[y].space||S[y+1].name!==\"l_paren\")){var $=S[y++],nr=I.__lookup_operator_classes(R,$.value);if(nr&&nr.indexOf(\"fy\")>-1){var St=z(I,S,y,R,J);if(St.type!==A)return $.value===\"-\"&&!$.space&&x.type.is_number(St.value)?{value:new x.type.Num(-St.value.value,St.value.is_float),len:St.len,type:p}:{value:new x.type.Term($.value,[St.value]),len:St.len,type:p};X=St}else if(nr&&nr.indexOf(\"fx\")>-1){var St=z(I,S,y,Et,J);if(St.type!==A)return{value:new x.type.Term($.value,[St.value]),len:St.len,type:p};X=St}}y=qt;var St=z(I,S,y,Et,J);if(St.type===p){y=St.len;var $=S[y];if(S[y]&&(S[y].name===\"atom\"&&I.__lookup_operator_classes(R,$.value)||S[y].name===\"bar\"&&I.__lookup_operator_classes(R,\"|\"))){var cn=Et,Pr=R,nr=I.__lookup_operator_classes(R,$.value);if(nr.indexOf(\"xf\")>-1)return{value:new x.type.Term($.value,[St.value]),len:++St.len,type:p};if(nr.indexOf(\"xfx\")>-1){var yr=z(I,S,y+1,cn,J);return yr.type===p?{value:new x.type.Term($.value,[St.value,yr.value]),len:yr.len,type:p}:(yr.derived=!0,yr)}else if(nr.indexOf(\"xfy\")>-1){var yr=z(I,S,y+1,Pr,J);return yr.type===p?{value:new x.type.Term($.value,[St.value,yr.value]),len:yr.len,type:p}:(yr.derived=!0,yr)}else if(St.type!==A)for(;;){y=St.len;var $=S[y];if($&&$.name===\"atom\"&&I.__lookup_operator_classes(R,$.value)){var nr=I.__lookup_operator_classes(R,$.value);if(nr.indexOf(\"yf\")>-1)St={value:new x.type.Term($.value,[St.value]),len:++y,type:p};else if(nr.indexOf(\"yfx\")>-1){var yr=z(I,S,++y,cn,J);if(yr.type===A)return yr.derived=!0,yr;y=yr.len,St={value:new x.type.Term($.value,[St.value,yr.value]),len:y,type:p}}else break}else break}}else X={type:A,value:x.error.syntax(S[St.len-1],\"operator expected\")};return St}return St}function te(I,S,y,R){if(!S[y]||S[y].name===\"atom\"&&S[y].raw===\".\"&&!R&&(S[y].space||!S[y+1]||S[y+1].name!==\"l_paren\"))return{type:A,derived:!1,value:x.error.syntax(S[y-1],\"unfounded token\")};var J=S[y],X=[];if(S[y].name===\"atom\"&&S[y].raw!==\",\"){if(y++,S[y-1].space)return{type:p,len:y,value:new x.type.Term(J.value,X)};if(S[y]&&S[y].name===\"l_paren\"){if(S[y+1]&&S[y+1].name===\"r_paren\")return{type:A,derived:!0,value:x.error.syntax(S[y+1],\"argument expected\")};var $=z(I,S,++y,\"999\",!0);if($.type===A)return $.derived?$:{type:A,derived:!0,value:x.error.syntax(S[y]?S[y]:S[y-1],\"argument expected\",!S[y])};for(X.push($.value),y=$.len;S[y]&&S[y].name===\"atom\"&&S[y].value===\",\";){if($=z(I,S,y+1,\"999\",!0),$.type===A)return $.derived?$:{type:A,derived:!0,value:x.error.syntax(S[y+1]?S[y+1]:S[y],\"argument expected\",!S[y+1])};X.push($.value),y=$.len}if(S[y]&&S[y].name===\"r_paren\")y++;else return{type:A,derived:!0,value:x.error.syntax(S[y]?S[y]:S[y-1],\", or ) expected\",!S[y])}}return{type:p,len:y,value:new x.type.Term(J.value,X)}}return{type:A,derived:!1,value:x.error.syntax(S[y],\"term expected\")}}function le(I,S,y){if(!S[y])return{type:A,derived:!1,value:x.error.syntax(S[y-1],\"[ expected\")};if(S[y]&&S[y].name===\"l_brace\"){var R=z(I,S,++y,\"999\",!0),J=[R.value],X=void 0;if(R.type===A)return S[y]&&S[y].name===\"r_brace\"?{type:p,len:y+1,value:new x.type.Term(\"[]\",[])}:{type:A,derived:!0,value:x.error.syntax(S[y],\"] expected\")};for(y=R.len;S[y]&&S[y].name===\"atom\"&&S[y].value===\",\";){if(R=z(I,S,y+1,\"999\",!0),R.type===A)return R.derived?R:{type:A,derived:!0,value:x.error.syntax(S[y+1]?S[y+1]:S[y],\"argument expected\",!S[y+1])};J.push(R.value),y=R.len}var $=!1;if(S[y]&&S[y].name===\"bar\"){if($=!0,R=z(I,S,y+1,\"999\",!0),R.type===A)return R.derived?R:{type:A,derived:!0,value:x.error.syntax(S[y+1]?S[y+1]:S[y],\"argument expected\",!S[y+1])};X=R.value,y=R.len}return S[y]&&S[y].name===\"r_brace\"?{type:p,len:y+1,value:g(J,X)}:{type:A,derived:!0,value:x.error.syntax(S[y]?S[y]:S[y-1],$?\"] expected\":\", or | or ] expected\",!S[y])}}return{type:A,derived:!1,value:x.error.syntax(S[y],\"list expected\")}}function ce(I,S,y){var R=S[y].line,J=z(I,S,y,I.__get_max_priority(),!1),X=null,$;if(J.type!==A)if(y=J.len,S[y]&&S[y].name===\"atom\"&&S[y].raw===\".\")if(y++,x.type.is_term(J.value)){if(J.value.indicator===\":-/2\"?(X=new x.type.Rule(J.value.args[0],Ee(J.value.args[1])),$={value:X,len:y,type:p}):J.value.indicator===\"-->/2\"?(X=he(new x.type.Rule(J.value.args[0],J.value.args[1]),I),X.body=Ee(X.body),$={value:X,len:y,type:x.type.is_rule(X)?p:A}):(X=new x.type.Rule(J.value,null),$={value:X,len:y,type:p}),X){var se=X.singleton_variables();se.length>0&&I.throw_warning(x.warning.singleton(se,X.head.indicator,R))}return $}else return{type:A,value:x.error.syntax(S[y],\"callable expected\")};else return{type:A,value:x.error.syntax(S[y]?S[y]:S[y-1],\". or operator expected\")};return J}function ue(I,S,y){y=y||{},y.from=y.from?y.from:\"$tau-js\",y.reconsult=y.reconsult!==void 0?y.reconsult:!0;var R=new U(I),J={},X;R.new_text(S);var $=0,se=R.get_tokens($);do{if(se===null||!se[$])break;var be=ce(I,se,$);if(be.type===A)return new q(\"throw\",[be.value]);if(be.value.body===null&&be.value.head.indicator===\"?-/1\"){var Fe=new tt(I.session);Fe.add_goal(be.value.head.args[0]),Fe.answer(function(Et){x.type.is_error(Et)?I.throw_warning(Et.args[0]):(Et===!1||Et===null)&&I.throw_warning(x.warning.failed_goal(be.value.head.args[0],be.len))}),$=be.len;var lt=!0}else if(be.value.body===null&&be.value.head.indicator===\":-/1\"){var lt=I.run_directive(be.value.head.args[0]);$=be.len,be.value.head.args[0].indicator===\"char_conversion/2\"&&(se=R.get_tokens($),$=0)}else{X=be.value.head.indicator,y.reconsult!==!1&&J[X]!==!0&&!I.is_multifile_predicate(X)&&(I.session.rules[X]=a(I.session.rules[X]||[],function(qt){return qt.dynamic}),J[X]=!0);var lt=I.add_rule(be.value,y);$=be.len}if(!lt)return lt}while(!0);return!0}function Ie(I,S){var y=new U(I);y.new_text(S);var R=0;do{var J=y.get_tokens(R);if(J===null)break;var X=z(I,J,0,I.__get_max_priority(),!1);if(X.type!==A){var $=X.len,se=$;if(J[$]&&J[$].name===\"atom\"&&J[$].raw===\".\")I.add_goal(Ee(X.value));else{var be=J[$];return new q(\"throw\",[x.error.syntax(be||J[$-1],\". or operator expected\",!be)])}R=X.len+1}else return new q(\"throw\",[X.value])}while(!0);return!0}function he(I,S){I=I.rename(S);var y=S.next_free_variable(),R=De(I.body,y,S);return R.error?R.value:(I.body=R.value,I.head.args=I.head.args.concat([y,R.variable]),I.head=new q(I.head.id,I.head.args),I)}function De(I,S,y){var R;if(x.type.is_term(I)&&I.indicator===\"!/0\")return{value:I,variable:S,error:!1};if(x.type.is_term(I)&&I.indicator===\",/2\"){var J=De(I.args[0],S,y);if(J.error)return J;var X=De(I.args[1],J.variable,y);return X.error?X:{value:new q(\",\",[J.value,X.value]),variable:X.variable,error:!1}}else{if(x.type.is_term(I)&&I.indicator===\"{}/1\")return{value:I.args[0],variable:S,error:!1};if(x.type.is_empty_list(I))return{value:new q(\"true\",[]),variable:S,error:!1};if(x.type.is_list(I)){R=y.next_free_variable();for(var $=I,se;$.indicator===\"./2\";)se=$,$=$.args[1];return x.type.is_variable($)?{value:x.error.instantiation(\"DCG\"),variable:S,error:!0}:x.type.is_empty_list($)?(se.args[1]=R,{value:new q(\"=\",[S,I]),variable:R,error:!1}):{value:x.error.type(\"list\",I,\"DCG\"),variable:S,error:!0}}else return x.type.is_callable(I)?(R=y.next_free_variable(),I.args=I.args.concat([S,R]),I=new q(I.id,I.args),{value:I,variable:R,error:!1}):{value:x.error.type(\"callable\",I,\"DCG\"),variable:S,error:!0}}}function Ee(I){return x.type.is_variable(I)?new q(\"call\",[I]):x.type.is_term(I)&&[\",/2\",\";/2\",\"->/2\"].indexOf(I.indicator)!==-1?new q(I.id,[Ee(I.args[0]),Ee(I.args[1])]):I}function g(I,S){for(var y=S||new x.type.Term(\"[]\",[]),R=I.length-1;R>=0;R--)y=new x.type.Term(\".\",[I[R],y]);return y}function me(I,S){for(var y=I.length-1;y>=0;y--)I[y]===S&&I.splice(y,1)}function Ce(I){for(var S={},y=[],R=0;R<I.length;R++)I[R]in S||(y.push(I[R]),S[I[R]]=!0);return y}function fe(I,S,y,R){if(I.session.rules[y]!==null){for(var J=0;J<I.session.rules[y].length;J++)if(I.session.rules[y][J]===R){I.session.rules[y].splice(J,1),I.success(S);break}}}function ie(I){return function(S,y,R){var J=R.args[0],X=R.args.slice(1,I);if(x.type.is_variable(J))S.throw_error(x.error.instantiation(S.level));else if(!x.type.is_callable(J))S.throw_error(x.error.type(\"callable\",J,S.level));else{var $=new q(J.id,J.args.concat(X));S.prepend([new ke(y.goal.replace($),y.substitution,y)])}}}function Z(I){for(var S=I.length-1;S>=0;S--)if(I.charAt(S)===\"/\")return new q(\"/\",[new q(I.substring(0,S)),new Re(parseInt(I.substring(S+1)),!1)])}function Pe(I){this.id=I}function Re(I,S){this.is_float=S!==void 0?S:parseInt(I)!==I,this.value=this.is_float?I:parseInt(I)}var ht=0;function q(I,S,y){this.ref=y||++ht,this.id=I,this.args=S||[],this.indicator=I+\"/\"+this.args.length}var nt=0;function Le(I,S,y,R,J,X){this.id=nt++,this.stream=I,this.mode=S,this.alias=y,this.type=R!==void 0?R:\"text\",this.reposition=J!==void 0?J:!0,this.eof_action=X!==void 0?X:\"eof_code\",this.position=this.mode===\"append\"?\"end_of_stream\":0,this.output=this.mode===\"write\"||this.mode===\"append\",this.input=this.mode===\"read\"}function Te(I){I=I||{},this.links=I}function ke(I,S,y){S=S||new Te,y=y||null,this.goal=I,this.substitution=S,this.parent=y}function Ve(I,S,y){this.head=I,this.body=S,this.dynamic=y||!1}function xe(I){I=I===void 0||I<=0?1e3:I,this.rules={},this.src_predicates={},this.rename=0,this.modules=[],this.thread=new tt(this),this.total_threads=1,this.renamed_variables={},this.public_predicates={},this.multifile_predicates={},this.limit=I,this.streams={user_input:new Le(typeof El<\"u\"&&El.exports?nodejs_user_input:tau_user_input,\"read\",\"user_input\",\"text\",!1,\"reset\"),user_output:new Le(typeof El<\"u\"&&El.exports?nodejs_user_output:tau_user_output,\"write\",\"user_output\",\"text\",!1,\"eof_code\")},this.file_system=typeof El<\"u\"&&El.exports?nodejs_file_system:tau_file_system,this.standard_input=this.streams.user_input,this.standard_output=this.streams.user_output,this.current_input=this.streams.user_input,this.current_output=this.streams.user_output,this.format_success=function(S){return S.substitution},this.format_error=function(S){return S.goal},this.flag={bounded:x.flag.bounded.value,max_integer:x.flag.max_integer.value,min_integer:x.flag.min_integer.value,integer_rounding_function:x.flag.integer_rounding_function.value,char_conversion:x.flag.char_conversion.value,debug:x.flag.debug.value,max_arity:x.flag.max_arity.value,unknown:x.flag.unknown.value,double_quotes:x.flag.double_quotes.value,occurs_check:x.flag.occurs_check.value,dialect:x.flag.dialect.value,version_data:x.flag.version_data.value,nodejs:x.flag.nodejs.value},this.__loaded_modules=[],this.__char_conversion={},this.__operators={1200:{\":-\":[\"fx\",\"xfx\"],\"-->\":[\"xfx\"],\"?-\":[\"fx\"]},1100:{\";\":[\"xfy\"]},1050:{\"->\":[\"xfy\"]},1e3:{\",\":[\"xfy\"]},900:{\"\\\\+\":[\"fy\"]},700:{\"=\":[\"xfx\"],\"\\\\=\":[\"xfx\"],\"==\":[\"xfx\"],\"\\\\==\":[\"xfx\"],\"@<\":[\"xfx\"],\"@=<\":[\"xfx\"],\"@>\":[\"xfx\"],\"@>=\":[\"xfx\"],\"=..\":[\"xfx\"],is:[\"xfx\"],\"=:=\":[\"xfx\"],\"=\\\\=\":[\"xfx\"],\"<\":[\"xfx\"],\"=<\":[\"xfx\"],\">\":[\"xfx\"],\">=\":[\"xfx\"]},600:{\":\":[\"xfy\"]},500:{\"+\":[\"yfx\"],\"-\":[\"yfx\"],\"/\\\\\":[\"yfx\"],\"\\\\/\":[\"yfx\"]},400:{\"*\":[\"yfx\"],\"/\":[\"yfx\"],\"//\":[\"yfx\"],rem:[\"yfx\"],mod:[\"yfx\"],\"<<\":[\"yfx\"],\">>\":[\"yfx\"]},200:{\"**\":[\"xfx\"],\"^\":[\"xfy\"],\"-\":[\"fy\"],\"+\":[\"fy\"],\"\\\\\":[\"fy\"]}}}function tt(I){this.epoch=Date.now(),this.session=I,this.session.total_threads++,this.total_steps=0,this.cpu_time=0,this.cpu_time_last=0,this.points=[],this.debugger=!1,this.debugger_states=[],this.level=\"top_level/0\",this.__calls=[],this.current_limit=this.session.limit,this.warnings=[]}function He(I,S,y){this.id=I,this.rules=S,this.exports=y,x.module[I]=this}He.prototype.exports_predicate=function(I){return this.exports.indexOf(I)!==-1},Pe.prototype.unify=function(I,S){if(S&&e(I.variables(),this.id)!==-1&&!x.type.is_variable(I))return null;var y={};return y[this.id]=I,new Te(y)},Re.prototype.unify=function(I,S){return x.type.is_number(I)&&this.value===I.value&&this.is_float===I.is_float?new Te:null},q.prototype.unify=function(I,S){if(x.type.is_term(I)&&this.indicator===I.indicator){for(var y=new Te,R=0;R<this.args.length;R++){var J=x.unify(this.args[R].apply(y),I.args[R].apply(y),S);if(J===null)return null;for(var X in J.links)y.links[X]=J.links[X];y=y.apply(J)}return y}return null},Le.prototype.unify=function(I,S){return x.type.is_stream(I)&&this.id===I.id?new Te:null},Pe.prototype.toString=function(I){return this.id},Re.prototype.toString=function(I){return this.is_float&&e(this.value.toString(),\".\")===-1?this.value+\".0\":this.value.toString()},q.prototype.toString=function(I,S,y){if(I=I||{},I.quoted=I.quoted===void 0?!0:I.quoted,I.ignore_ops=I.ignore_ops===void 0?!1:I.ignore_ops,I.numbervars=I.numbervars===void 0?!1:I.numbervars,S=S===void 0?1200:S,y=y===void 0?\"\":y,I.numbervars&&this.indicator===\"$VAR/1\"&&x.type.is_integer(this.args[0])&&this.args[0].value>=0){var R=this.args[0].value,J=Math.floor(R/26),X=R%26;return\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"[X]+(J!==0?J:\"\")}switch(this.indicator){case\"[]/0\":case\"{}/0\":case\"!/0\":return this.id;case\"{}/1\":return\"{\"+this.args[0].toString(I)+\"}\";case\"./2\":for(var $=\"[\"+this.args[0].toString(I),se=this.args[1];se.indicator===\"./2\";)$+=\", \"+se.args[0].toString(I),se=se.args[1];return se.indicator!==\"[]/0\"&&($+=\"|\"+se.toString(I)),$+=\"]\",$;case\",/2\":return\"(\"+this.args[0].toString(I)+\", \"+this.args[1].toString(I)+\")\";default:var be=this.id,Fe=I.session?I.session.lookup_operator(this.id,this.args.length):null;if(I.session===void 0||I.ignore_ops||Fe===null)return I.quoted&&!/^(!|,|;|[a-z][0-9a-zA-Z_]*)$/.test(be)&&be!==\"{}\"&&be!==\"[]\"&&(be=\"'\"+b(be)+\"'\"),be+(this.args.length?\"(\"+o(this.args,function(nr){return nr.toString(I)}).join(\", \")+\")\":\"\");var lt=Fe.priority>S.priority||Fe.priority===S.priority&&(Fe.class===\"xfy\"&&this.indicator!==S.indicator||Fe.class===\"yfx\"&&this.indicator!==S.indicator||this.indicator===S.indicator&&Fe.class===\"yfx\"&&y===\"right\"||this.indicator===S.indicator&&Fe.class===\"xfy\"&&y===\"left\");Fe.indicator=this.indicator;var Et=lt?\"(\":\"\",qt=lt?\")\":\"\";return this.args.length===0?\"(\"+this.id+\")\":[\"fy\",\"fx\"].indexOf(Fe.class)!==-1?Et+be+\" \"+this.args[0].toString(I,Fe)+qt:[\"yf\",\"xf\"].indexOf(Fe.class)!==-1?Et+this.args[0].toString(I,Fe)+\" \"+be+qt:Et+this.args[0].toString(I,Fe,\"left\")+\" \"+this.id+\" \"+this.args[1].toString(I,Fe,\"right\")+qt}},Le.prototype.toString=function(I){return\"<stream>(\"+this.id+\")\"},Te.prototype.toString=function(I){var S=\"{\";for(var y in this.links)this.links.hasOwnProperty(y)&&(S!==\"{\"&&(S+=\", \"),S+=y+\"/\"+this.links[y].toString(I));return S+=\"}\",S},ke.prototype.toString=function(I){return this.goal===null?\"<\"+this.substitution.toString(I)+\">\":\"<\"+this.goal.toString(I)+\", \"+this.substitution.toString(I)+\">\"},Ve.prototype.toString=function(I){return this.body?this.head.toString(I)+\" :- \"+this.body.toString(I)+\".\":this.head.toString(I)+\".\"},xe.prototype.toString=function(I){for(var S=\"\",y=0;y<this.modules.length;y++)S+=\":- use_module(library(\"+this.modules[y]+`)).\n`;S+=`\n`;for(key in this.rules)for(y=0;y<this.rules[key].length;y++)S+=this.rules[key][y].toString(I),S+=`\n`;return S},Pe.prototype.clone=function(){return new Pe(this.id)},Re.prototype.clone=function(){return new Re(this.value,this.is_float)},q.prototype.clone=function(){return new q(this.id,o(this.args,function(I){return I.clone()}))},Le.prototype.clone=function(){return new Stram(this.stream,this.mode,this.alias,this.type,this.reposition,this.eof_action)},Te.prototype.clone=function(){var I={};for(var S in this.links)this.links.hasOwnProperty(S)&&(I[S]=this.links[S].clone());return new Te(I)},ke.prototype.clone=function(){return new ke(this.goal.clone(),this.substitution.clone(),this.parent)},Ve.prototype.clone=function(){return new Ve(this.head.clone(),this.body!==null?this.body.clone():null)},Pe.prototype.equals=function(I){return x.type.is_variable(I)&&this.id===I.id},Re.prototype.equals=function(I){return x.type.is_number(I)&&this.value===I.value&&this.is_float===I.is_float},q.prototype.equals=function(I){if(!x.type.is_term(I)||this.indicator!==I.indicator)return!1;for(var S=0;S<this.args.length;S++)if(!this.args[S].equals(I.args[S]))return!1;return!0},Le.prototype.equals=function(I){return x.type.is_stream(I)&&this.id===I.id},Te.prototype.equals=function(I){var S;if(!x.type.is_substitution(I))return!1;for(S in this.links)if(this.links.hasOwnProperty(S)&&(!I.links[S]||!this.links[S].equals(I.links[S])))return!1;for(S in I.links)if(I.links.hasOwnProperty(S)&&!this.links[S])return!1;return!0},ke.prototype.equals=function(I){return x.type.is_state(I)&&this.goal.equals(I.goal)&&this.substitution.equals(I.substitution)&&this.parent===I.parent},Ve.prototype.equals=function(I){return x.type.is_rule(I)&&this.head.equals(I.head)&&(this.body===null&&I.body===null||this.body!==null&&this.body.equals(I.body))},Pe.prototype.rename=function(I){return I.get_free_variable(this)},Re.prototype.rename=function(I){return this},q.prototype.rename=function(I){return new q(this.id,o(this.args,function(S){return S.rename(I)}))},Le.prototype.rename=function(I){return this},Ve.prototype.rename=function(I){return new Ve(this.head.rename(I),this.body!==null?this.body.rename(I):null)},Pe.prototype.variables=function(){return[this.id]},Re.prototype.variables=function(){return[]},q.prototype.variables=function(){return[].concat.apply([],o(this.args,function(I){return I.variables()}))},Le.prototype.variables=function(){return[]},Ve.prototype.variables=function(){return this.body===null?this.head.variables():this.head.variables().concat(this.body.variables())},Pe.prototype.apply=function(I){return I.lookup(this.id)?I.lookup(this.id):this},Re.prototype.apply=function(I){return this},q.prototype.apply=function(I){if(this.indicator===\"./2\"){for(var S=[],y=this;y.indicator===\"./2\";)S.push(y.args[0].apply(I)),y=y.args[1];for(var R=y.apply(I),J=S.length-1;J>=0;J--)R=new q(\".\",[S[J],R]);return R}return new q(this.id,o(this.args,function(X){return X.apply(I)}),this.ref)},Le.prototype.apply=function(I){return this},Ve.prototype.apply=function(I){return new Ve(this.head.apply(I),this.body!==null?this.body.apply(I):null)},Te.prototype.apply=function(I){var S,y={};for(S in this.links)this.links.hasOwnProperty(S)&&(y[S]=this.links[S].apply(I));return new Te(y)},q.prototype.select=function(){for(var I=this;I.indicator===\",/2\";)I=I.args[0];return I},q.prototype.replace=function(I){return this.indicator===\",/2\"?this.args[0].indicator===\",/2\"?new q(\",\",[this.args[0].replace(I),this.args[1]]):I===null?this.args[1]:new q(\",\",[I,this.args[1]]):I},q.prototype.search=function(I){if(x.type.is_term(I)&&I.ref!==void 0&&this.ref===I.ref)return!0;for(var S=0;S<this.args.length;S++)if(x.type.is_term(this.args[S])&&this.args[S].search(I))return!0;return!1},xe.prototype.get_current_input=function(){return this.current_input},tt.prototype.get_current_input=function(){return this.session.get_current_input()},xe.prototype.get_current_output=function(){return this.current_output},tt.prototype.get_current_output=function(){return this.session.get_current_output()},xe.prototype.set_current_input=function(I){this.current_input=I},tt.prototype.set_current_input=function(I){return this.session.set_current_input(I)},xe.prototype.set_current_output=function(I){this.current_input=I},tt.prototype.set_current_output=function(I){return this.session.set_current_output(I)},xe.prototype.get_stream_by_alias=function(I){return this.streams[I]},tt.prototype.get_stream_by_alias=function(I){return this.session.get_stream_by_alias(I)},xe.prototype.file_system_open=function(I,S,y){return this.file_system.open(I,S,y)},tt.prototype.file_system_open=function(I,S,y){return this.session.file_system_open(I,S,y)},xe.prototype.get_char_conversion=function(I){return this.__char_conversion[I]||I},tt.prototype.get_char_conversion=function(I){return this.session.get_char_conversion(I)},xe.prototype.parse=function(I){return this.thread.parse(I)},tt.prototype.parse=function(I){var S=new U(this);S.new_text(I);var y=S.get_tokens();if(y===null)return!1;var R=z(this,y,0,this.__get_max_priority(),!1);return R.len!==y.length?!1:{value:R.value,expr:R,tokens:y}},xe.prototype.get_flag=function(I){return this.flag[I]},tt.prototype.get_flag=function(I){return this.session.get_flag(I)},xe.prototype.add_rule=function(I,S){return S=S||{},S.from=S.from?S.from:\"$tau-js\",this.src_predicates[I.head.indicator]=S.from,this.rules[I.head.indicator]||(this.rules[I.head.indicator]=[]),this.rules[I.head.indicator].push(I),this.public_predicates.hasOwnProperty(I.head.indicator)||(this.public_predicates[I.head.indicator]=!1),!0},tt.prototype.add_rule=function(I,S){return this.session.add_rule(I,S)},xe.prototype.run_directive=function(I){this.thread.run_directive(I)},tt.prototype.run_directive=function(I){return x.type.is_directive(I)?(x.directive[I.indicator](this,I),!0):!1},xe.prototype.__get_max_priority=function(){return\"1200\"},tt.prototype.__get_max_priority=function(){return this.session.__get_max_priority()},xe.prototype.__get_next_priority=function(I){var S=0;I=parseInt(I);for(var y in this.__operators)if(this.__operators.hasOwnProperty(y)){var R=parseInt(y);R>S&&R<I&&(S=R)}return S.toString()},tt.prototype.__get_next_priority=function(I){return this.session.__get_next_priority(I)},xe.prototype.__lookup_operator_classes=function(I,S){return this.__operators.hasOwnProperty(I)&&this.__operators[I][S]instanceof Array&&this.__operators[I][S]||!1},tt.prototype.__lookup_operator_classes=function(I,S){return this.session.__lookup_operator_classes(I,S)},xe.prototype.lookup_operator=function(I,S){for(var y in this.__operators)if(this.__operators[y][I]){for(var R=0;R<this.__operators[y][I].length;R++)if(S===0||this.__operators[y][I][R].length===S+1)return{priority:y,class:this.__operators[y][I][R]}}return null},tt.prototype.lookup_operator=function(I,S){return this.session.lookup_operator(I,S)},xe.prototype.throw_warning=function(I){this.thread.throw_warning(I)},tt.prototype.throw_warning=function(I){this.warnings.push(I)},xe.prototype.get_warnings=function(){return this.thread.get_warnings()},tt.prototype.get_warnings=function(){return this.warnings},xe.prototype.add_goal=function(I,S){this.thread.add_goal(I,S)},tt.prototype.add_goal=function(I,S,y){y=y||null,S===!0&&(this.points=[]);for(var R=I.variables(),J={},X=0;X<R.length;X++)J[R[X]]=new Pe(R[X]);this.points.push(new ke(I,new Te(J),y))},xe.prototype.consult=function(I,S){return this.thread.consult(I,S)},tt.prototype.consult=function(I,S){var y=\"\";if(typeof I==\"string\"){y=I;var R=y.length;if(y.substring(R-3,R)===\".pl\"&&document.getElementById(y)){var J=document.getElementById(y),X=J.getAttribute(\"type\");X!==null&&X.replace(/ /g,\"\").toLowerCase()===\"text/prolog\"&&(y=J.text)}}else if(I.nodeName)switch(I.nodeName.toLowerCase()){case\"input\":case\"textarea\":y=I.value;break;default:y=I.innerHTML;break}else return!1;return this.warnings=[],ue(this,y,S)},xe.prototype.query=function(I){return this.thread.query(I)},tt.prototype.query=function(I){return this.points=[],this.debugger_points=[],Ie(this,I)},xe.prototype.head_point=function(){return this.thread.head_point()},tt.prototype.head_point=function(){return this.points[this.points.length-1]},xe.prototype.get_free_variable=function(I){return this.thread.get_free_variable(I)},tt.prototype.get_free_variable=function(I){var S=[];if(I.id===\"_\"||this.session.renamed_variables[I.id]===void 0){for(this.session.rename++,this.points.length>0&&(S=this.head_point().substitution.domain());e(S,x.format_variable(this.session.rename))!==-1;)this.session.rename++;if(I.id===\"_\")return new Pe(x.format_variable(this.session.rename));this.session.renamed_variables[I.id]=x.format_variable(this.session.rename)}return new Pe(this.session.renamed_variables[I.id])},xe.prototype.next_free_variable=function(){return this.thread.next_free_variable()},tt.prototype.next_free_variable=function(){this.session.rename++;var I=[];for(this.points.length>0&&(I=this.head_point().substitution.domain());e(I,x.format_variable(this.session.rename))!==-1;)this.session.rename++;return new Pe(x.format_variable(this.session.rename))},xe.prototype.is_public_predicate=function(I){return!this.public_predicates.hasOwnProperty(I)||this.public_predicates[I]===!0},tt.prototype.is_public_predicate=function(I){return this.session.is_public_predicate(I)},xe.prototype.is_multifile_predicate=function(I){return this.multifile_predicates.hasOwnProperty(I)&&this.multifile_predicates[I]===!0},tt.prototype.is_multifile_predicate=function(I){return this.session.is_multifile_predicate(I)},xe.prototype.prepend=function(I){return this.thread.prepend(I)},tt.prototype.prepend=function(I){for(var S=I.length-1;S>=0;S--)this.points.push(I[S])},xe.prototype.success=function(I,S){return this.thread.success(I,S)},tt.prototype.success=function(I,y){var y=typeof y>\"u\"?I:y;this.prepend([new ke(I.goal.replace(null),I.substitution,y)])},xe.prototype.throw_error=function(I){return this.thread.throw_error(I)},tt.prototype.throw_error=function(I){this.prepend([new ke(new q(\"throw\",[I]),new Te,null,null)])},xe.prototype.step_rule=function(I,S){return this.thread.step_rule(I,S)},tt.prototype.step_rule=function(I,S){var y=S.indicator;if(I===\"user\"&&(I=null),I===null&&this.session.rules.hasOwnProperty(y))return this.session.rules[y];for(var R=I===null?this.session.modules:e(this.session.modules,I)===-1?[]:[I],J=0;J<R.length;J++){var X=x.module[R[J]];if(X.rules.hasOwnProperty(y)&&(X.rules.hasOwnProperty(this.level)||X.exports_predicate(y)))return x.module[R[J]].rules[y]}return null},xe.prototype.step=function(){return this.thread.step()},tt.prototype.step=function(){if(this.points.length!==0){var I=!1,S=this.points.pop();if(this.debugger&&this.debugger_states.push(S),x.type.is_term(S.goal)){var y=S.goal.select(),R=null,J=[];if(y!==null){this.total_steps++;for(var X=S;X.parent!==null&&X.parent.goal.search(y);)X=X.parent;if(this.level=X.parent===null?\"top_level/0\":X.parent.goal.select().indicator,x.type.is_term(y)&&y.indicator===\":/2\"&&(R=y.args[0].id,y=y.args[1]),R===null&&x.type.is_builtin(y))this.__call_indicator=y.indicator,I=x.predicate[y.indicator](this,S,y);else{var $=this.step_rule(R,y);if($===null)this.session.rules.hasOwnProperty(y.indicator)||(this.get_flag(\"unknown\").id===\"error\"?this.throw_error(x.error.existence(\"procedure\",y.indicator,this.level)):this.get_flag(\"unknown\").id===\"warning\"&&this.throw_warning(\"unknown procedure \"+y.indicator+\" (from \"+this.level+\")\"));else if($ instanceof Function)I=$(this,S,y);else{for(var se in $)if($.hasOwnProperty(se)){var be=$[se];this.session.renamed_variables={},be=be.rename(this);var Fe=this.get_flag(\"occurs_check\").indicator===\"true/0\",lt=new ke,Et=x.unify(y,be.head,Fe);Et!==null&&(lt.goal=S.goal.replace(be.body),lt.goal!==null&&(lt.goal=lt.goal.apply(Et)),lt.substitution=S.substitution.apply(Et),lt.parent=S,J.push(lt))}this.prepend(J)}}}}else x.type.is_variable(S.goal)?this.throw_error(x.error.instantiation(this.level)):this.throw_error(x.error.type(\"callable\",S.goal,this.level));return I}},xe.prototype.answer=function(I){return this.thread.answer(I)},tt.prototype.answer=function(I){I=I||function(S){},this.__calls.push(I),!(this.__calls.length>1)&&this.again()},xe.prototype.answers=function(I,S,y){return this.thread.answers(I,S,y)},tt.prototype.answers=function(I,S,y){var R=S||1e3,J=this;if(S<=0){y&&y();return}this.answer(function(X){I(X),X!==!1?setTimeout(function(){J.answers(I,S-1,y)},1):y&&y()})},xe.prototype.again=function(I){return this.thread.again(I)},tt.prototype.again=function(I){for(var S,y=Date.now();this.__calls.length>0;){for(this.warnings=[],I!==!1&&(this.current_limit=this.session.limit);this.current_limit>0&&this.points.length>0&&this.head_point().goal!==null&&!x.type.is_error(this.head_point().goal);)if(this.current_limit--,this.step()===!0)return;var R=Date.now();this.cpu_time_last=R-y,this.cpu_time+=this.cpu_time_last;var J=this.__calls.shift();this.current_limit<=0?J(null):this.points.length===0?J(!1):x.type.is_error(this.head_point().goal)?(S=this.session.format_error(this.points.pop()),this.points=[],J(S)):(this.debugger&&this.debugger_states.push(this.head_point()),S=this.session.format_success(this.points.pop()),J(S))}},xe.prototype.unfold=function(I){if(I.body===null)return!1;var S=I.head,y=I.body,R=y.select(),J=new tt(this),X=[];J.add_goal(R),J.step();for(var $=J.points.length-1;$>=0;$--){var se=J.points[$],be=S.apply(se.substitution),Fe=y.replace(se.goal);Fe!==null&&(Fe=Fe.apply(se.substitution)),X.push(new Ve(be,Fe))}var lt=this.rules[S.indicator],Et=e(lt,I);return X.length>0&&Et!==-1?(lt.splice.apply(lt,[Et,1].concat(X)),!0):!1},tt.prototype.unfold=function(I){return this.session.unfold(I)},Pe.prototype.interpret=function(I){return x.error.instantiation(I.level)},Re.prototype.interpret=function(I){return this},q.prototype.interpret=function(I){return x.type.is_unitary_list(this)?this.args[0].interpret(I):x.operate(I,this)},Pe.prototype.compare=function(I){return this.id<I.id?-1:this.id>I.id?1:0},Re.prototype.compare=function(I){if(this.value===I.value&&this.is_float===I.is_float)return 0;if(this.value<I.value||this.value===I.value&&this.is_float&&!I.is_float)return-1;if(this.value>I.value)return 1},q.prototype.compare=function(I){if(this.args.length<I.args.length||this.args.length===I.args.length&&this.id<I.id)return-1;if(this.args.length>I.args.length||this.args.length===I.args.length&&this.id>I.id)return 1;for(var S=0;S<this.args.length;S++){var y=x.compare(this.args[S],I.args[S]);if(y!==0)return y}return 0},Te.prototype.lookup=function(I){return this.links[I]?this.links[I]:null},Te.prototype.filter=function(I){var S={};for(var y in this.links)if(this.links.hasOwnProperty(y)){var R=this.links[y];I(y,R)&&(S[y]=R)}return new Te(S)},Te.prototype.exclude=function(I){var S={};for(var y in this.links)this.links.hasOwnProperty(y)&&e(I,y)===-1&&(S[y]=this.links[y]);return new Te(S)},Te.prototype.add=function(I,S){this.links[I]=S},Te.prototype.domain=function(I){var S=I===!0?function(J){return J}:function(J){return new Pe(J)},y=[];for(var R in this.links)y.push(S(R));return y},Pe.prototype.compile=function(){return'new pl.type.Var(\"'+this.id.toString()+'\")'},Re.prototype.compile=function(){return\"new pl.type.Num(\"+this.value.toString()+\", \"+this.is_float.toString()+\")\"},q.prototype.compile=function(){return'new pl.type.Term(\"'+this.id.replace(/\"/g,'\\\\\"')+'\", ['+o(this.args,function(I){return I.compile()})+\"])\"},Ve.prototype.compile=function(){return\"new pl.type.Rule(\"+this.head.compile()+\", \"+(this.body===null?\"null\":this.body.compile())+\")\"},xe.prototype.compile=function(){var I,S=[],y;for(var R in this.rules)if(this.rules.hasOwnProperty(R)){var J=this.rules[R];y=[],I='\"'+R+'\": [';for(var X=0;X<J.length;X++)y.push(J[X].compile());I+=y.join(),I+=\"]\",S.push(I)}return\"{\"+S.join()+\"};\"},Pe.prototype.toJavaScript=function(){},Re.prototype.toJavaScript=function(){return this.value},q.prototype.toJavaScript=function(){if(this.args.length===0&&this.indicator!==\"[]/0\")return this.id;if(x.type.is_list(this)){for(var I=[],S=this,y;S.indicator===\"./2\";){if(y=S.args[0].toJavaScript(),y===void 0)return;I.push(y),S=S.args[1]}if(S.indicator===\"[]/0\")return I}},Ve.prototype.singleton_variables=function(){var I=this.head.variables(),S={},y=[];this.body!==null&&(I=I.concat(this.body.variables()));for(var R=0;R<I.length;R++)S[I[R]]===void 0&&(S[I[R]]=0),S[I[R]]++;for(var J in S)J!==\"_\"&&S[J]===1&&y.push(J);return y};var x={__env:typeof El<\"u\"&&El.exports?global:window,module:{},version:t,parser:{tokenizer:U,expression:z},utils:{str_indicator:Z,codePointAt:n,fromCodePoint:u},statistics:{getCountTerms:function(){return ht}},fromJavaScript:{test:{boolean:function(I){return I===!0||I===!1},number:function(I){return typeof I==\"number\"},string:function(I){return typeof I==\"string\"},list:function(I){return I instanceof Array},variable:function(I){return I===void 0},any:function(I){return!0}},conversion:{boolean:function(I){return new q(I?\"true\":\"false\",[])},number:function(I){return new Re(I,I%1!==0)},string:function(I){return new q(I,[])},list:function(I){for(var S=[],y,R=0;R<I.length;R++){if(y=x.fromJavaScript.apply(I[R]),y===void 0)return;S.push(y)}return g(S)},variable:function(I){return new Pe(\"_\")},any:function(I){}},apply:function(I){for(var S in x.fromJavaScript.test)if(S!==\"any\"&&x.fromJavaScript.test[S](I))return x.fromJavaScript.conversion[S](I);return x.fromJavaScript.conversion.any(I)}},type:{Var:Pe,Num:Re,Term:q,Rule:Ve,State:ke,Stream:Le,Module:He,Thread:tt,Session:xe,Substitution:Te,order:[Pe,Re,q,Le],compare:function(I,S){var y=e(x.type.order,I.constructor),R=e(x.type.order,S.constructor);if(y<R)return-1;if(y>R)return 1;if(I.constructor===Re){if(I.is_float&&S.is_float)return 0;if(I.is_float)return-1;if(S.is_float)return 1}return 0},is_substitution:function(I){return I instanceof Te},is_state:function(I){return I instanceof ke},is_rule:function(I){return I instanceof Ve},is_variable:function(I){return I instanceof Pe},is_stream:function(I){return I instanceof Le},is_anonymous_var:function(I){return I instanceof Pe&&I.id===\"_\"},is_callable:function(I){return I instanceof q},is_number:function(I){return I instanceof Re},is_integer:function(I){return I instanceof Re&&!I.is_float},is_float:function(I){return I instanceof Re&&I.is_float},is_term:function(I){return I instanceof q},is_atom:function(I){return I instanceof q&&I.args.length===0},is_ground:function(I){if(I instanceof Pe)return!1;if(I instanceof q){for(var S=0;S<I.args.length;S++)if(!x.type.is_ground(I.args[S]))return!1}return!0},is_atomic:function(I){return I instanceof q&&I.args.length===0||I instanceof Re},is_compound:function(I){return I instanceof q&&I.args.length>0},is_list:function(I){return I instanceof q&&(I.indicator===\"[]/0\"||I.indicator===\"./2\")},is_empty_list:function(I){return I instanceof q&&I.indicator===\"[]/0\"},is_non_empty_list:function(I){return I instanceof q&&I.indicator===\"./2\"},is_fully_list:function(I){for(;I instanceof q&&I.indicator===\"./2\";)I=I.args[1];return I instanceof Pe||I instanceof q&&I.indicator===\"[]/0\"},is_instantiated_list:function(I){for(;I instanceof q&&I.indicator===\"./2\";)I=I.args[1];return I instanceof q&&I.indicator===\"[]/0\"},is_unitary_list:function(I){return I instanceof q&&I.indicator===\"./2\"&&I.args[1]instanceof q&&I.args[1].indicator===\"[]/0\"},is_character:function(I){return I instanceof q&&(I.id.length===1||I.id.length>0&&I.id.length<=2&&n(I.id,0)>=65536)},is_character_code:function(I){return I instanceof Re&&!I.is_float&&I.value>=0&&I.value<=1114111},is_byte:function(I){return I instanceof Re&&!I.is_float&&I.value>=0&&I.value<=255},is_operator:function(I){return I instanceof q&&x.arithmetic.evaluation[I.indicator]},is_directive:function(I){return I instanceof q&&x.directive[I.indicator]!==void 0},is_builtin:function(I){return I instanceof q&&x.predicate[I.indicator]!==void 0},is_error:function(I){return I instanceof q&&I.indicator===\"throw/1\"},is_predicate_indicator:function(I){return I instanceof q&&I.indicator===\"//2\"&&I.args[0]instanceof q&&I.args[0].args.length===0&&I.args[1]instanceof Re&&I.args[1].is_float===!1},is_flag:function(I){return I instanceof q&&I.args.length===0&&x.flag[I.id]!==void 0},is_value_flag:function(I,S){if(!x.type.is_flag(I))return!1;for(var y in x.flag[I.id].allowed)if(x.flag[I.id].allowed.hasOwnProperty(y)&&x.flag[I.id].allowed[y].equals(S))return!0;return!1},is_io_mode:function(I){return x.type.is_atom(I)&&[\"read\",\"write\",\"append\"].indexOf(I.id)!==-1},is_stream_option:function(I){return x.type.is_term(I)&&(I.indicator===\"alias/1\"&&x.type.is_atom(I.args[0])||I.indicator===\"reposition/1\"&&x.type.is_atom(I.args[0])&&(I.args[0].id===\"true\"||I.args[0].id===\"false\")||I.indicator===\"type/1\"&&x.type.is_atom(I.args[0])&&(I.args[0].id===\"text\"||I.args[0].id===\"binary\")||I.indicator===\"eof_action/1\"&&x.type.is_atom(I.args[0])&&(I.args[0].id===\"error\"||I.args[0].id===\"eof_code\"||I.args[0].id===\"reset\"))},is_stream_position:function(I){return x.type.is_integer(I)&&I.value>=0||x.type.is_atom(I)&&(I.id===\"end_of_stream\"||I.id===\"past_end_of_stream\")},is_stream_property:function(I){return x.type.is_term(I)&&(I.indicator===\"input/0\"||I.indicator===\"output/0\"||I.indicator===\"alias/1\"&&(x.type.is_variable(I.args[0])||x.type.is_atom(I.args[0]))||I.indicator===\"file_name/1\"&&(x.type.is_variable(I.args[0])||x.type.is_atom(I.args[0]))||I.indicator===\"position/1\"&&(x.type.is_variable(I.args[0])||x.type.is_stream_position(I.args[0]))||I.indicator===\"reposition/1\"&&(x.type.is_variable(I.args[0])||x.type.is_atom(I.args[0])&&(I.args[0].id===\"true\"||I.args[0].id===\"false\"))||I.indicator===\"type/1\"&&(x.type.is_variable(I.args[0])||x.type.is_atom(I.args[0])&&(I.args[0].id===\"text\"||I.args[0].id===\"binary\"))||I.indicator===\"mode/1\"&&(x.type.is_variable(I.args[0])||x.type.is_atom(I.args[0])&&(I.args[0].id===\"read\"||I.args[0].id===\"write\"||I.args[0].id===\"append\"))||I.indicator===\"eof_action/1\"&&(x.type.is_variable(I.args[0])||x.type.is_atom(I.args[0])&&(I.args[0].id===\"error\"||I.args[0].id===\"eof_code\"||I.args[0].id===\"reset\"))||I.indicator===\"end_of_stream/1\"&&(x.type.is_variable(I.args[0])||x.type.is_atom(I.args[0])&&(I.args[0].id===\"at\"||I.args[0].id===\"past\"||I.args[0].id===\"not\")))},is_streamable:function(I){return I.__proto__.stream!==void 0},is_read_option:function(I){return x.type.is_term(I)&&[\"variables/1\",\"variable_names/1\",\"singletons/1\"].indexOf(I.indicator)!==-1},is_write_option:function(I){return x.type.is_term(I)&&(I.indicator===\"quoted/1\"&&x.type.is_atom(I.args[0])&&(I.args[0].id===\"true\"||I.args[0].id===\"false\")||I.indicator===\"ignore_ops/1\"&&x.type.is_atom(I.args[0])&&(I.args[0].id===\"true\"||I.args[0].id===\"false\")||I.indicator===\"numbervars/1\"&&x.type.is_atom(I.args[0])&&(I.args[0].id===\"true\"||I.args[0].id===\"false\"))},is_close_option:function(I){return x.type.is_term(I)&&I.indicator===\"force/1\"&&x.type.is_atom(I.args[0])&&(I.args[0].id===\"true\"||I.args[0].id===\"false\")},is_modifiable_flag:function(I){return x.type.is_flag(I)&&x.flag[I.id].changeable},is_module:function(I){return I instanceof q&&I.indicator===\"library/1\"&&I.args[0]instanceof q&&I.args[0].args.length===0&&x.module[I.args[0].id]!==void 0}},arithmetic:{evaluation:{\"e/0\":{type_args:null,type_result:!0,fn:function(I){return Math.E}},\"pi/0\":{type_args:null,type_result:!0,fn:function(I){return Math.PI}},\"tau/0\":{type_args:null,type_result:!0,fn:function(I){return 2*Math.PI}},\"epsilon/0\":{type_args:null,type_result:!0,fn:function(I){return Number.EPSILON}},\"+/1\":{type_args:null,type_result:null,fn:function(I,S){return I}},\"-/1\":{type_args:null,type_result:null,fn:function(I,S){return-I}},\"\\\\/1\":{type_args:!1,type_result:!1,fn:function(I,S){return~I}},\"abs/1\":{type_args:null,type_result:null,fn:function(I,S){return Math.abs(I)}},\"sign/1\":{type_args:null,type_result:null,fn:function(I,S){return Math.sign(I)}},\"float_integer_part/1\":{type_args:!0,type_result:!1,fn:function(I,S){return parseInt(I)}},\"float_fractional_part/1\":{type_args:!0,type_result:!0,fn:function(I,S){return I-parseInt(I)}},\"float/1\":{type_args:null,type_result:!0,fn:function(I,S){return parseFloat(I)}},\"floor/1\":{type_args:!0,type_result:!1,fn:function(I,S){return Math.floor(I)}},\"truncate/1\":{type_args:!0,type_result:!1,fn:function(I,S){return parseInt(I)}},\"round/1\":{type_args:!0,type_result:!1,fn:function(I,S){return Math.round(I)}},\"ceiling/1\":{type_args:!0,type_result:!1,fn:function(I,S){return Math.ceil(I)}},\"sin/1\":{type_args:null,type_result:!0,fn:function(I,S){return Math.sin(I)}},\"cos/1\":{type_args:null,type_result:!0,fn:function(I,S){return Math.cos(I)}},\"tan/1\":{type_args:null,type_result:!0,fn:function(I,S){return Math.tan(I)}},\"asin/1\":{type_args:null,type_result:!0,fn:function(I,S){return Math.asin(I)}},\"acos/1\":{type_args:null,type_result:!0,fn:function(I,S){return Math.acos(I)}},\"atan/1\":{type_args:null,type_result:!0,fn:function(I,S){return Math.atan(I)}},\"atan2/2\":{type_args:null,type_result:!0,fn:function(I,S,y){return Math.atan2(I,S)}},\"exp/1\":{type_args:null,type_result:!0,fn:function(I,S){return Math.exp(I)}},\"sqrt/1\":{type_args:null,type_result:!0,fn:function(I,S){return Math.sqrt(I)}},\"log/1\":{type_args:null,type_result:!0,fn:function(I,S){return I>0?Math.log(I):x.error.evaluation(\"undefined\",S.__call_indicator)}},\"+/2\":{type_args:null,type_result:null,fn:function(I,S,y){return I+S}},\"-/2\":{type_args:null,type_result:null,fn:function(I,S,y){return I-S}},\"*/2\":{type_args:null,type_result:null,fn:function(I,S,y){return I*S}},\"//2\":{type_args:null,type_result:!0,fn:function(I,S,y){return S?I/S:x.error.evaluation(\"zero_division\",y.__call_indicator)}},\"///2\":{type_args:!1,type_result:!1,fn:function(I,S,y){return S?parseInt(I/S):x.error.evaluation(\"zero_division\",y.__call_indicator)}},\"**/2\":{type_args:null,type_result:!0,fn:function(I,S,y){return Math.pow(I,S)}},\"^/2\":{type_args:null,type_result:null,fn:function(I,S,y){return Math.pow(I,S)}},\"<</2\":{type_args:!1,type_result:!1,fn:function(I,S,y){return I<<S}},\">>/2\":{type_args:!1,type_result:!1,fn:function(I,S,y){return I>>S}},\"/\\\\/2\":{type_args:!1,type_result:!1,fn:function(I,S,y){return I&S}},\"\\\\//2\":{type_args:!1,type_result:!1,fn:function(I,S,y){return I|S}},\"xor/2\":{type_args:!1,type_result:!1,fn:function(I,S,y){return I^S}},\"rem/2\":{type_args:!1,type_result:!1,fn:function(I,S,y){return S?I%S:x.error.evaluation(\"zero_division\",y.__call_indicator)}},\"mod/2\":{type_args:!1,type_result:!1,fn:function(I,S,y){return S?I-parseInt(I/S)*S:x.error.evaluation(\"zero_division\",y.__call_indicator)}},\"max/2\":{type_args:null,type_result:null,fn:function(I,S,y){return Math.max(I,S)}},\"min/2\":{type_args:null,type_result:null,fn:function(I,S,y){return Math.min(I,S)}}}},directive:{\"dynamic/1\":function(I,S){var y=S.args[0];if(x.type.is_variable(y))I.throw_error(x.error.instantiation(S.indicator));else if(!x.type.is_compound(y)||y.indicator!==\"//2\")I.throw_error(x.error.type(\"predicate_indicator\",y,S.indicator));else if(x.type.is_variable(y.args[0])||x.type.is_variable(y.args[1]))I.throw_error(x.error.instantiation(S.indicator));else if(!x.type.is_atom(y.args[0]))I.throw_error(x.error.type(\"atom\",y.args[0],S.indicator));else if(!x.type.is_integer(y.args[1]))I.throw_error(x.error.type(\"integer\",y.args[1],S.indicator));else{var R=S.args[0].args[0].id+\"/\"+S.args[0].args[1].value;I.session.public_predicates[R]=!0,I.session.rules[R]||(I.session.rules[R]=[])}},\"multifile/1\":function(I,S){var y=S.args[0];x.type.is_variable(y)?I.throw_error(x.error.instantiation(S.indicator)):!x.type.is_compound(y)||y.indicator!==\"//2\"?I.throw_error(x.error.type(\"predicate_indicator\",y,S.indicator)):x.type.is_variable(y.args[0])||x.type.is_variable(y.args[1])?I.throw_error(x.error.instantiation(S.indicator)):x.type.is_atom(y.args[0])?x.type.is_integer(y.args[1])?I.session.multifile_predicates[S.args[0].args[0].id+\"/\"+S.args[0].args[1].value]=!0:I.throw_error(x.error.type(\"integer\",y.args[1],S.indicator)):I.throw_error(x.error.type(\"atom\",y.args[0],S.indicator))},\"set_prolog_flag/2\":function(I,S){var y=S.args[0],R=S.args[1];x.type.is_variable(y)||x.type.is_variable(R)?I.throw_error(x.error.instantiation(S.indicator)):x.type.is_atom(y)?x.type.is_flag(y)?x.type.is_value_flag(y,R)?x.type.is_modifiable_flag(y)?I.session.flag[y.id]=R:I.throw_error(x.error.permission(\"modify\",\"flag\",y)):I.throw_error(x.error.domain(\"flag_value\",new q(\"+\",[y,R]),S.indicator)):I.throw_error(x.error.domain(\"prolog_flag\",y,S.indicator)):I.throw_error(x.error.type(\"atom\",y,S.indicator))},\"use_module/1\":function(I,S){var y=S.args[0];if(x.type.is_variable(y))I.throw_error(x.error.instantiation(S.indicator));else if(!x.type.is_term(y))I.throw_error(x.error.type(\"term\",y,S.indicator));else if(x.type.is_module(y)){var R=y.args[0].id;e(I.session.modules,R)===-1&&I.session.modules.push(R)}},\"char_conversion/2\":function(I,S){var y=S.args[0],R=S.args[1];x.type.is_variable(y)||x.type.is_variable(R)?I.throw_error(x.error.instantiation(S.indicator)):x.type.is_character(y)?x.type.is_character(R)?y.id===R.id?delete I.session.__char_conversion[y.id]:I.session.__char_conversion[y.id]=R.id:I.throw_error(x.error.type(\"character\",R,S.indicator)):I.throw_error(x.error.type(\"character\",y,S.indicator))},\"op/3\":function(I,S){var y=S.args[0],R=S.args[1],J=S.args[2];if(x.type.is_variable(y)||x.type.is_variable(R)||x.type.is_variable(J))I.throw_error(x.error.instantiation(S.indicator));else if(!x.type.is_integer(y))I.throw_error(x.error.type(\"integer\",y,S.indicator));else if(!x.type.is_atom(R))I.throw_error(x.error.type(\"atom\",R,S.indicator));else if(!x.type.is_atom(J))I.throw_error(x.error.type(\"atom\",J,S.indicator));else if(y.value<0||y.value>1200)I.throw_error(x.error.domain(\"operator_priority\",y,S.indicator));else if(J.id===\",\")I.throw_error(x.error.permission(\"modify\",\"operator\",J,S.indicator));else if(J.id===\"|\"&&(y.value<1001||R.id.length!==3))I.throw_error(x.error.permission(\"modify\",\"operator\",J,S.indicator));else if([\"fy\",\"fx\",\"yf\",\"xf\",\"xfx\",\"yfx\",\"xfy\"].indexOf(R.id)===-1)I.throw_error(x.error.domain(\"operator_specifier\",R,S.indicator));else{var X={prefix:null,infix:null,postfix:null};for(var $ in I.session.__operators)if(I.session.__operators.hasOwnProperty($)){var se=I.session.__operators[$][J.id];se&&(e(se,\"fx\")!==-1&&(X.prefix={priority:$,type:\"fx\"}),e(se,\"fy\")!==-1&&(X.prefix={priority:$,type:\"fy\"}),e(se,\"xf\")!==-1&&(X.postfix={priority:$,type:\"xf\"}),e(se,\"yf\")!==-1&&(X.postfix={priority:$,type:\"yf\"}),e(se,\"xfx\")!==-1&&(X.infix={priority:$,type:\"xfx\"}),e(se,\"xfy\")!==-1&&(X.infix={priority:$,type:\"xfy\"}),e(se,\"yfx\")!==-1&&(X.infix={priority:$,type:\"yfx\"}))}var be;switch(R.id){case\"fy\":case\"fx\":be=\"prefix\";break;case\"yf\":case\"xf\":be=\"postfix\";break;default:be=\"infix\";break}if(((X.prefix&&be===\"prefix\"||X.postfix&&be===\"postfix\"||X.infix&&be===\"infix\")&&X[be].type!==R.id||X.infix&&be===\"postfix\"||X.postfix&&be===\"infix\")&&y.value!==0)I.throw_error(x.error.permission(\"create\",\"operator\",J,S.indicator));else return X[be]&&(me(I.session.__operators[X[be].priority][J.id],R.id),I.session.__operators[X[be].priority][J.id].length===0&&delete I.session.__operators[X[be].priority][J.id]),y.value>0&&(I.session.__operators[y.value]||(I.session.__operators[y.value.toString()]={}),I.session.__operators[y.value][J.id]||(I.session.__operators[y.value][J.id]=[]),I.session.__operators[y.value][J.id].push(R.id)),!0}}},predicate:{\"op/3\":function(I,S,y){x.directive[\"op/3\"](I,y)&&I.success(S)},\"current_op/3\":function(I,S,y){var R=y.args[0],J=y.args[1],X=y.args[2],$=[];for(var se in I.session.__operators)for(var be in I.session.__operators[se])for(var Fe=0;Fe<I.session.__operators[se][be].length;Fe++)$.push(new ke(S.goal.replace(new q(\",\",[new q(\"=\",[new Re(se,!1),R]),new q(\",\",[new q(\"=\",[new q(I.session.__operators[se][be][Fe],[]),J]),new q(\"=\",[new q(be,[]),X])])])),S.substitution,S));I.prepend($)},\";/2\":function(I,S,y){if(x.type.is_term(y.args[0])&&y.args[0].indicator===\"->/2\"){var R=I.points,J=I.session.format_success,X=I.session.format_error;I.session.format_success=function(Fe){return Fe.substitution},I.session.format_error=function(Fe){return Fe.goal},I.points=[new ke(y.args[0].args[0],S.substitution,S)];var $=function(Fe){I.points=R,I.session.format_success=J,I.session.format_error=X,Fe===!1?I.prepend([new ke(S.goal.replace(y.args[1]),S.substitution,S)]):x.type.is_error(Fe)?I.throw_error(Fe.args[0]):Fe===null?(I.prepend([S]),I.__calls.shift()(null)):I.prepend([new ke(S.goal.replace(y.args[0].args[1]).apply(Fe),S.substitution.apply(Fe),S)])};I.__calls.unshift($)}else{var se=new ke(S.goal.replace(y.args[0]),S.substitution,S),be=new ke(S.goal.replace(y.args[1]),S.substitution,S);I.prepend([se,be])}},\"!/0\":function(I,S,y){var R,J,X=[];for(R=S,J=null;R.parent!==null&&R.parent.goal.search(y);)if(J=R,R=R.parent,R.goal!==null){var $=R.goal.select();if($&&$.id===\"call\"&&$.search(y)){R=J;break}}for(var se=I.points.length-1;se>=0;se--){for(var be=I.points[se],Fe=be.parent;Fe!==null&&Fe!==R.parent;)Fe=Fe.parent;Fe===null&&Fe!==R.parent&&X.push(be)}I.points=X.reverse(),I.success(S)},\"\\\\+/1\":function(I,S,y){var R=y.args[0];x.type.is_variable(R)?I.throw_error(x.error.instantiation(I.level)):x.type.is_callable(R)?I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\",\",[new q(\"call\",[R]),new q(\"!\",[])]),new q(\"fail\",[])])),S.substitution,S),new ke(S.goal.replace(null),S.substitution,S)]):I.throw_error(x.error.type(\"callable\",R,I.level))},\"->/2\":function(I,S,y){var R=S.goal.replace(new q(\",\",[y.args[0],new q(\",\",[new q(\"!\"),y.args[1]])]));I.prepend([new ke(R,S.substitution,S)])},\"fail/0\":function(I,S,y){},\"false/0\":function(I,S,y){},\"true/0\":function(I,S,y){I.success(S)},\"call/1\":ie(1),\"call/2\":ie(2),\"call/3\":ie(3),\"call/4\":ie(4),\"call/5\":ie(5),\"call/6\":ie(6),\"call/7\":ie(7),\"call/8\":ie(8),\"once/1\":function(I,S,y){var R=y.args[0];I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"call\",[R]),new q(\"!\",[])])),S.substitution,S)])},\"forall/2\":function(I,S,y){var R=y.args[0],J=y.args[1];I.prepend([new ke(S.goal.replace(new q(\"\\\\+\",[new q(\",\",[new q(\"call\",[R]),new q(\"\\\\+\",[new q(\"call\",[J])])])])),S.substitution,S)])},\"repeat/0\":function(I,S,y){I.prepend([new ke(S.goal.replace(null),S.substitution,S),S])},\"throw/1\":function(I,S,y){x.type.is_variable(y.args[0])?I.throw_error(x.error.instantiation(I.level)):I.throw_error(y.args[0])},\"catch/3\":function(I,S,y){var R=I.points;I.points=[],I.prepend([new ke(y.args[0],S.substitution,S)]);var J=I.session.format_success,X=I.session.format_error;I.session.format_success=function(se){return se.substitution},I.session.format_error=function(se){return se.goal};var $=function(se){var be=I.points;if(I.points=R,I.session.format_success=J,I.session.format_error=X,x.type.is_error(se)){for(var Fe=[],lt=I.points.length-1;lt>=0;lt--){for(var nr=I.points[lt],Et=nr.parent;Et!==null&&Et!==S.parent;)Et=Et.parent;Et===null&&Et!==S.parent&&Fe.push(nr)}I.points=Fe;var qt=I.get_flag(\"occurs_check\").indicator===\"true/0\",nr=new ke,St=x.unify(se.args[0],y.args[1],qt);St!==null?(nr.substitution=S.substitution.apply(St),nr.goal=S.goal.replace(y.args[2]).apply(St),nr.parent=S,I.prepend([nr])):I.throw_error(se.args[0])}else if(se!==!1){for(var cn=se===null?[]:[new ke(S.goal.apply(se).replace(null),S.substitution.apply(se),S)],Pr=[],lt=be.length-1;lt>=0;lt--){Pr.push(be[lt]);var yr=be[lt].goal!==null?be[lt].goal.select():null;if(x.type.is_term(yr)&&yr.indicator===\"!/0\")break}var Rr=o(Pr,function(Xr){return Xr.goal===null&&(Xr.goal=new q(\"true\",[])),Xr=new ke(S.goal.replace(new q(\"catch\",[Xr.goal,y.args[1],y.args[2]])),S.substitution.apply(Xr.substitution),Xr.parent),Xr.exclude=y.args[0].variables(),Xr}).reverse();I.prepend(Rr),I.prepend(cn),se===null&&(this.current_limit=0,I.__calls.shift()(null))}};I.__calls.unshift($)},\"=/2\":function(I,S,y){var R=I.get_flag(\"occurs_check\").indicator===\"true/0\",J=new ke,X=x.unify(y.args[0],y.args[1],R);X!==null&&(J.goal=S.goal.apply(X).replace(null),J.substitution=S.substitution.apply(X),J.parent=S,I.prepend([J]))},\"unify_with_occurs_check/2\":function(I,S,y){var R=new ke,J=x.unify(y.args[0],y.args[1],!0);J!==null&&(R.goal=S.goal.apply(J).replace(null),R.substitution=S.substitution.apply(J),R.parent=S,I.prepend([R]))},\"\\\\=/2\":function(I,S,y){var R=I.get_flag(\"occurs_check\").indicator===\"true/0\",J=x.unify(y.args[0],y.args[1],R);J===null&&I.success(S)},\"subsumes_term/2\":function(I,S,y){var R=I.get_flag(\"occurs_check\").indicator===\"true/0\",J=x.unify(y.args[1],y.args[0],R);J!==null&&y.args[1].apply(J).equals(y.args[1])&&I.success(S)},\"findall/3\":function(I,S,y){var R=y.args[0],J=y.args[1],X=y.args[2];if(x.type.is_variable(J))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_callable(J))I.throw_error(x.error.type(\"callable\",J,y.indicator));else if(!x.type.is_variable(X)&&!x.type.is_list(X))I.throw_error(x.error.type(\"list\",X,y.indicator));else{var $=I.next_free_variable(),se=new q(\",\",[J,new q(\"=\",[$,R])]),be=I.points,Fe=I.session.limit,lt=I.session.format_success;I.session.format_success=function(nr){return nr.substitution},I.add_goal(se,!0,S);var Et=[],qt=function(nr){if(nr!==!1&&nr!==null&&!x.type.is_error(nr))I.__calls.unshift(qt),Et.push(nr.links[$.id]),I.session.limit=I.current_limit;else if(I.points=be,I.session.limit=Fe,I.session.format_success=lt,x.type.is_error(nr))I.throw_error(nr.args[0]);else if(I.current_limit>0){for(var St=new q(\"[]\"),cn=Et.length-1;cn>=0;cn--)St=new q(\".\",[Et[cn],St]);I.prepend([new ke(S.goal.replace(new q(\"=\",[X,St])),S.substitution,S)])}};I.__calls.unshift(qt)}},\"bagof/3\":function(I,S,y){var R,J=y.args[0],X=y.args[1],$=y.args[2];if(x.type.is_variable(X))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_callable(X))I.throw_error(x.error.type(\"callable\",X,y.indicator));else if(!x.type.is_variable($)&&!x.type.is_list($))I.throw_error(x.error.type(\"list\",$,y.indicator));else{var se=I.next_free_variable(),be;X.indicator===\"^/2\"?(be=X.args[0].variables(),X=X.args[1]):be=[],be=be.concat(J.variables());for(var Fe=X.variables().filter(function(Rr){return e(be,Rr)===-1}),lt=new q(\"[]\"),Et=Fe.length-1;Et>=0;Et--)lt=new q(\".\",[new Pe(Fe[Et]),lt]);var qt=new q(\",\",[X,new q(\"=\",[se,new q(\",\",[lt,J])])]),nr=I.points,St=I.session.limit,cn=I.session.format_success;I.session.format_success=function(Rr){return Rr.substitution},I.add_goal(qt,!0,S);var Pr=[],yr=function(Rr){if(Rr!==!1&&Rr!==null&&!x.type.is_error(Rr)){I.__calls.unshift(yr);var Xr=!1,$n=Rr.links[se.id].args[0],Xs=Rr.links[se.id].args[1];for(var Hi in Pr)if(Pr.hasOwnProperty(Hi)){var Qs=Pr[Hi];if(Qs.variables.equals($n)){Qs.answers.push(Xs),Xr=!0;break}}Xr||Pr.push({variables:$n,answers:[Xs]}),I.session.limit=I.current_limit}else if(I.points=nr,I.session.limit=St,I.session.format_success=cn,x.type.is_error(Rr))I.throw_error(Rr.args[0]);else if(I.current_limit>0){for(var Zs=[],bi=0;bi<Pr.length;bi++){Rr=Pr[bi].answers;for(var Fs=new q(\"[]\"),$s=Rr.length-1;$s>=0;$s--)Fs=new q(\".\",[Rr[$s],Fs]);Zs.push(new ke(S.goal.replace(new q(\",\",[new q(\"=\",[lt,Pr[bi].variables]),new q(\"=\",[$,Fs])])),S.substitution,S))}I.prepend(Zs)}};I.__calls.unshift(yr)}},\"setof/3\":function(I,S,y){var R,J=y.args[0],X=y.args[1],$=y.args[2];if(x.type.is_variable(X))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_callable(X))I.throw_error(x.error.type(\"callable\",X,y.indicator));else if(!x.type.is_variable($)&&!x.type.is_list($))I.throw_error(x.error.type(\"list\",$,y.indicator));else{var se=I.next_free_variable(),be;X.indicator===\"^/2\"?(be=X.args[0].variables(),X=X.args[1]):be=[],be=be.concat(J.variables());for(var Fe=X.variables().filter(function(Rr){return e(be,Rr)===-1}),lt=new q(\"[]\"),Et=Fe.length-1;Et>=0;Et--)lt=new q(\".\",[new Pe(Fe[Et]),lt]);var qt=new q(\",\",[X,new q(\"=\",[se,new q(\",\",[lt,J])])]),nr=I.points,St=I.session.limit,cn=I.session.format_success;I.session.format_success=function(Rr){return Rr.substitution},I.add_goal(qt,!0,S);var Pr=[],yr=function(Rr){if(Rr!==!1&&Rr!==null&&!x.type.is_error(Rr)){I.__calls.unshift(yr);var Xr=!1,$n=Rr.links[se.id].args[0],Xs=Rr.links[se.id].args[1];for(var Hi in Pr)if(Pr.hasOwnProperty(Hi)){var Qs=Pr[Hi];if(Qs.variables.equals($n)){Qs.answers.push(Xs),Xr=!0;break}}Xr||Pr.push({variables:$n,answers:[Xs]}),I.session.limit=I.current_limit}else if(I.points=nr,I.session.limit=St,I.session.format_success=cn,x.type.is_error(Rr))I.throw_error(Rr.args[0]);else if(I.current_limit>0){for(var Zs=[],bi=0;bi<Pr.length;bi++){Rr=Pr[bi].answers.sort(x.compare);for(var Fs=new q(\"[]\"),$s=Rr.length-1;$s>=0;$s--)Fs=new q(\".\",[Rr[$s],Fs]);Zs.push(new ke(S.goal.replace(new q(\",\",[new q(\"=\",[lt,Pr[bi].variables]),new q(\"=\",[$,Fs])])),S.substitution,S))}I.prepend(Zs)}};I.__calls.unshift(yr)}},\"functor/3\":function(I,S,y){var R,J=y.args[0],X=y.args[1],$=y.args[2];if(x.type.is_variable(J)&&(x.type.is_variable(X)||x.type.is_variable($)))I.throw_error(x.error.instantiation(\"functor/3\"));else if(!x.type.is_variable($)&&!x.type.is_integer($))I.throw_error(x.error.type(\"integer\",y.args[2],\"functor/3\"));else if(!x.type.is_variable(X)&&!x.type.is_atomic(X))I.throw_error(x.error.type(\"atomic\",y.args[1],\"functor/3\"));else if(x.type.is_integer(X)&&x.type.is_integer($)&&$.value!==0)I.throw_error(x.error.type(\"atom\",y.args[1],\"functor/3\"));else if(x.type.is_variable(J)){if(y.args[2].value>=0){for(var se=[],be=0;be<$.value;be++)se.push(I.next_free_variable());var Fe=x.type.is_integer(X)?X:new q(X.id,se);I.prepend([new ke(S.goal.replace(new q(\"=\",[J,Fe])),S.substitution,S)])}}else{var lt=x.type.is_integer(J)?J:new q(J.id,[]),Et=x.type.is_integer(J)?new Re(0,!1):new Re(J.args.length,!1),qt=new q(\",\",[new q(\"=\",[lt,X]),new q(\"=\",[Et,$])]);I.prepend([new ke(S.goal.replace(qt),S.substitution,S)])}},\"arg/3\":function(I,S,y){if(x.type.is_variable(y.args[0])||x.type.is_variable(y.args[1]))I.throw_error(x.error.instantiation(y.indicator));else if(y.args[0].value<0)I.throw_error(x.error.domain(\"not_less_than_zero\",y.args[0],y.indicator));else if(!x.type.is_compound(y.args[1]))I.throw_error(x.error.type(\"compound\",y.args[1],y.indicator));else{var R=y.args[0].value;if(R>0&&R<=y.args[1].args.length){var J=new q(\"=\",[y.args[1].args[R-1],y.args[2]]);I.prepend([new ke(S.goal.replace(J),S.substitution,S)])}}},\"=../2\":function(I,S,y){var R;if(x.type.is_variable(y.args[0])&&(x.type.is_variable(y.args[1])||x.type.is_non_empty_list(y.args[1])&&x.type.is_variable(y.args[1].args[0])))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_fully_list(y.args[1]))I.throw_error(x.error.type(\"list\",y.args[1],y.indicator));else if(x.type.is_variable(y.args[0])){if(!x.type.is_variable(y.args[1])){var X=[];for(R=y.args[1].args[1];R.indicator===\"./2\";)X.push(R.args[0]),R=R.args[1];x.type.is_variable(y.args[0])&&x.type.is_variable(R)?I.throw_error(x.error.instantiation(y.indicator)):X.length===0&&x.type.is_compound(y.args[1].args[0])?I.throw_error(x.error.type(\"atomic\",y.args[1].args[0],y.indicator)):X.length>0&&(x.type.is_compound(y.args[1].args[0])||x.type.is_number(y.args[1].args[0]))?I.throw_error(x.error.type(\"atom\",y.args[1].args[0],y.indicator)):X.length===0?I.prepend([new ke(S.goal.replace(new q(\"=\",[y.args[1].args[0],y.args[0]],S)),S.substitution,S)]):I.prepend([new ke(S.goal.replace(new q(\"=\",[new q(y.args[1].args[0].id,X),y.args[0]])),S.substitution,S)])}}else{if(x.type.is_atomic(y.args[0]))R=new q(\".\",[y.args[0],new q(\"[]\")]);else{R=new q(\"[]\");for(var J=y.args[0].args.length-1;J>=0;J--)R=new q(\".\",[y.args[0].args[J],R]);R=new q(\".\",[new q(y.args[0].id),R])}I.prepend([new ke(S.goal.replace(new q(\"=\",[R,y.args[1]])),S.substitution,S)])}},\"copy_term/2\":function(I,S,y){var R=y.args[0].rename(I);I.prepend([new ke(S.goal.replace(new q(\"=\",[R,y.args[1]])),S.substitution,S.parent)])},\"term_variables/2\":function(I,S,y){var R=y.args[0],J=y.args[1];if(!x.type.is_fully_list(J))I.throw_error(x.error.type(\"list\",J,y.indicator));else{var X=g(o(Ce(R.variables()),function($){return new Pe($)}));I.prepend([new ke(S.goal.replace(new q(\"=\",[J,X])),S.substitution,S)])}},\"clause/2\":function(I,S,y){if(x.type.is_variable(y.args[0]))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_callable(y.args[0]))I.throw_error(x.error.type(\"callable\",y.args[0],y.indicator));else if(!x.type.is_variable(y.args[1])&&!x.type.is_callable(y.args[1]))I.throw_error(x.error.type(\"callable\",y.args[1],y.indicator));else if(I.session.rules[y.args[0].indicator]!==void 0)if(I.is_public_predicate(y.args[0].indicator)){var R=[];for(var J in I.session.rules[y.args[0].indicator])if(I.session.rules[y.args[0].indicator].hasOwnProperty(J)){var X=I.session.rules[y.args[0].indicator][J];I.session.renamed_variables={},X=X.rename(I),X.body===null&&(X.body=new q(\"true\"));var $=new q(\",\",[new q(\"=\",[X.head,y.args[0]]),new q(\"=\",[X.body,y.args[1]])]);R.push(new ke(S.goal.replace($),S.substitution,S))}I.prepend(R)}else I.throw_error(x.error.permission(\"access\",\"private_procedure\",y.args[0].indicator,y.indicator))},\"current_predicate/1\":function(I,S,y){var R=y.args[0];if(!x.type.is_variable(R)&&(!x.type.is_compound(R)||R.indicator!==\"//2\"))I.throw_error(x.error.type(\"predicate_indicator\",R,y.indicator));else if(!x.type.is_variable(R)&&!x.type.is_variable(R.args[0])&&!x.type.is_atom(R.args[0]))I.throw_error(x.error.type(\"atom\",R.args[0],y.indicator));else if(!x.type.is_variable(R)&&!x.type.is_variable(R.args[1])&&!x.type.is_integer(R.args[1]))I.throw_error(x.error.type(\"integer\",R.args[1],y.indicator));else{var J=[];for(var X in I.session.rules)if(I.session.rules.hasOwnProperty(X)){var $=X.lastIndexOf(\"/\"),se=X.substr(0,$),be=parseInt(X.substr($+1,X.length-($+1))),Fe=new q(\"/\",[new q(se),new Re(be,!1)]),lt=new q(\"=\",[Fe,R]);J.push(new ke(S.goal.replace(lt),S.substitution,S))}I.prepend(J)}},\"asserta/1\":function(I,S,y){if(x.type.is_variable(y.args[0]))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_callable(y.args[0]))I.throw_error(x.error.type(\"callable\",y.args[0],y.indicator));else{var R,J;y.args[0].indicator===\":-/2\"?(R=y.args[0].args[0],J=Ee(y.args[0].args[1])):(R=y.args[0],J=null),x.type.is_callable(R)?J!==null&&!x.type.is_callable(J)?I.throw_error(x.error.type(\"callable\",J,y.indicator)):I.is_public_predicate(R.indicator)?(I.session.rules[R.indicator]===void 0&&(I.session.rules[R.indicator]=[]),I.session.public_predicates[R.indicator]=!0,I.session.rules[R.indicator]=[new Ve(R,J,!0)].concat(I.session.rules[R.indicator]),I.success(S)):I.throw_error(x.error.permission(\"modify\",\"static_procedure\",R.indicator,y.indicator)):I.throw_error(x.error.type(\"callable\",R,y.indicator))}},\"assertz/1\":function(I,S,y){if(x.type.is_variable(y.args[0]))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_callable(y.args[0]))I.throw_error(x.error.type(\"callable\",y.args[0],y.indicator));else{var R,J;y.args[0].indicator===\":-/2\"?(R=y.args[0].args[0],J=Ee(y.args[0].args[1])):(R=y.args[0],J=null),x.type.is_callable(R)?J!==null&&!x.type.is_callable(J)?I.throw_error(x.error.type(\"callable\",J,y.indicator)):I.is_public_predicate(R.indicator)?(I.session.rules[R.indicator]===void 0&&(I.session.rules[R.indicator]=[]),I.session.public_predicates[R.indicator]=!0,I.session.rules[R.indicator].push(new Ve(R,J,!0)),I.success(S)):I.throw_error(x.error.permission(\"modify\",\"static_procedure\",R.indicator,y.indicator)):I.throw_error(x.error.type(\"callable\",R,y.indicator))}},\"retract/1\":function(I,S,y){if(x.type.is_variable(y.args[0]))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_callable(y.args[0]))I.throw_error(x.error.type(\"callable\",y.args[0],y.indicator));else{var R,J;if(y.args[0].indicator===\":-/2\"?(R=y.args[0].args[0],J=y.args[0].args[1]):(R=y.args[0],J=new q(\"true\")),typeof S.retract>\"u\")if(I.is_public_predicate(R.indicator)){if(I.session.rules[R.indicator]!==void 0){for(var X=[],$=0;$<I.session.rules[R.indicator].length;$++){I.session.renamed_variables={};var se=I.session.rules[R.indicator][$],be=se.rename(I);be.body===null&&(be.body=new q(\"true\",[]));var Fe=I.get_flag(\"occurs_check\").indicator===\"true/0\",lt=x.unify(new q(\",\",[R,J]),new q(\",\",[be.head,be.body]),Fe);if(lt!==null){var Et=new ke(S.goal.replace(new q(\",\",[new q(\"retract\",[new q(\":-\",[R,J])]),new q(\",\",[new q(\"=\",[R,be.head]),new q(\"=\",[J,be.body])])])),S.substitution,S);Et.retract=se,X.push(Et)}}I.prepend(X)}}else I.throw_error(x.error.permission(\"modify\",\"static_procedure\",R.indicator,y.indicator));else fe(I,S,R.indicator,S.retract)}},\"retractall/1\":function(I,S,y){var R=y.args[0];x.type.is_variable(R)?I.throw_error(x.error.instantiation(y.indicator)):x.type.is_callable(R)?I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"retract\",[new x.type.Term(\":-\",[R,new Pe(\"_\")])]),new q(\"fail\",[])])),S.substitution,S),new ke(S.goal.replace(null),S.substitution,S)]):I.throw_error(x.error.type(\"callable\",R,y.indicator))},\"abolish/1\":function(I,S,y){if(x.type.is_variable(y.args[0])||x.type.is_term(y.args[0])&&y.args[0].indicator===\"//2\"&&(x.type.is_variable(y.args[0].args[0])||x.type.is_variable(y.args[0].args[1])))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_term(y.args[0])||y.args[0].indicator!==\"//2\")I.throw_error(x.error.type(\"predicate_indicator\",y.args[0],y.indicator));else if(!x.type.is_atom(y.args[0].args[0]))I.throw_error(x.error.type(\"atom\",y.args[0].args[0],y.indicator));else if(!x.type.is_integer(y.args[0].args[1]))I.throw_error(x.error.type(\"integer\",y.args[0].args[1],y.indicator));else if(y.args[0].args[1].value<0)I.throw_error(x.error.domain(\"not_less_than_zero\",y.args[0].args[1],y.indicator));else if(x.type.is_number(I.get_flag(\"max_arity\"))&&y.args[0].args[1].value>I.get_flag(\"max_arity\").value)I.throw_error(x.error.representation(\"max_arity\",y.indicator));else{var R=y.args[0].args[0].id+\"/\"+y.args[0].args[1].value;I.is_public_predicate(R)?(delete I.session.rules[R],I.success(S)):I.throw_error(x.error.permission(\"modify\",\"static_procedure\",R,y.indicator))}},\"atom_length/2\":function(I,S,y){if(x.type.is_variable(y.args[0]))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_atom(y.args[0]))I.throw_error(x.error.type(\"atom\",y.args[0],y.indicator));else if(!x.type.is_variable(y.args[1])&&!x.type.is_integer(y.args[1]))I.throw_error(x.error.type(\"integer\",y.args[1],y.indicator));else if(x.type.is_integer(y.args[1])&&y.args[1].value<0)I.throw_error(x.error.domain(\"not_less_than_zero\",y.args[1],y.indicator));else{var R=new Re(y.args[0].id.length,!1);I.prepend([new ke(S.goal.replace(new q(\"=\",[R,y.args[1]])),S.substitution,S)])}},\"atom_concat/3\":function(I,S,y){var R,J,X=y.args[0],$=y.args[1],se=y.args[2];if(x.type.is_variable(se)&&(x.type.is_variable(X)||x.type.is_variable($)))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_variable(X)&&!x.type.is_atom(X))I.throw_error(x.error.type(\"atom\",X,y.indicator));else if(!x.type.is_variable($)&&!x.type.is_atom($))I.throw_error(x.error.type(\"atom\",$,y.indicator));else if(!x.type.is_variable(se)&&!x.type.is_atom(se))I.throw_error(x.error.type(\"atom\",se,y.indicator));else{var be=x.type.is_variable(X),Fe=x.type.is_variable($);if(!be&&!Fe)J=new q(\"=\",[se,new q(X.id+$.id)]),I.prepend([new ke(S.goal.replace(J),S.substitution,S)]);else if(be&&!Fe)R=se.id.substr(0,se.id.length-$.id.length),R+$.id===se.id&&(J=new q(\"=\",[X,new q(R)]),I.prepend([new ke(S.goal.replace(J),S.substitution,S)]));else if(Fe&&!be)R=se.id.substr(X.id.length),X.id+R===se.id&&(J=new q(\"=\",[$,new q(R)]),I.prepend([new ke(S.goal.replace(J),S.substitution,S)]));else{for(var lt=[],Et=0;Et<=se.id.length;Et++){var qt=new q(se.id.substr(0,Et)),nr=new q(se.id.substr(Et));J=new q(\",\",[new q(\"=\",[qt,X]),new q(\"=\",[nr,$])]),lt.push(new ke(S.goal.replace(J),S.substitution,S))}I.prepend(lt)}}},\"sub_atom/5\":function(I,S,y){var R,J=y.args[0],X=y.args[1],$=y.args[2],se=y.args[3],be=y.args[4];if(x.type.is_variable(J))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_variable(X)&&!x.type.is_integer(X))I.throw_error(x.error.type(\"integer\",X,y.indicator));else if(!x.type.is_variable($)&&!x.type.is_integer($))I.throw_error(x.error.type(\"integer\",$,y.indicator));else if(!x.type.is_variable(se)&&!x.type.is_integer(se))I.throw_error(x.error.type(\"integer\",se,y.indicator));else if(x.type.is_integer(X)&&X.value<0)I.throw_error(x.error.domain(\"not_less_than_zero\",X,y.indicator));else if(x.type.is_integer($)&&$.value<0)I.throw_error(x.error.domain(\"not_less_than_zero\",$,y.indicator));else if(x.type.is_integer(se)&&se.value<0)I.throw_error(x.error.domain(\"not_less_than_zero\",se,y.indicator));else{var Fe=[],lt=[],Et=[];if(x.type.is_variable(X))for(R=0;R<=J.id.length;R++)Fe.push(R);else Fe.push(X.value);if(x.type.is_variable($))for(R=0;R<=J.id.length;R++)lt.push(R);else lt.push($.value);if(x.type.is_variable(se))for(R=0;R<=J.id.length;R++)Et.push(R);else Et.push(se.value);var qt=[];for(var nr in Fe)if(Fe.hasOwnProperty(nr)){R=Fe[nr];for(var St in lt)if(lt.hasOwnProperty(St)){var cn=lt[St],Pr=J.id.length-R-cn;if(e(Et,Pr)!==-1&&R+cn+Pr===J.id.length){var yr=J.id.substr(R,cn);if(J.id===J.id.substr(0,R)+yr+J.id.substr(R+cn,Pr)){var Rr=new q(\"=\",[new q(yr),be]),Xr=new q(\"=\",[X,new Re(R)]),$n=new q(\"=\",[$,new Re(cn)]),Xs=new q(\"=\",[se,new Re(Pr)]),Hi=new q(\",\",[new q(\",\",[new q(\",\",[Xr,$n]),Xs]),Rr]);qt.push(new ke(S.goal.replace(Hi),S.substitution,S))}}}}I.prepend(qt)}},\"atom_chars/2\":function(I,S,y){var R=y.args[0],J=y.args[1];if(x.type.is_variable(R)&&x.type.is_variable(J))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_variable(R)&&!x.type.is_atom(R))I.throw_error(x.error.type(\"atom\",R,y.indicator));else if(x.type.is_variable(R)){for(var se=J,be=x.type.is_variable(R),Fe=\"\";se.indicator===\"./2\";){if(x.type.is_character(se.args[0]))Fe+=se.args[0].id;else if(x.type.is_variable(se.args[0])&&be){I.throw_error(x.error.instantiation(y.indicator));return}else if(!x.type.is_variable(se.args[0])){I.throw_error(x.error.type(\"character\",se.args[0],y.indicator));return}se=se.args[1]}x.type.is_variable(se)&&be?I.throw_error(x.error.instantiation(y.indicator)):!x.type.is_empty_list(se)&&!x.type.is_variable(se)?I.throw_error(x.error.type(\"list\",J,y.indicator)):I.prepend([new ke(S.goal.replace(new q(\"=\",[new q(Fe),R])),S.substitution,S)])}else{for(var X=new q(\"[]\"),$=R.id.length-1;$>=0;$--)X=new q(\".\",[new q(R.id.charAt($)),X]);I.prepend([new ke(S.goal.replace(new q(\"=\",[J,X])),S.substitution,S)])}},\"atom_codes/2\":function(I,S,y){var R=y.args[0],J=y.args[1];if(x.type.is_variable(R)&&x.type.is_variable(J))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_variable(R)&&!x.type.is_atom(R))I.throw_error(x.error.type(\"atom\",R,y.indicator));else if(x.type.is_variable(R)){for(var se=J,be=x.type.is_variable(R),Fe=\"\";se.indicator===\"./2\";){if(x.type.is_character_code(se.args[0]))Fe+=u(se.args[0].value);else if(x.type.is_variable(se.args[0])&&be){I.throw_error(x.error.instantiation(y.indicator));return}else if(!x.type.is_variable(se.args[0])){I.throw_error(x.error.representation(\"character_code\",y.indicator));return}se=se.args[1]}x.type.is_variable(se)&&be?I.throw_error(x.error.instantiation(y.indicator)):!x.type.is_empty_list(se)&&!x.type.is_variable(se)?I.throw_error(x.error.type(\"list\",J,y.indicator)):I.prepend([new ke(S.goal.replace(new q(\"=\",[new q(Fe),R])),S.substitution,S)])}else{for(var X=new q(\"[]\"),$=R.id.length-1;$>=0;$--)X=new q(\".\",[new Re(n(R.id,$),!1),X]);I.prepend([new ke(S.goal.replace(new q(\"=\",[J,X])),S.substitution,S)])}},\"char_code/2\":function(I,S,y){var R=y.args[0],J=y.args[1];if(x.type.is_variable(R)&&x.type.is_variable(J))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_variable(R)&&!x.type.is_character(R))I.throw_error(x.error.type(\"character\",R,y.indicator));else if(!x.type.is_variable(J)&&!x.type.is_integer(J))I.throw_error(x.error.type(\"integer\",J,y.indicator));else if(!x.type.is_variable(J)&&!x.type.is_character_code(J))I.throw_error(x.error.representation(\"character_code\",y.indicator));else if(x.type.is_variable(J)){var X=new Re(n(R.id,0),!1);I.prepend([new ke(S.goal.replace(new q(\"=\",[X,J])),S.substitution,S)])}else{var $=new q(u(J.value));I.prepend([new ke(S.goal.replace(new q(\"=\",[$,R])),S.substitution,S)])}},\"number_chars/2\":function(I,S,y){var R,J=y.args[0],X=y.args[1];if(x.type.is_variable(J)&&x.type.is_variable(X))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_variable(J)&&!x.type.is_number(J))I.throw_error(x.error.type(\"number\",J,y.indicator));else if(!x.type.is_variable(X)&&!x.type.is_list(X))I.throw_error(x.error.type(\"list\",X,y.indicator));else{var $=x.type.is_variable(J);if(!x.type.is_variable(X)){var se=X,be=!0;for(R=\"\";se.indicator===\"./2\";){if(x.type.is_character(se.args[0]))R+=se.args[0].id;else if(x.type.is_variable(se.args[0]))be=!1;else if(!x.type.is_variable(se.args[0])){I.throw_error(x.error.type(\"character\",se.args[0],y.indicator));return}se=se.args[1]}if(be=be&&x.type.is_empty_list(se),!x.type.is_empty_list(se)&&!x.type.is_variable(se)){I.throw_error(x.error.type(\"list\",X,y.indicator));return}if(!be&&$){I.throw_error(x.error.instantiation(y.indicator));return}else if(be)if(x.type.is_variable(se)&&$){I.throw_error(x.error.instantiation(y.indicator));return}else{var Fe=I.parse(R),lt=Fe.value;!x.type.is_number(lt)||Fe.tokens[Fe.tokens.length-1].space?I.throw_error(x.error.syntax_by_predicate(\"parseable_number\",y.indicator)):I.prepend([new ke(S.goal.replace(new q(\"=\",[J,lt])),S.substitution,S)]);return}}if(!$){R=J.toString();for(var Et=new q(\"[]\"),qt=R.length-1;qt>=0;qt--)Et=new q(\".\",[new q(R.charAt(qt)),Et]);I.prepend([new ke(S.goal.replace(new q(\"=\",[X,Et])),S.substitution,S)])}}},\"number_codes/2\":function(I,S,y){var R,J=y.args[0],X=y.args[1];if(x.type.is_variable(J)&&x.type.is_variable(X))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_variable(J)&&!x.type.is_number(J))I.throw_error(x.error.type(\"number\",J,y.indicator));else if(!x.type.is_variable(X)&&!x.type.is_list(X))I.throw_error(x.error.type(\"list\",X,y.indicator));else{var $=x.type.is_variable(J);if(!x.type.is_variable(X)){var se=X,be=!0;for(R=\"\";se.indicator===\"./2\";){if(x.type.is_character_code(se.args[0]))R+=u(se.args[0].value);else if(x.type.is_variable(se.args[0]))be=!1;else if(!x.type.is_variable(se.args[0])){I.throw_error(x.error.type(\"character_code\",se.args[0],y.indicator));return}se=se.args[1]}if(be=be&&x.type.is_empty_list(se),!x.type.is_empty_list(se)&&!x.type.is_variable(se)){I.throw_error(x.error.type(\"list\",X,y.indicator));return}if(!be&&$){I.throw_error(x.error.instantiation(y.indicator));return}else if(be)if(x.type.is_variable(se)&&$){I.throw_error(x.error.instantiation(y.indicator));return}else{var Fe=I.parse(R),lt=Fe.value;!x.type.is_number(lt)||Fe.tokens[Fe.tokens.length-1].space?I.throw_error(x.error.syntax_by_predicate(\"parseable_number\",y.indicator)):I.prepend([new ke(S.goal.replace(new q(\"=\",[J,lt])),S.substitution,S)]);return}}if(!$){R=J.toString();for(var Et=new q(\"[]\"),qt=R.length-1;qt>=0;qt--)Et=new q(\".\",[new Re(n(R,qt),!1),Et]);I.prepend([new ke(S.goal.replace(new q(\"=\",[X,Et])),S.substitution,S)])}}},\"upcase_atom/2\":function(I,S,y){var R=y.args[0],J=y.args[1];x.type.is_variable(R)?I.throw_error(x.error.instantiation(y.indicator)):x.type.is_atom(R)?!x.type.is_variable(J)&&!x.type.is_atom(J)?I.throw_error(x.error.type(\"atom\",J,y.indicator)):I.prepend([new ke(S.goal.replace(new q(\"=\",[J,new q(R.id.toUpperCase(),[])])),S.substitution,S)]):I.throw_error(x.error.type(\"atom\",R,y.indicator))},\"downcase_atom/2\":function(I,S,y){var R=y.args[0],J=y.args[1];x.type.is_variable(R)?I.throw_error(x.error.instantiation(y.indicator)):x.type.is_atom(R)?!x.type.is_variable(J)&&!x.type.is_atom(J)?I.throw_error(x.error.type(\"atom\",J,y.indicator)):I.prepend([new ke(S.goal.replace(new q(\"=\",[J,new q(R.id.toLowerCase(),[])])),S.substitution,S)]):I.throw_error(x.error.type(\"atom\",R,y.indicator))},\"atomic_list_concat/2\":function(I,S,y){var R=y.args[0],J=y.args[1];I.prepend([new ke(S.goal.replace(new q(\"atomic_list_concat\",[R,new q(\"\",[]),J])),S.substitution,S)])},\"atomic_list_concat/3\":function(I,S,y){var R=y.args[0],J=y.args[1],X=y.args[2];if(x.type.is_variable(J)||x.type.is_variable(R)&&x.type.is_variable(X))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_variable(R)&&!x.type.is_list(R))I.throw_error(x.error.type(\"list\",R,y.indicator));else if(!x.type.is_variable(X)&&!x.type.is_atom(X))I.throw_error(x.error.type(\"atom\",X,y.indicator));else if(x.type.is_variable(X)){for(var se=\"\",be=R;x.type.is_term(be)&&be.indicator===\"./2\";){if(!x.type.is_atom(be.args[0])&&!x.type.is_number(be.args[0])){I.throw_error(x.error.type(\"atomic\",be.args[0],y.indicator));return}se!==\"\"&&(se+=J.id),x.type.is_atom(be.args[0])?se+=be.args[0].id:se+=\"\"+be.args[0].value,be=be.args[1]}se=new q(se,[]),x.type.is_variable(be)?I.throw_error(x.error.instantiation(y.indicator)):!x.type.is_term(be)||be.indicator!==\"[]/0\"?I.throw_error(x.error.type(\"list\",R,y.indicator)):I.prepend([new ke(S.goal.replace(new q(\"=\",[se,X])),S.substitution,S)])}else{var $=g(o(X.id.split(J.id),function(Fe){return new q(Fe,[])}));I.prepend([new ke(S.goal.replace(new q(\"=\",[$,R])),S.substitution,S)])}},\"@=</2\":function(I,S,y){x.compare(y.args[0],y.args[1])<=0&&I.success(S)},\"==/2\":function(I,S,y){x.compare(y.args[0],y.args[1])===0&&I.success(S)},\"\\\\==/2\":function(I,S,y){x.compare(y.args[0],y.args[1])!==0&&I.success(S)},\"@</2\":function(I,S,y){x.compare(y.args[0],y.args[1])<0&&I.success(S)},\"@>/2\":function(I,S,y){x.compare(y.args[0],y.args[1])>0&&I.success(S)},\"@>=/2\":function(I,S,y){x.compare(y.args[0],y.args[1])>=0&&I.success(S)},\"compare/3\":function(I,S,y){var R=y.args[0],J=y.args[1],X=y.args[2];if(!x.type.is_variable(R)&&!x.type.is_atom(R))I.throw_error(x.error.type(\"atom\",R,y.indicator));else if(x.type.is_atom(R)&&[\"<\",\">\",\"=\"].indexOf(R.id)===-1)I.throw_error(x.type.domain(\"order\",R,y.indicator));else{var $=x.compare(J,X);$=$===0?\"=\":$===-1?\"<\":\">\",I.prepend([new ke(S.goal.replace(new q(\"=\",[R,new q($,[])])),S.substitution,S)])}},\"is/2\":function(I,S,y){var R=y.args[1].interpret(I);x.type.is_number(R)?I.prepend([new ke(S.goal.replace(new q(\"=\",[y.args[0],R],I.level)),S.substitution,S)]):I.throw_error(R)},\"between/3\":function(I,S,y){var R=y.args[0],J=y.args[1],X=y.args[2];if(x.type.is_variable(R)||x.type.is_variable(J))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_integer(R))I.throw_error(x.error.type(\"integer\",R,y.indicator));else if(!x.type.is_integer(J))I.throw_error(x.error.type(\"integer\",J,y.indicator));else if(!x.type.is_variable(X)&&!x.type.is_integer(X))I.throw_error(x.error.type(\"integer\",X,y.indicator));else if(x.type.is_variable(X)){var $=[new ke(S.goal.replace(new q(\"=\",[X,R])),S.substitution,S)];R.value<J.value&&$.push(new ke(S.goal.replace(new q(\"between\",[new Re(R.value+1,!1),J,X])),S.substitution,S)),I.prepend($)}else R.value<=X.value&&J.value>=X.value&&I.success(S)},\"succ/2\":function(I,S,y){var R=y.args[0],J=y.args[1];x.type.is_variable(R)&&x.type.is_variable(J)?I.throw_error(x.error.instantiation(y.indicator)):!x.type.is_variable(R)&&!x.type.is_integer(R)?I.throw_error(x.error.type(\"integer\",R,y.indicator)):!x.type.is_variable(J)&&!x.type.is_integer(J)?I.throw_error(x.error.type(\"integer\",J,y.indicator)):!x.type.is_variable(R)&&R.value<0?I.throw_error(x.error.domain(\"not_less_than_zero\",R,y.indicator)):!x.type.is_variable(J)&&J.value<0?I.throw_error(x.error.domain(\"not_less_than_zero\",J,y.indicator)):(x.type.is_variable(J)||J.value>0)&&(x.type.is_variable(R)?I.prepend([new ke(S.goal.replace(new q(\"=\",[R,new Re(J.value-1,!1)])),S.substitution,S)]):I.prepend([new ke(S.goal.replace(new q(\"=\",[J,new Re(R.value+1,!1)])),S.substitution,S)]))},\"=:=/2\":function(I,S,y){var R=x.arithmetic_compare(I,y.args[0],y.args[1]);x.type.is_term(R)?I.throw_error(R):R===0&&I.success(S)},\"=\\\\=/2\":function(I,S,y){var R=x.arithmetic_compare(I,y.args[0],y.args[1]);x.type.is_term(R)?I.throw_error(R):R!==0&&I.success(S)},\"</2\":function(I,S,y){var R=x.arithmetic_compare(I,y.args[0],y.args[1]);x.type.is_term(R)?I.throw_error(R):R<0&&I.success(S)},\"=</2\":function(I,S,y){var R=x.arithmetic_compare(I,y.args[0],y.args[1]);x.type.is_term(R)?I.throw_error(R):R<=0&&I.success(S)},\">/2\":function(I,S,y){var R=x.arithmetic_compare(I,y.args[0],y.args[1]);x.type.is_term(R)?I.throw_error(R):R>0&&I.success(S)},\">=/2\":function(I,S,y){var R=x.arithmetic_compare(I,y.args[0],y.args[1]);x.type.is_term(R)?I.throw_error(R):R>=0&&I.success(S)},\"var/1\":function(I,S,y){x.type.is_variable(y.args[0])&&I.success(S)},\"atom/1\":function(I,S,y){x.type.is_atom(y.args[0])&&I.success(S)},\"atomic/1\":function(I,S,y){x.type.is_atomic(y.args[0])&&I.success(S)},\"compound/1\":function(I,S,y){x.type.is_compound(y.args[0])&&I.success(S)},\"integer/1\":function(I,S,y){x.type.is_integer(y.args[0])&&I.success(S)},\"float/1\":function(I,S,y){x.type.is_float(y.args[0])&&I.success(S)},\"number/1\":function(I,S,y){x.type.is_number(y.args[0])&&I.success(S)},\"nonvar/1\":function(I,S,y){x.type.is_variable(y.args[0])||I.success(S)},\"ground/1\":function(I,S,y){y.variables().length===0&&I.success(S)},\"acyclic_term/1\":function(I,S,y){for(var R=S.substitution.apply(S.substitution),J=y.args[0].variables(),X=0;X<J.length;X++)if(S.substitution.links[J[X]]!==void 0&&!S.substitution.links[J[X]].equals(R.links[J[X]]))return;I.success(S)},\"callable/1\":function(I,S,y){x.type.is_callable(y.args[0])&&I.success(S)},\"is_list/1\":function(I,S,y){for(var R=y.args[0];x.type.is_term(R)&&R.indicator===\"./2\";)R=R.args[1];x.type.is_term(R)&&R.indicator===\"[]/0\"&&I.success(S)},\"current_input/1\":function(I,S,y){var R=y.args[0];!x.type.is_variable(R)&&!x.type.is_stream(R)&&!x.type.is_atom(R)?I.throw_error(x.error.domain(\"stream\",R,y.indicator)):(x.type.is_atom(R)&&I.get_stream_by_alias(R.id)&&(R=I.get_stream_by_alias(R.id)),I.prepend([new ke(S.goal.replace(new q(\"=\",[R,I.get_current_input()])),S.substitution,S)]))},\"current_output/1\":function(I,S,y){var R=y.args[0];!x.type.is_variable(R)&&!x.type.is_stream(R)&&!x.type.is_atom(R)?I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator)):(x.type.is_atom(R)&&I.get_stream_by_alias(R.id)&&(R=I.get_stream_by_alias(R.id)),I.prepend([new ke(S.goal.replace(new q(\"=\",[R,I.get_current_output()])),S.substitution,S)]))},\"set_input/1\":function(I,S,y){var R=y.args[0],J=x.type.is_stream(R)?R:I.get_stream_by_alias(R.id);x.type.is_variable(R)?I.throw_error(x.error.instantiation(y.indicator)):!x.type.is_variable(R)&&!x.type.is_stream(R)&&!x.type.is_atom(R)?I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator)):x.type.is_stream(J)?J.output===!0?I.throw_error(x.error.permission(\"input\",\"stream\",R,y.indicator)):(I.set_current_input(J),I.success(S)):I.throw_error(x.error.existence(\"stream\",R,y.indicator))},\"set_output/1\":function(I,S,y){var R=y.args[0],J=x.type.is_stream(R)?R:I.get_stream_by_alias(R.id);x.type.is_variable(R)?I.throw_error(x.error.instantiation(y.indicator)):!x.type.is_variable(R)&&!x.type.is_stream(R)&&!x.type.is_atom(R)?I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator)):x.type.is_stream(J)?J.input===!0?I.throw_error(x.error.permission(\"output\",\"stream\",R,y.indicator)):(I.set_current_output(J),I.success(S)):I.throw_error(x.error.existence(\"stream\",R,y.indicator))},\"open/3\":function(I,S,y){var R=y.args[0],J=y.args[1],X=y.args[2];I.prepend([new ke(S.goal.replace(new q(\"open\",[R,J,X,new q(\"[]\",[])])),S.substitution,S)])},\"open/4\":function(I,S,y){var R=y.args[0],J=y.args[1],X=y.args[2],$=y.args[3];if(x.type.is_variable(R)||x.type.is_variable(J))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_variable(J)&&!x.type.is_atom(J))I.throw_error(x.error.type(\"atom\",J,y.indicator));else if(!x.type.is_list($))I.throw_error(x.error.type(\"list\",$,y.indicator));else if(!x.type.is_variable(X))I.throw_error(x.error.type(\"variable\",X,y.indicator));else if(!x.type.is_atom(R)&&!x.type.is_streamable(R))I.throw_error(x.error.domain(\"source_sink\",R,y.indicator));else if(!x.type.is_io_mode(J))I.throw_error(x.error.domain(\"io_mode\",J,y.indicator));else{for(var se={},be=$,Fe;x.type.is_term(be)&&be.indicator===\"./2\";){if(Fe=be.args[0],x.type.is_variable(Fe)){I.throw_error(x.error.instantiation(y.indicator));return}else if(!x.type.is_stream_option(Fe)){I.throw_error(x.error.domain(\"stream_option\",Fe,y.indicator));return}se[Fe.id]=Fe.args[0].id,be=be.args[1]}if(be.indicator!==\"[]/0\"){x.type.is_variable(be)?I.throw_error(x.error.instantiation(y.indicator)):I.throw_error(x.error.type(\"list\",$,y.indicator));return}else{var lt=se.alias;if(lt&&I.get_stream_by_alias(lt)){I.throw_error(x.error.permission(\"open\",\"source_sink\",new q(\"alias\",[new q(lt,[])]),y.indicator));return}se.type||(se.type=\"text\");var Et;if(x.type.is_atom(R)?Et=I.file_system_open(R.id,se.type,J.id):Et=R.stream(se.type,J.id),Et===!1){I.throw_error(x.error.permission(\"open\",\"source_sink\",R,y.indicator));return}else if(Et===null){I.throw_error(x.error.existence(\"source_sink\",R,y.indicator));return}var qt=new Le(Et,J.id,se.alias,se.type,se.reposition===\"true\",se.eof_action);lt?I.session.streams[lt]=qt:I.session.streams[qt.id]=qt,I.prepend([new ke(S.goal.replace(new q(\"=\",[X,qt])),S.substitution,S)])}}},\"close/1\":function(I,S,y){var R=y.args[0];I.prepend([new ke(S.goal.replace(new q(\"close\",[R,new q(\"[]\",[])])),S.substitution,S)])},\"close/2\":function(I,S,y){var R=y.args[0],J=y.args[1],X=x.type.is_stream(R)?R:I.get_stream_by_alias(R.id);if(x.type.is_variable(R)||x.type.is_variable(J))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_list(J))I.throw_error(x.error.type(\"list\",J,y.indicator));else if(!x.type.is_stream(R)&&!x.type.is_atom(R))I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator));else if(!x.type.is_stream(X)||X.stream===null)I.throw_error(x.error.existence(\"stream\",R,y.indicator));else{for(var $={},se=J,be;x.type.is_term(se)&&se.indicator===\"./2\";){if(be=se.args[0],x.type.is_variable(be)){I.throw_error(x.error.instantiation(y.indicator));return}else if(!x.type.is_close_option(be)){I.throw_error(x.error.domain(\"close_option\",be,y.indicator));return}$[be.id]=be.args[0].id===\"true\",se=se.args[1]}if(se.indicator!==\"[]/0\"){x.type.is_variable(se)?I.throw_error(x.error.instantiation(y.indicator)):I.throw_error(x.error.type(\"list\",J,y.indicator));return}else{if(X===I.session.standard_input||X===I.session.standard_output){I.success(S);return}else X===I.session.current_input?I.session.current_input=I.session.standard_input:X===I.session.current_output&&(I.session.current_output=I.session.current_output);X.alias!==null?delete I.session.streams[X.alias]:delete I.session.streams[X.id],X.output&&X.stream.flush();var Fe=X.stream.close();X.stream=null,($.force===!0||Fe===!0)&&I.success(S)}}},\"flush_output/0\":function(I,S,y){I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_output\",[new Pe(\"S\")]),new q(\"flush_output\",[new Pe(\"S\")])])),S.substitution,S)])},\"flush_output/1\":function(I,S,y){var R=y.args[0],J=x.type.is_stream(R)?R:I.get_stream_by_alias(R.id);x.type.is_variable(R)?I.throw_error(x.error.instantiation(y.indicator)):!x.type.is_stream(R)&&!x.type.is_atom(R)?I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator)):!x.type.is_stream(J)||J.stream===null?I.throw_error(x.error.existence(\"stream\",R,y.indicator)):R.input===!0?I.throw_error(x.error.permission(\"output\",\"stream\",output,y.indicator)):(J.stream.flush(),I.success(S))},\"stream_property/2\":function(I,S,y){var R=y.args[0],J=y.args[1],X=x.type.is_stream(R)?R:I.get_stream_by_alias(R.id);if(!x.type.is_variable(R)&&!x.type.is_stream(R)&&!x.type.is_atom(R))I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator));else if(!x.type.is_variable(R)&&(!x.type.is_stream(X)||X.stream===null))I.throw_error(x.error.existence(\"stream\",R,y.indicator));else if(!x.type.is_variable(J)&&!x.type.is_stream_property(J))I.throw_error(x.error.domain(\"stream_property\",J,y.indicator));else{var $=[],se=[];if(!x.type.is_variable(R))$.push(X);else for(var be in I.session.streams)$.push(I.session.streams[be]);for(var Fe=0;Fe<$.length;Fe++){var lt=[];$[Fe].filename&&lt.push(new q(\"file_name\",[new q($[Fe].file_name,[])])),lt.push(new q(\"mode\",[new q($[Fe].mode,[])])),lt.push(new q($[Fe].input?\"input\":\"output\",[])),$[Fe].alias&&lt.push(new q(\"alias\",[new q($[Fe].alias,[])])),lt.push(new q(\"position\",[typeof $[Fe].position==\"number\"?new Re($[Fe].position,!1):new q($[Fe].position,[])])),lt.push(new q(\"end_of_stream\",[new q($[Fe].position===\"end_of_stream\"?\"at\":$[Fe].position===\"past_end_of_stream\"?\"past\":\"not\",[])])),lt.push(new q(\"eof_action\",[new q($[Fe].eof_action,[])])),lt.push(new q(\"reposition\",[new q($[Fe].reposition?\"true\":\"false\",[])])),lt.push(new q(\"type\",[new q($[Fe].type,[])]));for(var Et=0;Et<lt.length;Et++)se.push(new ke(S.goal.replace(new q(\",\",[new q(\"=\",[x.type.is_variable(R)?R:X,$[Fe]]),new q(\"=\",[J,lt[Et]])])),S.substitution,S))}I.prepend(se)}},\"at_end_of_stream/0\":function(I,S,y){I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_input\",[new Pe(\"S\")]),new q(\",\",[new q(\"stream_property\",[new Pe(\"S\"),new q(\"end_of_stream\",[new Pe(\"E\")])]),new q(\",\",[new q(\"!\",[]),new q(\";\",[new q(\"=\",[new Pe(\"E\"),new q(\"at\",[])]),new q(\"=\",[new Pe(\"E\"),new q(\"past\",[])])])])])])),S.substitution,S)])},\"at_end_of_stream/1\":function(I,S,y){var R=y.args[0];I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"stream_property\",[R,new q(\"end_of_stream\",[new Pe(\"E\")])]),new q(\",\",[new q(\"!\",[]),new q(\";\",[new q(\"=\",[new Pe(\"E\"),new q(\"at\",[])]),new q(\"=\",[new Pe(\"E\"),new q(\"past\",[])])])])])),S.substitution,S)])},\"set_stream_position/2\":function(I,S,y){var R=y.args[0],J=y.args[1],X=x.type.is_stream(R)?R:I.get_stream_by_alias(R.id);x.type.is_variable(R)||x.type.is_variable(J)?I.throw_error(x.error.instantiation(y.indicator)):!x.type.is_stream(R)&&!x.type.is_atom(R)?I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator)):!x.type.is_stream(X)||X.stream===null?I.throw_error(x.error.existence(\"stream\",R,y.indicator)):x.type.is_stream_position(J)?X.reposition===!1?I.throw_error(x.error.permission(\"reposition\",\"stream\",R,y.indicator)):(x.type.is_integer(J)?X.position=J.value:X.position=J.id,I.success(S)):I.throw_error(x.error.domain(\"stream_position\",J,y.indicator))},\"get_char/1\":function(I,S,y){var R=y.args[0];I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_input\",[new Pe(\"S\")]),new q(\"get_char\",[new Pe(\"S\"),R])])),S.substitution,S)])},\"get_char/2\":function(I,S,y){var R=y.args[0],J=y.args[1],X=x.type.is_stream(R)?R:I.get_stream_by_alias(R.id);if(x.type.is_variable(R))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_variable(J)&&!x.type.is_character(J))I.throw_error(x.error.type(\"in_character\",J,y.indicator));else if(!x.type.is_stream(R)&&!x.type.is_atom(R))I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator));else if(!x.type.is_stream(X)||X.stream===null)I.throw_error(x.error.existence(\"stream\",R,y.indicator));else if(X.output)I.throw_error(x.error.permission(\"input\",\"stream\",R,y.indicator));else if(X.type===\"binary\")I.throw_error(x.error.permission(\"input\",\"binary_stream\",R,y.indicator));else if(X.position===\"past_end_of_stream\"&&X.eof_action===\"error\")I.throw_error(x.error.permission(\"input\",\"past_end_of_stream\",R,y.indicator));else{var $;if(X.position===\"end_of_stream\")$=\"end_of_file\",X.position=\"past_end_of_stream\";else{if($=X.stream.get(1,X.position),$===null){I.throw_error(x.error.representation(\"character\",y.indicator));return}X.position++}I.prepend([new ke(S.goal.replace(new q(\"=\",[new q($,[]),J])),S.substitution,S)])}},\"get_code/1\":function(I,S,y){var R=y.args[0];I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_input\",[new Pe(\"S\")]),new q(\"get_code\",[new Pe(\"S\"),R])])),S.substitution,S)])},\"get_code/2\":function(I,S,y){var R=y.args[0],J=y.args[1],X=x.type.is_stream(R)?R:I.get_stream_by_alias(R.id);if(x.type.is_variable(R))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_variable(J)&&!x.type.is_integer(J))I.throw_error(x.error.type(\"integer\",char,y.indicator));else if(!x.type.is_variable(R)&&!x.type.is_stream(R)&&!x.type.is_atom(R))I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator));else if(!x.type.is_stream(X)||X.stream===null)I.throw_error(x.error.existence(\"stream\",R,y.indicator));else if(X.output)I.throw_error(x.error.permission(\"input\",\"stream\",R,y.indicator));else if(X.type===\"binary\")I.throw_error(x.error.permission(\"input\",\"binary_stream\",R,y.indicator));else if(X.position===\"past_end_of_stream\"&&X.eof_action===\"error\")I.throw_error(x.error.permission(\"input\",\"past_end_of_stream\",R,y.indicator));else{var $;if(X.position===\"end_of_stream\")$=-1,X.position=\"past_end_of_stream\";else{if($=X.stream.get(1,X.position),$===null){I.throw_error(x.error.representation(\"character\",y.indicator));return}$=n($,0),X.position++}I.prepend([new ke(S.goal.replace(new q(\"=\",[new Re($,!1),J])),S.substitution,S)])}},\"peek_char/1\":function(I,S,y){var R=y.args[0];I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_input\",[new Pe(\"S\")]),new q(\"peek_char\",[new Pe(\"S\"),R])])),S.substitution,S)])},\"peek_char/2\":function(I,S,y){var R=y.args[0],J=y.args[1],X=x.type.is_stream(R)?R:I.get_stream_by_alias(R.id);if(x.type.is_variable(R))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_variable(J)&&!x.type.is_character(J))I.throw_error(x.error.type(\"in_character\",J,y.indicator));else if(!x.type.is_stream(R)&&!x.type.is_atom(R))I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator));else if(!x.type.is_stream(X)||X.stream===null)I.throw_error(x.error.existence(\"stream\",R,y.indicator));else if(X.output)I.throw_error(x.error.permission(\"input\",\"stream\",R,y.indicator));else if(X.type===\"binary\")I.throw_error(x.error.permission(\"input\",\"binary_stream\",R,y.indicator));else if(X.position===\"past_end_of_stream\"&&X.eof_action===\"error\")I.throw_error(x.error.permission(\"input\",\"past_end_of_stream\",R,y.indicator));else{var $;if(X.position===\"end_of_stream\")$=\"end_of_file\",X.position=\"past_end_of_stream\";else if($=X.stream.get(1,X.position),$===null){I.throw_error(x.error.representation(\"character\",y.indicator));return}I.prepend([new ke(S.goal.replace(new q(\"=\",[new q($,[]),J])),S.substitution,S)])}},\"peek_code/1\":function(I,S,y){var R=y.args[0];I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_input\",[new Pe(\"S\")]),new q(\"peek_code\",[new Pe(\"S\"),R])])),S.substitution,S)])},\"peek_code/2\":function(I,S,y){var R=y.args[0],J=y.args[1],X=x.type.is_stream(R)?R:I.get_stream_by_alias(R.id);if(x.type.is_variable(R))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_variable(J)&&!x.type.is_integer(J))I.throw_error(x.error.type(\"integer\",char,y.indicator));else if(!x.type.is_variable(R)&&!x.type.is_stream(R)&&!x.type.is_atom(R))I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator));else if(!x.type.is_stream(X)||X.stream===null)I.throw_error(x.error.existence(\"stream\",R,y.indicator));else if(X.output)I.throw_error(x.error.permission(\"input\",\"stream\",R,y.indicator));else if(X.type===\"binary\")I.throw_error(x.error.permission(\"input\",\"binary_stream\",R,y.indicator));else if(X.position===\"past_end_of_stream\"&&X.eof_action===\"error\")I.throw_error(x.error.permission(\"input\",\"past_end_of_stream\",R,y.indicator));else{var $;if(X.position===\"end_of_stream\")$=-1,X.position=\"past_end_of_stream\";else{if($=X.stream.get(1,X.position),$===null){I.throw_error(x.error.representation(\"character\",y.indicator));return}$=n($,0)}I.prepend([new ke(S.goal.replace(new q(\"=\",[new Re($,!1),J])),S.substitution,S)])}},\"put_char/1\":function(I,S,y){var R=y.args[0];I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_output\",[new Pe(\"S\")]),new q(\"put_char\",[new Pe(\"S\"),R])])),S.substitution,S)])},\"put_char/2\":function(I,S,y){var R=y.args[0],J=y.args[1],X=x.type.is_stream(R)?R:I.get_stream_by_alias(R.id);x.type.is_variable(R)||x.type.is_variable(J)?I.throw_error(x.error.instantiation(y.indicator)):x.type.is_character(J)?!x.type.is_variable(R)&&!x.type.is_stream(R)&&!x.type.is_atom(R)?I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator)):!x.type.is_stream(X)||X.stream===null?I.throw_error(x.error.existence(\"stream\",R,y.indicator)):X.input?I.throw_error(x.error.permission(\"output\",\"stream\",R,y.indicator)):X.type===\"binary\"?I.throw_error(x.error.permission(\"output\",\"binary_stream\",R,y.indicator)):X.stream.put(J.id,X.position)&&(typeof X.position==\"number\"&&X.position++,I.success(S)):I.throw_error(x.error.type(\"character\",J,y.indicator))},\"put_code/1\":function(I,S,y){var R=y.args[0];I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_output\",[new Pe(\"S\")]),new q(\"put_code\",[new Pe(\"S\"),R])])),S.substitution,S)])},\"put_code/2\":function(I,S,y){var R=y.args[0],J=y.args[1],X=x.type.is_stream(R)?R:I.get_stream_by_alias(R.id);x.type.is_variable(R)||x.type.is_variable(J)?I.throw_error(x.error.instantiation(y.indicator)):x.type.is_integer(J)?x.type.is_character_code(J)?!x.type.is_variable(R)&&!x.type.is_stream(R)&&!x.type.is_atom(R)?I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator)):!x.type.is_stream(X)||X.stream===null?I.throw_error(x.error.existence(\"stream\",R,y.indicator)):X.input?I.throw_error(x.error.permission(\"output\",\"stream\",R,y.indicator)):X.type===\"binary\"?I.throw_error(x.error.permission(\"output\",\"binary_stream\",R,y.indicator)):X.stream.put_char(u(J.value),X.position)&&(typeof X.position==\"number\"&&X.position++,I.success(S)):I.throw_error(x.error.representation(\"character_code\",y.indicator)):I.throw_error(x.error.type(\"integer\",J,y.indicator))},\"nl/0\":function(I,S,y){I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_output\",[new Pe(\"S\")]),new q(\"put_char\",[new Pe(\"S\"),new q(`\n`,[])])])),S.substitution,S)])},\"nl/1\":function(I,S,y){var R=y.args[0];I.prepend([new ke(S.goal.replace(new q(\"put_char\",[R,new q(`\n`,[])])),S.substitution,S)])},\"get_byte/1\":function(I,S,y){var R=y.args[0];I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_input\",[new Pe(\"S\")]),new q(\"get_byte\",[new Pe(\"S\"),R])])),S.substitution,S)])},\"get_byte/2\":function(I,S,y){var R=y.args[0],J=y.args[1],X=x.type.is_stream(R)?R:I.get_stream_by_alias(R.id);if(x.type.is_variable(R))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_variable(J)&&!x.type.is_byte(J))I.throw_error(x.error.type(\"in_byte\",char,y.indicator));else if(!x.type.is_stream(R)&&!x.type.is_atom(R))I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator));else if(!x.type.is_stream(X)||X.stream===null)I.throw_error(x.error.existence(\"stream\",R,y.indicator));else if(X.output)I.throw_error(x.error.permission(\"input\",\"stream\",R,y.indicator));else if(X.type===\"text\")I.throw_error(x.error.permission(\"input\",\"text_stream\",R,y.indicator));else if(X.position===\"past_end_of_stream\"&&X.eof_action===\"error\")I.throw_error(x.error.permission(\"input\",\"past_end_of_stream\",R,y.indicator));else{var $;if(X.position===\"end_of_stream\")$=\"end_of_file\",X.position=\"past_end_of_stream\";else{if($=X.stream.get_byte(X.position),$===null){I.throw_error(x.error.representation(\"byte\",y.indicator));return}X.position++}I.prepend([new ke(S.goal.replace(new q(\"=\",[new Re($,!1),J])),S.substitution,S)])}},\"peek_byte/1\":function(I,S,y){var R=y.args[0];I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_input\",[new Pe(\"S\")]),new q(\"peek_byte\",[new Pe(\"S\"),R])])),S.substitution,S)])},\"peek_byte/2\":function(I,S,y){var R=y.args[0],J=y.args[1],X=x.type.is_stream(R)?R:I.get_stream_by_alias(R.id);if(x.type.is_variable(R))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_variable(J)&&!x.type.is_byte(J))I.throw_error(x.error.type(\"in_byte\",char,y.indicator));else if(!x.type.is_stream(R)&&!x.type.is_atom(R))I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator));else if(!x.type.is_stream(X)||X.stream===null)I.throw_error(x.error.existence(\"stream\",R,y.indicator));else if(X.output)I.throw_error(x.error.permission(\"input\",\"stream\",R,y.indicator));else if(X.type===\"text\")I.throw_error(x.error.permission(\"input\",\"text_stream\",R,y.indicator));else if(X.position===\"past_end_of_stream\"&&X.eof_action===\"error\")I.throw_error(x.error.permission(\"input\",\"past_end_of_stream\",R,y.indicator));else{var $;if(X.position===\"end_of_stream\")$=\"end_of_file\",X.position=\"past_end_of_stream\";else if($=X.stream.get_byte(X.position),$===null){I.throw_error(x.error.representation(\"byte\",y.indicator));return}I.prepend([new ke(S.goal.replace(new q(\"=\",[new Re($,!1),J])),S.substitution,S)])}},\"put_byte/1\":function(I,S,y){var R=y.args[0];I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_output\",[new Pe(\"S\")]),new q(\"put_byte\",[new Pe(\"S\"),R])])),S.substitution,S)])},\"put_byte/2\":function(I,S,y){var R=y.args[0],J=y.args[1],X=x.type.is_stream(R)?R:I.get_stream_by_alias(R.id);x.type.is_variable(R)||x.type.is_variable(J)?I.throw_error(x.error.instantiation(y.indicator)):x.type.is_byte(J)?!x.type.is_variable(R)&&!x.type.is_stream(R)&&!x.type.is_atom(R)?I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator)):!x.type.is_stream(X)||X.stream===null?I.throw_error(x.error.existence(\"stream\",R,y.indicator)):X.input?I.throw_error(x.error.permission(\"output\",\"stream\",R,y.indicator)):X.type===\"text\"?I.throw_error(x.error.permission(\"output\",\"text_stream\",R,y.indicator)):X.stream.put_byte(J.value,X.position)&&(typeof X.position==\"number\"&&X.position++,I.success(S)):I.throw_error(x.error.type(\"byte\",J,y.indicator))},\"read/1\":function(I,S,y){var R=y.args[0];I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_input\",[new Pe(\"S\")]),new q(\"read_term\",[new Pe(\"S\"),R,new q(\"[]\",[])])])),S.substitution,S)])},\"read/2\":function(I,S,y){var R=y.args[0],J=y.args[1];I.prepend([new ke(S.goal.replace(new q(\"read_term\",[R,J,new q(\"[]\",[])])),S.substitution,S)])},\"read_term/2\":function(I,S,y){var R=y.args[0],J=y.args[1];I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_input\",[new Pe(\"S\")]),new q(\"read_term\",[new Pe(\"S\"),R,J])])),S.substitution,S)])},\"read_term/3\":function(I,S,y){var R=y.args[0],J=y.args[1],X=y.args[2],$=x.type.is_stream(R)?R:I.get_stream_by_alias(R.id);if(x.type.is_variable(R)||x.type.is_variable(X))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_list(X))I.throw_error(x.error.type(\"list\",X,y.indicator));else if(!x.type.is_stream(R)&&!x.type.is_atom(R))I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator));else if(!x.type.is_stream($)||$.stream===null)I.throw_error(x.error.existence(\"stream\",R,y.indicator));else if($.output)I.throw_error(x.error.permission(\"input\",\"stream\",R,y.indicator));else if($.type===\"binary\")I.throw_error(x.error.permission(\"input\",\"binary_stream\",R,y.indicator));else if($.position===\"past_end_of_stream\"&&$.eof_action===\"error\")I.throw_error(x.error.permission(\"input\",\"past_end_of_stream\",R,y.indicator));else{for(var se={},be=X,Fe;x.type.is_term(be)&&be.indicator===\"./2\";){if(Fe=be.args[0],x.type.is_variable(Fe)){I.throw_error(x.error.instantiation(y.indicator));return}else if(!x.type.is_read_option(Fe)){I.throw_error(x.error.domain(\"read_option\",Fe,y.indicator));return}se[Fe.id]=Fe.args[0],be=be.args[1]}if(be.indicator!==\"[]/0\"){x.type.is_variable(be)?I.throw_error(x.error.instantiation(y.indicator)):I.throw_error(x.error.type(\"list\",X,y.indicator));return}else{for(var lt,Et,qt,nr=\"\",St=[],cn=null;cn===null||cn.name!==\"atom\"||cn.value!==\".\"||qt.type===A&&x.flatten_error(new q(\"throw\",[qt.value])).found===\"token_not_found\";){if(lt=$.stream.get(1,$.position),lt===null){I.throw_error(x.error.representation(\"character\",y.indicator));return}if(lt===\"end_of_file\"||lt===\"past_end_of_file\"){qt?I.throw_error(x.error.syntax(St[qt.len-1],\". or expression expected\",!1)):I.throw_error(x.error.syntax(null,\"token not found\",!0));return}$.position++,nr+=lt,Et=new U(I),Et.new_text(nr),St=Et.get_tokens(),cn=St!==null&&St.length>0?St[St.length-1]:null,St!==null&&(qt=z(I,St,0,I.__get_max_priority(),!1))}if(qt.type===p&&qt.len===St.length-1&&cn.value===\".\"){qt=qt.value.rename(I);var Pr=new q(\"=\",[J,qt]);if(se.variables){var yr=g(o(Ce(qt.variables()),function(Rr){return new Pe(Rr)}));Pr=new q(\",\",[Pr,new q(\"=\",[se.variables,yr])])}if(se.variable_names){var yr=g(o(Ce(qt.variables()),function(Xr){var $n;for($n in I.session.renamed_variables)if(I.session.renamed_variables.hasOwnProperty($n)&&I.session.renamed_variables[$n]===Xr)break;return new q(\"=\",[new q($n,[]),new Pe(Xr)])}));Pr=new q(\",\",[Pr,new q(\"=\",[se.variable_names,yr])])}if(se.singletons){var yr=g(o(new Ve(qt,null).singleton_variables(),function(Xr){var $n;for($n in I.session.renamed_variables)if(I.session.renamed_variables.hasOwnProperty($n)&&I.session.renamed_variables[$n]===Xr)break;return new q(\"=\",[new q($n,[]),new Pe(Xr)])}));Pr=new q(\",\",[Pr,new q(\"=\",[se.singletons,yr])])}I.prepend([new ke(S.goal.replace(Pr),S.substitution,S)])}else qt.type===p?I.throw_error(x.error.syntax(St[qt.len],\"unexpected token\",!1)):I.throw_error(qt.value)}}},\"write/1\":function(I,S,y){var R=y.args[0];I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_output\",[new Pe(\"S\")]),new q(\"write\",[new Pe(\"S\"),R])])),S.substitution,S)])},\"write/2\":function(I,S,y){var R=y.args[0],J=y.args[1];I.prepend([new ke(S.goal.replace(new q(\"write_term\",[R,J,new q(\".\",[new q(\"quoted\",[new q(\"false\",[])]),new q(\".\",[new q(\"ignore_ops\",[new q(\"false\")]),new q(\".\",[new q(\"numbervars\",[new q(\"true\")]),new q(\"[]\",[])])])])])),S.substitution,S)])},\"writeq/1\":function(I,S,y){var R=y.args[0];I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_output\",[new Pe(\"S\")]),new q(\"writeq\",[new Pe(\"S\"),R])])),S.substitution,S)])},\"writeq/2\":function(I,S,y){var R=y.args[0],J=y.args[1];I.prepend([new ke(S.goal.replace(new q(\"write_term\",[R,J,new q(\".\",[new q(\"quoted\",[new q(\"true\",[])]),new q(\".\",[new q(\"ignore_ops\",[new q(\"false\")]),new q(\".\",[new q(\"numbervars\",[new q(\"true\")]),new q(\"[]\",[])])])])])),S.substitution,S)])},\"write_canonical/1\":function(I,S,y){var R=y.args[0];I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_output\",[new Pe(\"S\")]),new q(\"write_canonical\",[new Pe(\"S\"),R])])),S.substitution,S)])},\"write_canonical/2\":function(I,S,y){var R=y.args[0],J=y.args[1];I.prepend([new ke(S.goal.replace(new q(\"write_term\",[R,J,new q(\".\",[new q(\"quoted\",[new q(\"true\",[])]),new q(\".\",[new q(\"ignore_ops\",[new q(\"true\")]),new q(\".\",[new q(\"numbervars\",[new q(\"false\")]),new q(\"[]\",[])])])])])),S.substitution,S)])},\"write_term/2\":function(I,S,y){var R=y.args[0],J=y.args[1];I.prepend([new ke(S.goal.replace(new q(\",\",[new q(\"current_output\",[new Pe(\"S\")]),new q(\"write_term\",[new Pe(\"S\"),R,J])])),S.substitution,S)])},\"write_term/3\":function(I,S,y){var R=y.args[0],J=y.args[1],X=y.args[2],$=x.type.is_stream(R)?R:I.get_stream_by_alias(R.id);if(x.type.is_variable(R)||x.type.is_variable(X))I.throw_error(x.error.instantiation(y.indicator));else if(!x.type.is_list(X))I.throw_error(x.error.type(\"list\",X,y.indicator));else if(!x.type.is_stream(R)&&!x.type.is_atom(R))I.throw_error(x.error.domain(\"stream_or_alias\",R,y.indicator));else if(!x.type.is_stream($)||$.stream===null)I.throw_error(x.error.existence(\"stream\",R,y.indicator));else if($.input)I.throw_error(x.error.permission(\"output\",\"stream\",R,y.indicator));else if($.type===\"binary\")I.throw_error(x.error.permission(\"output\",\"binary_stream\",R,y.indicator));else if($.position===\"past_end_of_stream\"&&$.eof_action===\"error\")I.throw_error(x.error.permission(\"output\",\"past_end_of_stream\",R,y.indicator));else{for(var se={},be=X,Fe;x.type.is_term(be)&&be.indicator===\"./2\";){if(Fe=be.args[0],x.type.is_variable(Fe)){I.throw_error(x.error.instantiation(y.indicator));return}else if(!x.type.is_write_option(Fe)){I.throw_error(x.error.domain(\"write_option\",Fe,y.indicator));return}se[Fe.id]=Fe.args[0].id===\"true\",be=be.args[1]}if(be.indicator!==\"[]/0\"){x.type.is_variable(be)?I.throw_error(x.error.instantiation(y.indicator)):I.throw_error(x.error.type(\"list\",X,y.indicator));return}else{se.session=I.session;var lt=J.toString(se);$.stream.put(lt,$.position),typeof $.position==\"number\"&&($.position+=lt.length),I.success(S)}}},\"halt/0\":function(I,S,y){I.points=[]},\"halt/1\":function(I,S,y){var R=y.args[0];x.type.is_variable(R)?I.throw_error(x.error.instantiation(y.indicator)):x.type.is_integer(R)?I.points=[]:I.throw_error(x.error.type(\"integer\",R,y.indicator))},\"current_prolog_flag/2\":function(I,S,y){var R=y.args[0],J=y.args[1];if(!x.type.is_variable(R)&&!x.type.is_atom(R))I.throw_error(x.error.type(\"atom\",R,y.indicator));else if(!x.type.is_variable(R)&&!x.type.is_flag(R))I.throw_error(x.error.domain(\"prolog_flag\",R,y.indicator));else{var X=[];for(var $ in x.flag)if(x.flag.hasOwnProperty($)){var se=new q(\",\",[new q(\"=\",[new q($),R]),new q(\"=\",[I.get_flag($),J])]);X.push(new ke(S.goal.replace(se),S.substitution,S))}I.prepend(X)}},\"set_prolog_flag/2\":function(I,S,y){var R=y.args[0],J=y.args[1];x.type.is_variable(R)||x.type.is_variable(J)?I.throw_error(x.error.instantiation(y.indicator)):x.type.is_atom(R)?x.type.is_flag(R)?x.type.is_value_flag(R,J)?x.type.is_modifiable_flag(R)?(I.session.flag[R.id]=J,I.success(S)):I.throw_error(x.error.permission(\"modify\",\"flag\",R)):I.throw_error(x.error.domain(\"flag_value\",new q(\"+\",[R,J]),y.indicator)):I.throw_error(x.error.domain(\"prolog_flag\",R,y.indicator)):I.throw_error(x.error.type(\"atom\",R,y.indicator))}},flag:{bounded:{allowed:[new q(\"true\"),new q(\"false\")],value:new q(\"true\"),changeable:!1},max_integer:{allowed:[new Re(Number.MAX_SAFE_INTEGER)],value:new Re(Number.MAX_SAFE_INTEGER),changeable:!1},min_integer:{allowed:[new Re(Number.MIN_SAFE_INTEGER)],value:new Re(Number.MIN_SAFE_INTEGER),changeable:!1},integer_rounding_function:{allowed:[new q(\"down\"),new q(\"toward_zero\")],value:new q(\"toward_zero\"),changeable:!1},char_conversion:{allowed:[new q(\"on\"),new q(\"off\")],value:new q(\"on\"),changeable:!0},debug:{allowed:[new q(\"on\"),new q(\"off\")],value:new q(\"off\"),changeable:!0},max_arity:{allowed:[new q(\"unbounded\")],value:new q(\"unbounded\"),changeable:!1},unknown:{allowed:[new q(\"error\"),new q(\"fail\"),new q(\"warning\")],value:new q(\"error\"),changeable:!0},double_quotes:{allowed:[new q(\"chars\"),new q(\"codes\"),new q(\"atom\")],value:new q(\"codes\"),changeable:!0},occurs_check:{allowed:[new q(\"false\"),new q(\"true\")],value:new q(\"false\"),changeable:!0},dialect:{allowed:[new q(\"tau\")],value:new q(\"tau\"),changeable:!1},version_data:{allowed:[new q(\"tau\",[new Re(t.major,!1),new Re(t.minor,!1),new Re(t.patch,!1),new q(t.status)])],value:new q(\"tau\",[new Re(t.major,!1),new Re(t.minor,!1),new Re(t.patch,!1),new q(t.status)]),changeable:!1},nodejs:{allowed:[new q(\"yes\"),new q(\"no\")],value:new q(typeof El<\"u\"&&El.exports?\"yes\":\"no\"),changeable:!1}},unify:function(I,S,y){y=y===void 0?!1:y;for(var R=[{left:I,right:S}],J={};R.length!==0;){var X=R.pop();if(I=X.left,S=X.right,x.type.is_term(I)&&x.type.is_term(S)){if(I.indicator!==S.indicator)return null;for(var $=0;$<I.args.length;$++)R.push({left:I.args[$],right:S.args[$]})}else if(x.type.is_number(I)&&x.type.is_number(S)){if(I.value!==S.value||I.is_float!==S.is_float)return null}else if(x.type.is_variable(I)){if(x.type.is_variable(S)&&I.id===S.id)continue;if(y===!0&&S.variables().indexOf(I.id)!==-1)return null;if(I.id!==\"_\"){var se=new Te;se.add(I.id,S);for(var $=0;$<R.length;$++)R[$].left=R[$].left.apply(se),R[$].right=R[$].right.apply(se);for(var $ in J)J[$]=J[$].apply(se);J[I.id]=S}}else if(x.type.is_variable(S))R.push({left:S,right:I});else if(I.unify!==void 0){if(!I.unify(S))return null}else return null}return new Te(J)},compare:function(I,S){var y=x.type.compare(I,S);return y!==0?y:I.compare(S)},arithmetic_compare:function(I,S,y){var R=S.interpret(I);if(x.type.is_number(R)){var J=y.interpret(I);return x.type.is_number(J)?R.value<J.value?-1:R.value>J.value?1:0:J}else return R},operate:function(I,S){if(x.type.is_operator(S)){for(var y=x.type.is_operator(S),R=[],J,X=!1,$=0;$<S.args.length;$++){if(J=S.args[$].interpret(I),x.type.is_number(J)){if(y.type_args!==null&&J.is_float!==y.type_args)return x.error.type(y.type_args?\"float\":\"integer\",J,I.__call_indicator);R.push(J.value)}else return J;X=X||J.is_float}return R.push(I),J=x.arithmetic.evaluation[S.indicator].fn.apply(this,R),X=y.type_result===null?X:y.type_result,x.type.is_term(J)?J:J===Number.POSITIVE_INFINITY||J===Number.NEGATIVE_INFINITY?x.error.evaluation(\"overflow\",I.__call_indicator):X===!1&&I.get_flag(\"bounded\").id===\"true\"&&(J>I.get_flag(\"max_integer\").value||J<I.get_flag(\"min_integer\").value)?x.error.evaluation(\"int_overflow\",I.__call_indicator):new Re(J,X)}else return x.error.type(\"evaluable\",S.indicator,I.__call_indicator)},error:{existence:function(I,S,y){return typeof S==\"string\"&&(S=Z(S)),new q(\"error\",[new q(\"existence_error\",[new q(I),S]),Z(y)])},type:function(I,S,y){return new q(\"error\",[new q(\"type_error\",[new q(I),S]),Z(y)])},instantiation:function(I){return new q(\"error\",[new q(\"instantiation_error\"),Z(I)])},domain:function(I,S,y){return new q(\"error\",[new q(\"domain_error\",[new q(I),S]),Z(y)])},representation:function(I,S){return new q(\"error\",[new q(\"representation_error\",[new q(I)]),Z(S)])},permission:function(I,S,y,R){return new q(\"error\",[new q(\"permission_error\",[new q(I),new q(S),y]),Z(R)])},evaluation:function(I,S){return new q(\"error\",[new q(\"evaluation_error\",[new q(I)]),Z(S)])},syntax:function(I,S,y){I=I||{value:\"\",line:0,column:0,matches:[\"\"],start:0};var R=y&&I.matches.length>0?I.start+I.matches[0].length:I.start,J=y?new q(\"token_not_found\"):new q(\"found\",[new q(I.value.toString())]),X=new q(\".\",[new q(\"line\",[new Re(I.line+1)]),new q(\".\",[new q(\"column\",[new Re(R+1)]),new q(\".\",[J,new q(\"[]\",[])])])]);return new q(\"error\",[new q(\"syntax_error\",[new q(S)]),X])},syntax_by_predicate:function(I,S){return new q(\"error\",[new q(\"syntax_error\",[new q(I)]),Z(S)])}},warning:{singleton:function(I,S,y){for(var R=new q(\"[]\"),J=I.length-1;J>=0;J--)R=new q(\".\",[new Pe(I[J]),R]);return new q(\"warning\",[new q(\"singleton_variables\",[R,Z(S)]),new q(\".\",[new q(\"line\",[new Re(y,!1)]),new q(\"[]\")])])},failed_goal:function(I,S){return new q(\"warning\",[new q(\"failed_goal\",[I]),new q(\".\",[new q(\"line\",[new Re(S,!1)]),new q(\"[]\")])])}},format_variable:function(I){return\"_\"+I},format_answer:function(I,S,R){S instanceof xe&&(S=S.thread);var R=R||{};if(R.session=S?S.session:void 0,x.type.is_error(I))return\"uncaught exception: \"+I.args[0].toString();if(I===!1)return\"false.\";if(I===null)return\"limit exceeded ;\";var J=0,X=\"\";if(x.type.is_substitution(I)){var $=I.domain(!0);I=I.filter(function(Fe,lt){return!x.type.is_variable(lt)||$.indexOf(lt.id)!==-1&&Fe!==lt.id})}for(var se in I.links)I.links.hasOwnProperty(se)&&(J++,X!==\"\"&&(X+=\", \"),X+=se.toString(R)+\" = \"+I.links[se].toString(R));var be=typeof S>\"u\"||S.points.length>0?\" ;\":\".\";return J===0?\"true\"+be:X+be},flatten_error:function(I){if(!x.type.is_error(I))return null;I=I.args[0];var S={};return S.type=I.args[0].id,S.thrown=S.type===\"syntax_error\"?null:I.args[1].id,S.expected=null,S.found=null,S.representation=null,S.existence=null,S.existence_type=null,S.line=null,S.column=null,S.permission_operation=null,S.permission_type=null,S.evaluation_type=null,S.type===\"type_error\"||S.type===\"domain_error\"?(S.expected=I.args[0].args[0].id,S.found=I.args[0].args[1].toString()):S.type===\"syntax_error\"?I.args[1].indicator===\"./2\"?(S.expected=I.args[0].args[0].id,S.found=I.args[1].args[1].args[1].args[0],S.found=S.found.id===\"token_not_found\"?S.found.id:S.found.args[0].id,S.line=I.args[1].args[0].args[0].value,S.column=I.args[1].args[1].args[0].args[0].value):S.thrown=I.args[1].id:S.type===\"permission_error\"?(S.found=I.args[0].args[2].toString(),S.permission_operation=I.args[0].args[0].id,S.permission_type=I.args[0].args[1].id):S.type===\"evaluation_error\"?S.evaluation_type=I.args[0].args[0].id:S.type===\"representation_error\"?S.representation=I.args[0].args[0].id:S.type===\"existence_error\"&&(S.existence=I.args[0].args[1].toString(),S.existence_type=I.args[0].args[0].id),S},create:function(I){return new x.type.Session(I)}};typeof El<\"u\"?El.exports=x:window.pl=x})()});function Kme(t,e,r){t.prepend(r.map(o=>new Oa.default.type.State(e.goal.replace(o),e.substitution,e)))}function n6(t){let e=zme.get(t.session);if(e==null)throw new Error(\"Assertion failed: A project should have been registered for the active session\");return e}function Jme(t,e){zme.set(t,e),t.consult(`:- use_module(library(${Wgt.id})).`)}var i6,Oa,Vme,Nh,jgt,Ggt,zme,Wgt,Xme=It(()=>{Ke();i6=et(L2()),Oa=et(r6()),Vme=et(ve(\"vm\")),{is_atom:Nh,is_variable:jgt,is_instantiated_list:Ggt}=Oa.default.type;zme=new WeakMap;Wgt=new Oa.default.type.Module(\"constraints\",{\"project_workspaces_by_descriptor/3\":(t,e,r)=>{let[o,a,n]=r.args;if(!Nh(o)||!Nh(a)){t.throw_error(Oa.default.error.instantiation(r.indicator));return}let u=G.parseIdent(o.id),A=G.makeDescriptor(u,a.id),h=n6(t).tryWorkspaceByDescriptor(A);jgt(n)&&h!==null&&Kme(t,e,[new Oa.default.type.Term(\"=\",[n,new Oa.default.type.Term(String(h.relativeCwd))])]),Nh(n)&&h!==null&&h.relativeCwd===n.id&&t.success(e)},\"workspace_field/3\":(t,e,r)=>{let[o,a,n]=r.args;if(!Nh(o)||!Nh(a)){t.throw_error(Oa.default.error.instantiation(r.indicator));return}let A=n6(t).tryWorkspaceByCwd(o.id);if(A==null)return;let p=(0,i6.default)(A.manifest.raw,a.id);typeof p>\"u\"||Kme(t,e,[new Oa.default.type.Term(\"=\",[n,new Oa.default.type.Term(typeof p==\"object\"?JSON.stringify(p):p)])])},\"workspace_field_test/3\":(t,e,r)=>{let[o,a,n]=r.args;t.prepend([new Oa.default.type.State(e.goal.replace(new Oa.default.type.Term(\"workspace_field_test\",[o,a,n,new Oa.default.type.Term(\"[]\",[])])),e.substitution,e)])},\"workspace_field_test/4\":(t,e,r)=>{let[o,a,n,u]=r.args;if(!Nh(o)||!Nh(a)||!Nh(n)||!Ggt(u)){t.throw_error(Oa.default.error.instantiation(r.indicator));return}let p=n6(t).tryWorkspaceByCwd(o.id);if(p==null)return;let h=(0,i6.default)(p.manifest.raw,a.id);if(typeof h>\"u\")return;let E={$$:h};for(let[D,b]of u.toJavaScript().entries())E[`$${D}`]=b;Vme.default.runInNewContext(n.id,E)&&t.success(e)}},[\"project_workspaces_by_descriptor/3\",\"workspace_field/3\",\"workspace_field_test/3\",\"workspace_field_test/4\"])});var Y2={};Kt(Y2,{Constraints:()=>o6,DependencyType:()=>tye});function Vs(t){if(t instanceof rC.default.type.Num)return t.value;if(t instanceof rC.default.type.Term)switch(t.indicator){case\"throw/1\":return Vs(t.args[0]);case\"error/1\":return Vs(t.args[0]);case\"error/2\":if(t.args[0]instanceof rC.default.type.Term&&t.args[0].indicator===\"syntax_error/1\")return Object.assign(Vs(t.args[0]),...Vs(t.args[1]));{let e=Vs(t.args[0]);return e.message+=` (in ${Vs(t.args[1])})`,e}case\"syntax_error/1\":return new zt(43,`Syntax error: ${Vs(t.args[0])}`);case\"existence_error/2\":return new zt(44,`Existence error: ${Vs(t.args[0])} ${Vs(t.args[1])} not found`);case\"instantiation_error/0\":return new zt(75,\"Instantiation error: an argument is variable when an instantiated argument was expected\");case\"line/1\":return{line:Vs(t.args[0])};case\"column/1\":return{column:Vs(t.args[0])};case\"found/1\":return{found:Vs(t.args[0])};case\"./2\":return[Vs(t.args[0])].concat(Vs(t.args[1]));case\"//2\":return`${Vs(t.args[0])}/${Vs(t.args[1])}`;default:return t.id}throw`couldn't pretty print because of unsupported node ${t}`}function $me(t){let e;try{e=Vs(t)}catch(r){throw typeof r==\"string\"?new zt(42,`Unknown error: ${t} (note: ${r})`):r}return typeof e.line<\"u\"&&typeof e.column<\"u\"&&(e.message+=` at line ${e.line}, column ${e.column}`),e}function Zg(t){return t.id===\"null\"?null:`${t.toJavaScript()}`}function Ygt(t){if(t.id===\"null\")return null;{let e=t.toJavaScript();if(typeof e!=\"string\")return JSON.stringify(e);try{return JSON.stringify(JSON.parse(e))}catch{return JSON.stringify(e)}}}function Oh(t){return typeof t==\"string\"?`'${t}'`:\"[]\"}var eye,rC,tye,Zme,s6,o6,K2=It(()=>{Ke();Ke();Pt();eye=et(Qme()),rC=et(r6());j2();Xme();(0,eye.default)(rC.default);tye=(o=>(o.Dependencies=\"dependencies\",o.DevDependencies=\"devDependencies\",o.PeerDependencies=\"peerDependencies\",o))(tye||{}),Zme=[\"dependencies\",\"devDependencies\",\"peerDependencies\"];s6=class{constructor(e,r){let o=1e3*e.workspaces.length;this.session=rC.default.create(o),Jme(this.session,e),this.session.consult(\":- use_module(library(lists)).\"),this.session.consult(r)}fetchNextAnswer(){return new Promise(e=>{this.session.answer(r=>{e(r)})})}async*makeQuery(e){let r=this.session.query(e);if(r!==!0)throw $me(r);for(;;){let o=await this.fetchNextAnswer();if(o===null)throw new zt(79,\"Resolution limit exceeded\");if(!o)break;if(o.id===\"throw\")throw $me(o);yield o}}};o6=class t{constructor(e){this.source=\"\";this.project=e;let r=e.configuration.get(\"constraintsPath\");ae.existsSync(r)&&(this.source=ae.readFileSync(r,\"utf8\"))}static async find(e){return new t(e)}getProjectDatabase(){let e=\"\";for(let r of Zme)e+=`dependency_type(${r}).\n`;for(let r of this.project.workspacesByCwd.values()){let o=r.relativeCwd;e+=`workspace(${Oh(o)}).\n`,e+=`workspace_ident(${Oh(o)}, ${Oh(G.stringifyIdent(r.anchoredLocator))}).\n`,e+=`workspace_version(${Oh(o)}, ${Oh(r.manifest.version)}).\n`;for(let a of Zme)for(let n of r.manifest[a].values())e+=`workspace_has_dependency(${Oh(o)}, ${Oh(G.stringifyIdent(n))}, ${Oh(n.range)}, ${a}).\n`}return e+=`workspace(_) :- false.\n`,e+=`workspace_ident(_, _) :- false.\n`,e+=`workspace_version(_, _) :- false.\n`,e+=`workspace_has_dependency(_, _, _, _) :- false.\n`,e}getDeclarations(){let e=\"\";return e+=`gen_enforced_dependency(_, _, _, _) :- false.\n`,e+=`gen_enforced_field(_, _, _) :- false.\n`,e}get fullSource(){return`${this.getProjectDatabase()}\n${this.source}\n${this.getDeclarations()}`}createSession(){return new s6(this.project,this.fullSource)}async processClassic(){let e=this.createSession();return{enforcedDependencies:await this.genEnforcedDependencies(e),enforcedFields:await this.genEnforcedFields(e)}}async process(){let{enforcedDependencies:e,enforcedFields:r}=await this.processClassic(),o=new Map;for(let{workspace:a,dependencyIdent:n,dependencyRange:u,dependencyType:A}of e){let p=q2([A,G.stringifyIdent(n)]),h=qe.getMapWithDefault(o,a.cwd);qe.getMapWithDefault(h,p).set(u??void 0,new Set)}for(let{workspace:a,fieldPath:n,fieldValue:u}of r){let A=q2(n),p=qe.getMapWithDefault(o,a.cwd);qe.getMapWithDefault(p,A).set(JSON.parse(u)??void 0,new Set)}return{manifestUpdates:o,reportedErrors:new Map}}async genEnforcedDependencies(e){let r=[];for await(let o of e.makeQuery(\"workspace(WorkspaceCwd), dependency_type(DependencyType), gen_enforced_dependency(WorkspaceCwd, DependencyIdent, DependencyRange, DependencyType).\")){let a=K.resolve(this.project.cwd,Zg(o.links.WorkspaceCwd)),n=Zg(o.links.DependencyIdent),u=Zg(o.links.DependencyRange),A=Zg(o.links.DependencyType);if(a===null||n===null)throw new Error(\"Invalid rule\");let p=this.project.getWorkspaceByCwd(a),h=G.parseIdent(n);r.push({workspace:p,dependencyIdent:h,dependencyRange:u,dependencyType:A})}return qe.sortMap(r,[({dependencyRange:o})=>o!==null?\"0\":\"1\",({workspace:o})=>G.stringifyIdent(o.anchoredLocator),({dependencyIdent:o})=>G.stringifyIdent(o)])}async genEnforcedFields(e){let r=[];for await(let o of e.makeQuery(\"workspace(WorkspaceCwd), gen_enforced_field(WorkspaceCwd, FieldPath, FieldValue).\")){let a=K.resolve(this.project.cwd,Zg(o.links.WorkspaceCwd)),n=Zg(o.links.FieldPath),u=Ygt(o.links.FieldValue);if(a===null||n===null)throw new Error(\"Invalid rule\");let A=this.project.getWorkspaceByCwd(a);r.push({workspace:A,fieldPath:n,fieldValue:u})}return qe.sortMap(r,[({workspace:o})=>G.stringifyIdent(o.anchoredLocator),({fieldPath:o})=>o])}async*query(e){let r=this.createSession();for await(let o of r.makeQuery(e)){let a={};for(let[n,u]of Object.entries(o.links))n!==\"_\"&&(a[n]=Zg(u));yield a}}}});var uye=_(tQ=>{\"use strict\";Object.defineProperty(tQ,\"__esModule\",{value:!0});function lB(t){let e=[...t.caches],r=e.shift();return r===void 0?cye():{get(o,a,n={miss:()=>Promise.resolve()}){return r.get(o,a,n).catch(()=>lB({caches:e}).get(o,a,n))},set(o,a){return r.set(o,a).catch(()=>lB({caches:e}).set(o,a))},delete(o){return r.delete(o).catch(()=>lB({caches:e}).delete(o))},clear(){return r.clear().catch(()=>lB({caches:e}).clear())}}}function cye(){return{get(t,e,r={miss:()=>Promise.resolve()}){return e().then(a=>Promise.all([a,r.miss(a)])).then(([a])=>a)},set(t,e){return Promise.resolve(e)},delete(t){return Promise.resolve()},clear(){return Promise.resolve()}}}tQ.createFallbackableCache=lB;tQ.createNullCache=cye});var fye=_((pYt,Aye)=>{Aye.exports=uye()});var pye=_(C6=>{\"use strict\";Object.defineProperty(C6,\"__esModule\",{value:!0});function Adt(t={serializable:!0}){let e={};return{get(r,o,a={miss:()=>Promise.resolve()}){let n=JSON.stringify(r);if(n in e)return Promise.resolve(t.serializable?JSON.parse(e[n]):e[n]);let u=o(),A=a&&a.miss||(()=>Promise.resolve());return u.then(p=>A(p)).then(()=>u)},set(r,o){return e[JSON.stringify(r)]=t.serializable?JSON.stringify(o):o,Promise.resolve(o)},delete(r){return delete e[JSON.stringify(r)],Promise.resolve()},clear(){return e={},Promise.resolve()}}}C6.createInMemoryCache=Adt});var gye=_((gYt,hye)=>{hye.exports=pye()});var mye=_(su=>{\"use strict\";Object.defineProperty(su,\"__esModule\",{value:!0});function fdt(t,e,r){let o={\"x-algolia-api-key\":r,\"x-algolia-application-id\":e};return{headers(){return t===I6.WithinHeaders?o:{}},queryParameters(){return t===I6.WithinQueryParameters?o:{}}}}function pdt(t){let e=0,r=()=>(e++,new Promise(o=>{setTimeout(()=>{o(t(r))},Math.min(100*e,1e3))}));return t(r)}function dye(t,e=(r,o)=>Promise.resolve()){return Object.assign(t,{wait(r){return dye(t.then(o=>Promise.all([e(o,r),o])).then(o=>o[1]))}})}function hdt(t){let e=t.length-1;for(e;e>0;e--){let r=Math.floor(Math.random()*(e+1)),o=t[e];t[e]=t[r],t[r]=o}return t}function gdt(t,e){return e&&Object.keys(e).forEach(r=>{t[r]=e[r](t)}),t}function ddt(t,...e){let r=0;return t.replace(/%s/g,()=>encodeURIComponent(e[r++]))}var mdt=\"4.22.1\",ydt=t=>()=>t.transporter.requester.destroy(),I6={WithinQueryParameters:0,WithinHeaders:1};su.AuthMode=I6;su.addMethods=gdt;su.createAuth=fdt;su.createRetryablePromise=pdt;su.createWaitablePromise=dye;su.destroy=ydt;su.encode=ddt;su.shuffle=hdt;su.version=mdt});var cB=_((mYt,yye)=>{yye.exports=mye()});var Eye=_(w6=>{\"use strict\";Object.defineProperty(w6,\"__esModule\",{value:!0});var Edt={Delete:\"DELETE\",Get:\"GET\",Post:\"POST\",Put:\"PUT\"};w6.MethodEnum=Edt});var uB=_((EYt,Cye)=>{Cye.exports=Eye()});var Lye=_(Ti=>{\"use strict\";Object.defineProperty(Ti,\"__esModule\",{value:!0});var wye=uB();function B6(t,e){let r=t||{},o=r.data||{};return Object.keys(r).forEach(a=>{[\"timeout\",\"headers\",\"queryParameters\",\"data\",\"cacheable\"].indexOf(a)===-1&&(o[a]=r[a])}),{data:Object.entries(o).length>0?o:void 0,timeout:r.timeout||e,headers:r.headers||{},queryParameters:r.queryParameters||{},cacheable:r.cacheable}}var AB={Read:1,Write:2,Any:3},fC={Up:1,Down:2,Timeouted:3},Bye=2*60*1e3;function D6(t,e=fC.Up){return{...t,status:e,lastUpdate:Date.now()}}function vye(t){return t.status===fC.Up||Date.now()-t.lastUpdate>Bye}function Dye(t){return t.status===fC.Timeouted&&Date.now()-t.lastUpdate<=Bye}function P6(t){return typeof t==\"string\"?{protocol:\"https\",url:t,accept:AB.Any}:{protocol:t.protocol||\"https\",url:t.url,accept:t.accept||AB.Any}}function Cdt(t,e){return Promise.all(e.map(r=>t.get(r,()=>Promise.resolve(D6(r))))).then(r=>{let o=r.filter(A=>vye(A)),a=r.filter(A=>Dye(A)),n=[...o,...a],u=n.length>0?n.map(A=>P6(A)):e;return{getTimeout(A,p){return(a.length===0&&A===0?1:a.length+3+A)*p},statelessHosts:u}})}var Idt=({isTimedOut:t,status:e})=>!t&&~~e===0,wdt=t=>{let e=t.status;return t.isTimedOut||Idt(t)||~~(e/100)!==2&&~~(e/100)!==4},Bdt=({status:t})=>~~(t/100)===2,vdt=(t,e)=>wdt(t)?e.onRetry(t):Bdt(t)?e.onSuccess(t):e.onFail(t);function Iye(t,e,r,o){let a=[],n=kye(r,o),u=Qye(t,o),A=r.method,p=r.method!==wye.MethodEnum.Get?{}:{...r.data,...o.data},h={\"x-algolia-agent\":t.userAgent.value,...t.queryParameters,...p,...o.queryParameters},E=0,w=(D,b)=>{let C=D.pop();if(C===void 0)throw Tye(v6(a));let T={data:n,headers:u,method:A,url:xye(C,r.path,h),connectTimeout:b(E,t.timeouts.connect),responseTimeout:b(E,o.timeout)},N=z=>{let te={request:T,response:z,host:C,triesLeft:D.length};return a.push(te),te},U={onSuccess:z=>Pye(z),onRetry(z){let te=N(z);return z.isTimedOut&&E++,Promise.all([t.logger.info(\"Retryable failure\",S6(te)),t.hostsCache.set(C,D6(C,z.isTimedOut?fC.Timeouted:fC.Down))]).then(()=>w(D,b))},onFail(z){throw N(z),Sye(z,v6(a))}};return t.requester.send(T).then(z=>vdt(z,U))};return Cdt(t.hostsCache,e).then(D=>w([...D.statelessHosts].reverse(),D.getTimeout))}function Ddt(t){let{hostsCache:e,logger:r,requester:o,requestsCache:a,responsesCache:n,timeouts:u,userAgent:A,hosts:p,queryParameters:h,headers:E}=t,w={hostsCache:e,logger:r,requester:o,requestsCache:a,responsesCache:n,timeouts:u,userAgent:A,headers:E,queryParameters:h,hosts:p.map(D=>P6(D)),read(D,b){let C=B6(b,w.timeouts.read),T=()=>Iye(w,w.hosts.filter(z=>(z.accept&AB.Read)!==0),D,C);if((C.cacheable!==void 0?C.cacheable:D.cacheable)!==!0)return T();let U={request:D,mappedRequestOptions:C,transporter:{queryParameters:w.queryParameters,headers:w.headers}};return w.responsesCache.get(U,()=>w.requestsCache.get(U,()=>w.requestsCache.set(U,T()).then(z=>Promise.all([w.requestsCache.delete(U),z]),z=>Promise.all([w.requestsCache.delete(U),Promise.reject(z)])).then(([z,te])=>te)),{miss:z=>w.responsesCache.set(U,z)})},write(D,b){return Iye(w,w.hosts.filter(C=>(C.accept&AB.Write)!==0),D,B6(b,w.timeouts.write))}};return w}function Pdt(t){let e={value:`Algolia for JavaScript (${t})`,add(r){let o=`; ${r.segment}${r.version!==void 0?` (${r.version})`:\"\"}`;return e.value.indexOf(o)===-1&&(e.value=`${e.value}${o}`),e}};return e}function Pye(t){try{return JSON.parse(t.content)}catch(e){throw Rye(e.message,t)}}function Sye({content:t,status:e},r){let o=t;try{o=JSON.parse(t).message}catch{}return Fye(o,e,r)}function Sdt(t,...e){let r=0;return t.replace(/%s/g,()=>encodeURIComponent(e[r++]))}function xye(t,e,r){let o=bye(r),a=`${t.protocol}://${t.url}/${e.charAt(0)===\"/\"?e.substr(1):e}`;return o.length&&(a+=`?${o}`),a}function bye(t){let e=r=>Object.prototype.toString.call(r)===\"[object Object]\"||Object.prototype.toString.call(r)===\"[object Array]\";return Object.keys(t).map(r=>Sdt(\"%s=%s\",r,e(t[r])?JSON.stringify(t[r]):t[r])).join(\"&\")}function kye(t,e){if(t.method===wye.MethodEnum.Get||t.data===void 0&&e.data===void 0)return;let r=Array.isArray(t.data)?t.data:{...t.data,...e.data};return JSON.stringify(r)}function Qye(t,e){let r={...t.headers,...e.headers},o={};return Object.keys(r).forEach(a=>{let n=r[a];o[a.toLowerCase()]=n}),o}function v6(t){return t.map(e=>S6(e))}function S6(t){let e=t.request.headers[\"x-algolia-api-key\"]?{\"x-algolia-api-key\":\"*****\"}:{};return{...t,request:{...t.request,headers:{...t.request.headers,...e}}}}function Fye(t,e,r){return{name:\"ApiError\",message:t,status:e,transporterStackTrace:r}}function Rye(t,e){return{name:\"DeserializationError\",message:t,response:e}}function Tye(t){return{name:\"RetryError\",message:\"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.\",transporterStackTrace:t}}Ti.CallEnum=AB;Ti.HostStatusEnum=fC;Ti.createApiError=Fye;Ti.createDeserializationError=Rye;Ti.createMappedRequestOptions=B6;Ti.createRetryError=Tye;Ti.createStatefulHost=D6;Ti.createStatelessHost=P6;Ti.createTransporter=Ddt;Ti.createUserAgent=Pdt;Ti.deserializeFailure=Sye;Ti.deserializeSuccess=Pye;Ti.isStatefulHostTimeouted=Dye;Ti.isStatefulHostUp=vye;Ti.serializeData=kye;Ti.serializeHeaders=Qye;Ti.serializeQueryParameters=bye;Ti.serializeUrl=xye;Ti.stackFrameWithoutCredentials=S6;Ti.stackTraceWithoutCredentials=v6});var fB=_((IYt,Nye)=>{Nye.exports=Lye()});var Oye=_(Mh=>{\"use strict\";Object.defineProperty(Mh,\"__esModule\",{value:!0});var pC=cB(),xdt=fB(),pB=uB(),bdt=t=>{let e=t.region||\"us\",r=pC.createAuth(pC.AuthMode.WithinHeaders,t.appId,t.apiKey),o=xdt.createTransporter({hosts:[{url:`analytics.${e}.algolia.com`}],...t,headers:{...r.headers(),\"content-type\":\"application/json\",...t.headers},queryParameters:{...r.queryParameters(),...t.queryParameters}}),a=t.appId;return pC.addMethods({appId:a,transporter:o},t.methods)},kdt=t=>(e,r)=>t.transporter.write({method:pB.MethodEnum.Post,path:\"2/abtests\",data:e},r),Qdt=t=>(e,r)=>t.transporter.write({method:pB.MethodEnum.Delete,path:pC.encode(\"2/abtests/%s\",e)},r),Fdt=t=>(e,r)=>t.transporter.read({method:pB.MethodEnum.Get,path:pC.encode(\"2/abtests/%s\",e)},r),Rdt=t=>e=>t.transporter.read({method:pB.MethodEnum.Get,path:\"2/abtests\"},e),Tdt=t=>(e,r)=>t.transporter.write({method:pB.MethodEnum.Post,path:pC.encode(\"2/abtests/%s/stop\",e)},r);Mh.addABTest=kdt;Mh.createAnalyticsClient=bdt;Mh.deleteABTest=Qdt;Mh.getABTest=Fdt;Mh.getABTests=Rdt;Mh.stopABTest=Tdt});var Uye=_((BYt,Mye)=>{Mye.exports=Oye()});var Hye=_(hB=>{\"use strict\";Object.defineProperty(hB,\"__esModule\",{value:!0});var x6=cB(),Ldt=fB(),_ye=uB(),Ndt=t=>{let e=t.region||\"us\",r=x6.createAuth(x6.AuthMode.WithinHeaders,t.appId,t.apiKey),o=Ldt.createTransporter({hosts:[{url:`personalization.${e}.algolia.com`}],...t,headers:{...r.headers(),\"content-type\":\"application/json\",...t.headers},queryParameters:{...r.queryParameters(),...t.queryParameters}});return x6.addMethods({appId:t.appId,transporter:o},t.methods)},Odt=t=>e=>t.transporter.read({method:_ye.MethodEnum.Get,path:\"1/strategies/personalization\"},e),Mdt=t=>(e,r)=>t.transporter.write({method:_ye.MethodEnum.Post,path:\"1/strategies/personalization\",data:e},r);hB.createPersonalizationClient=Ndt;hB.getPersonalizationStrategy=Odt;hB.setPersonalizationStrategy=Mdt});var jye=_((DYt,qye)=>{qye.exports=Hye()});var nEe=_(Rt=>{\"use strict\";Object.defineProperty(Rt,\"__esModule\",{value:!0});var Wt=cB(),Ma=fB(),Dr=uB(),Udt=ve(\"crypto\");function rQ(t){let e=r=>t.request(r).then(o=>{if(t.batch!==void 0&&t.batch(o.hits),!t.shouldStop(o))return o.cursor?e({cursor:o.cursor}):e({page:(r.page||0)+1})});return e({})}var _dt=t=>{let e=t.appId,r=Wt.createAuth(t.authMode!==void 0?t.authMode:Wt.AuthMode.WithinHeaders,e,t.apiKey),o=Ma.createTransporter({hosts:[{url:`${e}-dsn.algolia.net`,accept:Ma.CallEnum.Read},{url:`${e}.algolia.net`,accept:Ma.CallEnum.Write}].concat(Wt.shuffle([{url:`${e}-1.algolianet.com`},{url:`${e}-2.algolianet.com`},{url:`${e}-3.algolianet.com`}])),...t,headers:{...r.headers(),\"content-type\":\"application/x-www-form-urlencoded\",...t.headers},queryParameters:{...r.queryParameters(),...t.queryParameters}}),a={transporter:o,appId:e,addAlgoliaAgent(n,u){o.userAgent.add({segment:n,version:u})},clearCache(){return Promise.all([o.requestsCache.clear(),o.responsesCache.clear()]).then(()=>{})}};return Wt.addMethods(a,t.methods)};function Gye(){return{name:\"MissingObjectIDError\",message:\"All objects must have an unique objectID (like a primary key) to be valid. Algolia is also able to generate objectIDs automatically but *it's not recommended*. To do it, use the `{'autoGenerateObjectIDIfNotExist': true}` option.\"}}function Wye(){return{name:\"ObjectNotFoundError\",message:\"Object not found.\"}}function Yye(){return{name:\"ValidUntilNotFoundError\",message:\"ValidUntil not found in given secured api key.\"}}var Hdt=t=>(e,r)=>{let{queryParameters:o,...a}=r||{},n={acl:e,...o!==void 0?{queryParameters:o}:{}},u=(A,p)=>Wt.createRetryablePromise(h=>gB(t)(A.key,p).catch(E=>{if(E.status!==404)throw E;return h()}));return Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:\"1/keys\",data:n},a),u)},qdt=t=>(e,r,o)=>{let a=Ma.createMappedRequestOptions(o);return a.queryParameters[\"X-Algolia-User-ID\"]=e,t.transporter.write({method:Dr.MethodEnum.Post,path:\"1/clusters/mapping\",data:{cluster:r}},a)},jdt=t=>(e,r,o)=>t.transporter.write({method:Dr.MethodEnum.Post,path:\"1/clusters/mapping/batch\",data:{users:e,cluster:r}},o),Gdt=t=>(e,r)=>Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Wt.encode(\"/1/dictionaries/%s/batch\",e),data:{clearExistingDictionaryEntries:!0,requests:{action:\"addEntry\",body:[]}}},r),(o,a)=>hC(t)(o.taskID,a)),nQ=t=>(e,r,o)=>{let a=(n,u)=>dB(t)(e,{methods:{waitTask:es}}).waitTask(n.taskID,u);return Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Wt.encode(\"1/indexes/%s/operation\",e),data:{operation:\"copy\",destination:r}},o),a)},Wdt=t=>(e,r,o)=>nQ(t)(e,r,{...o,scope:[sQ.Rules]}),Ydt=t=>(e,r,o)=>nQ(t)(e,r,{...o,scope:[sQ.Settings]}),Kdt=t=>(e,r,o)=>nQ(t)(e,r,{...o,scope:[sQ.Synonyms]}),Vdt=t=>(e,r)=>e.method===Dr.MethodEnum.Get?t.transporter.read(e,r):t.transporter.write(e,r),zdt=t=>(e,r)=>{let o=(a,n)=>Wt.createRetryablePromise(u=>gB(t)(e,n).then(u).catch(A=>{if(A.status!==404)throw A}));return Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Delete,path:Wt.encode(\"1/keys/%s\",e)},r),o)},Jdt=t=>(e,r,o)=>{let a=r.map(n=>({action:\"deleteEntry\",body:{objectID:n}}));return Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Wt.encode(\"/1/dictionaries/%s/batch\",e),data:{clearExistingDictionaryEntries:!1,requests:a}},o),(n,u)=>hC(t)(n.taskID,u))},Xdt=()=>(t,e)=>{let r=Ma.serializeQueryParameters(e),o=Udt.createHmac(\"sha256\",t).update(r).digest(\"hex\");return Buffer.from(o+r).toString(\"base64\")},gB=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Get,path:Wt.encode(\"1/keys/%s\",e)},r),Kye=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Get,path:Wt.encode(\"1/task/%s\",e.toString())},r),Zdt=t=>e=>t.transporter.read({method:Dr.MethodEnum.Get,path:\"/1/dictionaries/*/settings\"},e),$dt=t=>e=>t.transporter.read({method:Dr.MethodEnum.Get,path:\"1/logs\"},e),emt=()=>t=>{let e=Buffer.from(t,\"base64\").toString(\"ascii\"),r=/validUntil=(\\d+)/,o=e.match(r);if(o===null)throw Yye();return parseInt(o[1],10)-Math.round(new Date().getTime()/1e3)},tmt=t=>e=>t.transporter.read({method:Dr.MethodEnum.Get,path:\"1/clusters/mapping/top\"},e),rmt=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Get,path:Wt.encode(\"1/clusters/mapping/%s\",e)},r),nmt=t=>e=>{let{retrieveMappings:r,...o}=e||{};return r===!0&&(o.getClusters=!0),t.transporter.read({method:Dr.MethodEnum.Get,path:\"1/clusters/mapping/pending\"},o)},dB=t=>(e,r={})=>{let o={transporter:t.transporter,appId:t.appId,indexName:e};return Wt.addMethods(o,r.methods)},imt=t=>e=>t.transporter.read({method:Dr.MethodEnum.Get,path:\"1/keys\"},e),smt=t=>e=>t.transporter.read({method:Dr.MethodEnum.Get,path:\"1/clusters\"},e),omt=t=>e=>t.transporter.read({method:Dr.MethodEnum.Get,path:\"1/indexes\"},e),amt=t=>e=>t.transporter.read({method:Dr.MethodEnum.Get,path:\"1/clusters/mapping\"},e),lmt=t=>(e,r,o)=>{let a=(n,u)=>dB(t)(e,{methods:{waitTask:es}}).waitTask(n.taskID,u);return Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Wt.encode(\"1/indexes/%s/operation\",e),data:{operation:\"move\",destination:r}},o),a)},cmt=t=>(e,r)=>{let o=(a,n)=>Promise.all(Object.keys(a.taskID).map(u=>dB(t)(u,{methods:{waitTask:es}}).waitTask(a.taskID[u],n)));return Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:\"1/indexes/*/batch\",data:{requests:e}},r),o)},umt=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Post,path:\"1/indexes/*/objects\",data:{requests:e}},r),Amt=t=>(e,r)=>{let o=e.map(a=>({...a,params:Ma.serializeQueryParameters(a.params||{})}));return t.transporter.read({method:Dr.MethodEnum.Post,path:\"1/indexes/*/queries\",data:{requests:o},cacheable:!0},r)},fmt=t=>(e,r)=>Promise.all(e.map(o=>{let{facetName:a,facetQuery:n,...u}=o.params;return dB(t)(o.indexName,{methods:{searchForFacetValues:eEe}}).searchForFacetValues(a,n,{...r,...u})})),pmt=t=>(e,r)=>{let o=Ma.createMappedRequestOptions(r);return o.queryParameters[\"X-Algolia-User-ID\"]=e,t.transporter.write({method:Dr.MethodEnum.Delete,path:\"1/clusters/mapping\"},o)},hmt=t=>(e,r,o)=>{let a=r.map(n=>({action:\"addEntry\",body:n}));return Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Wt.encode(\"/1/dictionaries/%s/batch\",e),data:{clearExistingDictionaryEntries:!0,requests:a}},o),(n,u)=>hC(t)(n.taskID,u))},gmt=t=>(e,r)=>{let o=(a,n)=>Wt.createRetryablePromise(u=>gB(t)(e,n).catch(A=>{if(A.status!==404)throw A;return u()}));return Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Wt.encode(\"1/keys/%s/restore\",e)},r),o)},dmt=t=>(e,r,o)=>{let a=r.map(n=>({action:\"addEntry\",body:n}));return Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Wt.encode(\"/1/dictionaries/%s/batch\",e),data:{clearExistingDictionaryEntries:!1,requests:a}},o),(n,u)=>hC(t)(n.taskID,u))},mmt=t=>(e,r,o)=>t.transporter.read({method:Dr.MethodEnum.Post,path:Wt.encode(\"/1/dictionaries/%s/search\",e),data:{query:r},cacheable:!0},o),ymt=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Post,path:\"1/clusters/mapping/search\",data:{query:e}},r),Emt=t=>(e,r)=>Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Put,path:\"/1/dictionaries/*/settings\",data:e},r),(o,a)=>hC(t)(o.taskID,a)),Cmt=t=>(e,r)=>{let o=Object.assign({},r),{queryParameters:a,...n}=r||{},u=a?{queryParameters:a}:{},A=[\"acl\",\"indexes\",\"referers\",\"restrictSources\",\"queryParameters\",\"description\",\"maxQueriesPerIPPerHour\",\"maxHitsPerQuery\"],p=E=>Object.keys(o).filter(w=>A.indexOf(w)!==-1).every(w=>{if(Array.isArray(E[w])&&Array.isArray(o[w])){let D=E[w];return D.length===o[w].length&&D.every((b,C)=>b===o[w][C])}else return E[w]===o[w]}),h=(E,w)=>Wt.createRetryablePromise(D=>gB(t)(e,w).then(b=>p(b)?Promise.resolve():D()));return Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Put,path:Wt.encode(\"1/keys/%s\",e),data:u},n),h)},hC=t=>(e,r)=>Wt.createRetryablePromise(o=>Kye(t)(e,r).then(a=>a.status!==\"published\"?o():void 0)),Vye=t=>(e,r)=>{let o=(a,n)=>es(t)(a.taskID,n);return Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Wt.encode(\"1/indexes/%s/batch\",t.indexName),data:{requests:e}},r),o)},Imt=t=>e=>rQ({shouldStop:r=>r.cursor===void 0,...e,request:r=>t.transporter.read({method:Dr.MethodEnum.Post,path:Wt.encode(\"1/indexes/%s/browse\",t.indexName),data:r},e)}),wmt=t=>e=>{let r={hitsPerPage:1e3,...e};return rQ({shouldStop:o=>o.hits.length<r.hitsPerPage,...r,request(o){return tEe(t)(\"\",{...r,...o}).then(a=>({...a,hits:a.hits.map(n=>(delete n._highlightResult,n))}))}})},Bmt=t=>e=>{let r={hitsPerPage:1e3,...e};return rQ({shouldStop:o=>o.hits.length<r.hitsPerPage,...r,request(o){return rEe(t)(\"\",{...r,...o}).then(a=>({...a,hits:a.hits.map(n=>(delete n._highlightResult,n))}))}})},iQ=t=>(e,r,o)=>{let{batchSize:a,...n}=o||{},u={taskIDs:[],objectIDs:[]},A=(p=0)=>{let h=[],E;for(E=p;E<e.length&&(h.push(e[E]),h.length!==(a||1e3));E++);return h.length===0?Promise.resolve(u):Vye(t)(h.map(w=>({action:r,body:w})),n).then(w=>(u.objectIDs=u.objectIDs.concat(w.objectIDs),u.taskIDs.push(w.taskID),E++,A(E)))};return Wt.createWaitablePromise(A(),(p,h)=>Promise.all(p.taskIDs.map(E=>es(t)(E,h))))},vmt=t=>e=>Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Wt.encode(\"1/indexes/%s/clear\",t.indexName)},e),(r,o)=>es(t)(r.taskID,o)),Dmt=t=>e=>{let{forwardToReplicas:r,...o}=e||{},a=Ma.createMappedRequestOptions(o);return r&&(a.queryParameters.forwardToReplicas=1),Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Wt.encode(\"1/indexes/%s/rules/clear\",t.indexName)},a),(n,u)=>es(t)(n.taskID,u))},Pmt=t=>e=>{let{forwardToReplicas:r,...o}=e||{},a=Ma.createMappedRequestOptions(o);return r&&(a.queryParameters.forwardToReplicas=1),Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Wt.encode(\"1/indexes/%s/synonyms/clear\",t.indexName)},a),(n,u)=>es(t)(n.taskID,u))},Smt=t=>(e,r)=>Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Wt.encode(\"1/indexes/%s/deleteByQuery\",t.indexName),data:e},r),(o,a)=>es(t)(o.taskID,a)),xmt=t=>e=>Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Delete,path:Wt.encode(\"1/indexes/%s\",t.indexName)},e),(r,o)=>es(t)(r.taskID,o)),bmt=t=>(e,r)=>Wt.createWaitablePromise(zye(t)([e],r).then(o=>({taskID:o.taskIDs[0]})),(o,a)=>es(t)(o.taskID,a)),zye=t=>(e,r)=>{let o=e.map(a=>({objectID:a}));return iQ(t)(o,ed.DeleteObject,r)},kmt=t=>(e,r)=>{let{forwardToReplicas:o,...a}=r||{},n=Ma.createMappedRequestOptions(a);return o&&(n.queryParameters.forwardToReplicas=1),Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Delete,path:Wt.encode(\"1/indexes/%s/rules/%s\",t.indexName,e)},n),(u,A)=>es(t)(u.taskID,A))},Qmt=t=>(e,r)=>{let{forwardToReplicas:o,...a}=r||{},n=Ma.createMappedRequestOptions(a);return o&&(n.queryParameters.forwardToReplicas=1),Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Delete,path:Wt.encode(\"1/indexes/%s/synonyms/%s\",t.indexName,e)},n),(u,A)=>es(t)(u.taskID,A))},Fmt=t=>e=>Jye(t)(e).then(()=>!0).catch(r=>{if(r.status!==404)throw r;return!1}),Rmt=t=>(e,r,o)=>t.transporter.read({method:Dr.MethodEnum.Post,path:Wt.encode(\"1/answers/%s/prediction\",t.indexName),data:{query:e,queryLanguages:r},cacheable:!0},o),Tmt=t=>(e,r)=>{let{query:o,paginate:a,...n}=r||{},u=0,A=()=>$ye(t)(o||\"\",{...n,page:u}).then(p=>{for(let[h,E]of Object.entries(p.hits))if(e(E))return{object:E,position:parseInt(h,10),page:u};if(u++,a===!1||u>=p.nbPages)throw Wye();return A()});return A()},Lmt=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Get,path:Wt.encode(\"1/indexes/%s/%s\",t.indexName,e)},r),Nmt=()=>(t,e)=>{for(let[r,o]of Object.entries(t.hits))if(o.objectID===e)return parseInt(r,10);return-1},Omt=t=>(e,r)=>{let{attributesToRetrieve:o,...a}=r||{},n=e.map(u=>({indexName:t.indexName,objectID:u,...o?{attributesToRetrieve:o}:{}}));return t.transporter.read({method:Dr.MethodEnum.Post,path:\"1/indexes/*/objects\",data:{requests:n}},a)},Mmt=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Get,path:Wt.encode(\"1/indexes/%s/rules/%s\",t.indexName,e)},r),Jye=t=>e=>t.transporter.read({method:Dr.MethodEnum.Get,path:Wt.encode(\"1/indexes/%s/settings\",t.indexName),data:{getVersion:2}},e),Umt=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Get,path:Wt.encode(\"1/indexes/%s/synonyms/%s\",t.indexName,e)},r),Xye=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Get,path:Wt.encode(\"1/indexes/%s/task/%s\",t.indexName,e.toString())},r),_mt=t=>(e,r)=>Wt.createWaitablePromise(Zye(t)([e],r).then(o=>({objectID:o.objectIDs[0],taskID:o.taskIDs[0]})),(o,a)=>es(t)(o.taskID,a)),Zye=t=>(e,r)=>{let{createIfNotExists:o,...a}=r||{},n=o?ed.PartialUpdateObject:ed.PartialUpdateObjectNoCreate;return iQ(t)(e,n,a)},Hmt=t=>(e,r)=>{let{safe:o,autoGenerateObjectIDIfNotExist:a,batchSize:n,...u}=r||{},A=(C,T,N,U)=>Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Wt.encode(\"1/indexes/%s/operation\",C),data:{operation:N,destination:T}},U),(z,te)=>es(t)(z.taskID,te)),p=Math.random().toString(36).substring(7),h=`${t.indexName}_tmp_${p}`,E=b6({appId:t.appId,transporter:t.transporter,indexName:h}),w=[],D=A(t.indexName,h,\"copy\",{...u,scope:[\"settings\",\"synonyms\",\"rules\"]});w.push(D);let b=(o?D.wait(u):D).then(()=>{let C=E(e,{...u,autoGenerateObjectIDIfNotExist:a,batchSize:n});return w.push(C),o?C.wait(u):C}).then(()=>{let C=A(h,t.indexName,\"move\",u);return w.push(C),o?C.wait(u):C}).then(()=>Promise.all(w)).then(([C,T,N])=>({objectIDs:T.objectIDs,taskIDs:[C.taskID,...T.taskIDs,N.taskID]}));return Wt.createWaitablePromise(b,(C,T)=>Promise.all(w.map(N=>N.wait(T))))},qmt=t=>(e,r)=>k6(t)(e,{...r,clearExistingRules:!0}),jmt=t=>(e,r)=>Q6(t)(e,{...r,clearExistingSynonyms:!0}),Gmt=t=>(e,r)=>Wt.createWaitablePromise(b6(t)([e],r).then(o=>({objectID:o.objectIDs[0],taskID:o.taskIDs[0]})),(o,a)=>es(t)(o.taskID,a)),b6=t=>(e,r)=>{let{autoGenerateObjectIDIfNotExist:o,...a}=r||{},n=o?ed.AddObject:ed.UpdateObject;if(n===ed.UpdateObject){for(let u of e)if(u.objectID===void 0)return Wt.createWaitablePromise(Promise.reject(Gye()))}return iQ(t)(e,n,a)},Wmt=t=>(e,r)=>k6(t)([e],r),k6=t=>(e,r)=>{let{forwardToReplicas:o,clearExistingRules:a,...n}=r||{},u=Ma.createMappedRequestOptions(n);return o&&(u.queryParameters.forwardToReplicas=1),a&&(u.queryParameters.clearExistingRules=1),Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Wt.encode(\"1/indexes/%s/rules/batch\",t.indexName),data:e},u),(A,p)=>es(t)(A.taskID,p))},Ymt=t=>(e,r)=>Q6(t)([e],r),Q6=t=>(e,r)=>{let{forwardToReplicas:o,clearExistingSynonyms:a,replaceExistingSynonyms:n,...u}=r||{},A=Ma.createMappedRequestOptions(u);return o&&(A.queryParameters.forwardToReplicas=1),(n||a)&&(A.queryParameters.replaceExistingSynonyms=1),Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Post,path:Wt.encode(\"1/indexes/%s/synonyms/batch\",t.indexName),data:e},A),(p,h)=>es(t)(p.taskID,h))},$ye=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Post,path:Wt.encode(\"1/indexes/%s/query\",t.indexName),data:{query:e},cacheable:!0},r),eEe=t=>(e,r,o)=>t.transporter.read({method:Dr.MethodEnum.Post,path:Wt.encode(\"1/indexes/%s/facets/%s/query\",t.indexName,e),data:{facetQuery:r},cacheable:!0},o),tEe=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Post,path:Wt.encode(\"1/indexes/%s/rules/search\",t.indexName),data:{query:e}},r),rEe=t=>(e,r)=>t.transporter.read({method:Dr.MethodEnum.Post,path:Wt.encode(\"1/indexes/%s/synonyms/search\",t.indexName),data:{query:e}},r),Kmt=t=>(e,r)=>{let{forwardToReplicas:o,...a}=r||{},n=Ma.createMappedRequestOptions(a);return o&&(n.queryParameters.forwardToReplicas=1),Wt.createWaitablePromise(t.transporter.write({method:Dr.MethodEnum.Put,path:Wt.encode(\"1/indexes/%s/settings\",t.indexName),data:e},n),(u,A)=>es(t)(u.taskID,A))},es=t=>(e,r)=>Wt.createRetryablePromise(o=>Xye(t)(e,r).then(a=>a.status!==\"published\"?o():void 0)),Vmt={AddObject:\"addObject\",Analytics:\"analytics\",Browser:\"browse\",DeleteIndex:\"deleteIndex\",DeleteObject:\"deleteObject\",EditSettings:\"editSettings\",Inference:\"inference\",ListIndexes:\"listIndexes\",Logs:\"logs\",Personalization:\"personalization\",Recommendation:\"recommendation\",Search:\"search\",SeeUnretrievableAttributes:\"seeUnretrievableAttributes\",Settings:\"settings\",Usage:\"usage\"},ed={AddObject:\"addObject\",UpdateObject:\"updateObject\",PartialUpdateObject:\"partialUpdateObject\",PartialUpdateObjectNoCreate:\"partialUpdateObjectNoCreate\",DeleteObject:\"deleteObject\",DeleteIndex:\"delete\",ClearIndex:\"clear\"},sQ={Settings:\"settings\",Synonyms:\"synonyms\",Rules:\"rules\"},zmt={None:\"none\",StopIfEnoughMatches:\"stopIfEnoughMatches\"},Jmt={Synonym:\"synonym\",OneWaySynonym:\"oneWaySynonym\",AltCorrection1:\"altCorrection1\",AltCorrection2:\"altCorrection2\",Placeholder:\"placeholder\"};Rt.ApiKeyACLEnum=Vmt;Rt.BatchActionEnum=ed;Rt.ScopeEnum=sQ;Rt.StrategyEnum=zmt;Rt.SynonymEnum=Jmt;Rt.addApiKey=Hdt;Rt.assignUserID=qdt;Rt.assignUserIDs=jdt;Rt.batch=Vye;Rt.browseObjects=Imt;Rt.browseRules=wmt;Rt.browseSynonyms=Bmt;Rt.chunkedBatch=iQ;Rt.clearDictionaryEntries=Gdt;Rt.clearObjects=vmt;Rt.clearRules=Dmt;Rt.clearSynonyms=Pmt;Rt.copyIndex=nQ;Rt.copyRules=Wdt;Rt.copySettings=Ydt;Rt.copySynonyms=Kdt;Rt.createBrowsablePromise=rQ;Rt.createMissingObjectIDError=Gye;Rt.createObjectNotFoundError=Wye;Rt.createSearchClient=_dt;Rt.createValidUntilNotFoundError=Yye;Rt.customRequest=Vdt;Rt.deleteApiKey=zdt;Rt.deleteBy=Smt;Rt.deleteDictionaryEntries=Jdt;Rt.deleteIndex=xmt;Rt.deleteObject=bmt;Rt.deleteObjects=zye;Rt.deleteRule=kmt;Rt.deleteSynonym=Qmt;Rt.exists=Fmt;Rt.findAnswers=Rmt;Rt.findObject=Tmt;Rt.generateSecuredApiKey=Xdt;Rt.getApiKey=gB;Rt.getAppTask=Kye;Rt.getDictionarySettings=Zdt;Rt.getLogs=$dt;Rt.getObject=Lmt;Rt.getObjectPosition=Nmt;Rt.getObjects=Omt;Rt.getRule=Mmt;Rt.getSecuredApiKeyRemainingValidity=emt;Rt.getSettings=Jye;Rt.getSynonym=Umt;Rt.getTask=Xye;Rt.getTopUserIDs=tmt;Rt.getUserID=rmt;Rt.hasPendingMappings=nmt;Rt.initIndex=dB;Rt.listApiKeys=imt;Rt.listClusters=smt;Rt.listIndices=omt;Rt.listUserIDs=amt;Rt.moveIndex=lmt;Rt.multipleBatch=cmt;Rt.multipleGetObjects=umt;Rt.multipleQueries=Amt;Rt.multipleSearchForFacetValues=fmt;Rt.partialUpdateObject=_mt;Rt.partialUpdateObjects=Zye;Rt.removeUserID=pmt;Rt.replaceAllObjects=Hmt;Rt.replaceAllRules=qmt;Rt.replaceAllSynonyms=jmt;Rt.replaceDictionaryEntries=hmt;Rt.restoreApiKey=gmt;Rt.saveDictionaryEntries=dmt;Rt.saveObject=Gmt;Rt.saveObjects=b6;Rt.saveRule=Wmt;Rt.saveRules=k6;Rt.saveSynonym=Ymt;Rt.saveSynonyms=Q6;Rt.search=$ye;Rt.searchDictionaryEntries=mmt;Rt.searchForFacetValues=eEe;Rt.searchRules=tEe;Rt.searchSynonyms=rEe;Rt.searchUserIDs=ymt;Rt.setDictionarySettings=Emt;Rt.setSettings=Kmt;Rt.updateApiKey=Cmt;Rt.waitAppTask=hC;Rt.waitTask=es});var sEe=_((SYt,iEe)=>{iEe.exports=nEe()});var oEe=_(oQ=>{\"use strict\";Object.defineProperty(oQ,\"__esModule\",{value:!0});function Xmt(){return{debug(t,e){return Promise.resolve()},info(t,e){return Promise.resolve()},error(t,e){return Promise.resolve()}}}var Zmt={Debug:1,Info:2,Error:3};oQ.LogLevelEnum=Zmt;oQ.createNullLogger=Xmt});var lEe=_((bYt,aEe)=>{aEe.exports=oEe()});var fEe=_(F6=>{\"use strict\";Object.defineProperty(F6,\"__esModule\",{value:!0});var cEe=ve(\"http\"),uEe=ve(\"https\"),$mt=ve(\"url\"),AEe={keepAlive:!0},eyt=new cEe.Agent(AEe),tyt=new uEe.Agent(AEe);function ryt({agent:t,httpAgent:e,httpsAgent:r,requesterOptions:o={}}={}){let a=e||t||eyt,n=r||t||tyt;return{send(u){return new Promise(A=>{let p=$mt.parse(u.url),h=p.query===null?p.pathname:`${p.pathname}?${p.query}`,E={...o,agent:p.protocol===\"https:\"?n:a,hostname:p.hostname,path:h,method:u.method,headers:{...o&&o.headers?o.headers:{},...u.headers},...p.port!==void 0?{port:p.port||\"\"}:{}},w=(p.protocol===\"https:\"?uEe:cEe).request(E,T=>{let N=[];T.on(\"data\",U=>{N=N.concat(U)}),T.on(\"end\",()=>{clearTimeout(b),clearTimeout(C),A({status:T.statusCode||0,content:Buffer.concat(N).toString(),isTimedOut:!1})})}),D=(T,N)=>setTimeout(()=>{w.abort(),A({status:0,content:N,isTimedOut:!0})},T*1e3),b=D(u.connectTimeout,\"Connection timeout\"),C;w.on(\"error\",T=>{clearTimeout(b),clearTimeout(C),A({status:0,content:T.message,isTimedOut:!1})}),w.once(\"response\",()=>{clearTimeout(b),C=D(u.responseTimeout,\"Socket timeout\")}),u.data!==void 0&&w.write(u.data),w.end()})},destroy(){return a.destroy(),n.destroy(),Promise.resolve()}}}F6.createNodeHttpRequester=ryt});var hEe=_((QYt,pEe)=>{pEe.exports=fEe()});var yEe=_((FYt,mEe)=>{\"use strict\";var gEe=fye(),nyt=gye(),gC=Uye(),T6=cB(),R6=jye(),Ht=sEe(),iyt=lEe(),syt=hEe(),oyt=fB();function dEe(t,e,r){let o={appId:t,apiKey:e,timeouts:{connect:2,read:5,write:30},requester:syt.createNodeHttpRequester(),logger:iyt.createNullLogger(),responsesCache:gEe.createNullCache(),requestsCache:gEe.createNullCache(),hostsCache:nyt.createInMemoryCache(),userAgent:oyt.createUserAgent(T6.version).add({segment:\"Node.js\",version:process.versions.node})},a={...o,...r},n=()=>u=>R6.createPersonalizationClient({...o,...u,methods:{getPersonalizationStrategy:R6.getPersonalizationStrategy,setPersonalizationStrategy:R6.setPersonalizationStrategy}});return Ht.createSearchClient({...a,methods:{search:Ht.multipleQueries,searchForFacetValues:Ht.multipleSearchForFacetValues,multipleBatch:Ht.multipleBatch,multipleGetObjects:Ht.multipleGetObjects,multipleQueries:Ht.multipleQueries,copyIndex:Ht.copyIndex,copySettings:Ht.copySettings,copyRules:Ht.copyRules,copySynonyms:Ht.copySynonyms,moveIndex:Ht.moveIndex,listIndices:Ht.listIndices,getLogs:Ht.getLogs,listClusters:Ht.listClusters,multipleSearchForFacetValues:Ht.multipleSearchForFacetValues,getApiKey:Ht.getApiKey,addApiKey:Ht.addApiKey,listApiKeys:Ht.listApiKeys,updateApiKey:Ht.updateApiKey,deleteApiKey:Ht.deleteApiKey,restoreApiKey:Ht.restoreApiKey,assignUserID:Ht.assignUserID,assignUserIDs:Ht.assignUserIDs,getUserID:Ht.getUserID,searchUserIDs:Ht.searchUserIDs,listUserIDs:Ht.listUserIDs,getTopUserIDs:Ht.getTopUserIDs,removeUserID:Ht.removeUserID,hasPendingMappings:Ht.hasPendingMappings,generateSecuredApiKey:Ht.generateSecuredApiKey,getSecuredApiKeyRemainingValidity:Ht.getSecuredApiKeyRemainingValidity,destroy:T6.destroy,clearDictionaryEntries:Ht.clearDictionaryEntries,deleteDictionaryEntries:Ht.deleteDictionaryEntries,getDictionarySettings:Ht.getDictionarySettings,getAppTask:Ht.getAppTask,replaceDictionaryEntries:Ht.replaceDictionaryEntries,saveDictionaryEntries:Ht.saveDictionaryEntries,searchDictionaryEntries:Ht.searchDictionaryEntries,setDictionarySettings:Ht.setDictionarySettings,waitAppTask:Ht.waitAppTask,customRequest:Ht.customRequest,initIndex:u=>A=>Ht.initIndex(u)(A,{methods:{batch:Ht.batch,delete:Ht.deleteIndex,findAnswers:Ht.findAnswers,getObject:Ht.getObject,getObjects:Ht.getObjects,saveObject:Ht.saveObject,saveObjects:Ht.saveObjects,search:Ht.search,searchForFacetValues:Ht.searchForFacetValues,waitTask:Ht.waitTask,setSettings:Ht.setSettings,getSettings:Ht.getSettings,partialUpdateObject:Ht.partialUpdateObject,partialUpdateObjects:Ht.partialUpdateObjects,deleteObject:Ht.deleteObject,deleteObjects:Ht.deleteObjects,deleteBy:Ht.deleteBy,clearObjects:Ht.clearObjects,browseObjects:Ht.browseObjects,getObjectPosition:Ht.getObjectPosition,findObject:Ht.findObject,exists:Ht.exists,saveSynonym:Ht.saveSynonym,saveSynonyms:Ht.saveSynonyms,getSynonym:Ht.getSynonym,searchSynonyms:Ht.searchSynonyms,browseSynonyms:Ht.browseSynonyms,deleteSynonym:Ht.deleteSynonym,clearSynonyms:Ht.clearSynonyms,replaceAllObjects:Ht.replaceAllObjects,replaceAllSynonyms:Ht.replaceAllSynonyms,searchRules:Ht.searchRules,getRule:Ht.getRule,deleteRule:Ht.deleteRule,saveRule:Ht.saveRule,saveRules:Ht.saveRules,replaceAllRules:Ht.replaceAllRules,browseRules:Ht.browseRules,clearRules:Ht.clearRules}}),initAnalytics:()=>u=>gC.createAnalyticsClient({...o,...u,methods:{addABTest:gC.addABTest,getABTest:gC.getABTest,getABTests:gC.getABTests,stopABTest:gC.stopABTest,deleteABTest:gC.deleteABTest}}),initPersonalization:n,initRecommendation:()=>u=>(a.logger.info(\"The `initRecommendation` method is deprecated. Use `initPersonalization` instead.\"),n()(u))}})}dEe.version=T6.version;mEe.exports=dEe});var N6=_((RYt,L6)=>{var EEe=yEe();L6.exports=EEe;L6.exports.default=EEe});var U6=_((LYt,wEe)=>{\"use strict\";var IEe=Object.getOwnPropertySymbols,lyt=Object.prototype.hasOwnProperty,cyt=Object.prototype.propertyIsEnumerable;function uyt(t){if(t==null)throw new TypeError(\"Object.assign cannot be called with null or undefined\");return Object(t)}function Ayt(){try{if(!Object.assign)return!1;var t=new String(\"abc\");if(t[5]=\"de\",Object.getOwnPropertyNames(t)[0]===\"5\")return!1;for(var e={},r=0;r<10;r++)e[\"_\"+String.fromCharCode(r)]=r;var o=Object.getOwnPropertyNames(e).map(function(n){return e[n]});if(o.join(\"\")!==\"0123456789\")return!1;var a={};return\"abcdefghijklmnopqrst\".split(\"\").forEach(function(n){a[n]=n}),Object.keys(Object.assign({},a)).join(\"\")===\"abcdefghijklmnopqrst\"}catch{return!1}}wEe.exports=Ayt()?Object.assign:function(t,e){for(var r,o=uyt(t),a,n=1;n<arguments.length;n++){r=Object(arguments[n]);for(var u in r)lyt.call(r,u)&&(o[u]=r[u]);if(IEe){a=IEe(r);for(var A=0;A<a.length;A++)cyt.call(r,a[A])&&(o[a[A]]=r[a[A]])}}return o}});var MEe=_(Cn=>{\"use strict\";var H6=U6(),dC=60103,DEe=60106;Cn.Fragment=60107;Cn.StrictMode=60108;Cn.Profiler=60114;var PEe=60109,SEe=60110,xEe=60112;Cn.Suspense=60113;var bEe=60115,kEe=60116;typeof Symbol==\"function\"&&Symbol.for&&(sc=Symbol.for,dC=sc(\"react.element\"),DEe=sc(\"react.portal\"),Cn.Fragment=sc(\"react.fragment\"),Cn.StrictMode=sc(\"react.strict_mode\"),Cn.Profiler=sc(\"react.profiler\"),PEe=sc(\"react.provider\"),SEe=sc(\"react.context\"),xEe=sc(\"react.forward_ref\"),Cn.Suspense=sc(\"react.suspense\"),bEe=sc(\"react.memo\"),kEe=sc(\"react.lazy\"));var sc,BEe=typeof Symbol==\"function\"&&Symbol.iterator;function fyt(t){return t===null||typeof t!=\"object\"?null:(t=BEe&&t[BEe]||t[\"@@iterator\"],typeof t==\"function\"?t:null)}function mB(t){for(var e=\"https://reactjs.org/docs/error-decoder.html?invariant=\"+t,r=1;r<arguments.length;r++)e+=\"&args[]=\"+encodeURIComponent(arguments[r]);return\"Minified React error #\"+t+\"; visit \"+e+\" for the full message or use the non-minified dev environment for full errors and additional helpful warnings.\"}var QEe={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},FEe={};function mC(t,e,r){this.props=t,this.context=e,this.refs=FEe,this.updater=r||QEe}mC.prototype.isReactComponent={};mC.prototype.setState=function(t,e){if(typeof t!=\"object\"&&typeof t!=\"function\"&&t!=null)throw Error(mB(85));this.updater.enqueueSetState(this,t,e,\"setState\")};mC.prototype.forceUpdate=function(t){this.updater.enqueueForceUpdate(this,t,\"forceUpdate\")};function REe(){}REe.prototype=mC.prototype;function q6(t,e,r){this.props=t,this.context=e,this.refs=FEe,this.updater=r||QEe}var j6=q6.prototype=new REe;j6.constructor=q6;H6(j6,mC.prototype);j6.isPureReactComponent=!0;var G6={current:null},TEe=Object.prototype.hasOwnProperty,LEe={key:!0,ref:!0,__self:!0,__source:!0};function NEe(t,e,r){var o,a={},n=null,u=null;if(e!=null)for(o in e.ref!==void 0&&(u=e.ref),e.key!==void 0&&(n=\"\"+e.key),e)TEe.call(e,o)&&!LEe.hasOwnProperty(o)&&(a[o]=e[o]);var A=arguments.length-2;if(A===1)a.children=r;else if(1<A){for(var p=Array(A),h=0;h<A;h++)p[h]=arguments[h+2];a.children=p}if(t&&t.defaultProps)for(o in A=t.defaultProps,A)a[o]===void 0&&(a[o]=A[o]);return{$$typeof:dC,type:t,key:n,ref:u,props:a,_owner:G6.current}}function pyt(t,e){return{$$typeof:dC,type:t.type,key:e,ref:t.ref,props:t.props,_owner:t._owner}}function W6(t){return typeof t==\"object\"&&t!==null&&t.$$typeof===dC}function hyt(t){var e={\"=\":\"=0\",\":\":\"=2\"};return\"$\"+t.replace(/[=:]/g,function(r){return e[r]})}var vEe=/\\/+/g;function _6(t,e){return typeof t==\"object\"&&t!==null&&t.key!=null?hyt(\"\"+t.key):e.toString(36)}function lQ(t,e,r,o,a){var n=typeof t;(n===\"undefined\"||n===\"boolean\")&&(t=null);var u=!1;if(t===null)u=!0;else switch(n){case\"string\":case\"number\":u=!0;break;case\"object\":switch(t.$$typeof){case dC:case DEe:u=!0}}if(u)return u=t,a=a(u),t=o===\"\"?\".\"+_6(u,0):o,Array.isArray(a)?(r=\"\",t!=null&&(r=t.replace(vEe,\"$&/\")+\"/\"),lQ(a,e,r,\"\",function(h){return h})):a!=null&&(W6(a)&&(a=pyt(a,r+(!a.key||u&&u.key===a.key?\"\":(\"\"+a.key).replace(vEe,\"$&/\")+\"/\")+t)),e.push(a)),1;if(u=0,o=o===\"\"?\".\":o+\":\",Array.isArray(t))for(var A=0;A<t.length;A++){n=t[A];var p=o+_6(n,A);u+=lQ(n,e,r,p,a)}else if(p=fyt(t),typeof p==\"function\")for(t=p.call(t),A=0;!(n=t.next()).done;)n=n.value,p=o+_6(n,A++),u+=lQ(n,e,r,p,a);else if(n===\"object\")throw e=\"\"+t,Error(mB(31,e===\"[object Object]\"?\"object with keys {\"+Object.keys(t).join(\", \")+\"}\":e));return u}function aQ(t,e,r){if(t==null)return t;var o=[],a=0;return lQ(t,o,\"\",\"\",function(n){return e.call(r,n,a++)}),o}function gyt(t){if(t._status===-1){var e=t._result;e=e(),t._status=0,t._result=e,e.then(function(r){t._status===0&&(r=r.default,t._status=1,t._result=r)},function(r){t._status===0&&(t._status=2,t._result=r)})}if(t._status===1)return t._result;throw t._result}var OEe={current:null};function Vf(){var t=OEe.current;if(t===null)throw Error(mB(321));return t}var dyt={ReactCurrentDispatcher:OEe,ReactCurrentBatchConfig:{transition:0},ReactCurrentOwner:G6,IsSomeRendererActing:{current:!1},assign:H6};Cn.Children={map:aQ,forEach:function(t,e,r){aQ(t,function(){e.apply(this,arguments)},r)},count:function(t){var e=0;return aQ(t,function(){e++}),e},toArray:function(t){return aQ(t,function(e){return e})||[]},only:function(t){if(!W6(t))throw Error(mB(143));return t}};Cn.Component=mC;Cn.PureComponent=q6;Cn.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=dyt;Cn.cloneElement=function(t,e,r){if(t==null)throw Error(mB(267,t));var o=H6({},t.props),a=t.key,n=t.ref,u=t._owner;if(e!=null){if(e.ref!==void 0&&(n=e.ref,u=G6.current),e.key!==void 0&&(a=\"\"+e.key),t.type&&t.type.defaultProps)var A=t.type.defaultProps;for(p in e)TEe.call(e,p)&&!LEe.hasOwnProperty(p)&&(o[p]=e[p]===void 0&&A!==void 0?A[p]:e[p])}var p=arguments.length-2;if(p===1)o.children=r;else if(1<p){A=Array(p);for(var h=0;h<p;h++)A[h]=arguments[h+2];o.children=A}return{$$typeof:dC,type:t.type,key:a,ref:n,props:o,_owner:u}};Cn.createContext=function(t,e){return e===void 0&&(e=null),t={$$typeof:SEe,_calculateChangedBits:e,_currentValue:t,_currentValue2:t,_threadCount:0,Provider:null,Consumer:null},t.Provider={$$typeof:PEe,_context:t},t.Consumer=t};Cn.createElement=NEe;Cn.createFactory=function(t){var e=NEe.bind(null,t);return e.type=t,e};Cn.createRef=function(){return{current:null}};Cn.forwardRef=function(t){return{$$typeof:xEe,render:t}};Cn.isValidElement=W6;Cn.lazy=function(t){return{$$typeof:kEe,_payload:{_status:-1,_result:t},_init:gyt}};Cn.memo=function(t,e){return{$$typeof:bEe,type:t,compare:e===void 0?null:e}};Cn.useCallback=function(t,e){return Vf().useCallback(t,e)};Cn.useContext=function(t,e){return Vf().useContext(t,e)};Cn.useDebugValue=function(){};Cn.useEffect=function(t,e){return Vf().useEffect(t,e)};Cn.useImperativeHandle=function(t,e,r){return Vf().useImperativeHandle(t,e,r)};Cn.useLayoutEffect=function(t,e){return Vf().useLayoutEffect(t,e)};Cn.useMemo=function(t,e){return Vf().useMemo(t,e)};Cn.useReducer=function(t,e,r){return Vf().useReducer(t,e,r)};Cn.useRef=function(t){return Vf().useRef(t)};Cn.useState=function(t){return Vf().useState(t)};Cn.version=\"17.0.2\"});var ln=_((OYt,UEe)=>{\"use strict\";UEe.exports=MEe()});var K6=_((MYt,Y6)=>{\"use strict\";var gn=Y6.exports;Y6.exports.default=gn;var Gn=\"\\x1B[\",yB=\"\\x1B]\",yC=\"\\x07\",cQ=\";\",_Ee=process.env.TERM_PROGRAM===\"Apple_Terminal\";gn.cursorTo=(t,e)=>{if(typeof t!=\"number\")throw new TypeError(\"The `x` argument is required\");return typeof e!=\"number\"?Gn+(t+1)+\"G\":Gn+(e+1)+\";\"+(t+1)+\"H\"};gn.cursorMove=(t,e)=>{if(typeof t!=\"number\")throw new TypeError(\"The `x` argument is required\");let r=\"\";return t<0?r+=Gn+-t+\"D\":t>0&&(r+=Gn+t+\"C\"),e<0?r+=Gn+-e+\"A\":e>0&&(r+=Gn+e+\"B\"),r};gn.cursorUp=(t=1)=>Gn+t+\"A\";gn.cursorDown=(t=1)=>Gn+t+\"B\";gn.cursorForward=(t=1)=>Gn+t+\"C\";gn.cursorBackward=(t=1)=>Gn+t+\"D\";gn.cursorLeft=Gn+\"G\";gn.cursorSavePosition=_Ee?\"\\x1B7\":Gn+\"s\";gn.cursorRestorePosition=_Ee?\"\\x1B8\":Gn+\"u\";gn.cursorGetPosition=Gn+\"6n\";gn.cursorNextLine=Gn+\"E\";gn.cursorPrevLine=Gn+\"F\";gn.cursorHide=Gn+\"?25l\";gn.cursorShow=Gn+\"?25h\";gn.eraseLines=t=>{let e=\"\";for(let r=0;r<t;r++)e+=gn.eraseLine+(r<t-1?gn.cursorUp():\"\");return t&&(e+=gn.cursorLeft),e};gn.eraseEndLine=Gn+\"K\";gn.eraseStartLine=Gn+\"1K\";gn.eraseLine=Gn+\"2K\";gn.eraseDown=Gn+\"J\";gn.eraseUp=Gn+\"1J\";gn.eraseScreen=Gn+\"2J\";gn.scrollUp=Gn+\"S\";gn.scrollDown=Gn+\"T\";gn.clearScreen=\"\\x1Bc\";gn.clearTerminal=process.platform===\"win32\"?`${gn.eraseScreen}${Gn}0f`:`${gn.eraseScreen}${Gn}3J${Gn}H`;gn.beep=yC;gn.link=(t,e)=>[yB,\"8\",cQ,cQ,e,yC,t,yB,\"8\",cQ,cQ,yC].join(\"\");gn.image=(t,e={})=>{let r=`${yB}1337;File=inline=1`;return e.width&&(r+=`;width=${e.width}`),e.height&&(r+=`;height=${e.height}`),e.preserveAspectRatio===!1&&(r+=\";preserveAspectRatio=0\"),r+\":\"+t.toString(\"base64\")+yC};gn.iTerm={setCwd:(t=process.cwd())=>`${yB}50;CurrentDir=${t}${yC}`,annotation:(t,e={})=>{let r=`${yB}1337;`,o=typeof e.x<\"u\",a=typeof e.y<\"u\";if((o||a)&&!(o&&a&&typeof e.length<\"u\"))throw new Error(\"`x`, `y` and `length` must be defined when `x` or `y` is defined\");return t=t.replace(/\\|/g,\"\"),r+=e.isHidden?\"AddHiddenAnnotation=\":\"AddAnnotation=\",e.length>0?r+=(o?[t,e.length,e.x,e.y]:[e.length,t]).join(\"|\"):r+=t,r+yC}}});var qEe=_((UYt,V6)=>{\"use strict\";var HEe=(t,e)=>{for(let r of Reflect.ownKeys(e))Object.defineProperty(t,r,Object.getOwnPropertyDescriptor(e,r));return t};V6.exports=HEe;V6.exports.default=HEe});var GEe=_((_Yt,AQ)=>{\"use strict\";var myt=qEe(),uQ=new WeakMap,jEe=(t,e={})=>{if(typeof t!=\"function\")throw new TypeError(\"Expected a function\");let r,o=0,a=t.displayName||t.name||\"<anonymous>\",n=function(...u){if(uQ.set(n,++o),o===1)r=t.apply(this,u),t=null;else if(e.throw===!0)throw new Error(`Function \\`${a}\\` can only be called once`);return r};return myt(n,t),uQ.set(n,o),n};AQ.exports=jEe;AQ.exports.default=jEe;AQ.exports.callCount=t=>{if(!uQ.has(t))throw new Error(`The given function \\`${t.name}\\` is not wrapped by the \\`onetime\\` package`);return uQ.get(t)}});var WEe=_((HYt,fQ)=>{fQ.exports=[\"SIGABRT\",\"SIGALRM\",\"SIGHUP\",\"SIGINT\",\"SIGTERM\"];process.platform!==\"win32\"&&fQ.exports.push(\"SIGVTALRM\",\"SIGXCPU\",\"SIGXFSZ\",\"SIGUSR2\",\"SIGTRAP\",\"SIGSYS\",\"SIGQUIT\",\"SIGIOT\");process.platform===\"linux\"&&fQ.exports.push(\"SIGIO\",\"SIGPOLL\",\"SIGPWR\",\"SIGSTKFLT\",\"SIGUNUSED\")});var X6=_((qYt,IC)=>{var wi=global.process,td=function(t){return t&&typeof t==\"object\"&&typeof t.removeListener==\"function\"&&typeof t.emit==\"function\"&&typeof t.reallyExit==\"function\"&&typeof t.listeners==\"function\"&&typeof t.kill==\"function\"&&typeof t.pid==\"number\"&&typeof t.on==\"function\"};td(wi)?(YEe=ve(\"assert\"),EC=WEe(),KEe=/^win/i.test(wi.platform),EB=ve(\"events\"),typeof EB!=\"function\"&&(EB=EB.EventEmitter),wi.__signal_exit_emitter__?ks=wi.__signal_exit_emitter__:(ks=wi.__signal_exit_emitter__=new EB,ks.count=0,ks.emitted={}),ks.infinite||(ks.setMaxListeners(1/0),ks.infinite=!0),IC.exports=function(t,e){if(!td(global.process))return function(){};YEe.equal(typeof t,\"function\",\"a callback must be provided for exit handler\"),CC===!1&&z6();var r=\"exit\";e&&e.alwaysLast&&(r=\"afterexit\");var o=function(){ks.removeListener(r,t),ks.listeners(\"exit\").length===0&&ks.listeners(\"afterexit\").length===0&&pQ()};return ks.on(r,t),o},pQ=function(){!CC||!td(global.process)||(CC=!1,EC.forEach(function(e){try{wi.removeListener(e,hQ[e])}catch{}}),wi.emit=gQ,wi.reallyExit=J6,ks.count-=1)},IC.exports.unload=pQ,rd=function(e,r,o){ks.emitted[e]||(ks.emitted[e]=!0,ks.emit(e,r,o))},hQ={},EC.forEach(function(t){hQ[t]=function(){if(td(global.process)){var r=wi.listeners(t);r.length===ks.count&&(pQ(),rd(\"exit\",null,t),rd(\"afterexit\",null,t),KEe&&t===\"SIGHUP\"&&(t=\"SIGINT\"),wi.kill(wi.pid,t))}}}),IC.exports.signals=function(){return EC},CC=!1,z6=function(){CC||!td(global.process)||(CC=!0,ks.count+=1,EC=EC.filter(function(e){try{return wi.on(e,hQ[e]),!0}catch{return!1}}),wi.emit=zEe,wi.reallyExit=VEe)},IC.exports.load=z6,J6=wi.reallyExit,VEe=function(e){td(global.process)&&(wi.exitCode=e||0,rd(\"exit\",wi.exitCode,null),rd(\"afterexit\",wi.exitCode,null),J6.call(wi,wi.exitCode))},gQ=wi.emit,zEe=function(e,r){if(e===\"exit\"&&td(global.process)){r!==void 0&&(wi.exitCode=r);var o=gQ.apply(this,arguments);return rd(\"exit\",wi.exitCode,null),rd(\"afterexit\",wi.exitCode,null),o}else return gQ.apply(this,arguments)}):IC.exports=function(){return function(){}};var YEe,EC,KEe,EB,ks,pQ,rd,hQ,CC,z6,J6,VEe,gQ,zEe});var XEe=_((jYt,JEe)=>{\"use strict\";var yyt=GEe(),Eyt=X6();JEe.exports=yyt(()=>{Eyt(()=>{process.stderr.write(\"\\x1B[?25h\")},{alwaysLast:!0})})});var Z6=_(wC=>{\"use strict\";var Cyt=XEe(),dQ=!1;wC.show=(t=process.stderr)=>{t.isTTY&&(dQ=!1,t.write(\"\\x1B[?25h\"))};wC.hide=(t=process.stderr)=>{t.isTTY&&(Cyt(),dQ=!0,t.write(\"\\x1B[?25l\"))};wC.toggle=(t,e)=>{t!==void 0&&(dQ=t),dQ?wC.show(e):wC.hide(e)}});var tCe=_(CB=>{\"use strict\";var eCe=CB&&CB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(CB,\"__esModule\",{value:!0});var ZEe=eCe(K6()),$Ee=eCe(Z6()),Iyt=(t,{showCursor:e=!1}={})=>{let r=0,o=\"\",a=!1,n=u=>{!e&&!a&&($Ee.default.hide(),a=!0);let A=u+`\n`;A!==o&&(o=A,t.write(ZEe.default.eraseLines(r)+A),r=A.split(`\n`).length)};return n.clear=()=>{t.write(ZEe.default.eraseLines(r)),o=\"\",r=0},n.done=()=>{o=\"\",r=0,e||($Ee.default.show(),a=!1)},n};CB.default={create:Iyt}});var rCe=_((YYt,wyt)=>{wyt.exports=[{name:\"AppVeyor\",constant:\"APPVEYOR\",env:\"APPVEYOR\",pr:\"APPVEYOR_PULL_REQUEST_NUMBER\"},{name:\"Azure Pipelines\",constant:\"AZURE_PIPELINES\",env:\"SYSTEM_TEAMFOUNDATIONCOLLECTIONURI\",pr:\"SYSTEM_PULLREQUEST_PULLREQUESTID\"},{name:\"Bamboo\",constant:\"BAMBOO\",env:\"bamboo_planKey\"},{name:\"Bitbucket Pipelines\",constant:\"BITBUCKET\",env:\"BITBUCKET_COMMIT\",pr:\"BITBUCKET_PR_ID\"},{name:\"Bitrise\",constant:\"BITRISE\",env:\"BITRISE_IO\",pr:\"BITRISE_PULL_REQUEST\"},{name:\"Buddy\",constant:\"BUDDY\",env:\"BUDDY_WORKSPACE_ID\",pr:\"BUDDY_EXECUTION_PULL_REQUEST_ID\"},{name:\"Buildkite\",constant:\"BUILDKITE\",env:\"BUILDKITE\",pr:{env:\"BUILDKITE_PULL_REQUEST\",ne:\"false\"}},{name:\"CircleCI\",constant:\"CIRCLE\",env:\"CIRCLECI\",pr:\"CIRCLE_PULL_REQUEST\"},{name:\"Cirrus CI\",constant:\"CIRRUS\",env:\"CIRRUS_CI\",pr:\"CIRRUS_PR\"},{name:\"AWS CodeBuild\",constant:\"CODEBUILD\",env:\"CODEBUILD_BUILD_ARN\"},{name:\"Codeship\",constant:\"CODESHIP\",env:{CI_NAME:\"codeship\"}},{name:\"Drone\",constant:\"DRONE\",env:\"DRONE\",pr:{DRONE_BUILD_EVENT:\"pull_request\"}},{name:\"dsari\",constant:\"DSARI\",env:\"DSARI\"},{name:\"GitLab CI\",constant:\"GITLAB\",env:\"GITLAB_CI\"},{name:\"GoCD\",constant:\"GOCD\",env:\"GO_PIPELINE_LABEL\"},{name:\"Hudson\",constant:\"HUDSON\",env:\"HUDSON_URL\"},{name:\"Jenkins\",constant:\"JENKINS\",env:[\"JENKINS_URL\",\"BUILD_ID\"],pr:{any:[\"ghprbPullId\",\"CHANGE_ID\"]}},{name:\"Magnum CI\",constant:\"MAGNUM\",env:\"MAGNUM\"},{name:\"Netlify CI\",constant:\"NETLIFY\",env:\"NETLIFY_BUILD_BASE\",pr:{env:\"PULL_REQUEST\",ne:\"false\"}},{name:\"Sail CI\",constant:\"SAIL\",env:\"SAILCI\",pr:\"SAIL_PULL_REQUEST_NUMBER\"},{name:\"Semaphore\",constant:\"SEMAPHORE\",env:\"SEMAPHORE\",pr:\"PULL_REQUEST_NUMBER\"},{name:\"Shippable\",constant:\"SHIPPABLE\",env:\"SHIPPABLE\",pr:{IS_PULL_REQUEST:\"true\"}},{name:\"Solano CI\",constant:\"SOLANO\",env:\"TDDIUM\",pr:\"TDDIUM_PR_ID\"},{name:\"Strider CD\",constant:\"STRIDER\",env:\"STRIDER\"},{name:\"TaskCluster\",constant:\"TASKCLUSTER\",env:[\"TASK_ID\",\"RUN_ID\"]},{name:\"TeamCity\",constant:\"TEAMCITY\",env:\"TEAMCITY_VERSION\"},{name:\"Travis CI\",constant:\"TRAVIS\",env:\"TRAVIS\",pr:{env:\"TRAVIS_PULL_REQUEST\",ne:\"false\"}}]});var sCe=_(Cl=>{\"use strict\";var iCe=rCe(),gA=process.env;Object.defineProperty(Cl,\"_vendors\",{value:iCe.map(function(t){return t.constant})});Cl.name=null;Cl.isPR=null;iCe.forEach(function(t){var e=Array.isArray(t.env)?t.env:[t.env],r=e.every(function(o){return nCe(o)});if(Cl[t.constant]=r,r)switch(Cl.name=t.name,typeof t.pr){case\"string\":Cl.isPR=!!gA[t.pr];break;case\"object\":\"env\"in t.pr?Cl.isPR=t.pr.env in gA&&gA[t.pr.env]!==t.pr.ne:\"any\"in t.pr?Cl.isPR=t.pr.any.some(function(o){return!!gA[o]}):Cl.isPR=nCe(t.pr);break;default:Cl.isPR=null}});Cl.isCI=!!(gA.CI||gA.CONTINUOUS_INTEGRATION||gA.BUILD_NUMBER||gA.RUN_ID||Cl.name);function nCe(t){return typeof t==\"string\"?!!gA[t]:Object.keys(t).every(function(e){return gA[e]===t[e]})}});var aCe=_((VYt,oCe)=>{\"use strict\";oCe.exports=sCe().isCI});var cCe=_((zYt,lCe)=>{\"use strict\";var Byt=t=>{let e=new Set;do for(let r of Reflect.ownKeys(t))e.add([t,r]);while((t=Reflect.getPrototypeOf(t))&&t!==Object.prototype);return e};lCe.exports=(t,{include:e,exclude:r}={})=>{let o=a=>{let n=u=>typeof u==\"string\"?a===u:u.test(a);return e?e.some(n):r?!r.some(n):!0};for(let[a,n]of Byt(t.constructor.prototype)){if(n===\"constructor\"||!o(n))continue;let u=Reflect.getOwnPropertyDescriptor(a,n);u&&typeof u.value==\"function\"&&(t[n]=t[n].bind(t))}return t}});var gCe=_(Hn=>{\"use strict\";var vC,BB,CQ,sq;typeof performance==\"object\"&&typeof performance.now==\"function\"?(uCe=performance,Hn.unstable_now=function(){return uCe.now()}):($6=Date,ACe=$6.now(),Hn.unstable_now=function(){return $6.now()-ACe});var uCe,$6,ACe;typeof window>\"u\"||typeof MessageChannel!=\"function\"?(BC=null,eq=null,tq=function(){if(BC!==null)try{var t=Hn.unstable_now();BC(!0,t),BC=null}catch(e){throw setTimeout(tq,0),e}},vC=function(t){BC!==null?setTimeout(vC,0,t):(BC=t,setTimeout(tq,0))},BB=function(t,e){eq=setTimeout(t,e)},CQ=function(){clearTimeout(eq)},Hn.unstable_shouldYield=function(){return!1},sq=Hn.unstable_forceFrameRate=function(){}):(fCe=window.setTimeout,pCe=window.clearTimeout,typeof console<\"u\"&&(hCe=window.cancelAnimationFrame,typeof window.requestAnimationFrame!=\"function\"&&console.error(\"This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills\"),typeof hCe!=\"function\"&&console.error(\"This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills\")),IB=!1,wB=null,mQ=-1,rq=5,nq=0,Hn.unstable_shouldYield=function(){return Hn.unstable_now()>=nq},sq=function(){},Hn.unstable_forceFrameRate=function(t){0>t||125<t?console.error(\"forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported\"):rq=0<t?Math.floor(1e3/t):5},iq=new MessageChannel,yQ=iq.port2,iq.port1.onmessage=function(){if(wB!==null){var t=Hn.unstable_now();nq=t+rq;try{wB(!0,t)?yQ.postMessage(null):(IB=!1,wB=null)}catch(e){throw yQ.postMessage(null),e}}else IB=!1},vC=function(t){wB=t,IB||(IB=!0,yQ.postMessage(null))},BB=function(t,e){mQ=fCe(function(){t(Hn.unstable_now())},e)},CQ=function(){pCe(mQ),mQ=-1});var BC,eq,tq,fCe,pCe,hCe,IB,wB,mQ,rq,nq,iq,yQ;function oq(t,e){var r=t.length;t.push(e);e:for(;;){var o=r-1>>>1,a=t[o];if(a!==void 0&&0<EQ(a,e))t[o]=e,t[r]=a,r=o;else break e}}function ou(t){return t=t[0],t===void 0?null:t}function IQ(t){var e=t[0];if(e!==void 0){var r=t.pop();if(r!==e){t[0]=r;e:for(var o=0,a=t.length;o<a;){var n=2*(o+1)-1,u=t[n],A=n+1,p=t[A];if(u!==void 0&&0>EQ(u,r))p!==void 0&&0>EQ(p,u)?(t[o]=p,t[A]=r,o=A):(t[o]=u,t[n]=r,o=n);else if(p!==void 0&&0>EQ(p,r))t[o]=p,t[A]=r,o=A;else break e}}return e}return null}function EQ(t,e){var r=t.sortIndex-e.sortIndex;return r!==0?r:t.id-e.id}var dA=[],Uh=[],vyt=1,oc=null,bo=3,wQ=!1,nd=!1,vB=!1;function aq(t){for(var e=ou(Uh);e!==null;){if(e.callback===null)IQ(Uh);else if(e.startTime<=t)IQ(Uh),e.sortIndex=e.expirationTime,oq(dA,e);else break;e=ou(Uh)}}function lq(t){if(vB=!1,aq(t),!nd)if(ou(dA)!==null)nd=!0,vC(cq);else{var e=ou(Uh);e!==null&&BB(lq,e.startTime-t)}}function cq(t,e){nd=!1,vB&&(vB=!1,CQ()),wQ=!0;var r=bo;try{for(aq(e),oc=ou(dA);oc!==null&&(!(oc.expirationTime>e)||t&&!Hn.unstable_shouldYield());){var o=oc.callback;if(typeof o==\"function\"){oc.callback=null,bo=oc.priorityLevel;var a=o(oc.expirationTime<=e);e=Hn.unstable_now(),typeof a==\"function\"?oc.callback=a:oc===ou(dA)&&IQ(dA),aq(e)}else IQ(dA);oc=ou(dA)}if(oc!==null)var n=!0;else{var u=ou(Uh);u!==null&&BB(lq,u.startTime-e),n=!1}return n}finally{oc=null,bo=r,wQ=!1}}var Dyt=sq;Hn.unstable_IdlePriority=5;Hn.unstable_ImmediatePriority=1;Hn.unstable_LowPriority=4;Hn.unstable_NormalPriority=3;Hn.unstable_Profiling=null;Hn.unstable_UserBlockingPriority=2;Hn.unstable_cancelCallback=function(t){t.callback=null};Hn.unstable_continueExecution=function(){nd||wQ||(nd=!0,vC(cq))};Hn.unstable_getCurrentPriorityLevel=function(){return bo};Hn.unstable_getFirstCallbackNode=function(){return ou(dA)};Hn.unstable_next=function(t){switch(bo){case 1:case 2:case 3:var e=3;break;default:e=bo}var r=bo;bo=e;try{return t()}finally{bo=r}};Hn.unstable_pauseExecution=function(){};Hn.unstable_requestPaint=Dyt;Hn.unstable_runWithPriority=function(t,e){switch(t){case 1:case 2:case 3:case 4:case 5:break;default:t=3}var r=bo;bo=t;try{return e()}finally{bo=r}};Hn.unstable_scheduleCallback=function(t,e,r){var o=Hn.unstable_now();switch(typeof r==\"object\"&&r!==null?(r=r.delay,r=typeof r==\"number\"&&0<r?o+r:o):r=o,t){case 1:var a=-1;break;case 2:a=250;break;case 5:a=1073741823;break;case 4:a=1e4;break;default:a=5e3}return a=r+a,t={id:vyt++,callback:e,priorityLevel:t,startTime:r,expirationTime:a,sortIndex:-1},r>o?(t.sortIndex=r,oq(Uh,t),ou(dA)===null&&t===ou(Uh)&&(vB?CQ():vB=!0,BB(lq,r-o))):(t.sortIndex=a,oq(dA,t),nd||wQ||(nd=!0,vC(cq))),t};Hn.unstable_wrapCallback=function(t){var e=bo;return function(){var r=bo;bo=e;try{return t.apply(this,arguments)}finally{bo=r}}}});var uq=_((XYt,dCe)=>{\"use strict\";dCe.exports=gCe()});var mCe=_((ZYt,DB)=>{DB.exports=function(e){var r={},o=U6(),a=ln(),n=uq();function u(v){for(var P=\"https://reactjs.org/docs/error-decoder.html?invariant=\"+v,Q=1;Q<arguments.length;Q++)P+=\"&args[]=\"+encodeURIComponent(arguments[Q]);return\"Minified React error #\"+v+\"; visit \"+P+\" for the full message or use the non-minified dev environment for full errors and additional helpful warnings.\"}var A=a.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,p=60103,h=60106,E=60107,w=60108,D=60114,b=60109,C=60110,T=60112,N=60113,U=60120,z=60115,te=60116,le=60121,ce=60129,ue=60130,Ie=60131;if(typeof Symbol==\"function\"&&Symbol.for){var he=Symbol.for;p=he(\"react.element\"),h=he(\"react.portal\"),E=he(\"react.fragment\"),w=he(\"react.strict_mode\"),D=he(\"react.profiler\"),b=he(\"react.provider\"),C=he(\"react.context\"),T=he(\"react.forward_ref\"),N=he(\"react.suspense\"),U=he(\"react.suspense_list\"),z=he(\"react.memo\"),te=he(\"react.lazy\"),le=he(\"react.block\"),he(\"react.scope\"),ce=he(\"react.debug_trace_mode\"),ue=he(\"react.offscreen\"),Ie=he(\"react.legacy_hidden\")}var De=typeof Symbol==\"function\"&&Symbol.iterator;function Ee(v){return v===null||typeof v!=\"object\"?null:(v=De&&v[De]||v[\"@@iterator\"],typeof v==\"function\"?v:null)}function g(v){if(v==null)return null;if(typeof v==\"function\")return v.displayName||v.name||null;if(typeof v==\"string\")return v;switch(v){case E:return\"Fragment\";case h:return\"Portal\";case D:return\"Profiler\";case w:return\"StrictMode\";case N:return\"Suspense\";case U:return\"SuspenseList\"}if(typeof v==\"object\")switch(v.$$typeof){case C:return(v.displayName||\"Context\")+\".Consumer\";case b:return(v._context.displayName||\"Context\")+\".Provider\";case T:var P=v.render;return P=P.displayName||P.name||\"\",v.displayName||(P!==\"\"?\"ForwardRef(\"+P+\")\":\"ForwardRef\");case z:return g(v.type);case le:return g(v._render);case te:P=v._payload,v=v._init;try{return g(v(P))}catch{}}return null}function me(v){var P=v,Q=v;if(v.alternate)for(;P.return;)P=P.return;else{v=P;do P=v,P.flags&1026&&(Q=P.return),v=P.return;while(v)}return P.tag===3?Q:null}function Ce(v){if(me(v)!==v)throw Error(u(188))}function fe(v){var P=v.alternate;if(!P){if(P=me(v),P===null)throw Error(u(188));return P!==v?null:v}for(var Q=v,H=P;;){var Y=Q.return;if(Y===null)break;var ne=Y.alternate;if(ne===null){if(H=Y.return,H!==null){Q=H;continue}break}if(Y.child===ne.child){for(ne=Y.child;ne;){if(ne===Q)return Ce(Y),v;if(ne===H)return Ce(Y),P;ne=ne.sibling}throw Error(u(188))}if(Q.return!==H.return)Q=Y,H=ne;else{for(var Be=!1,Ue=Y.child;Ue;){if(Ue===Q){Be=!0,Q=Y,H=ne;break}if(Ue===H){Be=!0,H=Y,Q=ne;break}Ue=Ue.sibling}if(!Be){for(Ue=ne.child;Ue;){if(Ue===Q){Be=!0,Q=ne,H=Y;break}if(Ue===H){Be=!0,H=ne,Q=Y;break}Ue=Ue.sibling}if(!Be)throw Error(u(189))}}if(Q.alternate!==H)throw Error(u(190))}if(Q.tag!==3)throw Error(u(188));return Q.stateNode.current===Q?v:P}function ie(v){if(v=fe(v),!v)return null;for(var P=v;;){if(P.tag===5||P.tag===6)return P;if(P.child)P.child.return=P,P=P.child;else{if(P===v)break;for(;!P.sibling;){if(!P.return||P.return===v)return null;P=P.return}P.sibling.return=P.return,P=P.sibling}}return null}function Z(v){if(v=fe(v),!v)return null;for(var P=v;;){if(P.tag===5||P.tag===6)return P;if(P.child&&P.tag!==4)P.child.return=P,P=P.child;else{if(P===v)break;for(;!P.sibling;){if(!P.return||P.return===v)return null;P=P.return}P.sibling.return=P.return,P=P.sibling}}return null}function Pe(v,P){for(var Q=v.alternate;P!==null;){if(P===v||P===Q)return!0;P=P.return}return!1}var Re=e.getPublicInstance,ht=e.getRootHostContext,q=e.getChildHostContext,nt=e.prepareForCommit,Le=e.resetAfterCommit,Te=e.createInstance,ke=e.appendInitialChild,Ve=e.finalizeInitialChildren,xe=e.prepareUpdate,tt=e.shouldSetTextContent,He=e.createTextInstance,x=e.scheduleTimeout,I=e.cancelTimeout,S=e.noTimeout,y=e.isPrimaryRenderer,R=e.supportsMutation,J=e.supportsPersistence,X=e.supportsHydration,$=e.getInstanceFromNode,se=e.makeOpaqueHydratingObject,be=e.makeClientId,Fe=e.beforeActiveInstanceBlur,lt=e.afterActiveInstanceBlur,Et=e.preparePortalMount,qt=e.supportsTestSelectors,nr=e.findFiberRoot,St=e.getBoundingRect,cn=e.getTextContent,Pr=e.isHiddenSubtree,yr=e.matchAccessibilityRole,Rr=e.setFocusIfFocusable,Xr=e.setupIntersectionObserver,$n=e.appendChild,Xs=e.appendChildToContainer,Hi=e.commitTextUpdate,Qs=e.commitMount,Zs=e.commitUpdate,bi=e.insertBefore,Fs=e.insertInContainerBefore,$s=e.removeChild,SA=e.removeChildFromContainer,gu=e.resetTextContent,op=e.hideInstance,ap=e.hideTextInstance,Rs=e.unhideInstance,Nn=e.unhideTextInstance,hs=e.clearContainer,Ts=e.cloneInstance,pc=e.createContainerChildSet,hc=e.appendChildToContainerChildSet,gc=e.finalizeContainerChildren,xA=e.replaceContainerChildren,bA=e.cloneHiddenInstance,Ro=e.cloneHiddenTextInstance,To=e.canHydrateInstance,kA=e.canHydrateTextInstance,pr=e.isSuspenseInstancePending,Me=e.isSuspenseInstanceFallback,ia=e.getNextHydratableSibling,dc=e.getFirstHydratableChild,Er=e.hydrateInstance,du=e.hydrateTextInstance,QA=e.getNextHydratableInstanceAfterSuspenseInstance,FA=e.commitHydratedContainer,mc=e.commitHydratedSuspenseInstance,yc;function Il(v){if(yc===void 0)try{throw Error()}catch(Q){var P=Q.stack.trim().match(/\\n( *(at )?)/);yc=P&&P[1]||\"\"}return`\n`+yc+v}var we=!1;function Tt(v,P){if(!v||we)return\"\";we=!0;var Q=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(P)if(P=function(){throw Error()},Object.defineProperty(P.prototype,\"props\",{set:function(){throw Error()}}),typeof Reflect==\"object\"&&Reflect.construct){try{Reflect.construct(P,[])}catch(ft){var H=ft}Reflect.construct(v,[],P)}else{try{P.call()}catch(ft){H=ft}v.call(P.prototype)}else{try{throw Error()}catch(ft){H=ft}v()}}catch(ft){if(ft&&H&&typeof ft.stack==\"string\"){for(var Y=ft.stack.split(`\n`),ne=H.stack.split(`\n`),Be=Y.length-1,Ue=ne.length-1;1<=Be&&0<=Ue&&Y[Be]!==ne[Ue];)Ue--;for(;1<=Be&&0<=Ue;Be--,Ue--)if(Y[Be]!==ne[Ue]){if(Be!==1||Ue!==1)do if(Be--,Ue--,0>Ue||Y[Be]!==ne[Ue])return`\n`+Y[Be].replace(\" at new \",\" at \");while(1<=Be&&0<=Ue);break}}}finally{we=!1,Error.prepareStackTrace=Q}return(v=v?v.displayName||v.name:\"\")?Il(v):\"\"}var wl=[],Bi=-1;function Ls(v){return{current:v}}function Ft(v){0>Bi||(v.current=wl[Bi],wl[Bi]=null,Bi--)}function Bn(v,P){Bi++,wl[Bi]=v.current,v.current=P}var Lo={},ki=Ls(Lo),vi=Ls(!1),sa=Lo;function un(v,P){var Q=v.type.contextTypes;if(!Q)return Lo;var H=v.stateNode;if(H&&H.__reactInternalMemoizedUnmaskedChildContext===P)return H.__reactInternalMemoizedMaskedChildContext;var Y={},ne;for(ne in Q)Y[ne]=P[ne];return H&&(v=v.stateNode,v.__reactInternalMemoizedUnmaskedChildContext=P,v.__reactInternalMemoizedMaskedChildContext=Y),Y}function qn(v){return v=v.childContextTypes,v!=null}function Ec(){Ft(vi),Ft(ki)}function lp(v,P,Q){if(ki.current!==Lo)throw Error(u(168));Bn(ki,P),Bn(vi,Q)}function oa(v,P,Q){var H=v.stateNode;if(v=P.childContextTypes,typeof H.getChildContext!=\"function\")return Q;H=H.getChildContext();for(var Y in H)if(!(Y in v))throw Error(u(108,g(P)||\"Unknown\",Y));return o({},Q,H)}function aa(v){return v=(v=v.stateNode)&&v.__reactInternalMemoizedMergedChildContext||Lo,sa=ki.current,Bn(ki,v),Bn(vi,vi.current),!0}function la(v,P,Q){var H=v.stateNode;if(!H)throw Error(u(169));Q?(v=oa(v,P,sa),H.__reactInternalMemoizedMergedChildContext=v,Ft(vi),Ft(ki),Bn(ki,v)):Ft(vi),Bn(vi,Q)}var Ze=null,ca=null,mu=n.unstable_now;mu();var Bl=0,dn=8;function No(v){if(1&v)return dn=15,1;if(2&v)return dn=14,2;if(4&v)return dn=13,4;var P=24&v;return P!==0?(dn=12,P):v&32?(dn=11,32):(P=192&v,P!==0?(dn=10,P):v&256?(dn=9,256):(P=3584&v,P!==0?(dn=8,P):v&4096?(dn=7,4096):(P=4186112&v,P!==0?(dn=6,P):(P=62914560&v,P!==0?(dn=5,P):v&67108864?(dn=4,67108864):v&134217728?(dn=3,134217728):(P=805306368&v,P!==0?(dn=2,P):1073741824&v?(dn=1,1073741824):(dn=8,v))))))}function RA(v){switch(v){case 99:return 15;case 98:return 10;case 97:case 96:return 8;case 95:return 2;default:return 0}}function TA(v){switch(v){case 15:case 14:return 99;case 13:case 12:case 11:case 10:return 98;case 9:case 8:case 7:case 6:case 4:case 5:return 97;case 3:case 2:case 1:return 95;case 0:return 90;default:throw Error(u(358,v))}}function Oo(v,P){var Q=v.pendingLanes;if(Q===0)return dn=0;var H=0,Y=0,ne=v.expiredLanes,Be=v.suspendedLanes,Ue=v.pingedLanes;if(ne!==0)H=ne,Y=dn=15;else if(ne=Q&134217727,ne!==0){var ft=ne&~Be;ft!==0?(H=No(ft),Y=dn):(Ue&=ne,Ue!==0&&(H=No(Ue),Y=dn))}else ne=Q&~Be,ne!==0?(H=No(ne),Y=dn):Ue!==0&&(H=No(Ue),Y=dn);if(H===0)return 0;if(H=31-qi(H),H=Q&((0>H?0:1<<H)<<1)-1,P!==0&&P!==H&&!(P&Be)){if(No(P),Y<=dn)return P;dn=Y}if(P=v.entangledLanes,P!==0)for(v=v.entanglements,P&=H;0<P;)Q=31-qi(P),Y=1<<Q,H|=v[Q],P&=~Y;return H}function qa(v){return v=v.pendingLanes&-1073741825,v!==0?v:v&1073741824?1073741824:0}function Ot(v,P){switch(v){case 15:return 1;case 14:return 2;case 12:return v=vn(24&~P),v===0?Ot(10,P):v;case 10:return v=vn(192&~P),v===0?Ot(8,P):v;case 8:return v=vn(3584&~P),v===0&&(v=vn(4186112&~P),v===0&&(v=512)),v;case 2:return P=vn(805306368&~P),P===0&&(P=268435456),P}throw Error(u(358,v))}function vn(v){return v&-v}function Mo(v){for(var P=[],Q=0;31>Q;Q++)P.push(v);return P}function ua(v,P,Q){v.pendingLanes|=P;var H=P-1;v.suspendedLanes&=H,v.pingedLanes&=H,v=v.eventTimes,P=31-qi(P),v[P]=Q}var qi=Math.clz32?Math.clz32:Dl,vl=Math.log,Cc=Math.LN2;function Dl(v){return v===0?32:31-(vl(v)/Cc|0)|0}var Aa=n.unstable_runWithPriority,Di=n.unstable_scheduleCallback,rs=n.unstable_cancelCallback,ja=n.unstable_shouldYield,yu=n.unstable_requestPaint,Pl=n.unstable_now,pi=n.unstable_getCurrentPriorityLevel,Dn=n.unstable_ImmediatePriority,Sl=n.unstable_UserBlockingPriority,ze=n.unstable_NormalPriority,it=n.unstable_LowPriority,vt=n.unstable_IdlePriority,ar={},ee=yu!==void 0?yu:function(){},ye=null,Ne=null,gt=!1,mt=Pl(),Dt=1e4>mt?Pl:function(){return Pl()-mt};function er(){switch(pi()){case Dn:return 99;case Sl:return 98;case ze:return 97;case it:return 96;case vt:return 95;default:throw Error(u(332))}}function sn(v){switch(v){case 99:return Dn;case 98:return Sl;case 97:return ze;case 96:return it;case 95:return vt;default:throw Error(u(332))}}function ei(v,P){return v=sn(v),Aa(v,P)}function Qi(v,P,Q){return v=sn(v),Di(v,P,Q)}function Pn(){if(Ne!==null){var v=Ne;Ne=null,rs(v)}fa()}function fa(){if(!gt&&ye!==null){gt=!0;var v=0;try{var P=ye;ei(99,function(){for(;v<P.length;v++){var Q=P[v];do Q=Q(!0);while(Q!==null)}}),ye=null}catch(Q){throw ye!==null&&(ye=ye.slice(v+1)),Di(Dn,Pn),Q}finally{gt=!1}}}var wd=A.ReactCurrentBatchConfig;function BI(v,P){return v===P&&(v!==0||1/v===1/P)||v!==v&&P!==P}var eo=typeof Object.is==\"function\"?Object.is:BI,Bd=Object.prototype.hasOwnProperty;function cp(v,P){if(eo(v,P))return!0;if(typeof v!=\"object\"||v===null||typeof P!=\"object\"||P===null)return!1;var Q=Object.keys(v),H=Object.keys(P);if(Q.length!==H.length)return!1;for(H=0;H<Q.length;H++)if(!Bd.call(P,Q[H])||!eo(v[Q[H]],P[Q[H]]))return!1;return!0}function vI(v){switch(v.tag){case 5:return Il(v.type);case 16:return Il(\"Lazy\");case 13:return Il(\"Suspense\");case 19:return Il(\"SuspenseList\");case 0:case 2:case 15:return v=Tt(v.type,!1),v;case 11:return v=Tt(v.type.render,!1),v;case 22:return v=Tt(v.type._render,!1),v;case 1:return v=Tt(v.type,!0),v;default:return\"\"}}function to(v,P){if(v&&v.defaultProps){P=o({},P),v=v.defaultProps;for(var Q in v)P[Q]===void 0&&(P[Q]=v[Q]);return P}return P}var up=Ls(null),Ap=null,Ic=null,fp=null;function s0(){fp=Ic=Ap=null}function o0(v,P){v=v.type._context,y?(Bn(up,v._currentValue),v._currentValue=P):(Bn(up,v._currentValue2),v._currentValue2=P)}function a0(v){var P=up.current;Ft(up),v=v.type._context,y?v._currentValue=P:v._currentValue2=P}function vd(v,P){for(;v!==null;){var Q=v.alternate;if((v.childLanes&P)===P){if(Q===null||(Q.childLanes&P)===P)break;Q.childLanes|=P}else v.childLanes|=P,Q!==null&&(Q.childLanes|=P);v=v.return}}function Eu(v,P){Ap=v,fp=Ic=null,v=v.dependencies,v!==null&&v.firstContext!==null&&(v.lanes&P&&(Ye=!0),v.firstContext=null)}function ro(v,P){if(fp!==v&&P!==!1&&P!==0)if((typeof P!=\"number\"||P===1073741823)&&(fp=v,P=1073741823),P={context:v,observedBits:P,next:null},Ic===null){if(Ap===null)throw Error(u(308));Ic=P,Ap.dependencies={lanes:0,firstContext:P,responders:null}}else Ic=Ic.next=P;return y?v._currentValue:v._currentValue2}var Ga=!1;function pp(v){v.updateQueue={baseState:v.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null},effects:null}}function l0(v,P){v=v.updateQueue,P.updateQueue===v&&(P.updateQueue={baseState:v.baseState,firstBaseUpdate:v.firstBaseUpdate,lastBaseUpdate:v.lastBaseUpdate,shared:v.shared,effects:v.effects})}function Wa(v,P){return{eventTime:v,lane:P,tag:0,payload:null,callback:null,next:null}}function Ya(v,P){if(v=v.updateQueue,v!==null){v=v.shared;var Q=v.pending;Q===null?P.next=P:(P.next=Q.next,Q.next=P),v.pending=P}}function Dd(v,P){var Q=v.updateQueue,H=v.alternate;if(H!==null&&(H=H.updateQueue,Q===H)){var Y=null,ne=null;if(Q=Q.firstBaseUpdate,Q!==null){do{var Be={eventTime:Q.eventTime,lane:Q.lane,tag:Q.tag,payload:Q.payload,callback:Q.callback,next:null};ne===null?Y=ne=Be:ne=ne.next=Be,Q=Q.next}while(Q!==null);ne===null?Y=ne=P:ne=ne.next=P}else Y=ne=P;Q={baseState:H.baseState,firstBaseUpdate:Y,lastBaseUpdate:ne,shared:H.shared,effects:H.effects},v.updateQueue=Q;return}v=Q.lastBaseUpdate,v===null?Q.firstBaseUpdate=P:v.next=P,Q.lastBaseUpdate=P}function LA(v,P,Q,H){var Y=v.updateQueue;Ga=!1;var ne=Y.firstBaseUpdate,Be=Y.lastBaseUpdate,Ue=Y.shared.pending;if(Ue!==null){Y.shared.pending=null;var ft=Ue,jt=ft.next;ft.next=null,Be===null?ne=jt:Be.next=jt,Be=ft;var wr=v.alternate;if(wr!==null){wr=wr.updateQueue;var Tr=wr.lastBaseUpdate;Tr!==Be&&(Tr===null?wr.firstBaseUpdate=jt:Tr.next=jt,wr.lastBaseUpdate=ft)}}if(ne!==null){Tr=Y.baseState,Be=0,wr=jt=ft=null;do{Ue=ne.lane;var Xt=ne.eventTime;if((H&Ue)===Ue){wr!==null&&(wr=wr.next={eventTime:Xt,lane:0,tag:ne.tag,payload:ne.payload,callback:ne.callback,next:null});e:{var jn=v,li=ne;switch(Ue=P,Xt=Q,li.tag){case 1:if(jn=li.payload,typeof jn==\"function\"){Tr=jn.call(Xt,Tr,Ue);break e}Tr=jn;break e;case 3:jn.flags=jn.flags&-4097|64;case 0:if(jn=li.payload,Ue=typeof jn==\"function\"?jn.call(Xt,Tr,Ue):jn,Ue==null)break e;Tr=o({},Tr,Ue);break e;case 2:Ga=!0}}ne.callback!==null&&(v.flags|=32,Ue=Y.effects,Ue===null?Y.effects=[ne]:Ue.push(ne))}else Xt={eventTime:Xt,lane:Ue,tag:ne.tag,payload:ne.payload,callback:ne.callback,next:null},wr===null?(jt=wr=Xt,ft=Tr):wr=wr.next=Xt,Be|=Ue;if(ne=ne.next,ne===null){if(Ue=Y.shared.pending,Ue===null)break;ne=Ue.next,Ue.next=null,Y.lastBaseUpdate=Ue,Y.shared.pending=null}}while(!0);wr===null&&(ft=Tr),Y.baseState=ft,Y.firstBaseUpdate=jt,Y.lastBaseUpdate=wr,B0|=Be,v.lanes=Be,v.memoizedState=Tr}}function Pd(v,P,Q){if(v=P.effects,P.effects=null,v!==null)for(P=0;P<v.length;P++){var H=v[P],Y=H.callback;if(Y!==null){if(H.callback=null,H=Q,typeof Y!=\"function\")throw Error(u(191,Y));Y.call(H)}}}var Sd=new a.Component().refs;function NA(v,P,Q,H){P=v.memoizedState,Q=Q(H,P),Q=Q==null?P:o({},P,Q),v.memoizedState=Q,v.lanes===0&&(v.updateQueue.baseState=Q)}var OA={isMounted:function(v){return(v=v._reactInternals)?me(v)===v:!1},enqueueSetState:function(v,P,Q){v=v._reactInternals;var H=oo(),Y=ss(v),ne=Wa(H,Y);ne.payload=P,Q!=null&&(ne.callback=Q),Ya(v,ne),Xa(v,Y,H)},enqueueReplaceState:function(v,P,Q){v=v._reactInternals;var H=oo(),Y=ss(v),ne=Wa(H,Y);ne.tag=1,ne.payload=P,Q!=null&&(ne.callback=Q),Ya(v,ne),Xa(v,Y,H)},enqueueForceUpdate:function(v,P){v=v._reactInternals;var Q=oo(),H=ss(v),Y=Wa(Q,H);Y.tag=2,P!=null&&(Y.callback=P),Ya(v,Y),Xa(v,H,Q)}};function W(v,P,Q,H,Y,ne,Be){return v=v.stateNode,typeof v.shouldComponentUpdate==\"function\"?v.shouldComponentUpdate(H,ne,Be):P.prototype&&P.prototype.isPureReactComponent?!cp(Q,H)||!cp(Y,ne):!0}function xt(v,P,Q){var H=!1,Y=Lo,ne=P.contextType;return typeof ne==\"object\"&&ne!==null?ne=ro(ne):(Y=qn(P)?sa:ki.current,H=P.contextTypes,ne=(H=H!=null)?un(v,Y):Lo),P=new P(Q,ne),v.memoizedState=P.state!==null&&P.state!==void 0?P.state:null,P.updater=OA,v.stateNode=P,P._reactInternals=v,H&&(v=v.stateNode,v.__reactInternalMemoizedUnmaskedChildContext=Y,v.__reactInternalMemoizedMaskedChildContext=ne),P}function MA(v,P,Q,H){v=P.state,typeof P.componentWillReceiveProps==\"function\"&&P.componentWillReceiveProps(Q,H),typeof P.UNSAFE_componentWillReceiveProps==\"function\"&&P.UNSAFE_componentWillReceiveProps(Q,H),P.state!==v&&OA.enqueueReplaceState(P,P.state,null)}function no(v,P,Q,H){var Y=v.stateNode;Y.props=Q,Y.state=v.memoizedState,Y.refs=Sd,pp(v);var ne=P.contextType;typeof ne==\"object\"&&ne!==null?Y.context=ro(ne):(ne=qn(P)?sa:ki.current,Y.context=un(v,ne)),LA(v,Q,Y,H),Y.state=v.memoizedState,ne=P.getDerivedStateFromProps,typeof ne==\"function\"&&(NA(v,P,ne,Q),Y.state=v.memoizedState),typeof P.getDerivedStateFromProps==\"function\"||typeof Y.getSnapshotBeforeUpdate==\"function\"||typeof Y.UNSAFE_componentWillMount!=\"function\"&&typeof Y.componentWillMount!=\"function\"||(P=Y.state,typeof Y.componentWillMount==\"function\"&&Y.componentWillMount(),typeof Y.UNSAFE_componentWillMount==\"function\"&&Y.UNSAFE_componentWillMount(),P!==Y.state&&OA.enqueueReplaceState(Y,Y.state,null),LA(v,Q,Y,H),Y.state=v.memoizedState),typeof Y.componentDidMount==\"function\"&&(v.flags|=4)}var Cu=Array.isArray;function dt(v,P,Q){if(v=Q.ref,v!==null&&typeof v!=\"function\"&&typeof v!=\"object\"){if(Q._owner){if(Q=Q._owner,Q){if(Q.tag!==1)throw Error(u(309));var H=Q.stateNode}if(!H)throw Error(u(147,v));var Y=\"\"+v;return P!==null&&P.ref!==null&&typeof P.ref==\"function\"&&P.ref._stringRef===Y?P.ref:(P=function(ne){var Be=H.refs;Be===Sd&&(Be=H.refs={}),ne===null?delete Be[Y]:Be[Y]=ne},P._stringRef=Y,P)}if(typeof v!=\"string\")throw Error(u(284));if(!Q._owner)throw Error(u(290,v))}return v}function wc(v,P){if(v.type!==\"textarea\")throw Error(u(31,Object.prototype.toString.call(P)===\"[object Object]\"?\"object with keys {\"+Object.keys(P).join(\", \")+\"}\":P))}function xd(v){function P($e,je){if(v){var pt=$e.lastEffect;pt!==null?(pt.nextEffect=je,$e.lastEffect=je):$e.firstEffect=$e.lastEffect=je,je.nextEffect=null,je.flags=8}}function Q($e,je){if(!v)return null;for(;je!==null;)P($e,je),je=je.sibling;return null}function H($e,je){for($e=new Map;je!==null;)je.key!==null?$e.set(je.key,je):$e.set(je.index,je),je=je.sibling;return $e}function Y($e,je){return $e=Fc($e,je),$e.index=0,$e.sibling=null,$e}function ne($e,je,pt){return $e.index=pt,v?(pt=$e.alternate,pt!==null?(pt=pt.index,pt<je?($e.flags=2,je):pt):($e.flags=2,je)):je}function Be($e){return v&&$e.alternate===null&&($e.flags=2),$e}function Ue($e,je,pt,Jt){return je===null||je.tag!==6?(je=ZI(pt,$e.mode,Jt),je.return=$e,je):(je=Y(je,pt),je.return=$e,je)}function ft($e,je,pt,Jt){return je!==null&&je.elementType===pt.type?(Jt=Y(je,pt.props),Jt.ref=dt($e,je,pt),Jt.return=$e,Jt):(Jt=k0(pt.type,pt.key,pt.props,null,$e.mode,Jt),Jt.ref=dt($e,je,pt),Jt.return=$e,Jt)}function jt($e,je,pt,Jt){return je===null||je.tag!==4||je.stateNode.containerInfo!==pt.containerInfo||je.stateNode.implementation!==pt.implementation?(je=ao(pt,$e.mode,Jt),je.return=$e,je):(je=Y(je,pt.children||[]),je.return=$e,je)}function wr($e,je,pt,Jt,Br){return je===null||je.tag!==7?(je=Ru(pt,$e.mode,Jt,Br),je.return=$e,je):(je=Y(je,pt),je.return=$e,je)}function Tr($e,je,pt){if(typeof je==\"string\"||typeof je==\"number\")return je=ZI(\"\"+je,$e.mode,pt),je.return=$e,je;if(typeof je==\"object\"&&je!==null){switch(je.$$typeof){case p:return pt=k0(je.type,je.key,je.props,null,$e.mode,pt),pt.ref=dt($e,null,je),pt.return=$e,pt;case h:return je=ao(je,$e.mode,pt),je.return=$e,je}if(Cu(je)||Ee(je))return je=Ru(je,$e.mode,pt,null),je.return=$e,je;wc($e,je)}return null}function Xt($e,je,pt,Jt){var Br=je!==null?je.key:null;if(typeof pt==\"string\"||typeof pt==\"number\")return Br!==null?null:Ue($e,je,\"\"+pt,Jt);if(typeof pt==\"object\"&&pt!==null){switch(pt.$$typeof){case p:return pt.key===Br?pt.type===E?wr($e,je,pt.props.children,Jt,Br):ft($e,je,pt,Jt):null;case h:return pt.key===Br?jt($e,je,pt,Jt):null}if(Cu(pt)||Ee(pt))return Br!==null?null:wr($e,je,pt,Jt,null);wc($e,pt)}return null}function jn($e,je,pt,Jt,Br){if(typeof Jt==\"string\"||typeof Jt==\"number\")return $e=$e.get(pt)||null,Ue(je,$e,\"\"+Jt,Br);if(typeof Jt==\"object\"&&Jt!==null){switch(Jt.$$typeof){case p:return $e=$e.get(Jt.key===null?pt:Jt.key)||null,Jt.type===E?wr(je,$e,Jt.props.children,Br,Jt.key):ft(je,$e,Jt,Br);case h:return $e=$e.get(Jt.key===null?pt:Jt.key)||null,jt(je,$e,Jt,Br)}if(Cu(Jt)||Ee(Jt))return $e=$e.get(pt)||null,wr(je,$e,Jt,Br,null);wc(je,Jt)}return null}function li($e,je,pt,Jt){for(var Br=null,Wn=null,xr=je,Sn=je=0,Tn=null;xr!==null&&Sn<pt.length;Sn++){xr.index>Sn?(Tn=xr,xr=null):Tn=xr.sibling;var Yr=Xt($e,xr,pt[Sn],Jt);if(Yr===null){xr===null&&(xr=Tn);break}v&&xr&&Yr.alternate===null&&P($e,xr),je=ne(Yr,je,Sn),Wn===null?Br=Yr:Wn.sibling=Yr,Wn=Yr,xr=Tn}if(Sn===pt.length)return Q($e,xr),Br;if(xr===null){for(;Sn<pt.length;Sn++)xr=Tr($e,pt[Sn],Jt),xr!==null&&(je=ne(xr,je,Sn),Wn===null?Br=xr:Wn.sibling=xr,Wn=xr);return Br}for(xr=H($e,xr);Sn<pt.length;Sn++)Tn=jn(xr,$e,Sn,pt[Sn],Jt),Tn!==null&&(v&&Tn.alternate!==null&&xr.delete(Tn.key===null?Sn:Tn.key),je=ne(Tn,je,Sn),Wn===null?Br=Tn:Wn.sibling=Tn,Wn=Tn);return v&&xr.forEach(function(ti){return P($e,ti)}),Br}function Ea($e,je,pt,Jt){var Br=Ee(pt);if(typeof Br!=\"function\")throw Error(u(150));if(pt=Br.call(pt),pt==null)throw Error(u(151));for(var Wn=Br=null,xr=je,Sn=je=0,Tn=null,Yr=pt.next();xr!==null&&!Yr.done;Sn++,Yr=pt.next()){xr.index>Sn?(Tn=xr,xr=null):Tn=xr.sibling;var ti=Xt($e,xr,Yr.value,Jt);if(ti===null){xr===null&&(xr=Tn);break}v&&xr&&ti.alternate===null&&P($e,xr),je=ne(ti,je,Sn),Wn===null?Br=ti:Wn.sibling=ti,Wn=ti,xr=Tn}if(Yr.done)return Q($e,xr),Br;if(xr===null){for(;!Yr.done;Sn++,Yr=pt.next())Yr=Tr($e,Yr.value,Jt),Yr!==null&&(je=ne(Yr,je,Sn),Wn===null?Br=Yr:Wn.sibling=Yr,Wn=Yr);return Br}for(xr=H($e,xr);!Yr.done;Sn++,Yr=pt.next())Yr=jn(xr,$e,Sn,Yr.value,Jt),Yr!==null&&(v&&Yr.alternate!==null&&xr.delete(Yr.key===null?Sn:Yr.key),je=ne(Yr,je,Sn),Wn===null?Br=Yr:Wn.sibling=Yr,Wn=Yr);return v&&xr.forEach(function(Rc){return P($e,Rc)}),Br}return function($e,je,pt,Jt){var Br=typeof pt==\"object\"&&pt!==null&&pt.type===E&&pt.key===null;Br&&(pt=pt.props.children);var Wn=typeof pt==\"object\"&&pt!==null;if(Wn)switch(pt.$$typeof){case p:e:{for(Wn=pt.key,Br=je;Br!==null;){if(Br.key===Wn){switch(Br.tag){case 7:if(pt.type===E){Q($e,Br.sibling),je=Y(Br,pt.props.children),je.return=$e,$e=je;break e}break;default:if(Br.elementType===pt.type){Q($e,Br.sibling),je=Y(Br,pt.props),je.ref=dt($e,Br,pt),je.return=$e,$e=je;break e}}Q($e,Br);break}else P($e,Br);Br=Br.sibling}pt.type===E?(je=Ru(pt.props.children,$e.mode,Jt,pt.key),je.return=$e,$e=je):(Jt=k0(pt.type,pt.key,pt.props,null,$e.mode,Jt),Jt.ref=dt($e,je,pt),Jt.return=$e,$e=Jt)}return Be($e);case h:e:{for(Br=pt.key;je!==null;){if(je.key===Br)if(je.tag===4&&je.stateNode.containerInfo===pt.containerInfo&&je.stateNode.implementation===pt.implementation){Q($e,je.sibling),je=Y(je,pt.children||[]),je.return=$e,$e=je;break e}else{Q($e,je);break}else P($e,je);je=je.sibling}je=ao(pt,$e.mode,Jt),je.return=$e,$e=je}return Be($e)}if(typeof pt==\"string\"||typeof pt==\"number\")return pt=\"\"+pt,je!==null&&je.tag===6?(Q($e,je.sibling),je=Y(je,pt),je.return=$e,$e=je):(Q($e,je),je=ZI(pt,$e.mode,Jt),je.return=$e,$e=je),Be($e);if(Cu(pt))return li($e,je,pt,Jt);if(Ee(pt))return Ea($e,je,pt,Jt);if(Wn&&wc($e,pt),typeof pt>\"u\"&&!Br)switch($e.tag){case 1:case 22:case 0:case 11:case 15:throw Error(u(152,g($e.type)||\"Component\"))}return Q($e,je)}}var c0=xd(!0),DI=xd(!1),hp={},cr=Ls(hp),Ni=Ls(hp),Iu=Ls(hp);function pa(v){if(v===hp)throw Error(u(174));return v}function u0(v,P){Bn(Iu,P),Bn(Ni,v),Bn(cr,hp),v=ht(P),Ft(cr),Bn(cr,v)}function Bc(){Ft(cr),Ft(Ni),Ft(Iu)}function wu(v){var P=pa(Iu.current),Q=pa(cr.current);P=q(Q,v.type,P),Q!==P&&(Bn(Ni,v),Bn(cr,P))}function wt(v){Ni.current===v&&(Ft(cr),Ft(Ni))}var oi=Ls(0);function UA(v){for(var P=v;P!==null;){if(P.tag===13){var Q=P.memoizedState;if(Q!==null&&(Q=Q.dehydrated,Q===null||pr(Q)||Me(Q)))return P}else if(P.tag===19&&P.memoizedProps.revealOrder!==void 0){if(P.flags&64)return P}else if(P.child!==null){P.child.return=P,P=P.child;continue}if(P===v)break;for(;P.sibling===null;){if(P.return===null||P.return===v)return null;P=P.return}P.sibling.return=P.return,P=P.sibling}return null}var ha=null,Uo=null,ga=!1;function A0(v,P){var Q=ya(5,null,null,0);Q.elementType=\"DELETED\",Q.type=\"DELETED\",Q.stateNode=P,Q.return=v,Q.flags=8,v.lastEffect!==null?(v.lastEffect.nextEffect=Q,v.lastEffect=Q):v.firstEffect=v.lastEffect=Q}function gp(v,P){switch(v.tag){case 5:return P=To(P,v.type,v.pendingProps),P!==null?(v.stateNode=P,!0):!1;case 6:return P=kA(P,v.pendingProps),P!==null?(v.stateNode=P,!0):!1;case 13:return!1;default:return!1}}function f0(v){if(ga){var P=Uo;if(P){var Q=P;if(!gp(v,P)){if(P=ia(Q),!P||!gp(v,P)){v.flags=v.flags&-1025|2,ga=!1,ha=v;return}A0(ha,Q)}ha=v,Uo=dc(P)}else v.flags=v.flags&-1025|2,ga=!1,ha=v}}function bd(v){for(v=v.return;v!==null&&v.tag!==5&&v.tag!==3&&v.tag!==13;)v=v.return;ha=v}function _A(v){if(!X||v!==ha)return!1;if(!ga)return bd(v),ga=!0,!1;var P=v.type;if(v.tag!==5||P!==\"head\"&&P!==\"body\"&&!tt(P,v.memoizedProps))for(P=Uo;P;)A0(v,P),P=ia(P);if(bd(v),v.tag===13){if(!X)throw Error(u(316));if(v=v.memoizedState,v=v!==null?v.dehydrated:null,!v)throw Error(u(317));Uo=QA(v)}else Uo=ha?ia(v.stateNode):null;return!0}function p0(){X&&(Uo=ha=null,ga=!1)}var vc=[];function Dc(){for(var v=0;v<vc.length;v++){var P=vc[v];y?P._workInProgressVersionPrimary=null:P._workInProgressVersionSecondary=null}vc.length=0}var Bu=A.ReactCurrentDispatcher,gs=A.ReactCurrentBatchConfig,Pc=0,On=null,ji=null,Ci=null,HA=!1,vu=!1;function An(){throw Error(u(321))}function h0(v,P){if(P===null)return!1;for(var Q=0;Q<P.length&&Q<v.length;Q++)if(!eo(v[Q],P[Q]))return!1;return!0}function g0(v,P,Q,H,Y,ne){if(Pc=ne,On=P,P.memoizedState=null,P.updateQueue=null,P.lanes=0,Bu.current=v===null||v.memoizedState===null?L:V,v=Q(H,Y),vu){ne=0;do{if(vu=!1,!(25>ne))throw Error(u(301));ne+=1,Ci=ji=null,P.updateQueue=null,Bu.current=re,v=Q(H,Y)}while(vu)}if(Bu.current=bt,P=ji!==null&&ji.next!==null,Pc=0,Ci=ji=On=null,HA=!1,P)throw Error(u(300));return v}function Gi(){var v={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};return Ci===null?On.memoizedState=Ci=v:Ci=Ci.next=v,Ci}function Ka(){if(ji===null){var v=On.alternate;v=v!==null?v.memoizedState:null}else v=ji.next;var P=Ci===null?On.memoizedState:Ci.next;if(P!==null)Ci=P,ji=v;else{if(v===null)throw Error(u(310));ji=v,v={memoizedState:ji.memoizedState,baseState:ji.baseState,baseQueue:ji.baseQueue,queue:ji.queue,next:null},Ci===null?On.memoizedState=Ci=v:Ci=Ci.next=v}return Ci}function io(v,P){return typeof P==\"function\"?P(v):P}function Du(v){var P=Ka(),Q=P.queue;if(Q===null)throw Error(u(311));Q.lastRenderedReducer=v;var H=ji,Y=H.baseQueue,ne=Q.pending;if(ne!==null){if(Y!==null){var Be=Y.next;Y.next=ne.next,ne.next=Be}H.baseQueue=Y=ne,Q.pending=null}if(Y!==null){Y=Y.next,H=H.baseState;var Ue=Be=ne=null,ft=Y;do{var jt=ft.lane;if((Pc&jt)===jt)Ue!==null&&(Ue=Ue.next={lane:0,action:ft.action,eagerReducer:ft.eagerReducer,eagerState:ft.eagerState,next:null}),H=ft.eagerReducer===v?ft.eagerState:v(H,ft.action);else{var wr={lane:jt,action:ft.action,eagerReducer:ft.eagerReducer,eagerState:ft.eagerState,next:null};Ue===null?(Be=Ue=wr,ne=H):Ue=Ue.next=wr,On.lanes|=jt,B0|=jt}ft=ft.next}while(ft!==null&&ft!==Y);Ue===null?ne=H:Ue.next=Be,eo(H,P.memoizedState)||(Ye=!0),P.memoizedState=H,P.baseState=ne,P.baseQueue=Ue,Q.lastRenderedState=H}return[P.memoizedState,Q.dispatch]}function Pu(v){var P=Ka(),Q=P.queue;if(Q===null)throw Error(u(311));Q.lastRenderedReducer=v;var H=Q.dispatch,Y=Q.pending,ne=P.memoizedState;if(Y!==null){Q.pending=null;var Be=Y=Y.next;do ne=v(ne,Be.action),Be=Be.next;while(Be!==Y);eo(ne,P.memoizedState)||(Ye=!0),P.memoizedState=ne,P.baseQueue===null&&(P.baseState=ne),Q.lastRenderedState=ne}return[ne,H]}function Va(v,P,Q){var H=P._getVersion;H=H(P._source);var Y=y?P._workInProgressVersionPrimary:P._workInProgressVersionSecondary;if(Y!==null?v=Y===H:(v=v.mutableReadLanes,(v=(Pc&v)===v)&&(y?P._workInProgressVersionPrimary=H:P._workInProgressVersionSecondary=H,vc.push(P))),v)return Q(P._source);throw vc.push(P),Error(u(350))}function fn(v,P,Q,H){var Y=Os;if(Y===null)throw Error(u(349));var ne=P._getVersion,Be=ne(P._source),Ue=Bu.current,ft=Ue.useState(function(){return Va(Y,P,Q)}),jt=ft[1],wr=ft[0];ft=Ci;var Tr=v.memoizedState,Xt=Tr.refs,jn=Xt.getSnapshot,li=Tr.source;Tr=Tr.subscribe;var Ea=On;return v.memoizedState={refs:Xt,source:P,subscribe:H},Ue.useEffect(function(){Xt.getSnapshot=Q,Xt.setSnapshot=jt;var $e=ne(P._source);if(!eo(Be,$e)){$e=Q(P._source),eo(wr,$e)||(jt($e),$e=ss(Ea),Y.mutableReadLanes|=$e&Y.pendingLanes),$e=Y.mutableReadLanes,Y.entangledLanes|=$e;for(var je=Y.entanglements,pt=$e;0<pt;){var Jt=31-qi(pt),Br=1<<Jt;je[Jt]|=$e,pt&=~Br}}},[Q,P,H]),Ue.useEffect(function(){return H(P._source,function(){var $e=Xt.getSnapshot,je=Xt.setSnapshot;try{je($e(P._source));var pt=ss(Ea);Y.mutableReadLanes|=pt&Y.pendingLanes}catch(Jt){je(function(){throw Jt})}})},[P,H]),eo(jn,Q)&&eo(li,P)&&eo(Tr,H)||(v={pending:null,dispatch:null,lastRenderedReducer:io,lastRenderedState:wr},v.dispatch=jt=Ep.bind(null,On,v),ft.queue=v,ft.baseQueue=null,wr=Va(Y,P,Q),ft.memoizedState=ft.baseState=wr),wr}function so(v,P,Q){var H=Ka();return fn(H,v,P,Q)}function Sc(v){var P=Gi();return typeof v==\"function\"&&(v=v()),P.memoizedState=P.baseState=v,v=P.queue={pending:null,dispatch:null,lastRenderedReducer:io,lastRenderedState:v},v=v.dispatch=Ep.bind(null,On,v),[P.memoizedState,v]}function _o(v,P,Q,H){return v={tag:v,create:P,destroy:Q,deps:H,next:null},P=On.updateQueue,P===null?(P={lastEffect:null},On.updateQueue=P,P.lastEffect=v.next=v):(Q=P.lastEffect,Q===null?P.lastEffect=v.next=v:(H=Q.next,Q.next=v,v.next=H,P.lastEffect=v)),v}function ds(v){var P=Gi();return v={current:v},P.memoizedState=v}function dp(){return Ka().memoizedState}function qA(v,P,Q,H){var Y=Gi();On.flags|=v,Y.memoizedState=_o(1|P,Q,void 0,H===void 0?null:H)}function Su(v,P,Q,H){var Y=Ka();H=H===void 0?null:H;var ne=void 0;if(ji!==null){var Be=ji.memoizedState;if(ne=Be.destroy,H!==null&&h0(H,Be.deps)){_o(P,Q,ne,H);return}}On.flags|=v,Y.memoizedState=_o(1|P,Q,ne,H)}function Ns(v,P){return qA(516,4,v,P)}function Kr(v,P){return Su(516,4,v,P)}function mp(v,P){return Su(4,2,v,P)}function jA(v,P){if(typeof P==\"function\")return v=v(),P(v),function(){P(null)};if(P!=null)return v=v(),P.current=v,function(){P.current=null}}function kd(v,P,Q){return Q=Q!=null?Q.concat([v]):null,Su(4,2,jA.bind(null,P,v),Q)}function d0(){}function yp(v,P){var Q=Ka();P=P===void 0?null:P;var H=Q.memoizedState;return H!==null&&P!==null&&h0(P,H[1])?H[0]:(Q.memoizedState=[v,P],v)}function xl(v,P){var Q=Ka();P=P===void 0?null:P;var H=Q.memoizedState;return H!==null&&P!==null&&h0(P,H[1])?H[0]:(v=v(),Q.memoizedState=[v,P],v)}function Qd(v,P){var Q=er();ei(98>Q?98:Q,function(){v(!0)}),ei(97<Q?97:Q,function(){var H=gs.transition;gs.transition=1;try{v(!1),P()}finally{gs.transition=H}})}function Ep(v,P,Q){var H=oo(),Y=ss(v),ne={lane:Y,action:Q,eagerReducer:null,eagerState:null,next:null},Be=P.pending;if(Be===null?ne.next=ne:(ne.next=Be.next,Be.next=ne),P.pending=ne,Be=v.alternate,v===On||Be!==null&&Be===On)vu=HA=!0;else{if(v.lanes===0&&(Be===null||Be.lanes===0)&&(Be=P.lastRenderedReducer,Be!==null))try{var Ue=P.lastRenderedState,ft=Be(Ue,Q);if(ne.eagerReducer=Be,ne.eagerState=ft,eo(ft,Ue))return}catch{}finally{}Xa(v,Y,H)}}var bt={readContext:ro,useCallback:An,useContext:An,useEffect:An,useImperativeHandle:An,useLayoutEffect:An,useMemo:An,useReducer:An,useRef:An,useState:An,useDebugValue:An,useDeferredValue:An,useTransition:An,useMutableSource:An,useOpaqueIdentifier:An,unstable_isNewReconciler:!1},L={readContext:ro,useCallback:function(v,P){return Gi().memoizedState=[v,P===void 0?null:P],v},useContext:ro,useEffect:Ns,useImperativeHandle:function(v,P,Q){return Q=Q!=null?Q.concat([v]):null,qA(4,2,jA.bind(null,P,v),Q)},useLayoutEffect:function(v,P){return qA(4,2,v,P)},useMemo:function(v,P){var Q=Gi();return P=P===void 0?null:P,v=v(),Q.memoizedState=[v,P],v},useReducer:function(v,P,Q){var H=Gi();return P=Q!==void 0?Q(P):P,H.memoizedState=H.baseState=P,v=H.queue={pending:null,dispatch:null,lastRenderedReducer:v,lastRenderedState:P},v=v.dispatch=Ep.bind(null,On,v),[H.memoizedState,v]},useRef:ds,useState:Sc,useDebugValue:d0,useDeferredValue:function(v){var P=Sc(v),Q=P[0],H=P[1];return Ns(function(){var Y=gs.transition;gs.transition=1;try{H(v)}finally{gs.transition=Y}},[v]),Q},useTransition:function(){var v=Sc(!1),P=v[0];return v=Qd.bind(null,v[1]),ds(v),[v,P]},useMutableSource:function(v,P,Q){var H=Gi();return H.memoizedState={refs:{getSnapshot:P,setSnapshot:null},source:v,subscribe:Q},fn(H,v,P,Q)},useOpaqueIdentifier:function(){if(ga){var v=!1,P=se(function(){throw v||(v=!0,Q(be())),Error(u(355))}),Q=Sc(P)[1];return!(On.mode&2)&&(On.flags|=516,_o(5,function(){Q(be())},void 0,null)),P}return P=be(),Sc(P),P},unstable_isNewReconciler:!1},V={readContext:ro,useCallback:yp,useContext:ro,useEffect:Kr,useImperativeHandle:kd,useLayoutEffect:mp,useMemo:xl,useReducer:Du,useRef:dp,useState:function(){return Du(io)},useDebugValue:d0,useDeferredValue:function(v){var P=Du(io),Q=P[0],H=P[1];return Kr(function(){var Y=gs.transition;gs.transition=1;try{H(v)}finally{gs.transition=Y}},[v]),Q},useTransition:function(){var v=Du(io)[0];return[dp().current,v]},useMutableSource:so,useOpaqueIdentifier:function(){return Du(io)[0]},unstable_isNewReconciler:!1},re={readContext:ro,useCallback:yp,useContext:ro,useEffect:Kr,useImperativeHandle:kd,useLayoutEffect:mp,useMemo:xl,useReducer:Pu,useRef:dp,useState:function(){return Pu(io)},useDebugValue:d0,useDeferredValue:function(v){var P=Pu(io),Q=P[0],H=P[1];return Kr(function(){var Y=gs.transition;gs.transition=1;try{H(v)}finally{gs.transition=Y}},[v]),Q},useTransition:function(){var v=Pu(io)[0];return[dp().current,v]},useMutableSource:so,useOpaqueIdentifier:function(){return Pu(io)[0]},unstable_isNewReconciler:!1},ge=A.ReactCurrentOwner,Ye=!1;function At(v,P,Q,H){P.child=v===null?DI(P,null,Q,H):c0(P,v.child,Q,H)}function hr(v,P,Q,H,Y){Q=Q.render;var ne=P.ref;return Eu(P,Y),H=g0(v,P,Q,H,ne,Y),v!==null&&!Ye?(P.updateQueue=v.updateQueue,P.flags&=-517,v.lanes&=~Y,Mn(v,P,Y)):(P.flags|=1,At(v,P,H,Y),P.child)}function Ir(v,P,Q,H,Y,ne){if(v===null){var Be=Q.type;return typeof Be==\"function\"&&!JI(Be)&&Be.defaultProps===void 0&&Q.compare===null&&Q.defaultProps===void 0?(P.tag=15,P.type=Be,Rn(v,P,Be,H,Y,ne)):(v=k0(Q.type,null,H,P,P.mode,ne),v.ref=P.ref,v.return=P,P.child=v)}return Be=v.child,!(Y&ne)&&(Y=Be.memoizedProps,Q=Q.compare,Q=Q!==null?Q:cp,Q(Y,H)&&v.ref===P.ref)?Mn(v,P,ne):(P.flags|=1,v=Fc(Be,H),v.ref=P.ref,v.return=P,P.child=v)}function Rn(v,P,Q,H,Y,ne){if(v!==null&&cp(v.memoizedProps,H)&&v.ref===P.ref)if(Ye=!1,(ne&Y)!==0)v.flags&16384&&(Ye=!0);else return P.lanes=v.lanes,Mn(v,P,ne);return GA(v,P,Q,H,ne)}function ai(v,P,Q){var H=P.pendingProps,Y=H.children,ne=v!==null?v.memoizedState:null;if(H.mode===\"hidden\"||H.mode===\"unstable-defer-without-hiding\")if(!(P.mode&4))P.memoizedState={baseLanes:0},zd(P,Q);else if(Q&1073741824)P.memoizedState={baseLanes:0},zd(P,ne!==null?ne.baseLanes:Q);else return v=ne!==null?ne.baseLanes|Q:Q,P.lanes=P.childLanes=1073741824,P.memoizedState={baseLanes:v},zd(P,v),null;else ne!==null?(H=ne.baseLanes|Q,P.memoizedState=null):H=Q,zd(P,H);return At(v,P,Y,Q),P.child}function ns(v,P){var Q=P.ref;(v===null&&Q!==null||v!==null&&v.ref!==Q)&&(P.flags|=128)}function GA(v,P,Q,H,Y){var ne=qn(Q)?sa:ki.current;return ne=un(P,ne),Eu(P,Y),Q=g0(v,P,Q,H,ne,Y),v!==null&&!Ye?(P.updateQueue=v.updateQueue,P.flags&=-517,v.lanes&=~Y,Mn(v,P,Y)):(P.flags|=1,At(v,P,Q,Y),P.child)}function lD(v,P,Q,H,Y){if(qn(Q)){var ne=!0;aa(P)}else ne=!1;if(Eu(P,Y),P.stateNode===null)v!==null&&(v.alternate=null,P.alternate=null,P.flags|=2),xt(P,Q,H),no(P,Q,H,Y),H=!0;else if(v===null){var Be=P.stateNode,Ue=P.memoizedProps;Be.props=Ue;var ft=Be.context,jt=Q.contextType;typeof jt==\"object\"&&jt!==null?jt=ro(jt):(jt=qn(Q)?sa:ki.current,jt=un(P,jt));var wr=Q.getDerivedStateFromProps,Tr=typeof wr==\"function\"||typeof Be.getSnapshotBeforeUpdate==\"function\";Tr||typeof Be.UNSAFE_componentWillReceiveProps!=\"function\"&&typeof Be.componentWillReceiveProps!=\"function\"||(Ue!==H||ft!==jt)&&MA(P,Be,H,jt),Ga=!1;var Xt=P.memoizedState;Be.state=Xt,LA(P,H,Be,Y),ft=P.memoizedState,Ue!==H||Xt!==ft||vi.current||Ga?(typeof wr==\"function\"&&(NA(P,Q,wr,H),ft=P.memoizedState),(Ue=Ga||W(P,Q,Ue,H,Xt,ft,jt))?(Tr||typeof Be.UNSAFE_componentWillMount!=\"function\"&&typeof Be.componentWillMount!=\"function\"||(typeof Be.componentWillMount==\"function\"&&Be.componentWillMount(),typeof Be.UNSAFE_componentWillMount==\"function\"&&Be.UNSAFE_componentWillMount()),typeof Be.componentDidMount==\"function\"&&(P.flags|=4)):(typeof Be.componentDidMount==\"function\"&&(P.flags|=4),P.memoizedProps=H,P.memoizedState=ft),Be.props=H,Be.state=ft,Be.context=jt,H=Ue):(typeof Be.componentDidMount==\"function\"&&(P.flags|=4),H=!1)}else{Be=P.stateNode,l0(v,P),Ue=P.memoizedProps,jt=P.type===P.elementType?Ue:to(P.type,Ue),Be.props=jt,Tr=P.pendingProps,Xt=Be.context,ft=Q.contextType,typeof ft==\"object\"&&ft!==null?ft=ro(ft):(ft=qn(Q)?sa:ki.current,ft=un(P,ft));var jn=Q.getDerivedStateFromProps;(wr=typeof jn==\"function\"||typeof Be.getSnapshotBeforeUpdate==\"function\")||typeof Be.UNSAFE_componentWillReceiveProps!=\"function\"&&typeof Be.componentWillReceiveProps!=\"function\"||(Ue!==Tr||Xt!==ft)&&MA(P,Be,H,ft),Ga=!1,Xt=P.memoizedState,Be.state=Xt,LA(P,H,Be,Y);var li=P.memoizedState;Ue!==Tr||Xt!==li||vi.current||Ga?(typeof jn==\"function\"&&(NA(P,Q,jn,H),li=P.memoizedState),(jt=Ga||W(P,Q,jt,H,Xt,li,ft))?(wr||typeof Be.UNSAFE_componentWillUpdate!=\"function\"&&typeof Be.componentWillUpdate!=\"function\"||(typeof Be.componentWillUpdate==\"function\"&&Be.componentWillUpdate(H,li,ft),typeof Be.UNSAFE_componentWillUpdate==\"function\"&&Be.UNSAFE_componentWillUpdate(H,li,ft)),typeof Be.componentDidUpdate==\"function\"&&(P.flags|=4),typeof Be.getSnapshotBeforeUpdate==\"function\"&&(P.flags|=256)):(typeof Be.componentDidUpdate!=\"function\"||Ue===v.memoizedProps&&Xt===v.memoizedState||(P.flags|=4),typeof Be.getSnapshotBeforeUpdate!=\"function\"||Ue===v.memoizedProps&&Xt===v.memoizedState||(P.flags|=256),P.memoizedProps=H,P.memoizedState=li),Be.props=H,Be.state=li,Be.context=ft,H=jt):(typeof Be.componentDidUpdate!=\"function\"||Ue===v.memoizedProps&&Xt===v.memoizedState||(P.flags|=4),typeof Be.getSnapshotBeforeUpdate!=\"function\"||Ue===v.memoizedProps&&Xt===v.memoizedState||(P.flags|=256),H=!1)}return PI(v,P,Q,H,ne,Y)}function PI(v,P,Q,H,Y,ne){ns(v,P);var Be=(P.flags&64)!==0;if(!H&&!Be)return Y&&la(P,Q,!1),Mn(v,P,ne);H=P.stateNode,ge.current=P;var Ue=Be&&typeof Q.getDerivedStateFromError!=\"function\"?null:H.render();return P.flags|=1,v!==null&&Be?(P.child=c0(P,v.child,null,ne),P.child=c0(P,null,Ue,ne)):At(v,P,Ue,ne),P.memoizedState=H.state,Y&&la(P,Q,!0),P.child}function Fd(v){var P=v.stateNode;P.pendingContext?lp(v,P.pendingContext,P.pendingContext!==P.context):P.context&&lp(v,P.context,!1),u0(v,P.containerInfo)}var Cp={dehydrated:null,retryLane:0};function SI(v,P,Q){var H=P.pendingProps,Y=oi.current,ne=!1,Be;return(Be=(P.flags&64)!==0)||(Be=v!==null&&v.memoizedState===null?!1:(Y&2)!==0),Be?(ne=!0,P.flags&=-65):v!==null&&v.memoizedState===null||H.fallback===void 0||H.unstable_avoidThisFallback===!0||(Y|=1),Bn(oi,Y&1),v===null?(H.fallback!==void 0&&f0(P),v=H.children,Y=H.fallback,ne?(v=da(P,v,Y,Q),P.child.memoizedState={baseLanes:Q},P.memoizedState=Cp,v):typeof H.unstable_expectedLoadTime==\"number\"?(v=da(P,v,Y,Q),P.child.memoizedState={baseLanes:Q},P.memoizedState=Cp,P.lanes=33554432,v):(Q=XI({mode:\"visible\",children:v},P.mode,Q,null),Q.return=P,P.child=Q)):v.memoizedState!==null?ne?(H=WA(v,P,H.children,H.fallback,Q),ne=P.child,Y=v.child.memoizedState,ne.memoizedState=Y===null?{baseLanes:Q}:{baseLanes:Y.baseLanes|Q},ne.childLanes=v.childLanes&~Q,P.memoizedState=Cp,H):(Q=xI(v,P,H.children,Q),P.memoizedState=null,Q):ne?(H=WA(v,P,H.children,H.fallback,Q),ne=P.child,Y=v.child.memoizedState,ne.memoizedState=Y===null?{baseLanes:Q}:{baseLanes:Y.baseLanes|Q},ne.childLanes=v.childLanes&~Q,P.memoizedState=Cp,H):(Q=xI(v,P,H.children,Q),P.memoizedState=null,Q)}function da(v,P,Q,H){var Y=v.mode,ne=v.child;return P={mode:\"hidden\",children:P},!(Y&2)&&ne!==null?(ne.childLanes=0,ne.pendingProps=P):ne=XI(P,Y,0,null),Q=Ru(Q,Y,H,null),ne.return=v,Q.return=v,ne.sibling=Q,v.child=ne,Q}function xI(v,P,Q,H){var Y=v.child;return v=Y.sibling,Q=Fc(Y,{mode:\"visible\",children:Q}),!(P.mode&2)&&(Q.lanes=H),Q.return=P,Q.sibling=null,v!==null&&(v.nextEffect=null,v.flags=8,P.firstEffect=P.lastEffect=v),P.child=Q}function WA(v,P,Q,H,Y){var ne=P.mode,Be=v.child;v=Be.sibling;var Ue={mode:\"hidden\",children:Q};return!(ne&2)&&P.child!==Be?(Q=P.child,Q.childLanes=0,Q.pendingProps=Ue,Be=Q.lastEffect,Be!==null?(P.firstEffect=Q.firstEffect,P.lastEffect=Be,Be.nextEffect=null):P.firstEffect=P.lastEffect=null):Q=Fc(Be,Ue),v!==null?H=Fc(v,H):(H=Ru(H,ne,Y,null),H.flags|=2),H.return=P,Q.return=P,Q.sibling=H,P.child=Q,H}function Ip(v,P){v.lanes|=P;var Q=v.alternate;Q!==null&&(Q.lanes|=P),vd(v.return,P)}function Rd(v,P,Q,H,Y,ne){var Be=v.memoizedState;Be===null?v.memoizedState={isBackwards:P,rendering:null,renderingStartTime:0,last:H,tail:Q,tailMode:Y,lastEffect:ne}:(Be.isBackwards=P,Be.rendering=null,Be.renderingStartTime=0,Be.last=H,Be.tail=Q,Be.tailMode=Y,Be.lastEffect=ne)}function cD(v,P,Q){var H=P.pendingProps,Y=H.revealOrder,ne=H.tail;if(At(v,P,H.children,Q),H=oi.current,H&2)H=H&1|2,P.flags|=64;else{if(v!==null&&v.flags&64)e:for(v=P.child;v!==null;){if(v.tag===13)v.memoizedState!==null&&Ip(v,Q);else if(v.tag===19)Ip(v,Q);else if(v.child!==null){v.child.return=v,v=v.child;continue}if(v===P)break e;for(;v.sibling===null;){if(v.return===null||v.return===P)break e;v=v.return}v.sibling.return=v.return,v=v.sibling}H&=1}if(Bn(oi,H),!(P.mode&2))P.memoizedState=null;else switch(Y){case\"forwards\":for(Q=P.child,Y=null;Q!==null;)v=Q.alternate,v!==null&&UA(v)===null&&(Y=Q),Q=Q.sibling;Q=Y,Q===null?(Y=P.child,P.child=null):(Y=Q.sibling,Q.sibling=null),Rd(P,!1,Y,Q,ne,P.lastEffect);break;case\"backwards\":for(Q=null,Y=P.child,P.child=null;Y!==null;){if(v=Y.alternate,v!==null&&UA(v)===null){P.child=Y;break}v=Y.sibling,Y.sibling=Q,Q=Y,Y=v}Rd(P,!0,Q,null,ne,P.lastEffect);break;case\"together\":Rd(P,!1,null,null,void 0,P.lastEffect);break;default:P.memoizedState=null}return P.child}function Mn(v,P,Q){if(v!==null&&(P.dependencies=v.dependencies),B0|=P.lanes,Q&P.childLanes){if(v!==null&&P.child!==v.child)throw Error(u(153));if(P.child!==null){for(v=P.child,Q=Fc(v,v.pendingProps),P.child=Q,Q.return=P;v.sibling!==null;)v=v.sibling,Q=Q.sibling=Fc(v,v.pendingProps),Q.return=P;Q.sibling=null}return P.child}return null}function Wi(v){v.flags|=4}var za,Ja,xc,Ho;if(R)za=function(v,P){for(var Q=P.child;Q!==null;){if(Q.tag===5||Q.tag===6)ke(v,Q.stateNode);else if(Q.tag!==4&&Q.child!==null){Q.child.return=Q,Q=Q.child;continue}if(Q===P)break;for(;Q.sibling===null;){if(Q.return===null||Q.return===P)return;Q=Q.return}Q.sibling.return=Q.return,Q=Q.sibling}},Ja=function(){},xc=function(v,P,Q,H,Y){if(v=v.memoizedProps,v!==H){var ne=P.stateNode,Be=pa(cr.current);Q=xe(ne,Q,v,H,Y,Be),(P.updateQueue=Q)&&Wi(P)}},Ho=function(v,P,Q,H){Q!==H&&Wi(P)};else if(J){za=function(v,P,Q,H){for(var Y=P.child;Y!==null;){if(Y.tag===5){var ne=Y.stateNode;Q&&H&&(ne=bA(ne,Y.type,Y.memoizedProps,Y)),ke(v,ne)}else if(Y.tag===6)ne=Y.stateNode,Q&&H&&(ne=Ro(ne,Y.memoizedProps,Y)),ke(v,ne);else if(Y.tag!==4){if(Y.tag===13&&Y.flags&4&&(ne=Y.memoizedState!==null)){var Be=Y.child;if(Be!==null&&(Be.child!==null&&(Be.child.return=Be,za(v,Be,!0,ne)),ne=Be.sibling,ne!==null)){ne.return=Y,Y=ne;continue}}if(Y.child!==null){Y.child.return=Y,Y=Y.child;continue}}if(Y===P)break;for(;Y.sibling===null;){if(Y.return===null||Y.return===P)return;Y=Y.return}Y.sibling.return=Y.return,Y=Y.sibling}};var YA=function(v,P,Q,H){for(var Y=P.child;Y!==null;){if(Y.tag===5){var ne=Y.stateNode;Q&&H&&(ne=bA(ne,Y.type,Y.memoizedProps,Y)),hc(v,ne)}else if(Y.tag===6)ne=Y.stateNode,Q&&H&&(ne=Ro(ne,Y.memoizedProps,Y)),hc(v,ne);else if(Y.tag!==4){if(Y.tag===13&&Y.flags&4&&(ne=Y.memoizedState!==null)){var Be=Y.child;if(Be!==null&&(Be.child!==null&&(Be.child.return=Be,YA(v,Be,!0,ne)),ne=Be.sibling,ne!==null)){ne.return=Y,Y=ne;continue}}if(Y.child!==null){Y.child.return=Y,Y=Y.child;continue}}if(Y===P)break;for(;Y.sibling===null;){if(Y.return===null||Y.return===P)return;Y=Y.return}Y.sibling.return=Y.return,Y=Y.sibling}};Ja=function(v){var P=v.stateNode;if(v.firstEffect!==null){var Q=P.containerInfo,H=pc(Q);YA(H,v,!1,!1),P.pendingChildren=H,Wi(v),gc(Q,H)}},xc=function(v,P,Q,H,Y){var ne=v.stateNode,Be=v.memoizedProps;if((v=P.firstEffect===null)&&Be===H)P.stateNode=ne;else{var Ue=P.stateNode,ft=pa(cr.current),jt=null;Be!==H&&(jt=xe(Ue,Q,Be,H,Y,ft)),v&&jt===null?P.stateNode=ne:(ne=Ts(ne,jt,Q,Be,H,P,v,Ue),Ve(ne,Q,H,Y,ft)&&Wi(P),P.stateNode=ne,v?Wi(P):za(ne,P,!1,!1))}},Ho=function(v,P,Q,H){Q!==H?(v=pa(Iu.current),Q=pa(cr.current),P.stateNode=He(H,v,Q,P),Wi(P)):P.stateNode=v.stateNode}}else Ja=function(){},xc=function(){},Ho=function(){};function KA(v,P){if(!ga)switch(v.tailMode){case\"hidden\":P=v.tail;for(var Q=null;P!==null;)P.alternate!==null&&(Q=P),P=P.sibling;Q===null?v.tail=null:Q.sibling=null;break;case\"collapsed\":Q=v.tail;for(var H=null;Q!==null;)Q.alternate!==null&&(H=Q),Q=Q.sibling;H===null?P||v.tail===null?v.tail=null:v.tail.sibling=null:H.sibling=null}}function HF(v,P,Q){var H=P.pendingProps;switch(P.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return null;case 1:return qn(P.type)&&Ec(),null;case 3:return Bc(),Ft(vi),Ft(ki),Dc(),H=P.stateNode,H.pendingContext&&(H.context=H.pendingContext,H.pendingContext=null),(v===null||v.child===null)&&(_A(P)?Wi(P):H.hydrate||(P.flags|=256)),Ja(P),null;case 5:wt(P);var Y=pa(Iu.current);if(Q=P.type,v!==null&&P.stateNode!=null)xc(v,P,Q,H,Y),v.ref!==P.ref&&(P.flags|=128);else{if(!H){if(P.stateNode===null)throw Error(u(166));return null}if(v=pa(cr.current),_A(P)){if(!X)throw Error(u(175));v=Er(P.stateNode,P.type,P.memoizedProps,Y,v,P),P.updateQueue=v,v!==null&&Wi(P)}else{var ne=Te(Q,H,Y,v,P);za(ne,P,!1,!1),P.stateNode=ne,Ve(ne,Q,H,Y,v)&&Wi(P)}P.ref!==null&&(P.flags|=128)}return null;case 6:if(v&&P.stateNode!=null)Ho(v,P,v.memoizedProps,H);else{if(typeof H!=\"string\"&&P.stateNode===null)throw Error(u(166));if(v=pa(Iu.current),Y=pa(cr.current),_A(P)){if(!X)throw Error(u(176));du(P.stateNode,P.memoizedProps,P)&&Wi(P)}else P.stateNode=He(H,v,Y,P)}return null;case 13:return Ft(oi),H=P.memoizedState,P.flags&64?(P.lanes=Q,P):(H=H!==null,Y=!1,v===null?P.memoizedProps.fallback!==void 0&&_A(P):Y=v.memoizedState!==null,H&&!Y&&P.mode&2&&(v===null&&P.memoizedProps.unstable_avoidThisFallback!==!0||oi.current&1?is===0&&(is=3):((is===0||is===3)&&(is=4),Os===null||!(B0&134217727)&&!(vp&134217727)||Dp(Os,ms))),J&&H&&(P.flags|=4),R&&(H||Y)&&(P.flags|=4),null);case 4:return Bc(),Ja(P),v===null&&Et(P.stateNode.containerInfo),null;case 10:return a0(P),null;case 17:return qn(P.type)&&Ec(),null;case 19:if(Ft(oi),H=P.memoizedState,H===null)return null;if(Y=(P.flags&64)!==0,ne=H.rendering,ne===null)if(Y)KA(H,!1);else{if(is!==0||v!==null&&v.flags&64)for(v=P.child;v!==null;){if(ne=UA(v),ne!==null){for(P.flags|=64,KA(H,!1),v=ne.updateQueue,v!==null&&(P.updateQueue=v,P.flags|=4),H.lastEffect===null&&(P.firstEffect=null),P.lastEffect=H.lastEffect,v=Q,H=P.child;H!==null;)Y=H,Q=v,Y.flags&=2,Y.nextEffect=null,Y.firstEffect=null,Y.lastEffect=null,ne=Y.alternate,ne===null?(Y.childLanes=0,Y.lanes=Q,Y.child=null,Y.memoizedProps=null,Y.memoizedState=null,Y.updateQueue=null,Y.dependencies=null,Y.stateNode=null):(Y.childLanes=ne.childLanes,Y.lanes=ne.lanes,Y.child=ne.child,Y.memoizedProps=ne.memoizedProps,Y.memoizedState=ne.memoizedState,Y.updateQueue=ne.updateQueue,Y.type=ne.type,Q=ne.dependencies,Y.dependencies=Q===null?null:{lanes:Q.lanes,firstContext:Q.firstContext}),H=H.sibling;return Bn(oi,oi.current&1|2),P.child}v=v.sibling}H.tail!==null&&Dt()>qI&&(P.flags|=64,Y=!0,KA(H,!1),P.lanes=33554432)}else{if(!Y)if(v=UA(ne),v!==null){if(P.flags|=64,Y=!0,v=v.updateQueue,v!==null&&(P.updateQueue=v,P.flags|=4),KA(H,!0),H.tail===null&&H.tailMode===\"hidden\"&&!ne.alternate&&!ga)return P=P.lastEffect=H.lastEffect,P!==null&&(P.nextEffect=null),null}else 2*Dt()-H.renderingStartTime>qI&&Q!==1073741824&&(P.flags|=64,Y=!0,KA(H,!1),P.lanes=33554432);H.isBackwards?(ne.sibling=P.child,P.child=ne):(v=H.last,v!==null?v.sibling=ne:P.child=ne,H.last=ne)}return H.tail!==null?(v=H.tail,H.rendering=v,H.tail=v.sibling,H.lastEffect=P.lastEffect,H.renderingStartTime=Dt(),v.sibling=null,P=oi.current,Bn(oi,Y?P&1|2:P&1),v):null;case 23:case 24:return VI(),v!==null&&v.memoizedState!==null!=(P.memoizedState!==null)&&H.mode!==\"unstable-defer-without-hiding\"&&(P.flags|=4),null}throw Error(u(156,P.tag))}function qF(v){switch(v.tag){case 1:qn(v.type)&&Ec();var P=v.flags;return P&4096?(v.flags=P&-4097|64,v):null;case 3:if(Bc(),Ft(vi),Ft(ki),Dc(),P=v.flags,P&64)throw Error(u(285));return v.flags=P&-4097|64,v;case 5:return wt(v),null;case 13:return Ft(oi),P=v.flags,P&4096?(v.flags=P&-4097|64,v):null;case 19:return Ft(oi),null;case 4:return Bc(),null;case 10:return a0(v),null;case 23:case 24:return VI(),null;default:return null}}function m0(v,P){try{var Q=\"\",H=P;do Q+=vI(H),H=H.return;while(H);var Y=Q}catch(ne){Y=`\nError generating stack: `+ne.message+`\n`+ne.stack}return{value:v,source:P,stack:Y}}function y0(v,P){try{console.error(P.value)}catch(Q){setTimeout(function(){throw Q})}}var jF=typeof WeakMap==\"function\"?WeakMap:Map;function bI(v,P,Q){Q=Wa(-1,Q),Q.tag=3,Q.payload={element:null};var H=P.value;return Q.callback=function(){Wd||(Wd=!0,jI=H),y0(v,P)},Q}function E0(v,P,Q){Q=Wa(-1,Q),Q.tag=3;var H=v.type.getDerivedStateFromError;if(typeof H==\"function\"){var Y=P.value;Q.payload=function(){return y0(v,P),H(Y)}}var ne=v.stateNode;return ne!==null&&typeof ne.componentDidCatch==\"function\"&&(Q.callback=function(){typeof H!=\"function\"&&(bl===null?bl=new Set([this]):bl.add(this),y0(v,P));var Be=P.stack;this.componentDidCatch(P.value,{componentStack:Be!==null?Be:\"\"})}),Q}var GF=typeof WeakSet==\"function\"?WeakSet:Set;function kI(v){var P=v.ref;if(P!==null)if(typeof P==\"function\")try{P(null)}catch(Q){Fu(v,Q)}else P.current=null}function Td(v,P){switch(P.tag){case 0:case 11:case 15:case 22:return;case 1:if(P.flags&256&&v!==null){var Q=v.memoizedProps,H=v.memoizedState;v=P.stateNode,P=v.getSnapshotBeforeUpdate(P.elementType===P.type?Q:to(P.type,Q),H),v.__reactInternalSnapshotBeforeUpdate=P}return;case 3:R&&P.flags&256&&hs(P.stateNode.containerInfo);return;case 5:case 6:case 4:case 17:return}throw Error(u(163))}function wp(v,P){if(P=P.updateQueue,P=P!==null?P.lastEffect:null,P!==null){var Q=P=P.next;do{if((Q.tag&v)===v){var H=Q.destroy;Q.destroy=void 0,H!==void 0&&H()}Q=Q.next}while(Q!==P)}}function uD(v,P,Q){switch(Q.tag){case 0:case 11:case 15:case 22:if(P=Q.updateQueue,P=P!==null?P.lastEffect:null,P!==null){v=P=P.next;do{if((v.tag&3)===3){var H=v.create;v.destroy=H()}v=v.next}while(v!==P)}if(P=Q.updateQueue,P=P!==null?P.lastEffect:null,P!==null){v=P=P.next;do{var Y=v;H=Y.next,Y=Y.tag,Y&4&&Y&1&&(vD(Q,v),$F(Q,v)),v=H}while(v!==P)}return;case 1:v=Q.stateNode,Q.flags&4&&(P===null?v.componentDidMount():(H=Q.elementType===Q.type?P.memoizedProps:to(Q.type,P.memoizedProps),v.componentDidUpdate(H,P.memoizedState,v.__reactInternalSnapshotBeforeUpdate))),P=Q.updateQueue,P!==null&&Pd(Q,P,v);return;case 3:if(P=Q.updateQueue,P!==null){if(v=null,Q.child!==null)switch(Q.child.tag){case 5:v=Re(Q.child.stateNode);break;case 1:v=Q.child.stateNode}Pd(Q,P,v)}return;case 5:v=Q.stateNode,P===null&&Q.flags&4&&Qs(v,Q.type,Q.memoizedProps,Q);return;case 6:return;case 4:return;case 12:return;case 13:X&&Q.memoizedState===null&&(Q=Q.alternate,Q!==null&&(Q=Q.memoizedState,Q!==null&&(Q=Q.dehydrated,Q!==null&&mc(Q))));return;case 19:case 17:case 20:case 21:case 23:case 24:return}throw Error(u(163))}function AD(v,P){if(R)for(var Q=v;;){if(Q.tag===5){var H=Q.stateNode;P?op(H):Rs(Q.stateNode,Q.memoizedProps)}else if(Q.tag===6)H=Q.stateNode,P?ap(H):Nn(H,Q.memoizedProps);else if((Q.tag!==23&&Q.tag!==24||Q.memoizedState===null||Q===v)&&Q.child!==null){Q.child.return=Q,Q=Q.child;continue}if(Q===v)break;for(;Q.sibling===null;){if(Q.return===null||Q.return===v)return;Q=Q.return}Q.sibling.return=Q.return,Q=Q.sibling}}function Ld(v,P){if(ca&&typeof ca.onCommitFiberUnmount==\"function\")try{ca.onCommitFiberUnmount(Ze,P)}catch{}switch(P.tag){case 0:case 11:case 14:case 15:case 22:if(v=P.updateQueue,v!==null&&(v=v.lastEffect,v!==null)){var Q=v=v.next;do{var H=Q,Y=H.destroy;if(H=H.tag,Y!==void 0)if(H&4)vD(P,Q);else{H=P;try{Y()}catch(ne){Fu(H,ne)}}Q=Q.next}while(Q!==v)}break;case 1:if(kI(P),v=P.stateNode,typeof v.componentWillUnmount==\"function\")try{v.props=P.memoizedProps,v.state=P.memoizedState,v.componentWillUnmount()}catch(ne){Fu(P,ne)}break;case 5:kI(P);break;case 4:R?gD(v,P):J&&J&&(P=P.stateNode.containerInfo,v=pc(P),xA(P,v))}}function fD(v,P){for(var Q=P;;)if(Ld(v,Q),Q.child===null||R&&Q.tag===4){if(Q===P)break;for(;Q.sibling===null;){if(Q.return===null||Q.return===P)return;Q=Q.return}Q.sibling.return=Q.return,Q=Q.sibling}else Q.child.return=Q,Q=Q.child}function Nd(v){v.alternate=null,v.child=null,v.dependencies=null,v.firstEffect=null,v.lastEffect=null,v.memoizedProps=null,v.memoizedState=null,v.pendingProps=null,v.return=null,v.updateQueue=null}function pD(v){return v.tag===5||v.tag===3||v.tag===4}function hD(v){if(R){e:{for(var P=v.return;P!==null;){if(pD(P))break e;P=P.return}throw Error(u(160))}var Q=P;switch(P=Q.stateNode,Q.tag){case 5:var H=!1;break;case 3:P=P.containerInfo,H=!0;break;case 4:P=P.containerInfo,H=!0;break;default:throw Error(u(161))}Q.flags&16&&(gu(P),Q.flags&=-17);e:t:for(Q=v;;){for(;Q.sibling===null;){if(Q.return===null||pD(Q.return)){Q=null;break e}Q=Q.return}for(Q.sibling.return=Q.return,Q=Q.sibling;Q.tag!==5&&Q.tag!==6&&Q.tag!==18;){if(Q.flags&2||Q.child===null||Q.tag===4)continue t;Q.child.return=Q,Q=Q.child}if(!(Q.flags&2)){Q=Q.stateNode;break e}}H?QI(v,Q,P):FI(v,Q,P)}}function QI(v,P,Q){var H=v.tag,Y=H===5||H===6;if(Y)v=Y?v.stateNode:v.stateNode.instance,P?Fs(Q,v,P):Xs(Q,v);else if(H!==4&&(v=v.child,v!==null))for(QI(v,P,Q),v=v.sibling;v!==null;)QI(v,P,Q),v=v.sibling}function FI(v,P,Q){var H=v.tag,Y=H===5||H===6;if(Y)v=Y?v.stateNode:v.stateNode.instance,P?bi(Q,v,P):$n(Q,v);else if(H!==4&&(v=v.child,v!==null))for(FI(v,P,Q),v=v.sibling;v!==null;)FI(v,P,Q),v=v.sibling}function gD(v,P){for(var Q=P,H=!1,Y,ne;;){if(!H){H=Q.return;e:for(;;){if(H===null)throw Error(u(160));switch(Y=H.stateNode,H.tag){case 5:ne=!1;break e;case 3:Y=Y.containerInfo,ne=!0;break e;case 4:Y=Y.containerInfo,ne=!0;break e}H=H.return}H=!0}if(Q.tag===5||Q.tag===6)fD(v,Q),ne?SA(Y,Q.stateNode):$s(Y,Q.stateNode);else if(Q.tag===4){if(Q.child!==null){Y=Q.stateNode.containerInfo,ne=!0,Q.child.return=Q,Q=Q.child;continue}}else if(Ld(v,Q),Q.child!==null){Q.child.return=Q,Q=Q.child;continue}if(Q===P)break;for(;Q.sibling===null;){if(Q.return===null||Q.return===P)return;Q=Q.return,Q.tag===4&&(H=!1)}Q.sibling.return=Q.return,Q=Q.sibling}}function RI(v,P){if(R){switch(P.tag){case 0:case 11:case 14:case 15:case 22:wp(3,P);return;case 1:return;case 5:var Q=P.stateNode;if(Q!=null){var H=P.memoizedProps;v=v!==null?v.memoizedProps:H;var Y=P.type,ne=P.updateQueue;P.updateQueue=null,ne!==null&&Zs(Q,ne,Y,v,H,P)}return;case 6:if(P.stateNode===null)throw Error(u(162));Q=P.memoizedProps,Hi(P.stateNode,v!==null?v.memoizedProps:Q,Q);return;case 3:X&&(P=P.stateNode,P.hydrate&&(P.hydrate=!1,FA(P.containerInfo)));return;case 12:return;case 13:dD(P),C0(P);return;case 19:C0(P);return;case 17:return;case 23:case 24:AD(P,P.memoizedState!==null);return}throw Error(u(163))}switch(P.tag){case 0:case 11:case 14:case 15:case 22:wp(3,P);return;case 12:return;case 13:dD(P),C0(P);return;case 19:C0(P);return;case 3:X&&(Q=P.stateNode,Q.hydrate&&(Q.hydrate=!1,FA(Q.containerInfo)));break;case 23:case 24:return}e:if(J){switch(P.tag){case 1:case 5:case 6:case 20:break e;case 3:case 4:P=P.stateNode,xA(P.containerInfo,P.pendingChildren);break e}throw Error(u(163))}}function dD(v){v.memoizedState!==null&&(HI=Dt(),R&&AD(v.child,!0))}function C0(v){var P=v.updateQueue;if(P!==null){v.updateQueue=null;var Q=v.stateNode;Q===null&&(Q=v.stateNode=new GF),P.forEach(function(H){var Y=tR.bind(null,v,H);Q.has(H)||(Q.add(H),H.then(Y,Y))})}}function WF(v,P){return v!==null&&(v=v.memoizedState,v===null||v.dehydrated!==null)?(P=P.memoizedState,P!==null&&P.dehydrated===null):!1}var Od=0,Md=1,Ud=2,I0=3,_d=4;if(typeof Symbol==\"function\"&&Symbol.for){var w0=Symbol.for;Od=w0(\"selector.component\"),Md=w0(\"selector.has_pseudo_class\"),Ud=w0(\"selector.role\"),I0=w0(\"selector.test_id\"),_d=w0(\"selector.text\")}function Hd(v){var P=$(v);if(P!=null){if(typeof P.memoizedProps[\"data-testname\"]!=\"string\")throw Error(u(364));return P}if(v=nr(v),v===null)throw Error(u(362));return v.stateNode.current}function xu(v,P){switch(P.$$typeof){case Od:if(v.type===P.value)return!0;break;case Md:e:{P=P.value,v=[v,0];for(var Q=0;Q<v.length;){var H=v[Q++],Y=v[Q++],ne=P[Y];if(H.tag!==5||!Pr(H)){for(;ne!=null&&xu(H,ne);)Y++,ne=P[Y];if(Y===P.length){P=!0;break e}else for(H=H.child;H!==null;)v.push(H,Y),H=H.sibling}}P=!1}return P;case Ud:if(v.tag===5&&yr(v.stateNode,P.value))return!0;break;case _d:if((v.tag===5||v.tag===6)&&(v=cn(v),v!==null&&0<=v.indexOf(P.value)))return!0;break;case I0:if(v.tag===5&&(v=v.memoizedProps[\"data-testname\"],typeof v==\"string\"&&v.toLowerCase()===P.value.toLowerCase()))return!0;break;default:throw Error(u(365,P))}return!1}function bu(v){switch(v.$$typeof){case Od:return\"<\"+(g(v.value)||\"Unknown\")+\">\";case Md:return\":has(\"+(bu(v)||\"\")+\")\";case Ud:return'[role=\"'+v.value+'\"]';case _d:return'\"'+v.value+'\"';case I0:return'[data-testname=\"'+v.value+'\"]';default:throw Error(u(365,v))}}function TI(v,P){var Q=[];v=[v,0];for(var H=0;H<v.length;){var Y=v[H++],ne=v[H++],Be=P[ne];if(Y.tag!==5||!Pr(Y)){for(;Be!=null&&xu(Y,Be);)ne++,Be=P[ne];if(ne===P.length)Q.push(Y);else for(Y=Y.child;Y!==null;)v.push(Y,ne),Y=Y.sibling}}return Q}function LI(v,P){if(!qt)throw Error(u(363));v=Hd(v),v=TI(v,P),P=[],v=Array.from(v);for(var Q=0;Q<v.length;){var H=v[Q++];if(H.tag===5)Pr(H)||P.push(H.stateNode);else for(H=H.child;H!==null;)v.push(H),H=H.sibling}return P}var qd=null;function YF(v){if(qd===null)try{var P=(\"require\"+Math.random()).slice(0,7);qd=(DB&&DB[P]).call(DB,\"timers\").setImmediate}catch{qd=function(H){var Y=new MessageChannel;Y.port1.onmessage=H,Y.port2.postMessage(void 0)}}return qd(v)}var KF=Math.ceil,jd=A.ReactCurrentDispatcher,NI=A.ReactCurrentOwner,OI=A.IsSomeRendererActing,Sr=0,Os=null,Oi=null,ms=0,VA=0,MI=Ls(0),is=0,Gd=null,Bp=0,B0=0,vp=0,UI=0,_I=null,HI=0,qI=1/0;function ku(){qI=Dt()+500}var ir=null,Wd=!1,jI=null,bl=null,Qu=!1,v0=null,D0=90,GI=[],WI=[],bc=null,P0=0,YI=null,Yd=-1,kc=0,Kd=0,S0=null,x0=!1;function oo(){return Sr&48?Dt():Yd!==-1?Yd:Yd=Dt()}function ss(v){if(v=v.mode,!(v&2))return 1;if(!(v&4))return er()===99?1:2;if(kc===0&&(kc=Bp),wd.transition!==0){Kd!==0&&(Kd=_I!==null?_I.pendingLanes:0),v=kc;var P=4186112&~Kd;return P&=-P,P===0&&(v=4186112&~v,P=v&-v,P===0&&(P=8192)),P}return v=er(),Sr&4&&v===98?v=Ot(12,kc):(v=RA(v),v=Ot(v,kc)),v}function Xa(v,P,Q){if(50<P0)throw P0=0,YI=null,Error(u(185));if(v=Vd(v,P),v===null)return null;ua(v,P,Q),v===Os&&(vp|=P,is===4&&Dp(v,ms));var H=er();P===1?Sr&8&&!(Sr&48)?KI(v):(qo(v,Q),Sr===0&&(ku(),Pn())):(!(Sr&4)||H!==98&&H!==99||(bc===null?bc=new Set([v]):bc.add(v)),qo(v,Q)),_I=v}function Vd(v,P){v.lanes|=P;var Q=v.alternate;for(Q!==null&&(Q.lanes|=P),Q=v,v=v.return;v!==null;)v.childLanes|=P,Q=v.alternate,Q!==null&&(Q.childLanes|=P),Q=v,v=v.return;return Q.tag===3?Q.stateNode:null}function qo(v,P){for(var Q=v.callbackNode,H=v.suspendedLanes,Y=v.pingedLanes,ne=v.expirationTimes,Be=v.pendingLanes;0<Be;){var Ue=31-qi(Be),ft=1<<Ue,jt=ne[Ue];if(jt===-1){if(!(ft&H)||ft&Y){jt=P,No(ft);var wr=dn;ne[Ue]=10<=wr?jt+250:6<=wr?jt+5e3:-1}}else jt<=P&&(v.expiredLanes|=ft);Be&=~ft}if(H=Oo(v,v===Os?ms:0),P=dn,H===0)Q!==null&&(Q!==ar&&rs(Q),v.callbackNode=null,v.callbackPriority=0);else{if(Q!==null){if(v.callbackPriority===P)return;Q!==ar&&rs(Q)}P===15?(Q=KI.bind(null,v),ye===null?(ye=[Q],Ne=Di(Dn,fa)):ye.push(Q),Q=ar):P===14?Q=Qi(99,KI.bind(null,v)):(Q=TA(P),Q=Qi(Q,mD.bind(null,v))),v.callbackPriority=P,v.callbackNode=Q}}function mD(v){if(Yd=-1,Kd=kc=0,Sr&48)throw Error(u(327));var P=v.callbackNode;if(Qc()&&v.callbackNode!==P)return null;var Q=Oo(v,v===Os?ms:0);if(Q===0)return null;var H=Q,Y=Sr;Sr|=16;var ne=ID();(Os!==v||ms!==H)&&(ku(),Pp(v,H));do try{JF();break}catch(Ue){CD(v,Ue)}while(!0);if(s0(),jd.current=ne,Sr=Y,Oi!==null?H=0:(Os=null,ms=0,H=is),Bp&vp)Pp(v,0);else if(H!==0){if(H===2&&(Sr|=64,v.hydrate&&(v.hydrate=!1,hs(v.containerInfo)),Q=qa(v),Q!==0&&(H=b0(v,Q))),H===1)throw P=Gd,Pp(v,0),Dp(v,Q),qo(v,Dt()),P;switch(v.finishedWork=v.current.alternate,v.finishedLanes=Q,H){case 0:case 1:throw Error(u(345));case 2:zA(v);break;case 3:if(Dp(v,Q),(Q&62914560)===Q&&(H=HI+500-Dt(),10<H)){if(Oo(v,0)!==0)break;if(Y=v.suspendedLanes,(Y&Q)!==Q){oo(),v.pingedLanes|=v.suspendedLanes&Y;break}v.timeoutHandle=x(zA.bind(null,v),H);break}zA(v);break;case 4:if(Dp(v,Q),(Q&4186112)===Q)break;for(H=v.eventTimes,Y=-1;0<Q;){var Be=31-qi(Q);ne=1<<Be,Be=H[Be],Be>Y&&(Y=Be),Q&=~ne}if(Q=Y,Q=Dt()-Q,Q=(120>Q?120:480>Q?480:1080>Q?1080:1920>Q?1920:3e3>Q?3e3:4320>Q?4320:1960*KF(Q/1960))-Q,10<Q){v.timeoutHandle=x(zA.bind(null,v),Q);break}zA(v);break;case 5:zA(v);break;default:throw Error(u(329))}}return qo(v,Dt()),v.callbackNode===P?mD.bind(null,v):null}function Dp(v,P){for(P&=~UI,P&=~vp,v.suspendedLanes|=P,v.pingedLanes&=~P,v=v.expirationTimes;0<P;){var Q=31-qi(P),H=1<<Q;v[Q]=-1,P&=~H}}function KI(v){if(Sr&48)throw Error(u(327));if(Qc(),v===Os&&v.expiredLanes&ms){var P=ms,Q=b0(v,P);Bp&vp&&(P=Oo(v,P),Q=b0(v,P))}else P=Oo(v,0),Q=b0(v,P);if(v.tag!==0&&Q===2&&(Sr|=64,v.hydrate&&(v.hydrate=!1,hs(v.containerInfo)),P=qa(v),P!==0&&(Q=b0(v,P))),Q===1)throw Q=Gd,Pp(v,0),Dp(v,P),qo(v,Dt()),Q;return v.finishedWork=v.current.alternate,v.finishedLanes=P,zA(v),qo(v,Dt()),null}function VF(){if(bc!==null){var v=bc;bc=null,v.forEach(function(P){P.expiredLanes|=24&P.pendingLanes,qo(P,Dt())})}Pn()}function yD(v,P){var Q=Sr;Sr|=1;try{return v(P)}finally{Sr=Q,Sr===0&&(ku(),Pn())}}function ED(v,P){var Q=Sr;if(Q&48)return v(P);Sr|=1;try{if(v)return ei(99,v.bind(null,P))}finally{Sr=Q,Pn()}}function zd(v,P){Bn(MI,VA),VA|=P,Bp|=P}function VI(){VA=MI.current,Ft(MI)}function Pp(v,P){v.finishedWork=null,v.finishedLanes=0;var Q=v.timeoutHandle;if(Q!==S&&(v.timeoutHandle=S,I(Q)),Oi!==null)for(Q=Oi.return;Q!==null;){var H=Q;switch(H.tag){case 1:H=H.type.childContextTypes,H!=null&&Ec();break;case 3:Bc(),Ft(vi),Ft(ki),Dc();break;case 5:wt(H);break;case 4:Bc();break;case 13:Ft(oi);break;case 19:Ft(oi);break;case 10:a0(H);break;case 23:case 24:VI()}Q=Q.return}Os=v,Oi=Fc(v.current,null),ms=VA=Bp=P,is=0,Gd=null,UI=vp=B0=0}function CD(v,P){do{var Q=Oi;try{if(s0(),Bu.current=bt,HA){for(var H=On.memoizedState;H!==null;){var Y=H.queue;Y!==null&&(Y.pending=null),H=H.next}HA=!1}if(Pc=0,Ci=ji=On=null,vu=!1,NI.current=null,Q===null||Q.return===null){is=1,Gd=P,Oi=null;break}e:{var ne=v,Be=Q.return,Ue=Q,ft=P;if(P=ms,Ue.flags|=2048,Ue.firstEffect=Ue.lastEffect=null,ft!==null&&typeof ft==\"object\"&&typeof ft.then==\"function\"){var jt=ft;if(!(Ue.mode&2)){var wr=Ue.alternate;wr?(Ue.updateQueue=wr.updateQueue,Ue.memoizedState=wr.memoizedState,Ue.lanes=wr.lanes):(Ue.updateQueue=null,Ue.memoizedState=null)}var Tr=(oi.current&1)!==0,Xt=Be;do{var jn;if(jn=Xt.tag===13){var li=Xt.memoizedState;if(li!==null)jn=li.dehydrated!==null;else{var Ea=Xt.memoizedProps;jn=Ea.fallback===void 0?!1:Ea.unstable_avoidThisFallback!==!0?!0:!Tr}}if(jn){var $e=Xt.updateQueue;if($e===null){var je=new Set;je.add(jt),Xt.updateQueue=je}else $e.add(jt);if(!(Xt.mode&2)){if(Xt.flags|=64,Ue.flags|=16384,Ue.flags&=-2981,Ue.tag===1)if(Ue.alternate===null)Ue.tag=17;else{var pt=Wa(-1,1);pt.tag=2,Ya(Ue,pt)}Ue.lanes|=1;break e}ft=void 0,Ue=P;var Jt=ne.pingCache;if(Jt===null?(Jt=ne.pingCache=new jF,ft=new Set,Jt.set(jt,ft)):(ft=Jt.get(jt),ft===void 0&&(ft=new Set,Jt.set(jt,ft))),!ft.has(Ue)){ft.add(Ue);var Br=PD.bind(null,ne,jt,Ue);jt.then(Br,Br)}Xt.flags|=4096,Xt.lanes=P;break e}Xt=Xt.return}while(Xt!==null);ft=Error((g(Ue.type)||\"A React component\")+` suspended while rendering, but no fallback UI was specified.\n\nAdd a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.`)}is!==5&&(is=2),ft=m0(ft,Ue),Xt=Be;do{switch(Xt.tag){case 3:ne=ft,Xt.flags|=4096,P&=-P,Xt.lanes|=P;var Wn=bI(Xt,ne,P);Dd(Xt,Wn);break e;case 1:ne=ft;var xr=Xt.type,Sn=Xt.stateNode;if(!(Xt.flags&64)&&(typeof xr.getDerivedStateFromError==\"function\"||Sn!==null&&typeof Sn.componentDidCatch==\"function\"&&(bl===null||!bl.has(Sn)))){Xt.flags|=4096,P&=-P,Xt.lanes|=P;var Tn=E0(Xt,ne,P);Dd(Xt,Tn);break e}}Xt=Xt.return}while(Xt!==null)}BD(Q)}catch(Yr){P=Yr,Oi===Q&&Q!==null&&(Oi=Q=Q.return);continue}break}while(!0)}function ID(){var v=jd.current;return jd.current=bt,v===null?bt:v}function b0(v,P){var Q=Sr;Sr|=16;var H=ID();Os===v&&ms===P||Pp(v,P);do try{zF();break}catch(Y){CD(v,Y)}while(!0);if(s0(),Sr=Q,jd.current=H,Oi!==null)throw Error(u(261));return Os=null,ms=0,is}function zF(){for(;Oi!==null;)wD(Oi)}function JF(){for(;Oi!==null&&!ja();)wD(Oi)}function wD(v){var P=SD(v.alternate,v,VA);v.memoizedProps=v.pendingProps,P===null?BD(v):Oi=P,NI.current=null}function BD(v){var P=v;do{var Q=P.alternate;if(v=P.return,P.flags&2048){if(Q=qF(P),Q!==null){Q.flags&=2047,Oi=Q;return}v!==null&&(v.firstEffect=v.lastEffect=null,v.flags|=2048)}else{if(Q=HF(Q,P,VA),Q!==null){Oi=Q;return}if(Q=P,Q.tag!==24&&Q.tag!==23||Q.memoizedState===null||VA&1073741824||!(Q.mode&4)){for(var H=0,Y=Q.child;Y!==null;)H|=Y.lanes|Y.childLanes,Y=Y.sibling;Q.childLanes=H}v!==null&&!(v.flags&2048)&&(v.firstEffect===null&&(v.firstEffect=P.firstEffect),P.lastEffect!==null&&(v.lastEffect!==null&&(v.lastEffect.nextEffect=P.firstEffect),v.lastEffect=P.lastEffect),1<P.flags&&(v.lastEffect!==null?v.lastEffect.nextEffect=P:v.firstEffect=P,v.lastEffect=P))}if(P=P.sibling,P!==null){Oi=P;return}Oi=P=v}while(P!==null);is===0&&(is=5)}function zA(v){var P=er();return ei(99,XF.bind(null,v,P)),null}function XF(v,P){do Qc();while(v0!==null);if(Sr&48)throw Error(u(327));var Q=v.finishedWork;if(Q===null)return null;if(v.finishedWork=null,v.finishedLanes=0,Q===v.current)throw Error(u(177));v.callbackNode=null;var H=Q.lanes|Q.childLanes,Y=H,ne=v.pendingLanes&~Y;v.pendingLanes=Y,v.suspendedLanes=0,v.pingedLanes=0,v.expiredLanes&=Y,v.mutableReadLanes&=Y,v.entangledLanes&=Y,Y=v.entanglements;for(var Be=v.eventTimes,Ue=v.expirationTimes;0<ne;){var ft=31-qi(ne),jt=1<<ft;Y[ft]=0,Be[ft]=-1,Ue[ft]=-1,ne&=~jt}if(bc!==null&&!(H&24)&&bc.has(v)&&bc.delete(v),v===Os&&(Oi=Os=null,ms=0),1<Q.flags?Q.lastEffect!==null?(Q.lastEffect.nextEffect=Q,H=Q.firstEffect):H=Q:H=Q.firstEffect,H!==null){Y=Sr,Sr|=32,NI.current=null,S0=nt(v.containerInfo),x0=!1,ir=H;do try{ZF()}catch(je){if(ir===null)throw Error(u(330));Fu(ir,je),ir=ir.nextEffect}while(ir!==null);S0=null,ir=H;do try{for(Be=v;ir!==null;){var wr=ir.flags;if(wr&16&&R&&gu(ir.stateNode),wr&128){var Tr=ir.alternate;if(Tr!==null){var Xt=Tr.ref;Xt!==null&&(typeof Xt==\"function\"?Xt(null):Xt.current=null)}}switch(wr&1038){case 2:hD(ir),ir.flags&=-3;break;case 6:hD(ir),ir.flags&=-3,RI(ir.alternate,ir);break;case 1024:ir.flags&=-1025;break;case 1028:ir.flags&=-1025,RI(ir.alternate,ir);break;case 4:RI(ir.alternate,ir);break;case 8:Ue=Be,ne=ir,R?gD(Ue,ne):fD(Ue,ne);var jn=ne.alternate;Nd(ne),jn!==null&&Nd(jn)}ir=ir.nextEffect}}catch(je){if(ir===null)throw Error(u(330));Fu(ir,je),ir=ir.nextEffect}while(ir!==null);x0&&lt(),Le(v.containerInfo),v.current=Q,ir=H;do try{for(wr=v;ir!==null;){var li=ir.flags;if(li&36&&uD(wr,ir.alternate,ir),li&128){Tr=void 0;var Ea=ir.ref;if(Ea!==null){var $e=ir.stateNode;switch(ir.tag){case 5:Tr=Re($e);break;default:Tr=$e}typeof Ea==\"function\"?Ea(Tr):Ea.current=Tr}}ir=ir.nextEffect}}catch(je){if(ir===null)throw Error(u(330));Fu(ir,je),ir=ir.nextEffect}while(ir!==null);ir=null,ee(),Sr=Y}else v.current=Q;if(Qu)Qu=!1,v0=v,D0=P;else for(ir=H;ir!==null;)P=ir.nextEffect,ir.nextEffect=null,ir.flags&8&&(li=ir,li.sibling=null,li.stateNode=null),ir=P;if(H=v.pendingLanes,H===0&&(bl=null),H===1?v===YI?P0++:(P0=0,YI=v):P0=0,Q=Q.stateNode,ca&&typeof ca.onCommitFiberRoot==\"function\")try{ca.onCommitFiberRoot(Ze,Q,void 0,(Q.current.flags&64)===64)}catch{}if(qo(v,Dt()),Wd)throw Wd=!1,v=jI,jI=null,v;return Sr&8||Pn(),null}function ZF(){for(;ir!==null;){var v=ir.alternate;x0||S0===null||(ir.flags&8?Pe(ir,S0)&&(x0=!0,Fe()):ir.tag===13&&WF(v,ir)&&Pe(ir,S0)&&(x0=!0,Fe()));var P=ir.flags;P&256&&Td(v,ir),!(P&512)||Qu||(Qu=!0,Qi(97,function(){return Qc(),null})),ir=ir.nextEffect}}function Qc(){if(D0!==90){var v=97<D0?97:D0;return D0=90,ei(v,eR)}return!1}function $F(v,P){GI.push(P,v),Qu||(Qu=!0,Qi(97,function(){return Qc(),null}))}function vD(v,P){WI.push(P,v),Qu||(Qu=!0,Qi(97,function(){return Qc(),null}))}function eR(){if(v0===null)return!1;var v=v0;if(v0=null,Sr&48)throw Error(u(331));var P=Sr;Sr|=32;var Q=WI;WI=[];for(var H=0;H<Q.length;H+=2){var Y=Q[H],ne=Q[H+1],Be=Y.destroy;if(Y.destroy=void 0,typeof Be==\"function\")try{Be()}catch(ft){if(ne===null)throw Error(u(330));Fu(ne,ft)}}for(Q=GI,GI=[],H=0;H<Q.length;H+=2){Y=Q[H],ne=Q[H+1];try{var Ue=Y.create;Y.destroy=Ue()}catch(ft){if(ne===null)throw Error(u(330));Fu(ne,ft)}}for(Ue=v.current.firstEffect;Ue!==null;)v=Ue.nextEffect,Ue.nextEffect=null,Ue.flags&8&&(Ue.sibling=null,Ue.stateNode=null),Ue=v;return Sr=P,Pn(),!0}function DD(v,P,Q){P=m0(Q,P),P=bI(v,P,1),Ya(v,P),P=oo(),v=Vd(v,1),v!==null&&(ua(v,1,P),qo(v,P))}function Fu(v,P){if(v.tag===3)DD(v,v,P);else for(var Q=v.return;Q!==null;){if(Q.tag===3){DD(Q,v,P);break}else if(Q.tag===1){var H=Q.stateNode;if(typeof Q.type.getDerivedStateFromError==\"function\"||typeof H.componentDidCatch==\"function\"&&(bl===null||!bl.has(H))){v=m0(P,v);var Y=E0(Q,v,1);if(Ya(Q,Y),Y=oo(),Q=Vd(Q,1),Q!==null)ua(Q,1,Y),qo(Q,Y);else if(typeof H.componentDidCatch==\"function\"&&(bl===null||!bl.has(H)))try{H.componentDidCatch(P,v)}catch{}break}}Q=Q.return}}function PD(v,P,Q){var H=v.pingCache;H!==null&&H.delete(P),P=oo(),v.pingedLanes|=v.suspendedLanes&Q,Os===v&&(ms&Q)===Q&&(is===4||is===3&&(ms&62914560)===ms&&500>Dt()-HI?Pp(v,0):UI|=Q),qo(v,P)}function tR(v,P){var Q=v.stateNode;Q!==null&&Q.delete(P),P=0,P===0&&(P=v.mode,P&2?P&4?(kc===0&&(kc=Bp),P=vn(62914560&~kc),P===0&&(P=4194304)):P=er()===99?1:2:P=1),Q=oo(),v=Vd(v,P),v!==null&&(ua(v,P,Q),qo(v,Q))}var SD;SD=function(v,P,Q){var H=P.lanes;if(v!==null)if(v.memoizedProps!==P.pendingProps||vi.current)Ye=!0;else if(Q&H)Ye=!!(v.flags&16384);else{switch(Ye=!1,P.tag){case 3:Fd(P),p0();break;case 5:wu(P);break;case 1:qn(P.type)&&aa(P);break;case 4:u0(P,P.stateNode.containerInfo);break;case 10:o0(P,P.memoizedProps.value);break;case 13:if(P.memoizedState!==null)return Q&P.child.childLanes?SI(v,P,Q):(Bn(oi,oi.current&1),P=Mn(v,P,Q),P!==null?P.sibling:null);Bn(oi,oi.current&1);break;case 19:if(H=(Q&P.childLanes)!==0,v.flags&64){if(H)return cD(v,P,Q);P.flags|=64}var Y=P.memoizedState;if(Y!==null&&(Y.rendering=null,Y.tail=null,Y.lastEffect=null),Bn(oi,oi.current),H)break;return null;case 23:case 24:return P.lanes=0,ai(v,P,Q)}return Mn(v,P,Q)}else Ye=!1;switch(P.lanes=0,P.tag){case 2:if(H=P.type,v!==null&&(v.alternate=null,P.alternate=null,P.flags|=2),v=P.pendingProps,Y=un(P,ki.current),Eu(P,Q),Y=g0(null,P,H,v,Y,Q),P.flags|=1,typeof Y==\"object\"&&Y!==null&&typeof Y.render==\"function\"&&Y.$$typeof===void 0){if(P.tag=1,P.memoizedState=null,P.updateQueue=null,qn(H)){var ne=!0;aa(P)}else ne=!1;P.memoizedState=Y.state!==null&&Y.state!==void 0?Y.state:null,pp(P);var Be=H.getDerivedStateFromProps;typeof Be==\"function\"&&NA(P,H,Be,v),Y.updater=OA,P.stateNode=Y,Y._reactInternals=P,no(P,H,v,Q),P=PI(null,P,H,!0,ne,Q)}else P.tag=0,At(null,P,Y,Q),P=P.child;return P;case 16:Y=P.elementType;e:{switch(v!==null&&(v.alternate=null,P.alternate=null,P.flags|=2),v=P.pendingProps,ne=Y._init,Y=ne(Y._payload),P.type=Y,ne=P.tag=nR(Y),v=to(Y,v),ne){case 0:P=GA(null,P,Y,v,Q);break e;case 1:P=lD(null,P,Y,v,Q);break e;case 11:P=hr(null,P,Y,v,Q);break e;case 14:P=Ir(null,P,Y,to(Y.type,v),H,Q);break e}throw Error(u(306,Y,\"\"))}return P;case 0:return H=P.type,Y=P.pendingProps,Y=P.elementType===H?Y:to(H,Y),GA(v,P,H,Y,Q);case 1:return H=P.type,Y=P.pendingProps,Y=P.elementType===H?Y:to(H,Y),lD(v,P,H,Y,Q);case 3:if(Fd(P),H=P.updateQueue,v===null||H===null)throw Error(u(282));if(H=P.pendingProps,Y=P.memoizedState,Y=Y!==null?Y.element:null,l0(v,P),LA(P,H,null,Q),H=P.memoizedState.element,H===Y)p0(),P=Mn(v,P,Q);else{if(Y=P.stateNode,(ne=Y.hydrate)&&(X?(Uo=dc(P.stateNode.containerInfo),ha=P,ne=ga=!0):ne=!1),ne){if(X&&(v=Y.mutableSourceEagerHydrationData,v!=null))for(Y=0;Y<v.length;Y+=2)ne=v[Y],Be=v[Y+1],y?ne._workInProgressVersionPrimary=Be:ne._workInProgressVersionSecondary=Be,vc.push(ne);for(Q=DI(P,null,H,Q),P.child=Q;Q;)Q.flags=Q.flags&-3|1024,Q=Q.sibling}else At(v,P,H,Q),p0();P=P.child}return P;case 5:return wu(P),v===null&&f0(P),H=P.type,Y=P.pendingProps,ne=v!==null?v.memoizedProps:null,Be=Y.children,tt(H,Y)?Be=null:ne!==null&&tt(H,ne)&&(P.flags|=16),ns(v,P),At(v,P,Be,Q),P.child;case 6:return v===null&&f0(P),null;case 13:return SI(v,P,Q);case 4:return u0(P,P.stateNode.containerInfo),H=P.pendingProps,v===null?P.child=c0(P,null,H,Q):At(v,P,H,Q),P.child;case 11:return H=P.type,Y=P.pendingProps,Y=P.elementType===H?Y:to(H,Y),hr(v,P,H,Y,Q);case 7:return At(v,P,P.pendingProps,Q),P.child;case 8:return At(v,P,P.pendingProps.children,Q),P.child;case 12:return At(v,P,P.pendingProps.children,Q),P.child;case 10:e:{if(H=P.type._context,Y=P.pendingProps,Be=P.memoizedProps,ne=Y.value,o0(P,ne),Be!==null){var Ue=Be.value;if(ne=eo(Ue,ne)?0:(typeof H._calculateChangedBits==\"function\"?H._calculateChangedBits(Ue,ne):1073741823)|0,ne===0){if(Be.children===Y.children&&!vi.current){P=Mn(v,P,Q);break e}}else for(Ue=P.child,Ue!==null&&(Ue.return=P);Ue!==null;){var ft=Ue.dependencies;if(ft!==null){Be=Ue.child;for(var jt=ft.firstContext;jt!==null;){if(jt.context===H&&jt.observedBits&ne){Ue.tag===1&&(jt=Wa(-1,Q&-Q),jt.tag=2,Ya(Ue,jt)),Ue.lanes|=Q,jt=Ue.alternate,jt!==null&&(jt.lanes|=Q),vd(Ue.return,Q),ft.lanes|=Q;break}jt=jt.next}}else Be=Ue.tag===10&&Ue.type===P.type?null:Ue.child;if(Be!==null)Be.return=Ue;else for(Be=Ue;Be!==null;){if(Be===P){Be=null;break}if(Ue=Be.sibling,Ue!==null){Ue.return=Be.return,Be=Ue;break}Be=Be.return}Ue=Be}}At(v,P,Y.children,Q),P=P.child}return P;case 9:return Y=P.type,ne=P.pendingProps,H=ne.children,Eu(P,Q),Y=ro(Y,ne.unstable_observedBits),H=H(Y),P.flags|=1,At(v,P,H,Q),P.child;case 14:return Y=P.type,ne=to(Y,P.pendingProps),ne=to(Y.type,ne),Ir(v,P,Y,ne,H,Q);case 15:return Rn(v,P,P.type,P.pendingProps,H,Q);case 17:return H=P.type,Y=P.pendingProps,Y=P.elementType===H?Y:to(H,Y),v!==null&&(v.alternate=null,P.alternate=null,P.flags|=2),P.tag=1,qn(H)?(v=!0,aa(P)):v=!1,Eu(P,Q),xt(P,H,Y),no(P,H,Y,Q),PI(null,P,H,!0,v,Q);case 19:return cD(v,P,Q);case 23:return ai(v,P,Q);case 24:return ai(v,P,Q)}throw Error(u(156,P.tag))};var Jd={current:!1},ys=n.unstable_flushAllWithoutAsserting,xD=typeof ys==\"function\";function zI(){if(ys!==void 0)return ys();for(var v=!1;Qc();)v=!0;return v}function jo(v){try{zI(),YF(function(){zI()?jo(v):v()})}catch(P){v(P)}}var ma=0,Xd=!1;function rR(v,P,Q,H){this.tag=v,this.key=Q,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=P,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=H,this.flags=0,this.lastEffect=this.firstEffect=this.nextEffect=null,this.childLanes=this.lanes=0,this.alternate=null}function ya(v,P,Q,H){return new rR(v,P,Q,H)}function JI(v){return v=v.prototype,!(!v||!v.isReactComponent)}function nR(v){if(typeof v==\"function\")return JI(v)?1:0;if(v!=null){if(v=v.$$typeof,v===T)return 11;if(v===z)return 14}return 2}function Fc(v,P){var Q=v.alternate;return Q===null?(Q=ya(v.tag,P,v.key,v.mode),Q.elementType=v.elementType,Q.type=v.type,Q.stateNode=v.stateNode,Q.alternate=v,v.alternate=Q):(Q.pendingProps=P,Q.type=v.type,Q.flags=0,Q.nextEffect=null,Q.firstEffect=null,Q.lastEffect=null),Q.childLanes=v.childLanes,Q.lanes=v.lanes,Q.child=v.child,Q.memoizedProps=v.memoizedProps,Q.memoizedState=v.memoizedState,Q.updateQueue=v.updateQueue,P=v.dependencies,Q.dependencies=P===null?null:{lanes:P.lanes,firstContext:P.firstContext},Q.sibling=v.sibling,Q.index=v.index,Q.ref=v.ref,Q}function k0(v,P,Q,H,Y,ne){var Be=2;if(H=v,typeof v==\"function\")JI(v)&&(Be=1);else if(typeof v==\"string\")Be=5;else e:switch(v){case E:return Ru(Q.children,Y,ne,P);case ce:Be=8,Y|=16;break;case w:Be=8,Y|=1;break;case D:return v=ya(12,Q,P,Y|8),v.elementType=D,v.type=D,v.lanes=ne,v;case N:return v=ya(13,Q,P,Y),v.type=N,v.elementType=N,v.lanes=ne,v;case U:return v=ya(19,Q,P,Y),v.elementType=U,v.lanes=ne,v;case ue:return XI(Q,Y,ne,P);case Ie:return v=ya(24,Q,P,Y),v.elementType=Ie,v.lanes=ne,v;default:if(typeof v==\"object\"&&v!==null)switch(v.$$typeof){case b:Be=10;break e;case C:Be=9;break e;case T:Be=11;break e;case z:Be=14;break e;case te:Be=16,H=null;break e;case le:Be=22;break e}throw Error(u(130,v==null?v:typeof v,\"\"))}return P=ya(Be,Q,P,Y),P.elementType=v,P.type=H,P.lanes=ne,P}function Ru(v,P,Q,H){return v=ya(7,v,H,P),v.lanes=Q,v}function XI(v,P,Q,H){return v=ya(23,v,H,P),v.elementType=ue,v.lanes=Q,v}function ZI(v,P,Q){return v=ya(6,v,null,P),v.lanes=Q,v}function ao(v,P,Q){return P=ya(4,v.children!==null?v.children:[],v.key,P),P.lanes=Q,P.stateNode={containerInfo:v.containerInfo,pendingChildren:null,implementation:v.implementation},P}function iR(v,P,Q){this.tag=P,this.containerInfo=v,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=S,this.pendingContext=this.context=null,this.hydrate=Q,this.callbackNode=null,this.callbackPriority=0,this.eventTimes=Mo(0),this.expirationTimes=Mo(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=Mo(0),X&&(this.mutableSourceEagerHydrationData=null)}function bD(v){var P=v._reactInternals;if(P===void 0)throw typeof v.render==\"function\"?Error(u(188)):Error(u(268,Object.keys(v)));return v=ie(P),v===null?null:v.stateNode}function kD(v,P){if(v=v.memoizedState,v!==null&&v.dehydrated!==null){var Q=v.retryLane;v.retryLane=Q!==0&&Q<P?Q:P}}function Zd(v,P){kD(v,P),(v=v.alternate)&&kD(v,P)}function sR(v){return v=ie(v),v===null?null:v.stateNode}function oR(){return null}return r.IsThisRendererActing=Jd,r.act=function(v){function P(){ma--,OI.current=Q,Jd.current=H}Xd===!1&&(Xd=!0,console.error(\"act(...) is not supported in production builds of React, and might not behave as expected.\")),ma++;var Q=OI.current,H=Jd.current;OI.current=!0,Jd.current=!0;try{var Y=yD(v)}catch(ne){throw P(),ne}if(Y!==null&&typeof Y==\"object\"&&typeof Y.then==\"function\")return{then:function(ne,Be){Y.then(function(){1<ma||xD===!0&&Q===!0?(P(),ne()):jo(function(Ue){P(),Ue?Be(Ue):ne()})},function(Ue){P(),Be(Ue)})}};try{ma!==1||xD!==!1&&Q!==!1||zI(),P()}catch(ne){throw P(),ne}return{then:function(ne){ne()}}},r.attemptContinuousHydration=function(v){if(v.tag===13){var P=oo();Xa(v,67108864,P),Zd(v,67108864)}},r.attemptHydrationAtCurrentPriority=function(v){if(v.tag===13){var P=oo(),Q=ss(v);Xa(v,Q,P),Zd(v,Q)}},r.attemptSynchronousHydration=function(v){switch(v.tag){case 3:var P=v.stateNode;if(P.hydrate){var Q=No(P.pendingLanes);P.expiredLanes|=Q&P.pendingLanes,qo(P,Dt()),!(Sr&48)&&(ku(),Pn())}break;case 13:var H=oo();ED(function(){return Xa(v,1,H)}),Zd(v,4)}},r.attemptUserBlockingHydration=function(v){if(v.tag===13){var P=oo();Xa(v,4,P),Zd(v,4)}},r.batchedEventUpdates=function(v,P){var Q=Sr;Sr|=2;try{return v(P)}finally{Sr=Q,Sr===0&&(ku(),Pn())}},r.batchedUpdates=yD,r.createComponentSelector=function(v){return{$$typeof:Od,value:v}},r.createContainer=function(v,P,Q){return v=new iR(v,P,Q),P=ya(3,null,null,P===2?7:P===1?3:0),v.current=P,P.stateNode=v,pp(P),v},r.createHasPsuedoClassSelector=function(v){return{$$typeof:Md,value:v}},r.createPortal=function(v,P,Q){var H=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:h,key:H==null?null:\"\"+H,children:v,containerInfo:P,implementation:Q}},r.createRoleSelector=function(v){return{$$typeof:Ud,value:v}},r.createTestNameSelector=function(v){return{$$typeof:I0,value:v}},r.createTextSelector=function(v){return{$$typeof:_d,value:v}},r.deferredUpdates=function(v){return ei(97,v)},r.discreteUpdates=function(v,P,Q,H,Y){var ne=Sr;Sr|=4;try{return ei(98,v.bind(null,P,Q,H,Y))}finally{Sr=ne,Sr===0&&(ku(),Pn())}},r.findAllNodes=LI,r.findBoundingRects=function(v,P){if(!qt)throw Error(u(363));P=LI(v,P),v=[];for(var Q=0;Q<P.length;Q++)v.push(St(P[Q]));for(P=v.length-1;0<P;P--){Q=v[P];for(var H=Q.x,Y=H+Q.width,ne=Q.y,Be=ne+Q.height,Ue=P-1;0<=Ue;Ue--)if(P!==Ue){var ft=v[Ue],jt=ft.x,wr=jt+ft.width,Tr=ft.y,Xt=Tr+ft.height;if(H>=jt&&ne>=Tr&&Y<=wr&&Be<=Xt){v.splice(P,1);break}else if(H!==jt||Q.width!==ft.width||Xt<ne||Tr>Be){if(!(ne!==Tr||Q.height!==ft.height||wr<H||jt>Y)){jt>H&&(ft.width+=jt-H,ft.x=H),wr<Y&&(ft.width=Y-jt),v.splice(P,1);break}}else{Tr>ne&&(ft.height+=Tr-ne,ft.y=ne),Xt<Be&&(ft.height=Be-Tr),v.splice(P,1);break}}}return v},r.findHostInstance=bD,r.findHostInstanceWithNoPortals=function(v){return v=Z(v),v===null?null:v.tag===20?v.stateNode.instance:v.stateNode},r.findHostInstanceWithWarning=function(v){return bD(v)},r.flushControlled=function(v){var P=Sr;Sr|=1;try{ei(99,v)}finally{Sr=P,Sr===0&&(ku(),Pn())}},r.flushDiscreteUpdates=function(){!(Sr&49)&&(VF(),Qc())},r.flushPassiveEffects=Qc,r.flushSync=ED,r.focusWithin=function(v,P){if(!qt)throw Error(u(363));for(v=Hd(v),P=TI(v,P),P=Array.from(P),v=0;v<P.length;){var Q=P[v++];if(!Pr(Q)){if(Q.tag===5&&Rr(Q.stateNode))return!0;for(Q=Q.child;Q!==null;)P.push(Q),Q=Q.sibling}}return!1},r.getCurrentUpdateLanePriority=function(){return Bl},r.getFindAllNodesFailureDescription=function(v,P){if(!qt)throw Error(u(363));var Q=0,H=[];v=[Hd(v),0];for(var Y=0;Y<v.length;){var ne=v[Y++],Be=v[Y++],Ue=P[Be];if((ne.tag!==5||!Pr(ne))&&(xu(ne,Ue)&&(H.push(bu(Ue)),Be++,Be>Q&&(Q=Be)),Be<P.length))for(ne=ne.child;ne!==null;)v.push(ne,Be),ne=ne.sibling}if(Q<P.length){for(v=[];Q<P.length;Q++)v.push(bu(P[Q]));return`findAllNodes was able to match part of the selector:\n  `+(H.join(\" > \")+`\n\nNo matching component was found for:\n  `)+v.join(\" > \")}return null},r.getPublicRootInstance=function(v){if(v=v.current,!v.child)return null;switch(v.child.tag){case 5:return Re(v.child.stateNode);default:return v.child.stateNode}},r.injectIntoDevTools=function(v){if(v={bundleType:v.bundleType,version:v.version,rendererPackageName:v.rendererPackageName,rendererConfig:v.rendererConfig,overrideHookState:null,overrideHookStateDeletePath:null,overrideHookStateRenamePath:null,overrideProps:null,overridePropsDeletePath:null,overridePropsRenamePath:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:A.ReactCurrentDispatcher,findHostInstanceByFiber:sR,findFiberByHostInstance:v.findFiberByHostInstance||oR,findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null},typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>\"u\")v=!1;else{var P=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(!P.isDisabled&&P.supportsFiber)try{Ze=P.inject(v),ca=P}catch{}v=!0}return v},r.observeVisibleRects=function(v,P,Q,H){if(!qt)throw Error(u(363));v=LI(v,P);var Y=Xr(v,Q,H).disconnect;return{disconnect:function(){Y()}}},r.registerMutableSourceForHydration=function(v,P){var Q=P._getVersion;Q=Q(P._source),v.mutableSourceEagerHydrationData==null?v.mutableSourceEagerHydrationData=[P,Q]:v.mutableSourceEagerHydrationData.push(P,Q)},r.runWithPriority=function(v,P){var Q=Bl;try{return Bl=v,P()}finally{Bl=Q}},r.shouldSuspend=function(){return!1},r.unbatchedUpdates=function(v,P){var Q=Sr;Sr&=-2,Sr|=8;try{return v(P)}finally{Sr=Q,Sr===0&&(ku(),Pn())}},r.updateContainer=function(v,P,Q,H){var Y=P.current,ne=oo(),Be=ss(Y);e:if(Q){Q=Q._reactInternals;t:{if(me(Q)!==Q||Q.tag!==1)throw Error(u(170));var Ue=Q;do{switch(Ue.tag){case 3:Ue=Ue.stateNode.context;break t;case 1:if(qn(Ue.type)){Ue=Ue.stateNode.__reactInternalMemoizedMergedChildContext;break t}}Ue=Ue.return}while(Ue!==null);throw Error(u(171))}if(Q.tag===1){var ft=Q.type;if(qn(ft)){Q=oa(Q,ft,Ue);break e}}Q=Ue}else Q=Lo;return P.context===null?P.context=Q:P.pendingContext=Q,P=Wa(ne,Be),P.payload={element:v},H=H===void 0?null:H,H!==null&&(P.callback=H),Ya(Y,P),Xa(Y,Be,ne),Be},r}});var ECe=_(($Yt,yCe)=>{\"use strict\";yCe.exports=mCe()});var ICe=_((eKt,CCe)=>{\"use strict\";var Pyt={ALIGN_COUNT:8,ALIGN_AUTO:0,ALIGN_FLEX_START:1,ALIGN_CENTER:2,ALIGN_FLEX_END:3,ALIGN_STRETCH:4,ALIGN_BASELINE:5,ALIGN_SPACE_BETWEEN:6,ALIGN_SPACE_AROUND:7,DIMENSION_COUNT:2,DIMENSION_WIDTH:0,DIMENSION_HEIGHT:1,DIRECTION_COUNT:3,DIRECTION_INHERIT:0,DIRECTION_LTR:1,DIRECTION_RTL:2,DISPLAY_COUNT:2,DISPLAY_FLEX:0,DISPLAY_NONE:1,EDGE_COUNT:9,EDGE_LEFT:0,EDGE_TOP:1,EDGE_RIGHT:2,EDGE_BOTTOM:3,EDGE_START:4,EDGE_END:5,EDGE_HORIZONTAL:6,EDGE_VERTICAL:7,EDGE_ALL:8,EXPERIMENTAL_FEATURE_COUNT:1,EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS:0,FLEX_DIRECTION_COUNT:4,FLEX_DIRECTION_COLUMN:0,FLEX_DIRECTION_COLUMN_REVERSE:1,FLEX_DIRECTION_ROW:2,FLEX_DIRECTION_ROW_REVERSE:3,JUSTIFY_COUNT:6,JUSTIFY_FLEX_START:0,JUSTIFY_CENTER:1,JUSTIFY_FLEX_END:2,JUSTIFY_SPACE_BETWEEN:3,JUSTIFY_SPACE_AROUND:4,JUSTIFY_SPACE_EVENLY:5,LOG_LEVEL_COUNT:6,LOG_LEVEL_ERROR:0,LOG_LEVEL_WARN:1,LOG_LEVEL_INFO:2,LOG_LEVEL_DEBUG:3,LOG_LEVEL_VERBOSE:4,LOG_LEVEL_FATAL:5,MEASURE_MODE_COUNT:3,MEASURE_MODE_UNDEFINED:0,MEASURE_MODE_EXACTLY:1,MEASURE_MODE_AT_MOST:2,NODE_TYPE_COUNT:2,NODE_TYPE_DEFAULT:0,NODE_TYPE_TEXT:1,OVERFLOW_COUNT:3,OVERFLOW_VISIBLE:0,OVERFLOW_HIDDEN:1,OVERFLOW_SCROLL:2,POSITION_TYPE_COUNT:2,POSITION_TYPE_RELATIVE:0,POSITION_TYPE_ABSOLUTE:1,PRINT_OPTIONS_COUNT:3,PRINT_OPTIONS_LAYOUT:1,PRINT_OPTIONS_STYLE:2,PRINT_OPTIONS_CHILDREN:4,UNIT_COUNT:4,UNIT_UNDEFINED:0,UNIT_POINT:1,UNIT_PERCENT:2,UNIT_AUTO:3,WRAP_COUNT:3,WRAP_NO_WRAP:0,WRAP_WRAP:1,WRAP_WRAP_REVERSE:2};CCe.exports=Pyt});var DCe=_((tKt,vCe)=>{\"use strict\";var Syt=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var r=arguments[e];for(var o in r)Object.prototype.hasOwnProperty.call(r,o)&&(t[o]=r[o])}return t},BQ=function(){function t(e,r){for(var o=0;o<r.length;o++){var a=r[o];a.enumerable=a.enumerable||!1,a.configurable=!0,\"value\"in a&&(a.writable=!0),Object.defineProperty(e,a.key,a)}}return function(e,r,o){return r&&t(e.prototype,r),o&&t(e,o),e}}();function Aq(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function fq(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}var au=ICe(),xyt=function(){function t(e,r,o,a,n,u){fq(this,t),this.left=e,this.right=r,this.top=o,this.bottom=a,this.width=n,this.height=u}return BQ(t,[{key:\"fromJS\",value:function(r){r(this.left,this.right,this.top,this.bottom,this.width,this.height)}},{key:\"toString\",value:function(){return\"<Layout#\"+this.left+\":\"+this.right+\";\"+this.top+\":\"+this.bottom+\";\"+this.width+\":\"+this.height+\">\"}}]),t}(),wCe=function(){BQ(t,null,[{key:\"fromJS\",value:function(r){var o=r.width,a=r.height;return new t(o,a)}}]);function t(e,r){fq(this,t),this.width=e,this.height=r}return BQ(t,[{key:\"fromJS\",value:function(r){r(this.width,this.height)}},{key:\"toString\",value:function(){return\"<Size#\"+this.width+\"x\"+this.height+\">\"}}]),t}(),BCe=function(){function t(e,r){fq(this,t),this.unit=e,this.value=r}return BQ(t,[{key:\"fromJS\",value:function(r){r(this.unit,this.value)}},{key:\"toString\",value:function(){switch(this.unit){case au.UNIT_POINT:return String(this.value);case au.UNIT_PERCENT:return this.value+\"%\";case au.UNIT_AUTO:return\"auto\";default:return this.value+\"?\"}}},{key:\"valueOf\",value:function(){return this.value}}]),t}();vCe.exports=function(t,e){function r(u,A,p){var h=u[A];u[A]=function(){for(var E=arguments.length,w=Array(E),D=0;D<E;D++)w[D]=arguments[D];return p.call.apply(p,[this,h].concat(w))}}for(var o=[\"setPosition\",\"setMargin\",\"setFlexBasis\",\"setWidth\",\"setHeight\",\"setMinWidth\",\"setMinHeight\",\"setMaxWidth\",\"setMaxHeight\",\"setPadding\"],a=function(){var A,p=o[n],h=(A={},Aq(A,au.UNIT_POINT,e.Node.prototype[p]),Aq(A,au.UNIT_PERCENT,e.Node.prototype[p+\"Percent\"]),Aq(A,au.UNIT_AUTO,e.Node.prototype[p+\"Auto\"]),A);r(e.Node.prototype,p,function(E){for(var w=arguments.length,D=Array(w>1?w-1:0),b=1;b<w;b++)D[b-1]=arguments[b];var C=D.pop(),T=void 0,N=void 0;if(C===\"auto\")T=au.UNIT_AUTO,N=void 0;else if(C instanceof BCe)T=C.unit,N=C.valueOf();else if(T=typeof C==\"string\"&&C.endsWith(\"%\")?au.UNIT_PERCENT:au.UNIT_POINT,N=parseFloat(C),!Number.isNaN(C)&&Number.isNaN(N))throw new Error(\"Invalid value \"+C+\" for \"+p);if(!h[T])throw new Error('Failed to execute \"'+p+`\": Unsupported unit '`+C+\"'\");if(N!==void 0){var U;return(U=h[T]).call.apply(U,[this].concat(D,[N]))}else{var z;return(z=h[T]).call.apply(z,[this].concat(D))}})},n=0;n<o.length;n++)a();return r(e.Config.prototype,\"free\",function(){e.Config.destroy(this)}),r(e.Node,\"create\",function(u,A){return A?e.Node.createWithConfig(A):e.Node.createDefault()}),r(e.Node.prototype,\"free\",function(){e.Node.destroy(this)}),r(e.Node.prototype,\"freeRecursive\",function(){for(var u=0,A=this.getChildCount();u<A;++u)this.getChild(0).freeRecursive();this.free()}),r(e.Node.prototype,\"setMeasureFunc\",function(u,A){return A?u.call(this,function(){return wCe.fromJS(A.apply(void 0,arguments))}):this.unsetMeasureFunc()}),r(e.Node.prototype,\"calculateLayout\",function(u){var A=arguments.length>1&&arguments[1]!==void 0?arguments[1]:NaN,p=arguments.length>2&&arguments[2]!==void 0?arguments[2]:NaN,h=arguments.length>3&&arguments[3]!==void 0?arguments[3]:au.DIRECTION_LTR;return u.call(this,A,p,h)}),Syt({Config:e.Config,Node:e.Node,Layout:t(\"Layout\",xyt),Size:t(\"Size\",wCe),Value:t(\"Value\",BCe),getInstanceCount:function(){return e.getInstanceCount.apply(e,arguments)}},au)}});var PCe=_((exports,module)=>{(function(t,e){typeof define==\"function\"&&define.amd?define([],function(){return e}):typeof module==\"object\"&&module.exports?module.exports=e:(t.nbind=t.nbind||{}).init=e})(exports,function(Module,cb){typeof Module==\"function\"&&(cb=Module,Module={}),Module.onRuntimeInitialized=function(t,e){return function(){t&&t.apply(this,arguments);try{Module.ccall(\"nbind_init\")}catch(r){e(r);return}e(null,{bind:Module._nbind_value,reflect:Module.NBind.reflect,queryType:Module.NBind.queryType,toggleLightGC:Module.toggleLightGC,lib:Module})}}(Module.onRuntimeInitialized,cb);var Module;Module||(Module=(typeof Module<\"u\"?Module:null)||{});var moduleOverrides={};for(var key in Module)Module.hasOwnProperty(key)&&(moduleOverrides[key]=Module[key]);var ENVIRONMENT_IS_WEB=!1,ENVIRONMENT_IS_WORKER=!1,ENVIRONMENT_IS_NODE=!1,ENVIRONMENT_IS_SHELL=!1;if(Module.ENVIRONMENT)if(Module.ENVIRONMENT===\"WEB\")ENVIRONMENT_IS_WEB=!0;else if(Module.ENVIRONMENT===\"WORKER\")ENVIRONMENT_IS_WORKER=!0;else if(Module.ENVIRONMENT===\"NODE\")ENVIRONMENT_IS_NODE=!0;else if(Module.ENVIRONMENT===\"SHELL\")ENVIRONMENT_IS_SHELL=!0;else throw new Error(\"The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.\");else ENVIRONMENT_IS_WEB=typeof window==\"object\",ENVIRONMENT_IS_WORKER=typeof importScripts==\"function\",ENVIRONMENT_IS_NODE=typeof process==\"object\"&&typeof ve==\"function\"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER,ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE){Module.print||(Module.print=console.log),Module.printErr||(Module.printErr=console.warn);var nodeFS,nodePath;Module.read=function(e,r){nodeFS||(nodeFS={}(\"\")),nodePath||(nodePath={}(\"\")),e=nodePath.normalize(e);var o=nodeFS.readFileSync(e);return r?o:o.toString()},Module.readBinary=function(e){var r=Module.read(e,!0);return r.buffer||(r=new Uint8Array(r)),assert(r.buffer),r},Module.load=function(e){globalEval(read(e))},Module.thisProgram||(process.argv.length>1?Module.thisProgram=process.argv[1].replace(/\\\\/g,\"/\"):Module.thisProgram=\"unknown-program\"),Module.arguments=process.argv.slice(2),typeof module<\"u\"&&(module.exports=Module),Module.inspect=function(){return\"[Emscripten Module object]\"}}else if(ENVIRONMENT_IS_SHELL)Module.print||(Module.print=print),typeof printErr<\"u\"&&(Module.printErr=printErr),typeof read<\"u\"?Module.read=read:Module.read=function(){throw\"no read() available\"},Module.readBinary=function(e){if(typeof readbuffer==\"function\")return new Uint8Array(readbuffer(e));var r=read(e,\"binary\");return assert(typeof r==\"object\"),r},typeof scriptArgs<\"u\"?Module.arguments=scriptArgs:typeof arguments<\"u\"&&(Module.arguments=arguments),typeof quit==\"function\"&&(Module.quit=function(t,e){quit(t)});else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(Module.read=function(e){var r=new XMLHttpRequest;return r.open(\"GET\",e,!1),r.send(null),r.responseText},ENVIRONMENT_IS_WORKER&&(Module.readBinary=function(e){var r=new XMLHttpRequest;return r.open(\"GET\",e,!1),r.responseType=\"arraybuffer\",r.send(null),new Uint8Array(r.response)}),Module.readAsync=function(e,r,o){var a=new XMLHttpRequest;a.open(\"GET\",e,!0),a.responseType=\"arraybuffer\",a.onload=function(){a.status==200||a.status==0&&a.response?r(a.response):o()},a.onerror=o,a.send(null)},typeof arguments<\"u\"&&(Module.arguments=arguments),typeof console<\"u\")Module.print||(Module.print=function(e){console.log(e)}),Module.printErr||(Module.printErr=function(e){console.warn(e)});else{var TRY_USE_DUMP=!1;Module.print||(Module.print=TRY_USE_DUMP&&typeof dump<\"u\"?function(t){dump(t)}:function(t){})}ENVIRONMENT_IS_WORKER&&(Module.load=importScripts),typeof Module.setWindowTitle>\"u\"&&(Module.setWindowTitle=function(t){document.title=t})}else throw\"Unknown runtime environment. Where are we?\";function globalEval(t){eval.call(null,t)}!Module.load&&Module.read&&(Module.load=function(e){globalEval(Module.read(e))}),Module.print||(Module.print=function(){}),Module.printErr||(Module.printErr=Module.print),Module.arguments||(Module.arguments=[]),Module.thisProgram||(Module.thisProgram=\"./this.program\"),Module.quit||(Module.quit=function(t,e){throw e}),Module.print=Module.print,Module.printErr=Module.printErr,Module.preRun=[],Module.postRun=[];for(var key in moduleOverrides)moduleOverrides.hasOwnProperty(key)&&(Module[key]=moduleOverrides[key]);moduleOverrides=void 0;var Runtime={setTempRet0:function(t){return tempRet0=t,t},getTempRet0:function(){return tempRet0},stackSave:function(){return STACKTOP},stackRestore:function(t){STACKTOP=t},getNativeTypeSize:function(t){switch(t){case\"i1\":case\"i8\":return 1;case\"i16\":return 2;case\"i32\":return 4;case\"i64\":return 8;case\"float\":return 4;case\"double\":return 8;default:{if(t[t.length-1]===\"*\")return Runtime.QUANTUM_SIZE;if(t[0]===\"i\"){var e=parseInt(t.substr(1));return assert(e%8===0),e/8}else return 0}}},getNativeFieldSize:function(t){return Math.max(Runtime.getNativeTypeSize(t),Runtime.QUANTUM_SIZE)},STACK_ALIGN:16,prepVararg:function(t,e){return e===\"double\"||e===\"i64\"?t&7&&(assert((t&7)===4),t+=4):assert((t&3)===0),t},getAlignSize:function(t,e,r){return!r&&(t==\"i64\"||t==\"double\")?8:t?Math.min(e||(t?Runtime.getNativeFieldSize(t):0),Runtime.QUANTUM_SIZE):Math.min(e,8)},dynCall:function(t,e,r){return r&&r.length?Module[\"dynCall_\"+t].apply(null,[e].concat(r)):Module[\"dynCall_\"+t].call(null,e)},functionPointers:[],addFunction:function(t){for(var e=0;e<Runtime.functionPointers.length;e++)if(!Runtime.functionPointers[e])return Runtime.functionPointers[e]=t,2*(1+e);throw\"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.\"},removeFunction:function(t){Runtime.functionPointers[(t-2)/2]=null},warnOnce:function(t){Runtime.warnOnce.shown||(Runtime.warnOnce.shown={}),Runtime.warnOnce.shown[t]||(Runtime.warnOnce.shown[t]=1,Module.printErr(t))},funcWrappers:{},getFuncWrapper:function(t,e){if(t){assert(e),Runtime.funcWrappers[e]||(Runtime.funcWrappers[e]={});var r=Runtime.funcWrappers[e];return r[t]||(e.length===1?r[t]=function(){return Runtime.dynCall(e,t)}:e.length===2?r[t]=function(a){return Runtime.dynCall(e,t,[a])}:r[t]=function(){return Runtime.dynCall(e,t,Array.prototype.slice.call(arguments))}),r[t]}},getCompilerSetting:function(t){throw\"You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work\"},stackAlloc:function(t){var e=STACKTOP;return STACKTOP=STACKTOP+t|0,STACKTOP=STACKTOP+15&-16,e},staticAlloc:function(t){var e=STATICTOP;return STATICTOP=STATICTOP+t|0,STATICTOP=STATICTOP+15&-16,e},dynamicAlloc:function(t){var e=HEAP32[DYNAMICTOP_PTR>>2],r=(e+t+15|0)&-16;if(HEAP32[DYNAMICTOP_PTR>>2]=r,r>=TOTAL_MEMORY){var o=enlargeMemory();if(!o)return HEAP32[DYNAMICTOP_PTR>>2]=e,0}return e},alignMemory:function(t,e){var r=t=Math.ceil(t/(e||16))*(e||16);return r},makeBigInt:function(t,e,r){var o=r?+(t>>>0)+ +(e>>>0)*4294967296:+(t>>>0)+ +(e|0)*4294967296;return o},GLOBAL_BASE:8,QUANTUM_SIZE:4,__dummy__:0};Module.Runtime=Runtime;var ABORT=0,EXITSTATUS=0;function assert(t,e){t||abort(\"Assertion failed: \"+e)}function getCFunc(ident){var func=Module[\"_\"+ident];if(!func)try{func=eval(\"_\"+ident)}catch(t){}return assert(func,\"Cannot call unknown function \"+ident+\" (perhaps LLVM optimizations or closure removed it?)\"),func}var cwrap,ccall;(function(){var JSfuncs={stackSave:function(){Runtime.stackSave()},stackRestore:function(){Runtime.stackRestore()},arrayToC:function(t){var e=Runtime.stackAlloc(t.length);return writeArrayToMemory(t,e),e},stringToC:function(t){var e=0;if(t!=null&&t!==0){var r=(t.length<<2)+1;e=Runtime.stackAlloc(r),stringToUTF8(t,e,r)}return e}},toC={string:JSfuncs.stringToC,array:JSfuncs.arrayToC};ccall=function(e,r,o,a,n){var u=getCFunc(e),A=[],p=0;if(a)for(var h=0;h<a.length;h++){var E=toC[o[h]];E?(p===0&&(p=Runtime.stackSave()),A[h]=E(a[h])):A[h]=a[h]}var w=u.apply(null,A);if(r===\"string\"&&(w=Pointer_stringify(w)),p!==0){if(n&&n.async){EmterpreterAsync.asyncFinalizers.push(function(){Runtime.stackRestore(p)});return}Runtime.stackRestore(p)}return w};var sourceRegex=/^function\\s*[a-zA-Z$_0-9]*\\s*\\(([^)]*)\\)\\s*{\\s*([^*]*?)[\\s;]*(?:return\\s*(.*?)[;\\s]*)?}$/;function parseJSFunc(t){var e=t.toString().match(sourceRegex).slice(1);return{arguments:e[0],body:e[1],returnValue:e[2]}}var JSsource=null;function ensureJSsource(){if(!JSsource){JSsource={};for(var t in JSfuncs)JSfuncs.hasOwnProperty(t)&&(JSsource[t]=parseJSFunc(JSfuncs[t]))}}cwrap=function cwrap(ident,returnType,argTypes){argTypes=argTypes||[];var cfunc=getCFunc(ident),numericArgs=argTypes.every(function(t){return t===\"number\"}),numericRet=returnType!==\"string\";if(numericRet&&numericArgs)return cfunc;var argNames=argTypes.map(function(t,e){return\"$\"+e}),funcstr=\"(function(\"+argNames.join(\",\")+\") {\",nargs=argTypes.length;if(!numericArgs){ensureJSsource(),funcstr+=\"var stack = \"+JSsource.stackSave.body+\";\";for(var i=0;i<nargs;i++){var arg=argNames[i],type=argTypes[i];if(type!==\"number\"){var convertCode=JSsource[type+\"ToC\"];funcstr+=\"var \"+convertCode.arguments+\" = \"+arg+\";\",funcstr+=convertCode.body+\";\",funcstr+=arg+\"=(\"+convertCode.returnValue+\");\"}}}var cfuncname=parseJSFunc(function(){return cfunc}).returnValue;if(funcstr+=\"var ret = \"+cfuncname+\"(\"+argNames.join(\",\")+\");\",!numericRet){var strgfy=parseJSFunc(function(){return Pointer_stringify}).returnValue;funcstr+=\"ret = \"+strgfy+\"(ret);\"}return numericArgs||(ensureJSsource(),funcstr+=JSsource.stackRestore.body.replace(\"()\",\"(stack)\")+\";\"),funcstr+=\"return ret})\",eval(funcstr)}})(),Module.ccall=ccall,Module.cwrap=cwrap;function setValue(t,e,r,o){switch(r=r||\"i8\",r.charAt(r.length-1)===\"*\"&&(r=\"i32\"),r){case\"i1\":HEAP8[t>>0]=e;break;case\"i8\":HEAP8[t>>0]=e;break;case\"i16\":HEAP16[t>>1]=e;break;case\"i32\":HEAP32[t>>2]=e;break;case\"i64\":tempI64=[e>>>0,(tempDouble=e,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[t>>2]=tempI64[0],HEAP32[t+4>>2]=tempI64[1];break;case\"float\":HEAPF32[t>>2]=e;break;case\"double\":HEAPF64[t>>3]=e;break;default:abort(\"invalid type for setValue: \"+r)}}Module.setValue=setValue;function getValue(t,e,r){switch(e=e||\"i8\",e.charAt(e.length-1)===\"*\"&&(e=\"i32\"),e){case\"i1\":return HEAP8[t>>0];case\"i8\":return HEAP8[t>>0];case\"i16\":return HEAP16[t>>1];case\"i32\":return HEAP32[t>>2];case\"i64\":return HEAP32[t>>2];case\"float\":return HEAPF32[t>>2];case\"double\":return HEAPF64[t>>3];default:abort(\"invalid type for setValue: \"+e)}return null}Module.getValue=getValue;var ALLOC_NORMAL=0,ALLOC_STACK=1,ALLOC_STATIC=2,ALLOC_DYNAMIC=3,ALLOC_NONE=4;Module.ALLOC_NORMAL=ALLOC_NORMAL,Module.ALLOC_STACK=ALLOC_STACK,Module.ALLOC_STATIC=ALLOC_STATIC,Module.ALLOC_DYNAMIC=ALLOC_DYNAMIC,Module.ALLOC_NONE=ALLOC_NONE;function allocate(t,e,r,o){var a,n;typeof t==\"number\"?(a=!0,n=t):(a=!1,n=t.length);var u=typeof e==\"string\"?e:null,A;if(r==ALLOC_NONE?A=o:A=[typeof _malloc==\"function\"?_malloc:Runtime.staticAlloc,Runtime.stackAlloc,Runtime.staticAlloc,Runtime.dynamicAlloc][r===void 0?ALLOC_STATIC:r](Math.max(n,u?1:e.length)),a){var o=A,p;for(assert((A&3)==0),p=A+(n&-4);o<p;o+=4)HEAP32[o>>2]=0;for(p=A+n;o<p;)HEAP8[o++>>0]=0;return A}if(u===\"i8\")return t.subarray||t.slice?HEAPU8.set(t,A):HEAPU8.set(new Uint8Array(t),A),A;for(var h=0,E,w,D;h<n;){var b=t[h];if(typeof b==\"function\"&&(b=Runtime.getFunctionIndex(b)),E=u||e[h],E===0){h++;continue}E==\"i64\"&&(E=\"i32\"),setValue(A+h,b,E),D!==E&&(w=Runtime.getNativeTypeSize(E),D=E),h+=w}return A}Module.allocate=allocate;function getMemory(t){return staticSealed?runtimeInitialized?_malloc(t):Runtime.dynamicAlloc(t):Runtime.staticAlloc(t)}Module.getMemory=getMemory;function Pointer_stringify(t,e){if(e===0||!t)return\"\";for(var r=0,o,a=0;o=HEAPU8[t+a>>0],r|=o,!(o==0&&!e||(a++,e&&a==e)););e||(e=a);var n=\"\";if(r<128){for(var u=1024,A;e>0;)A=String.fromCharCode.apply(String,HEAPU8.subarray(t,t+Math.min(e,u))),n=n?n+A:A,t+=u,e-=u;return n}return Module.UTF8ToString(t)}Module.Pointer_stringify=Pointer_stringify;function AsciiToString(t){for(var e=\"\";;){var r=HEAP8[t++>>0];if(!r)return e;e+=String.fromCharCode(r)}}Module.AsciiToString=AsciiToString;function stringToAscii(t,e){return writeAsciiToMemory(t,e,!1)}Module.stringToAscii=stringToAscii;var UTF8Decoder=typeof TextDecoder<\"u\"?new TextDecoder(\"utf8\"):void 0;function UTF8ArrayToString(t,e){for(var r=e;t[r];)++r;if(r-e>16&&t.subarray&&UTF8Decoder)return UTF8Decoder.decode(t.subarray(e,r));for(var o,a,n,u,A,p,h=\"\";;){if(o=t[e++],!o)return h;if(!(o&128)){h+=String.fromCharCode(o);continue}if(a=t[e++]&63,(o&224)==192){h+=String.fromCharCode((o&31)<<6|a);continue}if(n=t[e++]&63,(o&240)==224?o=(o&15)<<12|a<<6|n:(u=t[e++]&63,(o&248)==240?o=(o&7)<<18|a<<12|n<<6|u:(A=t[e++]&63,(o&252)==248?o=(o&3)<<24|a<<18|n<<12|u<<6|A:(p=t[e++]&63,o=(o&1)<<30|a<<24|n<<18|u<<12|A<<6|p))),o<65536)h+=String.fromCharCode(o);else{var E=o-65536;h+=String.fromCharCode(55296|E>>10,56320|E&1023)}}}Module.UTF8ArrayToString=UTF8ArrayToString;function UTF8ToString(t){return UTF8ArrayToString(HEAPU8,t)}Module.UTF8ToString=UTF8ToString;function stringToUTF8Array(t,e,r,o){if(!(o>0))return 0;for(var a=r,n=r+o-1,u=0;u<t.length;++u){var A=t.charCodeAt(u);if(A>=55296&&A<=57343&&(A=65536+((A&1023)<<10)|t.charCodeAt(++u)&1023),A<=127){if(r>=n)break;e[r++]=A}else if(A<=2047){if(r+1>=n)break;e[r++]=192|A>>6,e[r++]=128|A&63}else if(A<=65535){if(r+2>=n)break;e[r++]=224|A>>12,e[r++]=128|A>>6&63,e[r++]=128|A&63}else if(A<=2097151){if(r+3>=n)break;e[r++]=240|A>>18,e[r++]=128|A>>12&63,e[r++]=128|A>>6&63,e[r++]=128|A&63}else if(A<=67108863){if(r+4>=n)break;e[r++]=248|A>>24,e[r++]=128|A>>18&63,e[r++]=128|A>>12&63,e[r++]=128|A>>6&63,e[r++]=128|A&63}else{if(r+5>=n)break;e[r++]=252|A>>30,e[r++]=128|A>>24&63,e[r++]=128|A>>18&63,e[r++]=128|A>>12&63,e[r++]=128|A>>6&63,e[r++]=128|A&63}}return e[r]=0,r-a}Module.stringToUTF8Array=stringToUTF8Array;function stringToUTF8(t,e,r){return stringToUTF8Array(t,HEAPU8,e,r)}Module.stringToUTF8=stringToUTF8;function lengthBytesUTF8(t){for(var e=0,r=0;r<t.length;++r){var o=t.charCodeAt(r);o>=55296&&o<=57343&&(o=65536+((o&1023)<<10)|t.charCodeAt(++r)&1023),o<=127?++e:o<=2047?e+=2:o<=65535?e+=3:o<=2097151?e+=4:o<=67108863?e+=5:e+=6}return e}Module.lengthBytesUTF8=lengthBytesUTF8;var UTF16Decoder=typeof TextDecoder<\"u\"?new TextDecoder(\"utf-16le\"):void 0;function demangle(t){var e=Module.___cxa_demangle||Module.__cxa_demangle;if(e){try{var r=t.substr(1),o=lengthBytesUTF8(r)+1,a=_malloc(o);stringToUTF8(r,a,o);var n=_malloc(4),u=e(a,0,0,n);if(getValue(n,\"i32\")===0&&u)return Pointer_stringify(u)}catch{}finally{a&&_free(a),n&&_free(n),u&&_free(u)}return t}return Runtime.warnOnce(\"warning: build with  -s DEMANGLE_SUPPORT=1  to link in libcxxabi demangling\"),t}function demangleAll(t){var e=/__Z[\\w\\d_]+/g;return t.replace(e,function(r){var o=demangle(r);return r===o?r:r+\" [\"+o+\"]\"})}function jsStackTrace(){var t=new Error;if(!t.stack){try{throw new Error(0)}catch(e){t=e}if(!t.stack)return\"(no stack trace available)\"}return t.stack.toString()}function stackTrace(){var t=jsStackTrace();return Module.extraStackTrace&&(t+=`\n`+Module.extraStackTrace()),demangleAll(t)}Module.stackTrace=stackTrace;var HEAP,buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferViews(){Module.HEAP8=HEAP8=new Int8Array(buffer),Module.HEAP16=HEAP16=new Int16Array(buffer),Module.HEAP32=HEAP32=new Int32Array(buffer),Module.HEAPU8=HEAPU8=new Uint8Array(buffer),Module.HEAPU16=HEAPU16=new Uint16Array(buffer),Module.HEAPU32=HEAPU32=new Uint32Array(buffer),Module.HEAPF32=HEAPF32=new Float32Array(buffer),Module.HEAPF64=HEAPF64=new Float64Array(buffer)}var STATIC_BASE,STATICTOP,staticSealed,STACK_BASE,STACKTOP,STACK_MAX,DYNAMIC_BASE,DYNAMICTOP_PTR;STATIC_BASE=STATICTOP=STACK_BASE=STACKTOP=STACK_MAX=DYNAMIC_BASE=DYNAMICTOP_PTR=0,staticSealed=!1;function abortOnCannotGrowMemory(){abort(\"Cannot enlarge memory arrays. Either (1) compile with  -s TOTAL_MEMORY=X  with X higher than the current value \"+TOTAL_MEMORY+\", (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or (4) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 \")}function enlargeMemory(){abortOnCannotGrowMemory()}var TOTAL_STACK=Module.TOTAL_STACK||5242880,TOTAL_MEMORY=Module.TOTAL_MEMORY||134217728;TOTAL_MEMORY<TOTAL_STACK&&Module.printErr(\"TOTAL_MEMORY should be larger than TOTAL_STACK, was \"+TOTAL_MEMORY+\"! (TOTAL_STACK=\"+TOTAL_STACK+\")\"),Module.buffer?buffer=Module.buffer:buffer=new ArrayBuffer(TOTAL_MEMORY),updateGlobalBufferViews();function getTotalMemory(){return TOTAL_MEMORY}if(HEAP32[0]=1668509029,HEAP16[1]=25459,HEAPU8[2]!==115||HEAPU8[3]!==99)throw\"Runtime error: expected the system to be little-endian!\";Module.HEAP=HEAP,Module.buffer=buffer,Module.HEAP8=HEAP8,Module.HEAP16=HEAP16,Module.HEAP32=HEAP32,Module.HEAPU8=HEAPU8,Module.HEAPU16=HEAPU16,Module.HEAPU32=HEAPU32,Module.HEAPF32=HEAPF32,Module.HEAPF64=HEAPF64;function callRuntimeCallbacks(t){for(;t.length>0;){var e=t.shift();if(typeof e==\"function\"){e();continue}var r=e.func;typeof r==\"number\"?e.arg===void 0?Module.dynCall_v(r):Module.dynCall_vi(r,e.arg):r(e.arg===void 0?null:e.arg)}}var __ATPRERUN__=[],__ATINIT__=[],__ATMAIN__=[],__ATEXIT__=[],__ATPOSTRUN__=[],runtimeInitialized=!1,runtimeExited=!1;function preRun(){if(Module.preRun)for(typeof Module.preRun==\"function\"&&(Module.preRun=[Module.preRun]);Module.preRun.length;)addOnPreRun(Module.preRun.shift());callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){runtimeInitialized||(runtimeInitialized=!0,callRuntimeCallbacks(__ATINIT__))}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__),runtimeExited=!0}function postRun(){if(Module.postRun)for(typeof Module.postRun==\"function\"&&(Module.postRun=[Module.postRun]);Module.postRun.length;)addOnPostRun(Module.postRun.shift());callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(t){__ATPRERUN__.unshift(t)}Module.addOnPreRun=addOnPreRun;function addOnInit(t){__ATINIT__.unshift(t)}Module.addOnInit=addOnInit;function addOnPreMain(t){__ATMAIN__.unshift(t)}Module.addOnPreMain=addOnPreMain;function addOnExit(t){__ATEXIT__.unshift(t)}Module.addOnExit=addOnExit;function addOnPostRun(t){__ATPOSTRUN__.unshift(t)}Module.addOnPostRun=addOnPostRun;function intArrayFromString(t,e,r){var o=r>0?r:lengthBytesUTF8(t)+1,a=new Array(o),n=stringToUTF8Array(t,a,0,a.length);return e&&(a.length=n),a}Module.intArrayFromString=intArrayFromString;function intArrayToString(t){for(var e=[],r=0;r<t.length;r++){var o=t[r];o>255&&(o&=255),e.push(String.fromCharCode(o))}return e.join(\"\")}Module.intArrayToString=intArrayToString;function writeStringToMemory(t,e,r){Runtime.warnOnce(\"writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!\");var o,a;r&&(a=e+lengthBytesUTF8(t),o=HEAP8[a]),stringToUTF8(t,e,1/0),r&&(HEAP8[a]=o)}Module.writeStringToMemory=writeStringToMemory;function writeArrayToMemory(t,e){HEAP8.set(t,e)}Module.writeArrayToMemory=writeArrayToMemory;function writeAsciiToMemory(t,e,r){for(var o=0;o<t.length;++o)HEAP8[e++>>0]=t.charCodeAt(o);r||(HEAP8[e>>0]=0)}if(Module.writeAsciiToMemory=writeAsciiToMemory,(!Math.imul||Math.imul(4294967295,5)!==-5)&&(Math.imul=function t(e,r){var o=e>>>16,a=e&65535,n=r>>>16,u=r&65535;return a*u+(o*u+a*n<<16)|0}),Math.imul=Math.imul,!Math.fround){var froundBuffer=new Float32Array(1);Math.fround=function(t){return froundBuffer[0]=t,froundBuffer[0]}}Math.fround=Math.fround,Math.clz32||(Math.clz32=function(t){t=t>>>0;for(var e=0;e<32;e++)if(t&1<<31-e)return e;return 32}),Math.clz32=Math.clz32,Math.trunc||(Math.trunc=function(t){return t<0?Math.ceil(t):Math.floor(t)}),Math.trunc=Math.trunc;var Math_abs=Math.abs,Math_cos=Math.cos,Math_sin=Math.sin,Math_tan=Math.tan,Math_acos=Math.acos,Math_asin=Math.asin,Math_atan=Math.atan,Math_atan2=Math.atan2,Math_exp=Math.exp,Math_log=Math.log,Math_sqrt=Math.sqrt,Math_ceil=Math.ceil,Math_floor=Math.floor,Math_pow=Math.pow,Math_imul=Math.imul,Math_fround=Math.fround,Math_round=Math.round,Math_min=Math.min,Math_clz32=Math.clz32,Math_trunc=Math.trunc,runDependencies=0,runDependencyWatcher=null,dependenciesFulfilled=null;function getUniqueRunDependency(t){return t}function addRunDependency(t){runDependencies++,Module.monitorRunDependencies&&Module.monitorRunDependencies(runDependencies)}Module.addRunDependency=addRunDependency;function removeRunDependency(t){if(runDependencies--,Module.monitorRunDependencies&&Module.monitorRunDependencies(runDependencies),runDependencies==0&&(runDependencyWatcher!==null&&(clearInterval(runDependencyWatcher),runDependencyWatcher=null),dependenciesFulfilled)){var e=dependenciesFulfilled;dependenciesFulfilled=null,e()}}Module.removeRunDependency=removeRunDependency,Module.preloadedImages={},Module.preloadedAudios={};var ASM_CONSTS=[function(t,e,r,o,a,n,u,A){return _nbind.callbackSignatureList[t].apply(this,arguments)}];function _emscripten_asm_const_iiiiiiii(t,e,r,o,a,n,u,A){return ASM_CONSTS[t](e,r,o,a,n,u,A)}function _emscripten_asm_const_iiiii(t,e,r,o,a){return ASM_CONSTS[t](e,r,o,a)}function _emscripten_asm_const_iiidddddd(t,e,r,o,a,n,u,A,p){return ASM_CONSTS[t](e,r,o,a,n,u,A,p)}function _emscripten_asm_const_iiididi(t,e,r,o,a,n,u){return ASM_CONSTS[t](e,r,o,a,n,u)}function _emscripten_asm_const_iiii(t,e,r,o){return ASM_CONSTS[t](e,r,o)}function _emscripten_asm_const_iiiid(t,e,r,o,a){return ASM_CONSTS[t](e,r,o,a)}function _emscripten_asm_const_iiiiii(t,e,r,o,a,n){return ASM_CONSTS[t](e,r,o,a,n)}STATIC_BASE=Runtime.GLOBAL_BASE,STATICTOP=STATIC_BASE+12800,__ATINIT__.push({func:function(){__GLOBAL__sub_I_Yoga_cpp()}},{func:function(){__GLOBAL__sub_I_nbind_cc()}},{func:function(){__GLOBAL__sub_I_common_cc()}},{func:function(){__GLOBAL__sub_I_Binding_cc()}}),allocate([0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,192,127,0,0,192,127,3,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,3,0,0,0,0,0,192,127,3,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,192,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,127,0,0,192,127,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,0,0,128,191,0,0,128,191,0,0,192,127,0,0,0,0,0,0,0,0,0,0,128,63,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,2,0,0,0,0,0,0,0,190,12,0,0,200,12,0,0,208,12,0,0,216,12,0,0,230,12,0,0,242,12,0,0,1,0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0,0,192,127,3,0,0,0,180,45,0,0,181,45,0,0,182,45,0,0,181,45,0,0,182,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,1,0,0,0,4,0,0,0,183,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,181,45,0,0,184,45,0,0,185,45,0,0,181,45,0,0,181,45,0,0,182,45,0,0,186,45,0,0,185,45,0,0,148,4,0,0,3,0,0,0,187,45,0,0,164,4,0,0,188,45,0,0,2,0,0,0,189,45,0,0,164,4,0,0,188,45,0,0,185,45,0,0,164,4,0,0,185,45,0,0,164,4,0,0,188,45,0,0,181,45,0,0,182,45,0,0,181,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,5,0,0,0,6,0,0,0,1,0,0,0,7,0,0,0,183,45,0,0,182,45,0,0,181,45,0,0,190,45,0,0,190,45,0,0,182,45,0,0,182,45,0,0,185,45,0,0,181,45,0,0,185,45,0,0,182,45,0,0,181,45,0,0,185,45,0,0,182,45,0,0,185,45,0,0,48,5,0,0,3,0,0,0,56,5,0,0,1,0,0,0,189,45,0,0,185,45,0,0,164,4,0,0,76,5,0,0,2,0,0,0,191,45,0,0,186,45,0,0,182,45,0,0,185,45,0,0,192,45,0,0,185,45,0,0,182,45,0,0,186,45,0,0,185,45,0,0,76,5,0,0,76,5,0,0,136,5,0,0,182,45,0,0,181,45,0,0,2,0,0,0,190,45,0,0,136,5,0,0,56,19,0,0,156,5,0,0,2,0,0,0,184,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,8,0,0,0,9,0,0,0,1,0,0,0,10,0,0,0,204,5,0,0,181,45,0,0,181,45,0,0,2,0,0,0,180,45,0,0,204,5,0,0,2,0,0,0,195,45,0,0,236,5,0,0,97,19,0,0,198,45,0,0,211,45,0,0,212,45,0,0,213,45,0,0,214,45,0,0,215,45,0,0,188,45,0,0,182,45,0,0,216,45,0,0,217,45,0,0,218,45,0,0,219,45,0,0,192,45,0,0,181,45,0,0,0,0,0,0,185,45,0,0,110,19,0,0,186,45,0,0,115,19,0,0,221,45,0,0,120,19,0,0,148,4,0,0,132,19,0,0,96,6,0,0,145,19,0,0,222,45,0,0,164,19,0,0,223,45,0,0,173,19,0,0,0,0,0,0,3,0,0,0,104,6,0,0,1,0,0,0,187,45,0,0,0,0,0,0,0,0,0,0,1,0,0,0,11,0,0,0,12,0,0,0,1,0,0,0,13,0,0,0,185,45,0,0,224,45,0,0,164,6,0,0,188,45,0,0,172,6,0,0,180,6,0,0,2,0,0,0,188,6,0,0,7,0,0,0,224,45,0,0,7,0,0,0,164,6,0,0,1,0,0,0,213,45,0,0,185,45,0,0,224,45,0,0,172,6,0,0,185,45,0,0,224,45,0,0,164,6,0,0,185,45,0,0,224,45,0,0,211,45,0,0,211,45,0,0,222,45,0,0,211,45,0,0,224,45,0,0,222,45,0,0,211,45,0,0,224,45,0,0,172,6,0,0,222,45,0,0,211,45,0,0,224,45,0,0,188,45,0,0,222,45,0,0,211,45,0,0,40,7,0,0,188,45,0,0,2,0,0,0,224,45,0,0,185,45,0,0,188,45,0,0,188,45,0,0,188,45,0,0,188,45,0,0,222,45,0,0,224,45,0,0,148,4,0,0,185,45,0,0,148,4,0,0,148,4,0,0,148,4,0,0,148,4,0,0,148,4,0,0,185,45,0,0,164,6,0,0,148,4,0,0,0,0,0,0,0,0,0,0,1,0,0,0,14,0,0,0,15,0,0,0,1,0,0,0,16,0,0,0,148,7,0,0,2,0,0,0,225,45,0,0,183,45,0,0,188,45,0,0,168,7,0,0,5,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,234,45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,148,45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,9,0,0,5,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,2,0,0,0,242,45,0,0,0,4,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67,111,117,108,100,32,110,111,116,32,97,108,108,111,99,97,116,101,32,109,101,109,111,114,121,32,102,111,114,32,110,111,100,101,0,67,97,110,110,111,116,32,114,101,115,101,116,32,97,32,110,111,100,101,32,119,104,105,99,104,32,115,116,105,108,108,32,104,97,115,32,99,104,105,108,100,114,101,110,32,97,116,116,97,99,104,101,100,0,67,97,110,110,111,116,32,114,101,115,101,116,32,97,32,110,111,100,101,32,115,116,105,108,108,32,97,116,116,97,99,104,101,100,32,116,111,32,97,32,112,97,114,101,110,116,0,67,111,117,108,100,32,110,111,116,32,97,108,108,111,99,97,116,101,32,109,101,109,111,114,121,32,102,111,114,32,99,111,110,102,105,103,0,67,97,110,110,111,116,32,115,101,116,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,58,32,78,111,100,101,115,32,119,105,116,104,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,32,99,97,110,110,111,116,32,104,97,118,101,32,99,104,105,108,100,114,101,110,46,0,67,104,105,108,100,32,97,108,114,101,97,100,121,32,104,97,115,32,97,32,112,97,114,101,110,116,44,32,105,116,32,109,117,115,116,32,98,101,32,114,101,109,111,118,101,100,32,102,105,114,115,116,46,0,67,97,110,110,111,116,32,97,100,100,32,99,104,105,108,100,58,32,78,111,100,101,115,32,119,105,116,104,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,32,99,97,110,110,111,116,32,104,97,118,101,32,99,104,105,108,100,114,101,110,46,0,79,110,108,121,32,108,101,97,102,32,110,111,100,101,115,32,119,105,116,104,32,99,117,115,116,111,109,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,115,115,104,111,117,108,100,32,109,97,110,117,97,108,108,121,32,109,97,114,107,32,116,104,101,109,115,101,108,118,101,115,32,97,115,32,100,105,114,116,121,0,67,97,110,110,111,116,32,103,101,116,32,108,97,121,111,117,116,32,112,114,111,112,101,114,116,105,101,115,32,111,102,32,109,117,108,116,105,45,101,100,103,101,32,115,104,111,114,116,104,97,110,100,115,0,37,115,37,100,46,123,91,115,107,105,112,112,101,100,93,32,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,97,119,58,32,37,102,32,97,104,58,32,37,102,32,61,62,32,100,58,32,40,37,102,44,32,37,102,41,32,37,115,10,0,37,115,37,100,46,123,37,115,0,42,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,97,119,58,32,37,102,32,97,104,58,32,37,102,32,37,115,10,0,37,115,37,100,46,125,37,115,0,119,109,58,32,37,115,44,32,104,109,58,32,37,115,44,32,100,58,32,40,37,102,44,32,37,102,41,32,37,115,10,0,79,117,116,32,111,102,32,99,97,99,104,101,32,101,110,116,114,105,101,115,33,10,0,83,99,97,108,101,32,102,97,99,116,111,114,32,115,104,111,117,108,100,32,110,111,116,32,98,101,32,108,101,115,115,32,116,104,97,110,32,122,101,114,111,0,105,110,105,116,105,97,108,0,37,115,10,0,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,0,85,78,68,69,70,73,78,69,68,0,69,88,65,67,84,76,89,0,65,84,95,77,79,83,84,0,76,65,89,95,85,78,68,69,70,73,78,69,68,0,76,65,89,95,69,88,65,67,84,76,89,0,76,65,89,95,65,84,95,77,79,83,84,0,97,118,97,105,108,97,98,108,101,87,105,100,116,104,32,105,115,32,105,110,100,101,102,105,110,105,116,101,32,115,111,32,119,105,100,116,104,77,101,97,115,117,114,101,77,111,100,101,32,109,117,115,116,32,98,101,32,89,71,77,101,97,115,117,114,101,77,111,100,101,85,110,100,101,102,105,110,101,100,0,97,118,97,105,108,97,98,108,101,72,101,105,103,104,116,32,105,115,32,105,110,100,101,102,105,110,105,116,101,32,115,111,32,104,101,105,103,104,116,77,101,97,115,117,114,101,77,111,100,101,32,109,117,115,116,32,98,101,32,89,71,77,101,97,115,117,114,101,77,111,100,101,85,110,100,101,102,105,110,101,100,0,102,108,101,120,0,115,116,114,101,116,99,104,0,109,117,108,116,105,108,105,110,101,45,115,116,114,101,116,99,104,0,69,120,112,101,99,116,101,100,32,110,111,100,101,32,116,111,32,104,97,118,101,32,99,117,115,116,111,109,32,109,101,97,115,117,114,101,32,102,117,110,99,116,105,111,110,0,109,101,97,115,117,114,101,0,69,120,112,101,99,116,32,99,117,115,116,111,109,32,98,97,115,101,108,105,110,101,32,102,117,110,99,116,105,111,110,32,116,111,32,110,111,116,32,114,101,116,117,114,110,32,78,97,78,0,97,98,115,45,109,101,97,115,117,114,101,0,97,98,115,45,108,97,121,111,117,116,0,78,111,100,101,0,99,114,101,97,116,101,68,101,102,97,117,108,116,0,99,114,101,97,116,101,87,105,116,104,67,111,110,102,105,103,0,100,101,115,116,114,111,121,0,114,101,115,101,116,0,99,111,112,121,83,116,121,108,101,0,115,101,116,80,111,115,105,116,105,111,110,84,121,112,101,0,115,101,116,80,111,115,105,116,105,111,110,0,115,101,116,80,111,115,105,116,105,111,110,80,101,114,99,101,110,116,0,115,101,116,65,108,105,103,110,67,111,110,116,101,110,116,0,115,101,116,65,108,105,103,110,73,116,101,109,115,0,115,101,116,65,108,105,103,110,83,101,108,102,0,115,101,116,70,108,101,120,68,105,114,101,99,116,105,111,110,0,115,101,116,70,108,101,120,87,114,97,112,0,115,101,116,74,117,115,116,105,102,121,67,111,110,116,101,110,116,0,115,101,116,77,97,114,103,105,110,0,115,101,116,77,97,114,103,105,110,80,101,114,99,101,110,116,0,115,101,116,77,97,114,103,105,110,65,117,116,111,0,115,101,116,79,118,101,114,102,108,111,119,0,115,101,116,68,105,115,112,108,97,121,0,115,101,116,70,108,101,120,0,115,101,116,70,108,101,120,66,97,115,105,115,0,115,101,116,70,108,101,120,66,97,115,105,115,80,101,114,99,101,110,116,0,115,101,116,70,108,101,120,71,114,111,119,0,115,101,116,70,108,101,120,83,104,114,105,110,107,0,115,101,116,87,105,100,116,104,0,115,101,116,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,87,105,100,116,104,65,117,116,111,0,115,101,116,72,101,105,103,104,116,0,115,101,116,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,72,101,105,103,104,116,65,117,116,111,0,115,101,116,77,105,110,87,105,100,116,104,0,115,101,116,77,105,110,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,77,105,110,72,101,105,103,104,116,0,115,101,116,77,105,110,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,77,97,120,87,105,100,116,104,0,115,101,116,77,97,120,87,105,100,116,104,80,101,114,99,101,110,116,0,115,101,116,77,97,120,72,101,105,103,104,116,0,115,101,116,77,97,120,72,101,105,103,104,116,80,101,114,99,101,110,116,0,115,101,116,65,115,112,101,99,116,82,97,116,105,111,0,115,101,116,66,111,114,100,101,114,0,115,101,116,80,97,100,100,105,110,103,0,115,101,116,80,97,100,100,105,110,103,80,101,114,99,101,110,116,0,103,101,116,80,111,115,105,116,105,111,110,84,121,112,101,0,103,101,116,80,111,115,105,116,105,111,110,0,103,101,116,65,108,105,103,110,67,111,110,116,101,110,116,0,103,101,116,65,108,105,103,110,73,116,101,109,115,0,103,101,116,65,108,105,103,110,83,101,108,102,0,103,101,116,70,108,101,120,68,105,114,101,99,116,105,111,110,0,103,101,116,70,108,101,120,87,114,97,112,0,103,101,116,74,117,115,116,105,102,121,67,111,110,116,101,110,116,0,103,101,116,77,97,114,103,105,110,0,103,101,116,70,108,101,120,66,97,115,105,115,0,103,101,116,70,108,101,120,71,114,111,119,0,103,101,116,70,108,101,120,83,104,114,105,110,107,0,103,101,116,87,105,100,116,104,0,103,101,116,72,101,105,103,104,116,0,103,101,116,77,105,110,87,105,100,116,104,0,103,101,116,77,105,110,72,101,105,103,104,116,0,103,101,116,77,97,120,87,105,100,116,104,0,103,101,116,77,97,120,72,101,105,103,104,116,0,103,101,116,65,115,112,101,99,116,82,97,116,105,111,0,103,101,116,66,111,114,100,101,114,0,103,101,116,79,118,101,114,102,108,111,119,0,103,101,116,68,105,115,112,108,97,121,0,103,101,116,80,97,100,100,105,110,103,0,105,110,115,101,114,116,67,104,105,108,100,0,114,101,109,111,118,101,67,104,105,108,100,0,103,101,116,67,104,105,108,100,67,111,117,110,116,0,103,101,116,80,97,114,101,110,116,0,103,101,116,67,104,105,108,100,0,115,101,116,77,101,97,115,117,114,101,70,117,110,99,0,117,110,115,101,116,77,101,97,115,117,114,101,70,117,110,99,0,109,97,114,107,68,105,114,116,121,0,105,115,68,105,114,116,121,0,99,97,108,99,117,108,97,116,101,76,97,121,111,117,116,0,103,101,116,67,111,109,112,117,116,101,100,76,101,102,116,0,103,101,116,67,111,109,112,117,116,101,100,82,105,103,104,116,0,103,101,116,67,111,109,112,117,116,101,100,84,111,112,0,103,101,116,67,111,109,112,117,116,101,100,66,111,116,116,111,109,0,103,101,116,67,111,109,112,117,116,101,100,87,105,100,116,104,0,103,101,116,67,111,109,112,117,116,101,100,72,101,105,103,104,116,0,103,101,116,67,111,109,112,117,116,101,100,76,97,121,111,117,116,0,103,101,116,67,111,109,112,117,116,101,100,77,97,114,103,105,110,0,103,101,116,67,111,109,112,117,116,101,100,66,111,114,100,101,114,0,103,101,116,67,111,109,112,117,116,101,100,80,97,100,100,105,110,103,0,67,111,110,102,105,103,0,99,114,101,97,116,101,0,115,101,116,69,120,112,101,114,105,109,101,110,116,97,108,70,101,97,116,117,114,101,69,110,97,98,108,101,100,0,115,101,116,80,111,105,110,116,83,99,97,108,101,70,97,99,116,111,114,0,105,115,69,120,112,101,114,105,109,101,110,116,97,108,70,101,97,116,117,114,101,69,110,97,98,108,101,100,0,86,97,108,117,101,0,76,97,121,111,117,116,0,83,105,122,101,0,103,101,116,73,110,115,116,97,110,99,101,67,111,117,110,116,0,73,110,116,54,52,0,1,1,1,2,2,4,4,4,4,8,8,4,8,118,111,105,100,0,98,111,111,108,0,115,116,100,58,58,115,116,114,105,110,103,0,99,98,70,117,110,99,116,105,111,110,32,38,0,99,111,110,115,116,32,99,98,70,117,110,99,116,105,111,110,32,38,0,69,120,116,101,114,110,97,108,0,66,117,102,102,101,114,0,78,66,105,110,100,73,68,0,78,66,105,110,100,0,98,105,110,100,95,118,97,108,117,101,0,114,101,102,108,101,99,116,0,113,117,101,114,121,84,121,112,101,0,108,97,108,108,111,99,0,108,114,101,115,101,116,0,123,114,101,116,117,114,110,40,95,110,98,105,110,100,46,99,97,108,108,98,97,99,107,83,105,103,110,97,116,117,114,101,76,105,115,116,91,36,48,93,46,97,112,112,108,121,40,116,104,105,115,44,97,114,103,117,109,101,110,116,115,41,41,59,125,0,95,110,98,105,110,100,95,110,101,119,0,17,0,10,0,17,17,17,0,0,0,0,5,0,0,0,0,0,0,9,0,0,0,0,11,0,0,0,0,0,0,0,0,17,0,15,10,17,17,17,3,10,7,0,1,19,9,11,11,0,0,9,6,11,0,0,11,0,6,17,0,0,0,17,17,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,17,0,10,10,17,17,17,0,10,0,0,2,0,9,11,0,0,0,9,0,11,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,12,0,0,0,0,9,12,0,0,0,0,0,12,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,13,0,0,0,4,13,0,0,0,0,9,14,0,0,0,0,0,14,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,15,0,0,0,0,9,16,0,0,0,0,0,16,0,0,16,0,0,18,0,0,0,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,0,18,18,18,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,10,0,0,0,0,9,11,0,0,0,0,0,11,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,12,0,0,0,0,9,12,0,0,0,0,0,12,0,0,12,0,0,45,43,32,32,32,48,88,48,120,0,40,110,117,108,108,41,0,45,48,88,43,48,88,32,48,88,45,48,120,43,48,120,32,48,120,0,105,110,102,0,73,78,70,0,110,97,110,0,78,65,78,0,48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,46,0,84,33,34,25,13,1,2,3,17,75,28,12,16,4,11,29,18,30,39,104,110,111,112,113,98,32,5,6,15,19,20,21,26,8,22,7,40,36,23,24,9,10,14,27,31,37,35,131,130,125,38,42,43,60,61,62,63,67,71,74,77,88,89,90,91,92,93,94,95,96,97,99,100,101,102,103,105,106,107,108,114,115,116,121,122,123,124,0,73,108,108,101,103,97,108,32,98,121,116,101,32,115,101,113,117,101,110,99,101,0,68,111,109,97,105,110,32,101,114,114,111,114,0,82,101,115,117,108,116,32,110,111,116,32,114,101,112,114,101,115,101,110,116,97,98,108,101,0,78,111,116,32,97,32,116,116,121,0,80,101,114,109,105,115,115,105,111,110,32,100,101,110,105,101,100,0,79,112,101,114,97,116,105,111,110,32,110,111,116,32,112,101,114,109,105,116,116,101,100,0,78,111,32,115,117,99,104,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121,0,78,111,32,115,117,99,104,32,112,114,111,99,101,115,115,0,70,105,108,101,32,101,120,105,115,116,115,0,86,97,108,117,101,32,116,111,111,32,108,97,114,103,101,32,102,111,114,32,100,97,116,97,32,116,121,112,101,0,78,111,32,115,112,97,99,101,32,108,101,102,116,32,111,110,32,100,101,118,105,99,101,0,79,117,116,32,111,102,32,109,101,109,111,114,121,0,82,101,115,111,117,114,99,101,32,98,117,115,121,0,73,110,116,101,114,114,117,112,116,101,100,32,115,121,115,116,101,109,32,99,97,108,108,0,82,101,115,111,117,114,99,101,32,116,101,109,112,111,114,97,114,105,108,121,32,117,110,97,118,97,105,108,97,98,108,101,0,73,110,118,97,108,105,100,32,115,101,101,107,0,67,114,111,115,115,45,100,101,118,105,99,101,32,108,105,110,107,0,82,101,97,100,45,111,110,108,121,32,102,105,108,101,32,115,121,115,116,101,109,0,68,105,114,101,99,116,111,114,121,32,110,111,116,32,101,109,112,116,121,0,67,111,110,110,101,99,116,105,111,110,32,114,101,115,101,116,32,98,121,32,112,101,101,114,0,79,112,101,114,97,116,105,111,110,32,116,105,109,101,100,32,111,117,116,0,67,111,110,110,101,99,116,105,111,110,32,114,101,102,117,115,101,100,0,72,111,115,116,32,105,115,32,100,111,119,110,0,72,111,115,116,32,105,115,32,117,110,114,101,97,99,104,97,98,108,101,0,65,100,100,114,101,115,115,32,105,110,32,117,115,101,0,66,114,111,107,101,110,32,112,105,112,101,0,73,47,79,32,101,114,114,111,114,0,78,111,32,115,117,99,104,32,100,101,118,105,99,101,32,111,114,32,97,100,100,114,101,115,115,0,66,108,111,99,107,32,100,101,118,105,99,101,32,114,101,113,117,105,114,101,100,0,78,111,32,115,117,99,104,32,100,101,118,105,99,101,0,78,111,116,32,97,32,100,105,114,101,99,116,111,114,121,0,73,115,32,97,32,100,105,114,101,99,116,111,114,121,0,84,101,120,116,32,102,105,108,101,32,98,117,115,121,0,69,120,101,99,32,102,111,114,109,97,116,32,101,114,114,111,114,0,73,110,118,97,108,105,100,32,97,114,103,117,109,101,110,116,0,65,114,103,117,109,101,110,116,32,108,105,115,116,32,116,111,111,32,108,111,110,103,0,83,121,109,98,111,108,105,99,32,108,105,110,107,32,108,111,111,112,0,70,105,108,101,110,97,109,101,32,116,111,111,32,108,111,110,103,0,84,111,111,32,109,97,110,121,32,111,112,101,110,32,102,105,108,101,115,32,105,110,32,115,121,115,116,101,109,0,78,111,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,115,32,97,118,97,105,108,97,98,108,101,0,66,97,100,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,0,78,111,32,99,104,105,108,100,32,112,114,111,99,101,115,115,0,66,97,100,32,97,100,100,114,101,115,115,0,70,105,108,101,32,116,111,111,32,108,97,114,103,101,0,84,111,111,32,109,97,110,121,32,108,105,110,107,115,0,78,111,32,108,111,99,107,115,32,97,118,97,105,108,97,98,108,101,0,82,101,115,111,117,114,99,101,32,100,101,97,100,108,111,99,107,32,119,111,117,108,100,32,111,99,99,117,114,0,83,116,97,116,101,32,110,111,116,32,114,101,99,111,118,101,114,97,98,108,101,0,80,114,101,118,105,111,117,115,32,111,119,110,101,114,32,100,105,101,100,0,79,112,101,114,97,116,105,111,110,32,99,97,110,99,101,108,101,100,0,70,117,110,99,116,105,111,110,32,110,111,116,32,105,109,112,108,101,109,101,110,116,101,100,0,78,111,32,109,101,115,115,97,103,101,32,111,102,32,100,101,115,105,114,101,100,32,116,121,112,101,0,73,100,101,110,116,105,102,105,101,114,32,114,101,109,111,118,101,100,0,68,101,118,105,99,101,32,110,111,116,32,97,32,115,116,114,101,97,109,0,78,111,32,100,97,116,97,32,97,118,97,105,108,97,98,108,101,0,68,101,118,105,99,101,32,116,105,109,101,111,117,116,0,79,117,116,32,111,102,32,115,116,114,101,97,109,115,32,114,101,115,111,117,114,99,101,115,0,76,105,110,107,32,104,97,115,32,98,101,101,110,32,115,101,118,101,114,101,100,0,80,114,111,116,111,99,111,108,32,101,114,114,111,114,0,66,97,100,32,109,101,115,115,97,103,101,0,70,105,108,101,32,100,101,115,99,114,105,112,116,111,114,32,105,110,32,98,97,100,32,115,116,97,116,101,0,78,111,116,32,97,32,115,111,99,107,101,116,0,68,101,115,116,105,110,97,116,105,111,110,32,97,100,100,114,101,115,115,32,114,101,113,117,105,114,101,100,0,77,101,115,115,97,103,101,32,116,111,111,32,108,97,114,103,101,0,80,114,111,116,111,99,111,108,32,119,114,111,110,103,32,116,121,112,101,32,102,111,114,32,115,111,99,107,101,116,0,80,114,111,116,111,99,111,108,32,110,111,116,32,97,118,97,105,108,97,98,108,101,0,80,114,111,116,111,99,111,108,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,83,111,99,107,101,116,32,116,121,112,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,78,111,116,32,115,117,112,112,111,114,116,101,100,0,80,114,111,116,111,99,111,108,32,102,97,109,105,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,65,100,100,114,101,115,115,32,102,97,109,105,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,98,121,32,112,114,111,116,111,99,111,108,0,65,100,100,114,101,115,115,32,110,111,116,32,97,118,97,105,108,97,98,108,101,0,78,101,116,119,111,114,107,32,105,115,32,100,111,119,110,0,78,101,116,119,111,114,107,32,117,110,114,101,97,99,104,97,98,108,101,0,67,111,110,110,101,99,116,105,111,110,32,114,101,115,101,116,32,98,121,32,110,101,116,119,111,114,107,0,67,111,110,110,101,99,116,105,111,110,32,97,98,111,114,116,101,100,0,78,111,32,98,117,102,102,101,114,32,115,112,97,99,101,32,97,118,97,105,108,97,98,108,101,0,83,111,99,107,101,116,32,105,115,32,99,111,110,110,101,99,116,101,100,0,83,111,99,107,101,116,32,110,111,116,32,99,111,110,110,101,99,116,101,100,0,67,97,110,110,111,116,32,115,101,110,100,32,97,102,116,101,114,32,115,111,99,107,101,116,32,115,104,117,116,100,111,119,110,0,79,112,101,114,97,116,105,111,110,32,97,108,114,101,97,100,121,32,105,110,32,112,114,111,103,114,101,115,115,0,79,112,101,114,97,116,105,111,110,32,105,110,32,112,114,111,103,114,101,115,115,0,83,116,97,108,101,32,102,105,108,101,32,104,97,110,100,108,101,0,82,101,109,111,116,101,32,73,47,79,32,101,114,114,111,114,0,81,117,111,116,97,32,101,120,99,101,101,100,101,100,0,78,111,32,109,101,100,105,117,109,32,102,111,117,110,100,0,87,114,111,110,103,32,109,101,100,105,117,109,32,116,121,112,101,0,78,111,32,101,114,114,111,114,32,105,110,102,111,114,109,97,116,105,111,110,0,0],\"i8\",ALLOC_NONE,Runtime.GLOBAL_BASE);var tempDoublePtr=STATICTOP;STATICTOP+=16;function _atexit(t,e){__ATEXIT__.unshift({func:t,arg:e})}function ___cxa_atexit(){return _atexit.apply(null,arguments)}function _abort(){Module.abort()}function __ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj(){Module.printErr(\"missing function: _ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj\"),abort(-1)}function __decorate(t,e,r,o){var a=arguments.length,n=a<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,r):o,u;if(typeof Reflect==\"object\"&&typeof Reflect.decorate==\"function\")n=Reflect.decorate(t,e,r,o);else for(var A=t.length-1;A>=0;A--)(u=t[A])&&(n=(a<3?u(n):a>3?u(e,r,n):u(e,r))||n);return a>3&&n&&Object.defineProperty(e,r,n),n}function _defineHidden(t){return function(e,r){Object.defineProperty(e,r,{configurable:!1,enumerable:!1,value:t,writable:!0})}}var _nbind={};function __nbind_free_external(t){_nbind.externalList[t].dereference(t)}function __nbind_reference_external(t){_nbind.externalList[t].reference()}function _llvm_stackrestore(t){var e=_llvm_stacksave,r=e.LLVM_SAVEDSTACKS[t];e.LLVM_SAVEDSTACKS.splice(t,1),Runtime.stackRestore(r)}function __nbind_register_pool(t,e,r,o){_nbind.Pool.pageSize=t,_nbind.Pool.usedPtr=e/4,_nbind.Pool.rootPtr=r,_nbind.Pool.pagePtr=o/4,HEAP32[e/4]=16909060,HEAP8[e]==1&&(_nbind.bigEndian=!0),HEAP32[e/4]=0,_nbind.makeTypeKindTbl=(n={},n[1024]=_nbind.PrimitiveType,n[64]=_nbind.Int64Type,n[2048]=_nbind.BindClass,n[3072]=_nbind.BindClassPtr,n[4096]=_nbind.SharedClassPtr,n[5120]=_nbind.ArrayType,n[6144]=_nbind.ArrayType,n[7168]=_nbind.CStringType,n[9216]=_nbind.CallbackType,n[10240]=_nbind.BindType,n),_nbind.makeTypeNameTbl={Buffer:_nbind.BufferType,External:_nbind.ExternalType,Int64:_nbind.Int64Type,_nbind_new:_nbind.CreateValueType,bool:_nbind.BooleanType,\"cbFunction &\":_nbind.CallbackType,\"const cbFunction &\":_nbind.CallbackType,\"const std::string &\":_nbind.StringType,\"std::string\":_nbind.StringType},Module.toggleLightGC=_nbind.toggleLightGC,_nbind.callUpcast=Module.dynCall_ii;var a=_nbind.makeType(_nbind.constructType,{flags:2048,id:0,name:\"\"});a.proto=Module,_nbind.BindClass.list.push(a);var n}function _emscripten_set_main_loop_timing(t,e){if(Browser.mainLoop.timingMode=t,Browser.mainLoop.timingValue=e,!Browser.mainLoop.func)return 1;if(t==0)Browser.mainLoop.scheduler=function(){var u=Math.max(0,Browser.mainLoop.tickStartTime+e-_emscripten_get_now())|0;setTimeout(Browser.mainLoop.runner,u)},Browser.mainLoop.method=\"timeout\";else if(t==1)Browser.mainLoop.scheduler=function(){Browser.requestAnimationFrame(Browser.mainLoop.runner)},Browser.mainLoop.method=\"rAF\";else if(t==2){if(!window.setImmediate){let n=function(u){u.source===window&&u.data===o&&(u.stopPropagation(),r.shift()())};var a=n,r=[],o=\"setimmediate\";window.addEventListener(\"message\",n,!0),window.setImmediate=function(A){r.push(A),ENVIRONMENT_IS_WORKER?(Module.setImmediates===void 0&&(Module.setImmediates=[]),Module.setImmediates.push(A),window.postMessage({target:o})):window.postMessage(o,\"*\")}}Browser.mainLoop.scheduler=function(){window.setImmediate(Browser.mainLoop.runner)},Browser.mainLoop.method=\"immediate\"}return 0}function _emscripten_get_now(){abort()}function _emscripten_set_main_loop(t,e,r,o,a){Module.noExitRuntime=!0,assert(!Browser.mainLoop.func,\"emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.\"),Browser.mainLoop.func=t,Browser.mainLoop.arg=o;var n;typeof o<\"u\"?n=function(){Module.dynCall_vi(t,o)}:n=function(){Module.dynCall_v(t)};var u=Browser.mainLoop.currentlyRunningMainloop;if(Browser.mainLoop.runner=function(){if(!ABORT){if(Browser.mainLoop.queue.length>0){var p=Date.now(),h=Browser.mainLoop.queue.shift();if(h.func(h.arg),Browser.mainLoop.remainingBlockers){var E=Browser.mainLoop.remainingBlockers,w=E%1==0?E-1:Math.floor(E);h.counted?Browser.mainLoop.remainingBlockers=w:(w=w+.5,Browser.mainLoop.remainingBlockers=(8*E+w)/9)}if(console.log('main loop blocker \"'+h.name+'\" took '+(Date.now()-p)+\" ms\"),Browser.mainLoop.updateStatus(),u<Browser.mainLoop.currentlyRunningMainloop)return;setTimeout(Browser.mainLoop.runner,0);return}if(!(u<Browser.mainLoop.currentlyRunningMainloop)){if(Browser.mainLoop.currentFrameNumber=Browser.mainLoop.currentFrameNumber+1|0,Browser.mainLoop.timingMode==1&&Browser.mainLoop.timingValue>1&&Browser.mainLoop.currentFrameNumber%Browser.mainLoop.timingValue!=0){Browser.mainLoop.scheduler();return}else Browser.mainLoop.timingMode==0&&(Browser.mainLoop.tickStartTime=_emscripten_get_now());Browser.mainLoop.method===\"timeout\"&&Module.ctx&&(Module.printErr(\"Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!\"),Browser.mainLoop.method=\"\"),Browser.mainLoop.runIter(n),!(u<Browser.mainLoop.currentlyRunningMainloop)&&(typeof SDL==\"object\"&&SDL.audio&&SDL.audio.queueNewAudioData&&SDL.audio.queueNewAudioData(),Browser.mainLoop.scheduler())}}},a||(e&&e>0?_emscripten_set_main_loop_timing(0,1e3/e):_emscripten_set_main_loop_timing(1,1),Browser.mainLoop.scheduler()),r)throw\"SimulateInfiniteLoop\"}var Browser={mainLoop:{scheduler:null,method:\"\",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function(){Browser.mainLoop.scheduler=null,Browser.mainLoop.currentlyRunningMainloop++},resume:function(){Browser.mainLoop.currentlyRunningMainloop++;var t=Browser.mainLoop.timingMode,e=Browser.mainLoop.timingValue,r=Browser.mainLoop.func;Browser.mainLoop.func=null,_emscripten_set_main_loop(r,0,!1,Browser.mainLoop.arg,!0),_emscripten_set_main_loop_timing(t,e),Browser.mainLoop.scheduler()},updateStatus:function(){if(Module.setStatus){var t=Module.statusMessage||\"Please wait...\",e=Browser.mainLoop.remainingBlockers,r=Browser.mainLoop.expectedBlockers;e?e<r?Module.setStatus(t+\" (\"+(r-e)+\"/\"+r+\")\"):Module.setStatus(t):Module.setStatus(\"\")}},runIter:function(t){if(!ABORT){if(Module.preMainLoop){var e=Module.preMainLoop();if(e===!1)return}try{t()}catch(r){if(r instanceof ExitStatus)return;throw r&&typeof r==\"object\"&&r.stack&&Module.printErr(\"exception thrown: \"+[r,r.stack]),r}Module.postMainLoop&&Module.postMainLoop()}}},isFullscreen:!1,pointerLock:!1,moduleContextCreatedCallbacks:[],workers:[],init:function(){if(Module.preloadPlugins||(Module.preloadPlugins=[]),Browser.initted)return;Browser.initted=!0;try{new Blob,Browser.hasBlobConstructor=!0}catch{Browser.hasBlobConstructor=!1,console.log(\"warning: no blob constructor, cannot create blobs with mimetypes\")}Browser.BlobBuilder=typeof MozBlobBuilder<\"u\"?MozBlobBuilder:typeof WebKitBlobBuilder<\"u\"?WebKitBlobBuilder:Browser.hasBlobConstructor?null:console.log(\"warning: no BlobBuilder\"),Browser.URLObject=typeof window<\"u\"?window.URL?window.URL:window.webkitURL:void 0,!Module.noImageDecoding&&typeof Browser.URLObject>\"u\"&&(console.log(\"warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available.\"),Module.noImageDecoding=!0);var t={};t.canHandle=function(n){return!Module.noImageDecoding&&/\\.(jpg|jpeg|png|bmp)$/i.test(n)},t.handle=function(n,u,A,p){var h=null;if(Browser.hasBlobConstructor)try{h=new Blob([n],{type:Browser.getMimetype(u)}),h.size!==n.length&&(h=new Blob([new Uint8Array(n).buffer],{type:Browser.getMimetype(u)}))}catch(b){Runtime.warnOnce(\"Blob constructor present but fails: \"+b+\"; falling back to blob builder\")}if(!h){var E=new Browser.BlobBuilder;E.append(new Uint8Array(n).buffer),h=E.getBlob()}var w=Browser.URLObject.createObjectURL(h),D=new Image;D.onload=function(){assert(D.complete,\"Image \"+u+\" could not be decoded\");var C=document.createElement(\"canvas\");C.width=D.width,C.height=D.height;var T=C.getContext(\"2d\");T.drawImage(D,0,0),Module.preloadedImages[u]=C,Browser.URLObject.revokeObjectURL(w),A&&A(n)},D.onerror=function(C){console.log(\"Image \"+w+\" could not be decoded\"),p&&p()},D.src=w},Module.preloadPlugins.push(t);var e={};e.canHandle=function(n){return!Module.noAudioDecoding&&n.substr(-4)in{\".ogg\":1,\".wav\":1,\".mp3\":1}},e.handle=function(n,u,A,p){var h=!1;function E(T){h||(h=!0,Module.preloadedAudios[u]=T,A&&A(n))}function w(){h||(h=!0,Module.preloadedAudios[u]=new Audio,p&&p())}if(Browser.hasBlobConstructor){try{var D=new Blob([n],{type:Browser.getMimetype(u)})}catch{return w()}var b=Browser.URLObject.createObjectURL(D),C=new Audio;C.addEventListener(\"canplaythrough\",function(){E(C)},!1),C.onerror=function(N){if(h)return;console.log(\"warning: browser could not fully decode audio \"+u+\", trying slower base64 approach\");function U(z){for(var te=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\",le=\"=\",ce=\"\",ue=0,Ie=0,he=0;he<z.length;he++)for(ue=ue<<8|z[he],Ie+=8;Ie>=6;){var De=ue>>Ie-6&63;Ie-=6,ce+=te[De]}return Ie==2?(ce+=te[(ue&3)<<4],ce+=le+le):Ie==4&&(ce+=te[(ue&15)<<2],ce+=le),ce}C.src=\"data:audio/x-\"+u.substr(-3)+\";base64,\"+U(n),E(C)},C.src=b,Browser.safeSetTimeout(function(){E(C)},1e4)}else return w()},Module.preloadPlugins.push(e);function r(){Browser.pointerLock=document.pointerLockElement===Module.canvas||document.mozPointerLockElement===Module.canvas||document.webkitPointerLockElement===Module.canvas||document.msPointerLockElement===Module.canvas}var o=Module.canvas;o&&(o.requestPointerLock=o.requestPointerLock||o.mozRequestPointerLock||o.webkitRequestPointerLock||o.msRequestPointerLock||function(){},o.exitPointerLock=document.exitPointerLock||document.mozExitPointerLock||document.webkitExitPointerLock||document.msExitPointerLock||function(){},o.exitPointerLock=o.exitPointerLock.bind(document),document.addEventListener(\"pointerlockchange\",r,!1),document.addEventListener(\"mozpointerlockchange\",r,!1),document.addEventListener(\"webkitpointerlockchange\",r,!1),document.addEventListener(\"mspointerlockchange\",r,!1),Module.elementPointerLock&&o.addEventListener(\"click\",function(a){!Browser.pointerLock&&Module.canvas.requestPointerLock&&(Module.canvas.requestPointerLock(),a.preventDefault())},!1))},createContext:function(t,e,r,o){if(e&&Module.ctx&&t==Module.canvas)return Module.ctx;var a,n;if(e){var u={antialias:!1,alpha:!1};if(o)for(var A in o)u[A]=o[A];n=GL.createContext(t,u),n&&(a=GL.getContext(n).GLctx)}else a=t.getContext(\"2d\");return a?(r&&(e||assert(typeof GLctx>\"u\",\"cannot set in module if GLctx is used, but we are a non-GL context that would replace it\"),Module.ctx=a,e&&GL.makeContextCurrent(n),Module.useWebGL=e,Browser.moduleContextCreatedCallbacks.forEach(function(p){p()}),Browser.init()),a):null},destroyContext:function(t,e,r){},fullscreenHandlersInstalled:!1,lockPointer:void 0,resizeCanvas:void 0,requestFullscreen:function(t,e,r){Browser.lockPointer=t,Browser.resizeCanvas=e,Browser.vrDevice=r,typeof Browser.lockPointer>\"u\"&&(Browser.lockPointer=!0),typeof Browser.resizeCanvas>\"u\"&&(Browser.resizeCanvas=!1),typeof Browser.vrDevice>\"u\"&&(Browser.vrDevice=null);var o=Module.canvas;function a(){Browser.isFullscreen=!1;var u=o.parentNode;(document.fullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||document.webkitFullscreenElement||document.webkitCurrentFullScreenElement)===u?(o.exitFullscreen=document.exitFullscreen||document.cancelFullScreen||document.mozCancelFullScreen||document.msExitFullscreen||document.webkitCancelFullScreen||function(){},o.exitFullscreen=o.exitFullscreen.bind(document),Browser.lockPointer&&o.requestPointerLock(),Browser.isFullscreen=!0,Browser.resizeCanvas&&Browser.setFullscreenCanvasSize()):(u.parentNode.insertBefore(o,u),u.parentNode.removeChild(u),Browser.resizeCanvas&&Browser.setWindowedCanvasSize()),Module.onFullScreen&&Module.onFullScreen(Browser.isFullscreen),Module.onFullscreen&&Module.onFullscreen(Browser.isFullscreen),Browser.updateCanvasDimensions(o)}Browser.fullscreenHandlersInstalled||(Browser.fullscreenHandlersInstalled=!0,document.addEventListener(\"fullscreenchange\",a,!1),document.addEventListener(\"mozfullscreenchange\",a,!1),document.addEventListener(\"webkitfullscreenchange\",a,!1),document.addEventListener(\"MSFullscreenChange\",a,!1));var n=document.createElement(\"div\");o.parentNode.insertBefore(n,o),n.appendChild(o),n.requestFullscreen=n.requestFullscreen||n.mozRequestFullScreen||n.msRequestFullscreen||(n.webkitRequestFullscreen?function(){n.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)}:null)||(n.webkitRequestFullScreen?function(){n.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT)}:null),r?n.requestFullscreen({vrDisplay:r}):n.requestFullscreen()},requestFullScreen:function(t,e,r){return Module.printErr(\"Browser.requestFullScreen() is deprecated. Please call Browser.requestFullscreen instead.\"),Browser.requestFullScreen=function(o,a,n){return Browser.requestFullscreen(o,a,n)},Browser.requestFullscreen(t,e,r)},nextRAF:0,fakeRequestAnimationFrame:function(t){var e=Date.now();if(Browser.nextRAF===0)Browser.nextRAF=e+1e3/60;else for(;e+2>=Browser.nextRAF;)Browser.nextRAF+=1e3/60;var r=Math.max(Browser.nextRAF-e,0);setTimeout(t,r)},requestAnimationFrame:function t(e){typeof window>\"u\"?Browser.fakeRequestAnimationFrame(e):(window.requestAnimationFrame||(window.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame||Browser.fakeRequestAnimationFrame),window.requestAnimationFrame(e))},safeCallback:function(t){return function(){if(!ABORT)return t.apply(null,arguments)}},allowAsyncCallbacks:!0,queuedAsyncCallbacks:[],pauseAsyncCallbacks:function(){Browser.allowAsyncCallbacks=!1},resumeAsyncCallbacks:function(){if(Browser.allowAsyncCallbacks=!0,Browser.queuedAsyncCallbacks.length>0){var t=Browser.queuedAsyncCallbacks;Browser.queuedAsyncCallbacks=[],t.forEach(function(e){e()})}},safeRequestAnimationFrame:function(t){return Browser.requestAnimationFrame(function(){ABORT||(Browser.allowAsyncCallbacks?t():Browser.queuedAsyncCallbacks.push(t))})},safeSetTimeout:function(t,e){return Module.noExitRuntime=!0,setTimeout(function(){ABORT||(Browser.allowAsyncCallbacks?t():Browser.queuedAsyncCallbacks.push(t))},e)},safeSetInterval:function(t,e){return Module.noExitRuntime=!0,setInterval(function(){ABORT||Browser.allowAsyncCallbacks&&t()},e)},getMimetype:function(t){return{jpg:\"image/jpeg\",jpeg:\"image/jpeg\",png:\"image/png\",bmp:\"image/bmp\",ogg:\"audio/ogg\",wav:\"audio/wav\",mp3:\"audio/mpeg\"}[t.substr(t.lastIndexOf(\".\")+1)]},getUserMedia:function(t){window.getUserMedia||(window.getUserMedia=navigator.getUserMedia||navigator.mozGetUserMedia),window.getUserMedia(t)},getMovementX:function(t){return t.movementX||t.mozMovementX||t.webkitMovementX||0},getMovementY:function(t){return t.movementY||t.mozMovementY||t.webkitMovementY||0},getMouseWheelDelta:function(t){var e=0;switch(t.type){case\"DOMMouseScroll\":e=t.detail;break;case\"mousewheel\":e=t.wheelDelta;break;case\"wheel\":e=t.deltaY;break;default:throw\"unrecognized mouse wheel event: \"+t.type}return e},mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(t){if(Browser.pointerLock)t.type!=\"mousemove\"&&\"mozMovementX\"in t?Browser.mouseMovementX=Browser.mouseMovementY=0:(Browser.mouseMovementX=Browser.getMovementX(t),Browser.mouseMovementY=Browser.getMovementY(t)),typeof SDL<\"u\"?(Browser.mouseX=SDL.mouseX+Browser.mouseMovementX,Browser.mouseY=SDL.mouseY+Browser.mouseMovementY):(Browser.mouseX+=Browser.mouseMovementX,Browser.mouseY+=Browser.mouseMovementY);else{var e=Module.canvas.getBoundingClientRect(),r=Module.canvas.width,o=Module.canvas.height,a=typeof window.scrollX<\"u\"?window.scrollX:window.pageXOffset,n=typeof window.scrollY<\"u\"?window.scrollY:window.pageYOffset;if(t.type===\"touchstart\"||t.type===\"touchend\"||t.type===\"touchmove\"){var u=t.touch;if(u===void 0)return;var A=u.pageX-(a+e.left),p=u.pageY-(n+e.top);A=A*(r/e.width),p=p*(o/e.height);var h={x:A,y:p};if(t.type===\"touchstart\")Browser.lastTouches[u.identifier]=h,Browser.touches[u.identifier]=h;else if(t.type===\"touchend\"||t.type===\"touchmove\"){var E=Browser.touches[u.identifier];E||(E=h),Browser.lastTouches[u.identifier]=E,Browser.touches[u.identifier]=h}return}var w=t.pageX-(a+e.left),D=t.pageY-(n+e.top);w=w*(r/e.width),D=D*(o/e.height),Browser.mouseMovementX=w-Browser.mouseX,Browser.mouseMovementY=D-Browser.mouseY,Browser.mouseX=w,Browser.mouseY=D}},asyncLoad:function(t,e,r,o){var a=o?\"\":\"al \"+t;Module.readAsync(t,function(n){assert(n,'Loading data file \"'+t+'\" failed (no arrayBuffer).'),e(new Uint8Array(n)),a&&removeRunDependency(a)},function(n){if(r)r();else throw'Loading data file \"'+t+'\" failed.'}),a&&addRunDependency(a)},resizeListeners:[],updateResizeListeners:function(){var t=Module.canvas;Browser.resizeListeners.forEach(function(e){e(t.width,t.height)})},setCanvasSize:function(t,e,r){var o=Module.canvas;Browser.updateCanvasDimensions(o,t,e),r||Browser.updateResizeListeners()},windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function(){if(typeof SDL<\"u\"){var t=HEAPU32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2];t=t|8388608,HEAP32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2]=t}Browser.updateResizeListeners()},setWindowedCanvasSize:function(){if(typeof SDL<\"u\"){var t=HEAPU32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2];t=t&-8388609,HEAP32[SDL.screen+Runtime.QUANTUM_SIZE*0>>2]=t}Browser.updateResizeListeners()},updateCanvasDimensions:function(t,e,r){e&&r?(t.widthNative=e,t.heightNative=r):(e=t.widthNative,r=t.heightNative);var o=e,a=r;if(Module.forcedAspectRatio&&Module.forcedAspectRatio>0&&(o/a<Module.forcedAspectRatio?o=Math.round(a*Module.forcedAspectRatio):a=Math.round(o/Module.forcedAspectRatio)),(document.fullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||document.webkitFullscreenElement||document.webkitCurrentFullScreenElement)===t.parentNode&&typeof screen<\"u\"){var n=Math.min(screen.width/o,screen.height/a);o=Math.round(o*n),a=Math.round(a*n)}Browser.resizeCanvas?(t.width!=o&&(t.width=o),t.height!=a&&(t.height=a),typeof t.style<\"u\"&&(t.style.removeProperty(\"width\"),t.style.removeProperty(\"height\"))):(t.width!=e&&(t.width=e),t.height!=r&&(t.height=r),typeof t.style<\"u\"&&(o!=e||a!=r?(t.style.setProperty(\"width\",o+\"px\",\"important\"),t.style.setProperty(\"height\",a+\"px\",\"important\")):(t.style.removeProperty(\"width\"),t.style.removeProperty(\"height\"))))},wgetRequests:{},nextWgetRequestHandle:0,getNextWgetRequestHandle:function(){var t=Browser.nextWgetRequestHandle;return Browser.nextWgetRequestHandle++,t}},SYSCALLS={varargs:0,get:function(t){SYSCALLS.varargs+=4;var e=HEAP32[SYSCALLS.varargs-4>>2];return e},getStr:function(){var t=Pointer_stringify(SYSCALLS.get());return t},get64:function(){var t=SYSCALLS.get(),e=SYSCALLS.get();return t>=0?assert(e===0):assert(e===-1),t},getZero:function(){assert(SYSCALLS.get()===0)}};function ___syscall6(t,e){SYSCALLS.varargs=e;try{var r=SYSCALLS.getStreamFromFD();return FS.close(r),0}catch(o){return(typeof FS>\"u\"||!(o instanceof FS.ErrnoError))&&abort(o),-o.errno}}function ___syscall54(t,e){SYSCALLS.varargs=e;try{return 0}catch(r){return(typeof FS>\"u\"||!(r instanceof FS.ErrnoError))&&abort(r),-r.errno}}function _typeModule(t){var e=[[0,1,\"X\"],[1,1,\"const X\"],[128,1,\"X *\"],[256,1,\"X &\"],[384,1,\"X &&\"],[512,1,\"std::shared_ptr<X>\"],[640,1,\"std::unique_ptr<X>\"],[5120,1,\"std::vector<X>\"],[6144,2,\"std::array<X, Y>\"],[9216,-1,\"std::function<X (Y)>\"]];function r(p,h,E,w,D,b){if(h==1){var C=w&896;(C==128||C==256||C==384)&&(p=\"X const\")}var T;return b?T=E.replace(\"X\",p).replace(\"Y\",D):T=p.replace(\"X\",E).replace(\"Y\",D),T.replace(/([*&]) (?=[*&])/g,\"$1\")}function o(p,h,E,w,D){throw new Error(p+\" type \"+E.replace(\"X\",h+\"?\")+(w?\" with flag \"+w:\"\")+\" in \"+D)}function a(p,h,E,w,D,b,C,T){b===void 0&&(b=\"X\"),T===void 0&&(T=1);var N=E(p);if(N)return N;var U=w(p),z=U.placeholderFlag,te=e[z];C&&te&&(b=r(C[2],C[0],b,te[0],\"?\",!0));var le;z==0&&(le=\"Unbound\"),z>=10&&(le=\"Corrupt\"),T>20&&(le=\"Deeply nested\"),le&&o(le,p,b,z,D||\"?\");var ce=U.paramList[0],ue=a(ce,h,E,w,D,b,te,T+1),Ie,he={flags:te[0],id:p,name:\"\",paramList:[ue]},De=[],Ee=\"?\";switch(U.placeholderFlag){case 1:Ie=ue.spec;break;case 2:if((ue.flags&15360)==1024&&ue.spec.ptrSize==1){he.flags=7168;break}case 3:case 6:case 5:Ie=ue.spec,ue.flags&15360;break;case 8:Ee=\"\"+U.paramList[1],he.paramList.push(U.paramList[1]);break;case 9:for(var g=0,me=U.paramList[1];g<me.length;g++){var Ce=me[g],fe=a(Ce,h,E,w,D,b,te,T+1);De.push(fe.name),he.paramList.push(fe)}Ee=De.join(\", \");break;default:break}if(he.name=r(te[2],te[0],ue.name,ue.flags,Ee),Ie){for(var ie=0,Z=Object.keys(Ie);ie<Z.length;ie++){var Pe=Z[ie];he[Pe]=he[Pe]||Ie[Pe]}he.flags|=Ie.flags}return n(h,he)}function n(p,h){var E=h.flags,w=E&896,D=E&15360;return!h.name&&D==1024&&(h.ptrSize==1?h.name=(E&16?\"\":(E&8?\"un\":\"\")+\"signed \")+\"char\":h.name=(E&8?\"u\":\"\")+(E&32?\"float\":\"int\")+(h.ptrSize*8+\"_t\")),h.ptrSize==8&&!(E&32)&&(D=64),D==2048&&(w==512||w==640?D=4096:w&&(D=3072)),p(D,h)}var u=function(){function p(h){this.id=h.id,this.name=h.name,this.flags=h.flags,this.spec=h}return p.prototype.toString=function(){return this.name},p}(),A={Type:u,getComplexType:a,makeType:n,structureList:e};return t.output=A,t.output||A}function __nbind_register_type(t,e){var r=_nbind.readAsciiString(e),o={flags:10240,id:t,name:r};_nbind.makeType(_nbind.constructType,o)}function __nbind_register_callback_signature(t,e){var r=_nbind.readTypeIdList(t,e),o=_nbind.callbackSignatureList.length;return _nbind.callbackSignatureList[o]=_nbind.makeJSCaller(r),o}function __extends(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r]);function o(){this.constructor=t}o.prototype=e.prototype,t.prototype=new o}function __nbind_register_class(t,e,r,o,a,n,u){var A=_nbind.readAsciiString(u),p=_nbind.readPolicyList(e),h=HEAPU32.subarray(t/4,t/4+2),E={flags:2048|(p.Value?2:0),id:h[0],name:A},w=_nbind.makeType(_nbind.constructType,E);w.ptrType=_nbind.getComplexType(h[1],_nbind.constructType,_nbind.getType,_nbind.queryType),w.destroy=_nbind.makeMethodCaller(w.ptrType,{boundID:E.id,flags:0,name:\"destroy\",num:0,ptr:n,title:w.name+\".free\",typeList:[\"void\",\"uint32_t\",\"uint32_t\"]}),a&&(w.superIdList=Array.prototype.slice.call(HEAPU32.subarray(r/4,r/4+a)),w.upcastList=Array.prototype.slice.call(HEAPU32.subarray(o/4,o/4+a))),Module[w.name]=w.makeBound(p),_nbind.BindClass.list.push(w)}function _removeAccessorPrefix(t){var e=/^[Gg]et_?([A-Z]?([A-Z]?))/;return t.replace(e,function(r,o,a){return a?o:o.toLowerCase()})}function __nbind_register_function(t,e,r,o,a,n,u,A,p,h){var E=_nbind.getType(t),w=_nbind.readPolicyList(e),D=_nbind.readTypeIdList(r,o),b;if(u==5)b=[{direct:a,name:\"__nbindConstructor\",ptr:0,title:E.name+\" constructor\",typeList:[\"uint32_t\"].concat(D.slice(1))},{direct:n,name:\"__nbindValueConstructor\",ptr:0,title:E.name+\" value constructor\",typeList:[\"void\",\"uint32_t\"].concat(D.slice(1))}];else{var C=_nbind.readAsciiString(A),T=(E.name&&E.name+\".\")+C;(u==3||u==4)&&(C=_removeAccessorPrefix(C)),b=[{boundID:t,direct:n,name:C,ptr:a,title:T,typeList:D}]}for(var N=0,U=b;N<U.length;N++){var z=U[N];z.signatureType=u,z.policyTbl=w,z.num=p,z.flags=h,E.addMethod(z)}}function _nbind_value(t,e){_nbind.typeNameTbl[t]||_nbind.throwError(\"Unknown value type \"+t),Module.NBind.bind_value(t,e),_defineHidden(_nbind.typeNameTbl[t].proto.prototype.__nbindValueConstructor)(e.prototype,\"__nbindValueConstructor\")}Module._nbind_value=_nbind_value;function __nbind_get_value_object(t,e){var r=_nbind.popValue(t);if(!r.fromJS)throw new Error(\"Object \"+r+\" has no fromJS function\");r.fromJS(function(){r.__nbindValueConstructor.apply(this,Array.prototype.concat.apply([e],arguments))})}function _emscripten_memcpy_big(t,e,r){return HEAPU8.set(HEAPU8.subarray(e,e+r),t),t}function __nbind_register_primitive(t,e,r){var o={flags:1024|r,id:t,ptrSize:e};_nbind.makeType(_nbind.constructType,o)}var cttz_i8=allocate([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0],\"i8\",ALLOC_STATIC);function ___setErrNo(t){return Module.___errno_location&&(HEAP32[Module.___errno_location()>>2]=t),t}function _llvm_stacksave(){var t=_llvm_stacksave;return t.LLVM_SAVEDSTACKS||(t.LLVM_SAVEDSTACKS=[]),t.LLVM_SAVEDSTACKS.push(Runtime.stackSave()),t.LLVM_SAVEDSTACKS.length-1}function ___syscall140(t,e){SYSCALLS.varargs=e;try{var r=SYSCALLS.getStreamFromFD(),o=SYSCALLS.get(),a=SYSCALLS.get(),n=SYSCALLS.get(),u=SYSCALLS.get(),A=a;return FS.llseek(r,A,u),HEAP32[n>>2]=r.position,r.getdents&&A===0&&u===0&&(r.getdents=null),0}catch(p){return(typeof FS>\"u\"||!(p instanceof FS.ErrnoError))&&abort(p),-p.errno}}function ___syscall146(t,e){SYSCALLS.varargs=e;try{var r=SYSCALLS.get(),o=SYSCALLS.get(),a=SYSCALLS.get(),n=0;___syscall146.buffer||(___syscall146.buffers=[null,[],[]],___syscall146.printChar=function(E,w){var D=___syscall146.buffers[E];assert(D),w===0||w===10?((E===1?Module.print:Module.printErr)(UTF8ArrayToString(D,0)),D.length=0):D.push(w)});for(var u=0;u<a;u++){for(var A=HEAP32[o+u*8>>2],p=HEAP32[o+(u*8+4)>>2],h=0;h<p;h++)___syscall146.printChar(r,HEAPU8[A+h]);n+=p}return n}catch(E){return(typeof FS>\"u\"||!(E instanceof FS.ErrnoError))&&abort(E),-E.errno}}function __nbind_finish(){for(var t=0,e=_nbind.BindClass.list;t<e.length;t++){var r=e[t];r.finish()}}var ___dso_handle=STATICTOP;STATICTOP+=16,function(_nbind){var typeIdTbl={};_nbind.typeNameTbl={};var Pool=function(){function t(){}return t.lalloc=function(e){e=e+7&-8;var r=HEAPU32[t.usedPtr];if(e>t.pageSize/2||e>t.pageSize-r){var o=_nbind.typeNameTbl.NBind.proto;return o.lalloc(e)}else return HEAPU32[t.usedPtr]=r+e,t.rootPtr+r},t.lreset=function(e,r){var o=HEAPU32[t.pagePtr];if(o){var a=_nbind.typeNameTbl.NBind.proto;a.lreset(e,r)}else HEAPU32[t.usedPtr]=e},t}();_nbind.Pool=Pool;function constructType(t,e){var r=t==10240?_nbind.makeTypeNameTbl[e.name]||_nbind.BindType:_nbind.makeTypeKindTbl[t],o=new r(e);return typeIdTbl[e.id]=o,_nbind.typeNameTbl[e.name]=o,o}_nbind.constructType=constructType;function getType(t){return typeIdTbl[t]}_nbind.getType=getType;function queryType(t){var e=HEAPU8[t],r=_nbind.structureList[e][1];t/=4,r<0&&(++t,r=HEAPU32[t]+1);var o=Array.prototype.slice.call(HEAPU32.subarray(t+1,t+1+r));return e==9&&(o=[o[0],o.slice(1)]),{paramList:o,placeholderFlag:e}}_nbind.queryType=queryType;function getTypes(t,e){return t.map(function(r){return typeof r==\"number\"?_nbind.getComplexType(r,constructType,getType,queryType,e):_nbind.typeNameTbl[r]})}_nbind.getTypes=getTypes;function readTypeIdList(t,e){return Array.prototype.slice.call(HEAPU32,t/4,t/4+e)}_nbind.readTypeIdList=readTypeIdList;function readAsciiString(t){for(var e=t;HEAPU8[e++];);return String.fromCharCode.apply(\"\",HEAPU8.subarray(t,e-1))}_nbind.readAsciiString=readAsciiString;function readPolicyList(t){var e={};if(t)for(;;){var r=HEAPU32[t/4];if(!r)break;e[readAsciiString(r)]=!0,t+=4}return e}_nbind.readPolicyList=readPolicyList;function getDynCall(t,e){var r={float32_t:\"d\",float64_t:\"d\",int64_t:\"d\",uint64_t:\"d\",void:\"v\"},o=t.map(function(n){return r[n.name]||\"i\"}).join(\"\"),a=Module[\"dynCall_\"+o];if(!a)throw new Error(\"dynCall_\"+o+\" not found for \"+e+\"(\"+t.map(function(n){return n.name}).join(\", \")+\")\");return a}_nbind.getDynCall=getDynCall;function addMethod(t,e,r,o){var a=t[e];t.hasOwnProperty(e)&&a?((a.arity||a.arity===0)&&(a=_nbind.makeOverloader(a,a.arity),t[e]=a),a.addMethod(r,o)):(r.arity=o,t[e]=r)}_nbind.addMethod=addMethod;function throwError(t){throw new Error(t)}_nbind.throwError=throwError,_nbind.bigEndian=!1,_a=_typeModule(_typeModule),_nbind.Type=_a.Type,_nbind.makeType=_a.makeType,_nbind.getComplexType=_a.getComplexType,_nbind.structureList=_a.structureList;var BindType=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.heap=HEAPU32,r.ptrSize=4,r}return e.prototype.needsWireRead=function(r){return!!this.wireRead||!!this.makeWireRead},e.prototype.needsWireWrite=function(r){return!!this.wireWrite||!!this.makeWireWrite},e}(_nbind.Type);_nbind.BindType=BindType;var PrimitiveType=function(t){__extends(e,t);function e(r){var o=t.call(this,r)||this,a=r.flags&32?{32:HEAPF32,64:HEAPF64}:r.flags&8?{8:HEAPU8,16:HEAPU16,32:HEAPU32}:{8:HEAP8,16:HEAP16,32:HEAP32};return o.heap=a[r.ptrSize*8],o.ptrSize=r.ptrSize,o}return e.prototype.needsWireWrite=function(r){return!!r&&!!r.Strict},e.prototype.makeWireWrite=function(r,o){return o&&o.Strict&&function(a){if(typeof a==\"number\")return a;throw new Error(\"Type mismatch\")}},e}(BindType);_nbind.PrimitiveType=PrimitiveType;function pushCString(t,e){if(t==null){if(e&&e.Nullable)return 0;throw new Error(\"Type mismatch\")}if(e&&e.Strict){if(typeof t!=\"string\")throw new Error(\"Type mismatch\")}else t=t.toString();var r=Module.lengthBytesUTF8(t)+1,o=_nbind.Pool.lalloc(r);return Module.stringToUTF8Array(t,HEAPU8,o,r),o}_nbind.pushCString=pushCString;function popCString(t){return t===0?null:Module.Pointer_stringify(t)}_nbind.popCString=popCString;var CStringType=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.wireRead=popCString,r.wireWrite=pushCString,r.readResources=[_nbind.resources.pool],r.writeResources=[_nbind.resources.pool],r}return e.prototype.makeWireWrite=function(r,o){return function(a){return pushCString(a,o)}},e}(BindType);_nbind.CStringType=CStringType;var BooleanType=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.wireRead=function(o){return!!o},r}return e.prototype.needsWireWrite=function(r){return!!r&&!!r.Strict},e.prototype.makeWireRead=function(r){return\"!!(\"+r+\")\"},e.prototype.makeWireWrite=function(r,o){return o&&o.Strict&&function(a){if(typeof a==\"boolean\")return a;throw new Error(\"Type mismatch\")}||r},e}(BindType);_nbind.BooleanType=BooleanType;var Wrapper=function(){function t(){}return t.prototype.persist=function(){this.__nbindState|=1},t}();_nbind.Wrapper=Wrapper;function makeBound(t,e){var r=function(o){__extends(a,o);function a(n,u,A,p){var h=o.call(this)||this;if(!(h instanceof a))return new(Function.prototype.bind.apply(a,Array.prototype.concat.apply([null],arguments)));var E=u,w=A,D=p;if(n!==_nbind.ptrMarker){var b=h.__nbindConstructor.apply(h,arguments);E=4608,D=HEAPU32[b/4],w=HEAPU32[b/4+1]}var C={configurable:!0,enumerable:!1,value:null,writable:!1},T={__nbindFlags:E,__nbindPtr:w};D&&(T.__nbindShared=D,_nbind.mark(h));for(var N=0,U=Object.keys(T);N<U.length;N++){var z=U[N];C.value=T[z],Object.defineProperty(h,z,C)}return _defineHidden(0)(h,\"__nbindState\"),h}return a.prototype.free=function(){e.destroy.call(this,this.__nbindShared,this.__nbindFlags),this.__nbindState|=2,disableMember(this,\"__nbindShared\"),disableMember(this,\"__nbindPtr\")},a}(Wrapper);return __decorate([_defineHidden()],r.prototype,\"__nbindConstructor\",void 0),__decorate([_defineHidden()],r.prototype,\"__nbindValueConstructor\",void 0),__decorate([_defineHidden(t)],r.prototype,\"__nbindPolicies\",void 0),r}_nbind.makeBound=makeBound;function disableMember(t,e){function r(){throw new Error(\"Accessing deleted object\")}Object.defineProperty(t,e,{configurable:!1,enumerable:!1,get:r,set:r})}_nbind.ptrMarker={};var BindClass=function(t){__extends(e,t);function e(r){var o=t.call(this,r)||this;return o.wireRead=function(a){return _nbind.popValue(a,o.ptrType)},o.wireWrite=function(a){return pushPointer(a,o.ptrType,!0)},o.pendingSuperCount=0,o.ready=!1,o.methodTbl={},r.paramList?(o.classType=r.paramList[0].classType,o.proto=o.classType.proto):o.classType=o,o}return e.prototype.makeBound=function(r){var o=_nbind.makeBound(r,this);return this.proto=o,this.ptrType.proto=o,o},e.prototype.addMethod=function(r){var o=this.methodTbl[r.name]||[];o.push(r),this.methodTbl[r.name]=o},e.prototype.registerMethods=function(r,o){for(var a,n=0,u=Object.keys(r.methodTbl);n<u.length;n++)for(var A=u[n],p=r.methodTbl[A],h=0,E=p;h<E.length;h++){var w=E[h],D=void 0,b=void 0;if(D=this.proto.prototype,!(o&&w.signatureType!=1))switch(w.signatureType){case 1:D=this.proto;case 5:b=_nbind.makeCaller(w),_nbind.addMethod(D,w.name,b,w.typeList.length-1);break;case 4:a=_nbind.makeMethodCaller(r.ptrType,w);break;case 3:Object.defineProperty(D,w.name,{configurable:!0,enumerable:!1,get:_nbind.makeMethodCaller(r.ptrType,w),set:a});break;case 2:b=_nbind.makeMethodCaller(r.ptrType,w),_nbind.addMethod(D,w.name,b,w.typeList.length-1);break;default:break}}},e.prototype.registerSuperMethods=function(r,o,a){if(!a[r.name]){a[r.name]=!0;for(var n=0,u,A=0,p=r.superIdList||[];A<p.length;A++){var h=p[A],E=_nbind.getType(h);n++<o||o<0?u=-1:u=0,this.registerSuperMethods(E,u,a)}this.registerMethods(r,o<0)}},e.prototype.finish=function(){if(this.ready)return this;this.ready=!0,this.superList=(this.superIdList||[]).map(function(a){return _nbind.getType(a).finish()});var r=this.proto;if(this.superList.length){var o=function(){this.constructor=r};o.prototype=this.superList[0].proto.prototype,r.prototype=new o}return r!=Module&&(r.prototype.__nbindType=this),this.registerSuperMethods(this,1,{}),this},e.prototype.upcastStep=function(r,o){if(r==this)return o;for(var a=0;a<this.superList.length;++a){var n=this.superList[a].upcastStep(r,_nbind.callUpcast(this.upcastList[a],o));if(n)return n}return 0},e}(_nbind.BindType);BindClass.list=[],_nbind.BindClass=BindClass;function popPointer(t,e){return t?new e.proto(_nbind.ptrMarker,e.flags,t):null}_nbind.popPointer=popPointer;function pushPointer(t,e,r){if(!(t instanceof _nbind.Wrapper)){if(r)return _nbind.pushValue(t);throw new Error(\"Type mismatch\")}var o=t.__nbindPtr,a=t.__nbindType.classType,n=e.classType;if(t instanceof e.proto)for(;a!=n;)o=_nbind.callUpcast(a.upcastList[0],o),a=a.superList[0];else if(o=a.upcastStep(n,o),!o)throw new Error(\"Type mismatch\");return o}_nbind.pushPointer=pushPointer;function pushMutablePointer(t,e){var r=pushPointer(t,e);if(t.__nbindFlags&1)throw new Error(\"Passing a const value as a non-const argument\");return r}var BindClassPtr=function(t){__extends(e,t);function e(r){var o=t.call(this,r)||this;o.classType=r.paramList[0].classType,o.proto=o.classType.proto;var a=r.flags&1,n=(o.flags&896)==256&&r.flags&2,u=a?pushPointer:pushMutablePointer,A=n?_nbind.popValue:popPointer;return o.makeWireWrite=function(p,h){return h.Nullable?function(E){return E?u(E,o):0}:function(E){return u(E,o)}},o.wireRead=function(p){return A(p,o)},o.wireWrite=function(p){return u(p,o)},o}return e}(_nbind.BindType);_nbind.BindClassPtr=BindClassPtr;function popShared(t,e){var r=HEAPU32[t/4],o=HEAPU32[t/4+1];return o?new e.proto(_nbind.ptrMarker,e.flags,o,r):null}_nbind.popShared=popShared;function pushShared(t,e){if(!(t instanceof e.proto))throw new Error(\"Type mismatch\");return t.__nbindShared}function pushMutableShared(t,e){if(!(t instanceof e.proto))throw new Error(\"Type mismatch\");if(t.__nbindFlags&1)throw new Error(\"Passing a const value as a non-const argument\");return t.__nbindShared}var SharedClassPtr=function(t){__extends(e,t);function e(r){var o=t.call(this,r)||this;o.readResources=[_nbind.resources.pool],o.classType=r.paramList[0].classType,o.proto=o.classType.proto;var a=r.flags&1,n=a?pushShared:pushMutableShared;return o.wireRead=function(u){return popShared(u,o)},o.wireWrite=function(u){return n(u,o)},o}return e}(_nbind.BindType);_nbind.SharedClassPtr=SharedClassPtr,_nbind.externalList=[0];var firstFreeExternal=0,External=function(){function t(e){this.refCount=1,this.data=e}return t.prototype.register=function(){var e=firstFreeExternal;return e?firstFreeExternal=_nbind.externalList[e]:e=_nbind.externalList.length,_nbind.externalList[e]=this,e},t.prototype.reference=function(){++this.refCount},t.prototype.dereference=function(e){--this.refCount==0&&(this.free&&this.free(),_nbind.externalList[e]=firstFreeExternal,firstFreeExternal=e)},t}();_nbind.External=External;function popExternal(t){var e=_nbind.externalList[t];return e.dereference(t),e.data}function pushExternal(t){var e=new External(t);return e.reference(),e.register()}var ExternalType=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.wireRead=popExternal,r.wireWrite=pushExternal,r}return e}(_nbind.BindType);_nbind.ExternalType=ExternalType,_nbind.callbackSignatureList=[];var CallbackType=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.wireWrite=function(o){return typeof o!=\"function\"&&_nbind.throwError(\"Type mismatch\"),new _nbind.External(o).register()},r}return e}(_nbind.BindType);_nbind.CallbackType=CallbackType,_nbind.valueList=[0];var firstFreeValue=0;function pushValue(t){var e=firstFreeValue;return e?firstFreeValue=_nbind.valueList[e]:e=_nbind.valueList.length,_nbind.valueList[e]=t,e*2+1}_nbind.pushValue=pushValue;function popValue(t,e){if(t||_nbind.throwError(\"Value type JavaScript class is missing or not registered\"),t&1){t>>=1;var r=_nbind.valueList[t];return _nbind.valueList[t]=firstFreeValue,firstFreeValue=t,r}else{if(e)return _nbind.popShared(t,e);throw new Error(\"Invalid value slot \"+t)}}_nbind.popValue=popValue;var valueBase=18446744073709552e3;function push64(t){return typeof t==\"number\"?t:pushValue(t)*4096+valueBase}function pop64(t){return t<valueBase?t:popValue((t-valueBase)/4096)}var CreateValueType=function(t){__extends(e,t);function e(){return t!==null&&t.apply(this,arguments)||this}return e.prototype.makeWireWrite=function(r){return\"(_nbind.pushValue(new \"+r+\"))\"},e}(_nbind.BindType);_nbind.CreateValueType=CreateValueType;var Int64Type=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.wireWrite=push64,r.wireRead=pop64,r}return e}(_nbind.BindType);_nbind.Int64Type=Int64Type;function pushArray(t,e){if(!t)return 0;var r=t.length;if((e.size||e.size===0)&&r<e.size)throw new Error(\"Type mismatch\");var o=e.memberType.ptrSize,a=_nbind.Pool.lalloc(4+r*o);HEAPU32[a/4]=r;var n=e.memberType.heap,u=(a+4)/o,A=e.memberType.wireWrite,p=0;if(A)for(;p<r;)n[u++]=A(t[p++]);else for(;p<r;)n[u++]=t[p++];return a}_nbind.pushArray=pushArray;function popArray(t,e){if(t===0)return null;var r=HEAPU32[t/4],o=new Array(r),a=e.memberType.heap;t=(t+4)/e.memberType.ptrSize;var n=e.memberType.wireRead,u=0;if(n)for(;u<r;)o[u++]=n(a[t++]);else for(;u<r;)o[u++]=a[t++];return o}_nbind.popArray=popArray;var ArrayType=function(t){__extends(e,t);function e(r){var o=t.call(this,r)||this;return o.wireRead=function(a){return popArray(a,o)},o.wireWrite=function(a){return pushArray(a,o)},o.readResources=[_nbind.resources.pool],o.writeResources=[_nbind.resources.pool],o.memberType=r.paramList[0],r.paramList[1]&&(o.size=r.paramList[1]),o}return e}(_nbind.BindType);_nbind.ArrayType=ArrayType;function pushString(t,e){if(t==null)if(e&&e.Nullable)t=\"\";else throw new Error(\"Type mismatch\");if(e&&e.Strict){if(typeof t!=\"string\")throw new Error(\"Type mismatch\")}else t=t.toString();var r=Module.lengthBytesUTF8(t),o=_nbind.Pool.lalloc(4+r+1);return HEAPU32[o/4]=r,Module.stringToUTF8Array(t,HEAPU8,o+4,r+1),o}_nbind.pushString=pushString;function popString(t){if(t===0)return null;var e=HEAPU32[t/4];return Module.Pointer_stringify(t+4,e)}_nbind.popString=popString;var StringType=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.wireRead=popString,r.wireWrite=pushString,r.readResources=[_nbind.resources.pool],r.writeResources=[_nbind.resources.pool],r}return e.prototype.makeWireWrite=function(r,o){return function(a){return pushString(a,o)}},e}(_nbind.BindType);_nbind.StringType=StringType;function makeArgList(t){return Array.apply(null,Array(t)).map(function(e,r){return\"a\"+(r+1)})}function anyNeedsWireWrite(t,e){return t.reduce(function(r,o){return r||o.needsWireWrite(e)},!1)}function anyNeedsWireRead(t,e){return t.reduce(function(r,o){return r||!!o.needsWireRead(e)},!1)}function makeWireRead(t,e,r,o){var a=t.length;return r.makeWireRead?r.makeWireRead(o,t,a):r.wireRead?(t[a]=r.wireRead,\"(convertParamList[\"+a+\"](\"+o+\"))\"):o}function makeWireWrite(t,e,r,o){var a,n=t.length;return r.makeWireWrite?a=r.makeWireWrite(o,e,t,n):a=r.wireWrite,a?typeof a==\"string\"?a:(t[n]=a,\"(convertParamList[\"+n+\"](\"+o+\"))\"):o}function buildCallerFunction(dynCall,ptrType,ptr,num,policyTbl,needsWireWrite,prefix,returnType,argTypeList,mask,err){var argList=makeArgList(argTypeList.length),convertParamList=[],callExpression=makeWireRead(convertParamList,policyTbl,returnType,\"dynCall(\"+[prefix].concat(argList.map(function(t,e){return makeWireWrite(convertParamList,policyTbl,argTypeList[e],t)})).join(\",\")+\")\"),resourceSet=_nbind.listResources([returnType],argTypeList),sourceCode=\"function(\"+argList.join(\",\")+\"){\"+(mask?\"this.__nbindFlags&mask&&err();\":\"\")+resourceSet.makeOpen()+\"var r=\"+callExpression+\";\"+resourceSet.makeClose()+\"return r;}\";return eval(\"(\"+sourceCode+\")\")}function buildJSCallerFunction(returnType,argTypeList){var argList=makeArgList(argTypeList.length),convertParamList=[],callExpression=makeWireWrite(convertParamList,null,returnType,\"_nbind.externalList[num].data(\"+argList.map(function(t,e){return makeWireRead(convertParamList,null,argTypeList[e],t)}).join(\",\")+\")\"),resourceSet=_nbind.listResources(argTypeList,[returnType]);resourceSet.remove(_nbind.resources.pool);var sourceCode=\"function(\"+[\"dummy\",\"num\"].concat(argList).join(\",\")+\"){\"+resourceSet.makeOpen()+\"var r=\"+callExpression+\";\"+resourceSet.makeClose()+\"return r;}\";return eval(\"(\"+sourceCode+\")\")}_nbind.buildJSCallerFunction=buildJSCallerFunction;function makeJSCaller(t){var e=t.length-1,r=_nbind.getTypes(t,\"callback\"),o=r[0],a=r.slice(1),n=anyNeedsWireRead(a,null),u=o.needsWireWrite(null);if(!u&&!n)switch(e){case 0:return function(A,p){return _nbind.externalList[p].data()};case 1:return function(A,p,h){return _nbind.externalList[p].data(h)};case 2:return function(A,p,h,E){return _nbind.externalList[p].data(h,E)};case 3:return function(A,p,h,E,w){return _nbind.externalList[p].data(h,E,w)};default:break}return buildJSCallerFunction(o,a)}_nbind.makeJSCaller=makeJSCaller;function makeMethodCaller(t,e){var r=e.typeList.length-1,o=e.typeList.slice(0);o.splice(1,0,\"uint32_t\",e.boundID);var a=_nbind.getTypes(o,e.title),n=a[0],u=a.slice(3),A=n.needsWireRead(e.policyTbl),p=anyNeedsWireWrite(u,e.policyTbl),h=e.ptr,E=e.num,w=_nbind.getDynCall(a,e.title),D=~e.flags&1;function b(){throw new Error(\"Calling a non-const method on a const object\")}if(!A&&!p)switch(r){case 0:return function(){return this.__nbindFlags&D?b():w(h,E,_nbind.pushPointer(this,t))};case 1:return function(C){return this.__nbindFlags&D?b():w(h,E,_nbind.pushPointer(this,t),C)};case 2:return function(C,T){return this.__nbindFlags&D?b():w(h,E,_nbind.pushPointer(this,t),C,T)};case 3:return function(C,T,N){return this.__nbindFlags&D?b():w(h,E,_nbind.pushPointer(this,t),C,T,N)};default:break}return buildCallerFunction(w,t,h,E,e.policyTbl,p,\"ptr,num,pushPointer(this,ptrType)\",n,u,D,b)}_nbind.makeMethodCaller=makeMethodCaller;function makeCaller(t){var e=t.typeList.length-1,r=_nbind.getTypes(t.typeList,t.title),o=r[0],a=r.slice(1),n=o.needsWireRead(t.policyTbl),u=anyNeedsWireWrite(a,t.policyTbl),A=t.direct,p=t.ptr;if(t.direct&&!n&&!u){var h=_nbind.getDynCall(r,t.title);switch(e){case 0:return function(){return h(A)};case 1:return function(b){return h(A,b)};case 2:return function(b,C){return h(A,b,C)};case 3:return function(b,C,T){return h(A,b,C,T)};default:break}p=0}var E;if(p){var w=t.typeList.slice(0);w.splice(1,0,\"uint32_t\"),r=_nbind.getTypes(w,t.title),E=\"ptr,num\"}else p=A,E=\"ptr\";var D=_nbind.getDynCall(r,t.title);return buildCallerFunction(D,null,p,t.num,t.policyTbl,u,E,o,a)}_nbind.makeCaller=makeCaller;function makeOverloader(t,e){var r=[];function o(){return r[arguments.length].apply(this,arguments)}return o.addMethod=function(a,n){r[n]=a},o.addMethod(t,e),o}_nbind.makeOverloader=makeOverloader;var Resource=function(){function t(e,r){var o=this;this.makeOpen=function(){return Object.keys(o.openTbl).join(\"\")},this.makeClose=function(){return Object.keys(o.closeTbl).join(\"\")},this.openTbl={},this.closeTbl={},e&&(this.openTbl[e]=!0),r&&(this.closeTbl[r]=!0)}return t.prototype.add=function(e){for(var r=0,o=Object.keys(e.openTbl);r<o.length;r++){var a=o[r];this.openTbl[a]=!0}for(var n=0,u=Object.keys(e.closeTbl);n<u.length;n++){var a=u[n];this.closeTbl[a]=!0}},t.prototype.remove=function(e){for(var r=0,o=Object.keys(e.openTbl);r<o.length;r++){var a=o[r];delete this.openTbl[a]}for(var n=0,u=Object.keys(e.closeTbl);n<u.length;n++){var a=u[n];delete this.closeTbl[a]}},t}();_nbind.Resource=Resource;function listResources(t,e){for(var r=new Resource,o=0,a=t;o<a.length;o++)for(var n=a[o],u=0,A=n.readResources||[];u<A.length;u++){var p=A[u];r.add(p)}for(var h=0,E=e;h<E.length;h++)for(var n=E[h],w=0,D=n.writeResources||[];w<D.length;w++){var p=D[w];r.add(p)}return r}_nbind.listResources=listResources,_nbind.resources={pool:new Resource(\"var used=HEAPU32[_nbind.Pool.usedPtr],page=HEAPU32[_nbind.Pool.pagePtr];\",\"_nbind.Pool.lreset(used,page);\")};var ExternalBuffer=function(t){__extends(e,t);function e(r,o){var a=t.call(this,r)||this;return a.ptr=o,a}return e.prototype.free=function(){_free(this.ptr)},e}(_nbind.External);function getBuffer(t){return t instanceof ArrayBuffer?new Uint8Array(t):t instanceof DataView?new Uint8Array(t.buffer,t.byteOffset,t.byteLength):t}function pushBuffer(t,e){if(t==null&&e&&e.Nullable&&(t=[]),typeof t!=\"object\")throw new Error(\"Type mismatch\");var r=t,o=r.byteLength||r.length;if(!o&&o!==0&&r.byteLength!==0)throw new Error(\"Type mismatch\");var a=_nbind.Pool.lalloc(8),n=_malloc(o),u=a/4;return HEAPU32[u++]=o,HEAPU32[u++]=n,HEAPU32[u++]=new ExternalBuffer(t,n).register(),HEAPU8.set(getBuffer(t),n),a}var BufferType=function(t){__extends(e,t);function e(){var r=t!==null&&t.apply(this,arguments)||this;return r.wireWrite=pushBuffer,r.readResources=[_nbind.resources.pool],r.writeResources=[_nbind.resources.pool],r}return e.prototype.makeWireWrite=function(r,o){return function(a){return pushBuffer(a,o)}},e}(_nbind.BindType);_nbind.BufferType=BufferType;function commitBuffer(t,e,r){var o=_nbind.externalList[t].data,a=Buffer;if(typeof Buffer!=\"function\"&&(a=function(){}),!(o instanceof Array)){var n=HEAPU8.subarray(e,e+r);if(o instanceof a){var u=void 0;typeof Buffer.from==\"function\"&&Buffer.from.length>=3?u=Buffer.from(n):u=new Buffer(n),u.copy(o)}else getBuffer(o).set(n)}}_nbind.commitBuffer=commitBuffer;var dirtyList=[],gcTimer=0;function sweep(){for(var t=0,e=dirtyList;t<e.length;t++){var r=e[t];r.__nbindState&3||r.free()}dirtyList=[],gcTimer=0}_nbind.mark=function(t){};function toggleLightGC(t){t?_nbind.mark=function(e){dirtyList.push(e),gcTimer||(gcTimer=setTimeout(sweep,0))}:_nbind.mark=function(e){}}_nbind.toggleLightGC=toggleLightGC}(_nbind),Module.requestFullScreen=function t(e,r,o){Module.printErr(\"Module.requestFullScreen is deprecated. Please call Module.requestFullscreen instead.\"),Module.requestFullScreen=Module.requestFullscreen,Browser.requestFullScreen(e,r,o)},Module.requestFullscreen=function t(e,r,o){Browser.requestFullscreen(e,r,o)},Module.requestAnimationFrame=function t(e){Browser.requestAnimationFrame(e)},Module.setCanvasSize=function t(e,r,o){Browser.setCanvasSize(e,r,o)},Module.pauseMainLoop=function t(){Browser.mainLoop.pause()},Module.resumeMainLoop=function t(){Browser.mainLoop.resume()},Module.getUserMedia=function t(){Browser.getUserMedia()},Module.createContext=function t(e,r,o,a){return Browser.createContext(e,r,o,a)},ENVIRONMENT_IS_NODE?_emscripten_get_now=function(){var e=process.hrtime();return e[0]*1e3+e[1]/1e6}:typeof dateNow<\"u\"?_emscripten_get_now=dateNow:typeof self==\"object\"&&self.performance&&typeof self.performance.now==\"function\"?_emscripten_get_now=function(){return self.performance.now()}:typeof performance==\"object\"&&typeof performance.now==\"function\"?_emscripten_get_now=function(){return performance.now()}:_emscripten_get_now=Date.now,__ATEXIT__.push(function(){var t=Module._fflush;t&&t(0);var e=___syscall146.printChar;if(e){var r=___syscall146.buffers;r[1].length&&e(1,10),r[2].length&&e(2,10)}}),DYNAMICTOP_PTR=allocate(1,\"i32\",ALLOC_STATIC),STACK_BASE=STACKTOP=Runtime.alignMemory(STATICTOP),STACK_MAX=STACK_BASE+TOTAL_STACK,DYNAMIC_BASE=Runtime.alignMemory(STACK_MAX),HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE,staticSealed=!0;function invoke_viiiii(t,e,r,o,a,n){try{Module.dynCall_viiiii(t,e,r,o,a,n)}catch(u){if(typeof u!=\"number\"&&u!==\"longjmp\")throw u;Module.setThrew(1,0)}}function invoke_vif(t,e,r){try{Module.dynCall_vif(t,e,r)}catch(o){if(typeof o!=\"number\"&&o!==\"longjmp\")throw o;Module.setThrew(1,0)}}function invoke_vid(t,e,r){try{Module.dynCall_vid(t,e,r)}catch(o){if(typeof o!=\"number\"&&o!==\"longjmp\")throw o;Module.setThrew(1,0)}}function invoke_fiff(t,e,r,o){try{return Module.dynCall_fiff(t,e,r,o)}catch(a){if(typeof a!=\"number\"&&a!==\"longjmp\")throw a;Module.setThrew(1,0)}}function invoke_vi(t,e){try{Module.dynCall_vi(t,e)}catch(r){if(typeof r!=\"number\"&&r!==\"longjmp\")throw r;Module.setThrew(1,0)}}function invoke_vii(t,e,r){try{Module.dynCall_vii(t,e,r)}catch(o){if(typeof o!=\"number\"&&o!==\"longjmp\")throw o;Module.setThrew(1,0)}}function invoke_ii(t,e){try{return Module.dynCall_ii(t,e)}catch(r){if(typeof r!=\"number\"&&r!==\"longjmp\")throw r;Module.setThrew(1,0)}}function invoke_viddi(t,e,r,o,a){try{Module.dynCall_viddi(t,e,r,o,a)}catch(n){if(typeof n!=\"number\"&&n!==\"longjmp\")throw n;Module.setThrew(1,0)}}function invoke_vidd(t,e,r,o){try{Module.dynCall_vidd(t,e,r,o)}catch(a){if(typeof a!=\"number\"&&a!==\"longjmp\")throw a;Module.setThrew(1,0)}}function invoke_iiii(t,e,r,o){try{return Module.dynCall_iiii(t,e,r,o)}catch(a){if(typeof a!=\"number\"&&a!==\"longjmp\")throw a;Module.setThrew(1,0)}}function invoke_diii(t,e,r,o){try{return Module.dynCall_diii(t,e,r,o)}catch(a){if(typeof a!=\"number\"&&a!==\"longjmp\")throw a;Module.setThrew(1,0)}}function invoke_di(t,e){try{return Module.dynCall_di(t,e)}catch(r){if(typeof r!=\"number\"&&r!==\"longjmp\")throw r;Module.setThrew(1,0)}}function invoke_iid(t,e,r){try{return Module.dynCall_iid(t,e,r)}catch(o){if(typeof o!=\"number\"&&o!==\"longjmp\")throw o;Module.setThrew(1,0)}}function invoke_iii(t,e,r){try{return Module.dynCall_iii(t,e,r)}catch(o){if(typeof o!=\"number\"&&o!==\"longjmp\")throw o;Module.setThrew(1,0)}}function invoke_viiddi(t,e,r,o,a,n){try{Module.dynCall_viiddi(t,e,r,o,a,n)}catch(u){if(typeof u!=\"number\"&&u!==\"longjmp\")throw u;Module.setThrew(1,0)}}function invoke_viiiiii(t,e,r,o,a,n,u){try{Module.dynCall_viiiiii(t,e,r,o,a,n,u)}catch(A){if(typeof A!=\"number\"&&A!==\"longjmp\")throw A;Module.setThrew(1,0)}}function invoke_dii(t,e,r){try{return Module.dynCall_dii(t,e,r)}catch(o){if(typeof o!=\"number\"&&o!==\"longjmp\")throw o;Module.setThrew(1,0)}}function invoke_i(t){try{return Module.dynCall_i(t)}catch(e){if(typeof e!=\"number\"&&e!==\"longjmp\")throw e;Module.setThrew(1,0)}}function invoke_iiiiii(t,e,r,o,a,n){try{return Module.dynCall_iiiiii(t,e,r,o,a,n)}catch(u){if(typeof u!=\"number\"&&u!==\"longjmp\")throw u;Module.setThrew(1,0)}}function invoke_viiid(t,e,r,o,a){try{Module.dynCall_viiid(t,e,r,o,a)}catch(n){if(typeof n!=\"number\"&&n!==\"longjmp\")throw n;Module.setThrew(1,0)}}function invoke_viififi(t,e,r,o,a,n,u){try{Module.dynCall_viififi(t,e,r,o,a,n,u)}catch(A){if(typeof A!=\"number\"&&A!==\"longjmp\")throw A;Module.setThrew(1,0)}}function invoke_viii(t,e,r,o){try{Module.dynCall_viii(t,e,r,o)}catch(a){if(typeof a!=\"number\"&&a!==\"longjmp\")throw a;Module.setThrew(1,0)}}function invoke_v(t){try{Module.dynCall_v(t)}catch(e){if(typeof e!=\"number\"&&e!==\"longjmp\")throw e;Module.setThrew(1,0)}}function invoke_viid(t,e,r,o){try{Module.dynCall_viid(t,e,r,o)}catch(a){if(typeof a!=\"number\"&&a!==\"longjmp\")throw a;Module.setThrew(1,0)}}function invoke_idd(t,e,r){try{return Module.dynCall_idd(t,e,r)}catch(o){if(typeof o!=\"number\"&&o!==\"longjmp\")throw o;Module.setThrew(1,0)}}function invoke_viiii(t,e,r,o,a){try{Module.dynCall_viiii(t,e,r,o,a)}catch(n){if(typeof n!=\"number\"&&n!==\"longjmp\")throw n;Module.setThrew(1,0)}}Module.asmGlobalArg={Math,Int8Array,Int16Array,Int32Array,Uint8Array,Uint16Array,Uint32Array,Float32Array,Float64Array,NaN:NaN,Infinity:1/0},Module.asmLibraryArg={abort,assert,enlargeMemory,getTotalMemory,abortOnCannotGrowMemory,invoke_viiiii,invoke_vif,invoke_vid,invoke_fiff,invoke_vi,invoke_vii,invoke_ii,invoke_viddi,invoke_vidd,invoke_iiii,invoke_diii,invoke_di,invoke_iid,invoke_iii,invoke_viiddi,invoke_viiiiii,invoke_dii,invoke_i,invoke_iiiiii,invoke_viiid,invoke_viififi,invoke_viii,invoke_v,invoke_viid,invoke_idd,invoke_viiii,_emscripten_asm_const_iiiii,_emscripten_asm_const_iiidddddd,_emscripten_asm_const_iiiid,__nbind_reference_external,_emscripten_asm_const_iiiiiiii,_removeAccessorPrefix,_typeModule,__nbind_register_pool,__decorate,_llvm_stackrestore,___cxa_atexit,__extends,__nbind_get_value_object,__ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj,_emscripten_set_main_loop_timing,__nbind_register_primitive,__nbind_register_type,_emscripten_memcpy_big,__nbind_register_function,___setErrNo,__nbind_register_class,__nbind_finish,_abort,_nbind_value,_llvm_stacksave,___syscall54,_defineHidden,_emscripten_set_main_loop,_emscripten_get_now,__nbind_register_callback_signature,_emscripten_asm_const_iiiiii,__nbind_free_external,_emscripten_asm_const_iiii,_emscripten_asm_const_iiididi,___syscall6,_atexit,___syscall140,___syscall146,DYNAMICTOP_PTR,tempDoublePtr,ABORT,STACKTOP,STACK_MAX,cttz_i8,___dso_handle};var asm=function(t,e,r){var o=new t.Int8Array(r),a=new t.Int16Array(r),n=new t.Int32Array(r),u=new t.Uint8Array(r),A=new t.Uint16Array(r),p=new t.Uint32Array(r),h=new t.Float32Array(r),E=new t.Float64Array(r),w=e.DYNAMICTOP_PTR|0,D=e.tempDoublePtr|0,b=e.ABORT|0,C=e.STACKTOP|0,T=e.STACK_MAX|0,N=e.cttz_i8|0,U=e.___dso_handle|0,z=0,te=0,le=0,ce=0,ue=t.NaN,Ie=t.Infinity,he=0,De=0,Ee=0,g=0,me=0,Ce=0,fe=t.Math.floor,ie=t.Math.abs,Z=t.Math.sqrt,Pe=t.Math.pow,Re=t.Math.cos,ht=t.Math.sin,q=t.Math.tan,nt=t.Math.acos,Le=t.Math.asin,Te=t.Math.atan,ke=t.Math.atan2,Ve=t.Math.exp,xe=t.Math.log,tt=t.Math.ceil,He=t.Math.imul,x=t.Math.min,I=t.Math.max,S=t.Math.clz32,y=t.Math.fround,R=e.abort,J=e.assert,X=e.enlargeMemory,$=e.getTotalMemory,se=e.abortOnCannotGrowMemory,be=e.invoke_viiiii,Fe=e.invoke_vif,lt=e.invoke_vid,Et=e.invoke_fiff,qt=e.invoke_vi,nr=e.invoke_vii,St=e.invoke_ii,cn=e.invoke_viddi,Pr=e.invoke_vidd,yr=e.invoke_iiii,Rr=e.invoke_diii,Xr=e.invoke_di,$n=e.invoke_iid,Xs=e.invoke_iii,Hi=e.invoke_viiddi,Qs=e.invoke_viiiiii,Zs=e.invoke_dii,bi=e.invoke_i,Fs=e.invoke_iiiiii,$s=e.invoke_viiid,SA=e.invoke_viififi,gu=e.invoke_viii,op=e.invoke_v,ap=e.invoke_viid,Rs=e.invoke_idd,Nn=e.invoke_viiii,hs=e._emscripten_asm_const_iiiii,Ts=e._emscripten_asm_const_iiidddddd,pc=e._emscripten_asm_const_iiiid,hc=e.__nbind_reference_external,gc=e._emscripten_asm_const_iiiiiiii,xA=e._removeAccessorPrefix,bA=e._typeModule,Ro=e.__nbind_register_pool,To=e.__decorate,kA=e._llvm_stackrestore,pr=e.___cxa_atexit,Me=e.__extends,ia=e.__nbind_get_value_object,dc=e.__ZN8facebook4yoga14YGNodeToStringEPNSt3__212basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6YGNode14YGPrintOptionsj,Er=e._emscripten_set_main_loop_timing,du=e.__nbind_register_primitive,QA=e.__nbind_register_type,FA=e._emscripten_memcpy_big,mc=e.__nbind_register_function,yc=e.___setErrNo,Il=e.__nbind_register_class,we=e.__nbind_finish,Tt=e._abort,wl=e._nbind_value,Bi=e._llvm_stacksave,Ls=e.___syscall54,Ft=e._defineHidden,Bn=e._emscripten_set_main_loop,Lo=e._emscripten_get_now,ki=e.__nbind_register_callback_signature,vi=e._emscripten_asm_const_iiiiii,sa=e.__nbind_free_external,un=e._emscripten_asm_const_iiii,qn=e._emscripten_asm_const_iiididi,Ec=e.___syscall6,lp=e._atexit,oa=e.___syscall140,aa=e.___syscall146,la=y(0);let Ze=y(0);function ca(s){s=s|0;var l=0;return l=C,C=C+s|0,C=C+15&-16,l|0}function mu(){return C|0}function Bl(s){s=s|0,C=s}function dn(s,l){s=s|0,l=l|0,C=s,T=l}function No(s,l){s=s|0,l=l|0,z||(z=s,te=l)}function RA(s){s=s|0,Ce=s}function TA(){return Ce|0}function Oo(){var s=0,l=0;br(8104,8,400)|0,br(8504,408,540)|0,s=9044,l=s+44|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));o[9088]=0,o[9089]=1,n[2273]=0,n[2274]=948,n[2275]=948,pr(17,8104,U|0)|0}function qa(s){s=s|0,gt(s+948|0)}function Ot(s){return s=y(s),((AD(s)|0)&2147483647)>>>0>2139095040|0}function vn(s,l,c){s=s|0,l=l|0,c=c|0;e:do if(n[s+(l<<3)+4>>2]|0)s=s+(l<<3)|0;else{if((l|2|0)==3&&n[s+60>>2]|0){s=s+56|0;break}switch(l|0){case 0:case 2:case 4:case 5:{if(n[s+52>>2]|0){s=s+48|0;break e}break}default:}if(n[s+68>>2]|0){s=s+64|0;break}else{s=(l|1|0)==5?948:c;break}}while(!1);return s|0}function Mo(s){s=s|0;var l=0;return l=_D(1e3)|0,ua(s,(l|0)!=0,2456),n[2276]=(n[2276]|0)+1,br(l|0,8104,1e3)|0,o[s+2>>0]|0&&(n[l+4>>2]=2,n[l+12>>2]=4),n[l+976>>2]=s,l|0}function ua(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;d=C,C=C+16|0,f=d,l||(n[f>>2]=c,d0(s,5,3197,f)),C=d}function qi(){return Mo(956)|0}function vl(s){s=s|0;var l=0;return l=Yt(1e3)|0,Cc(l,s),ua(n[s+976>>2]|0,1,2456),n[2276]=(n[2276]|0)+1,n[l+944>>2]=0,l|0}function Cc(s,l){s=s|0,l=l|0;var c=0;br(s|0,l|0,948)|0,Qd(s+948|0,l+948|0),c=s+960|0,s=l+960|0,l=c+40|0;do n[c>>2]=n[s>>2],c=c+4|0,s=s+4|0;while((c|0)<(l|0))}function Dl(s){s=s|0;var l=0,c=0,f=0,d=0;if(l=s+944|0,c=n[l>>2]|0,c|0&&(Aa(c+948|0,s)|0,n[l>>2]=0),c=Di(s)|0,c|0){l=0;do n[(rs(s,l)|0)+944>>2]=0,l=l+1|0;while((l|0)!=(c|0))}c=s+948|0,f=n[c>>2]|0,d=s+952|0,l=n[d>>2]|0,(l|0)!=(f|0)&&(n[d>>2]=l+(~((l+-4-f|0)>>>2)<<2)),ja(c),HD(s),n[2276]=(n[2276]|0)+-1}function Aa(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0;f=n[s>>2]|0,k=s+4|0,c=n[k>>2]|0,m=c;e:do if((f|0)==(c|0))d=f,B=4;else for(s=f;;){if((n[s>>2]|0)==(l|0)){d=s,B=4;break e}if(s=s+4|0,(s|0)==(c|0)){s=0;break}}while(!1);return(B|0)==4&&((d|0)!=(c|0)?(f=d+4|0,s=m-f|0,l=s>>2,l&&(rw(d|0,f|0,s|0)|0,c=n[k>>2]|0),s=d+(l<<2)|0,(c|0)==(s|0)||(n[k>>2]=c+(~((c+-4-s|0)>>>2)<<2)),s=1):s=0),s|0}function Di(s){return s=s|0,(n[s+952>>2]|0)-(n[s+948>>2]|0)>>2|0}function rs(s,l){s=s|0,l=l|0;var c=0;return c=n[s+948>>2]|0,(n[s+952>>2]|0)-c>>2>>>0>l>>>0?s=n[c+(l<<2)>>2]|0:s=0,s|0}function ja(s){s=s|0;var l=0,c=0,f=0,d=0;f=C,C=C+32|0,l=f,d=n[s>>2]|0,c=(n[s+4>>2]|0)-d|0,((n[s+8>>2]|0)-d|0)>>>0>c>>>0&&(d=c>>2,Ld(l,d,d,s+8|0),fD(s,l),Nd(l)),C=f}function yu(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0;M=Di(s)|0;do if(M|0){if((n[(rs(s,0)|0)+944>>2]|0)==(s|0)){if(!(Aa(s+948|0,l)|0))break;br(l+400|0,8504,540)|0,n[l+944>>2]=0,Ne(s);break}B=n[(n[s+976>>2]|0)+12>>2]|0,k=s+948|0,F=(B|0)==0,c=0,m=0;do f=n[(n[k>>2]|0)+(m<<2)>>2]|0,(f|0)==(l|0)?Ne(s):(d=vl(f)|0,n[(n[k>>2]|0)+(c<<2)>>2]=d,n[d+944>>2]=s,F||hT[B&15](f,d,s,c),c=c+1|0),m=m+1|0;while((m|0)!=(M|0));if(c>>>0<M>>>0){F=s+948|0,k=s+952|0,B=c,c=n[k>>2]|0;do m=(n[F>>2]|0)+(B<<2)|0,f=m+4|0,d=c-f|0,l=d>>2,l&&(rw(m|0,f|0,d|0)|0,c=n[k>>2]|0),d=c,f=m+(l<<2)|0,(d|0)!=(f|0)&&(c=d+(~((d+-4-f|0)>>>2)<<2)|0,n[k>>2]=c),B=B+1|0;while((B|0)!=(M|0))}}while(!1)}function Pl(s){s=s|0;var l=0,c=0,f=0,d=0;pi(s,(Di(s)|0)==0,2491),pi(s,(n[s+944>>2]|0)==0,2545),l=s+948|0,c=n[l>>2]|0,f=s+952|0,d=n[f>>2]|0,(d|0)!=(c|0)&&(n[f>>2]=d+(~((d+-4-c|0)>>>2)<<2)),ja(l),l=s+976|0,c=n[l>>2]|0,br(s|0,8104,1e3)|0,o[c+2>>0]|0&&(n[s+4>>2]=2,n[s+12>>2]=4),n[l>>2]=c}function pi(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;d=C,C=C+16|0,f=d,l||(n[f>>2]=c,so(s,5,3197,f)),C=d}function Dn(){return n[2276]|0}function Sl(){var s=0;return s=_D(20)|0,ze((s|0)!=0,2592),n[2277]=(n[2277]|0)+1,n[s>>2]=n[239],n[s+4>>2]=n[240],n[s+8>>2]=n[241],n[s+12>>2]=n[242],n[s+16>>2]=n[243],s|0}function ze(s,l){s=s|0,l=l|0;var c=0,f=0;f=C,C=C+16|0,c=f,s||(n[c>>2]=l,so(0,5,3197,c)),C=f}function it(s){s=s|0,HD(s),n[2277]=(n[2277]|0)+-1}function vt(s,l){s=s|0,l=l|0;var c=0;l?(pi(s,(Di(s)|0)==0,2629),c=1):(c=0,l=0),n[s+964>>2]=l,n[s+988>>2]=c}function ar(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,m=f+8|0,d=f+4|0,B=f,n[d>>2]=l,pi(s,(n[l+944>>2]|0)==0,2709),pi(s,(n[s+964>>2]|0)==0,2763),ee(s),l=s+948|0,n[B>>2]=(n[l>>2]|0)+(c<<2),n[m>>2]=n[B>>2],ye(l,m,d)|0,n[(n[d>>2]|0)+944>>2]=s,Ne(s),C=f}function ee(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0;if(c=Di(s)|0,c|0&&(n[(rs(s,0)|0)+944>>2]|0)!=(s|0)){f=n[(n[s+976>>2]|0)+12>>2]|0,d=s+948|0,m=(f|0)==0,l=0;do B=n[(n[d>>2]|0)+(l<<2)>>2]|0,k=vl(B)|0,n[(n[d>>2]|0)+(l<<2)>>2]=k,n[k+944>>2]=s,m||hT[f&15](B,k,s,l),l=l+1|0;while((l|0)!=(c|0))}}function ye(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0,We=0,Oe=0,Qe=0,rt=0,Xe=0;rt=C,C=C+64|0,j=rt+52|0,k=rt+48|0,oe=rt+28|0,We=rt+24|0,Oe=rt+20|0,Qe=rt,f=n[s>>2]|0,m=f,l=f+((n[l>>2]|0)-m>>2<<2)|0,f=s+4|0,d=n[f>>2]|0,B=s+8|0;do if(d>>>0<(n[B>>2]|0)>>>0){if((l|0)==(d|0)){n[l>>2]=n[c>>2],n[f>>2]=(n[f>>2]|0)+4;break}pD(s,l,d,l+4|0),l>>>0<=c>>>0&&(c=(n[f>>2]|0)>>>0>c>>>0?c+4|0:c),n[l>>2]=n[c>>2]}else{f=(d-m>>2)+1|0,d=L(s)|0,d>>>0<f>>>0&&Zr(s),O=n[s>>2]|0,M=(n[B>>2]|0)-O|0,m=M>>1,Ld(Qe,M>>2>>>0<d>>>1>>>0?m>>>0<f>>>0?f:m:d,l-O>>2,s+8|0),O=Qe+8|0,f=n[O>>2]|0,m=Qe+12|0,M=n[m>>2]|0,B=M,F=f;do if((f|0)==(M|0)){if(M=Qe+4|0,f=n[M>>2]|0,Xe=n[Qe>>2]|0,d=Xe,f>>>0<=Xe>>>0){f=B-d>>1,f=f|0?f:1,Ld(oe,f,f>>>2,n[Qe+16>>2]|0),n[We>>2]=n[M>>2],n[Oe>>2]=n[O>>2],n[k>>2]=n[We>>2],n[j>>2]=n[Oe>>2],QI(oe,k,j),f=n[Qe>>2]|0,n[Qe>>2]=n[oe>>2],n[oe>>2]=f,f=oe+4|0,Xe=n[M>>2]|0,n[M>>2]=n[f>>2],n[f>>2]=Xe,f=oe+8|0,Xe=n[O>>2]|0,n[O>>2]=n[f>>2],n[f>>2]=Xe,f=oe+12|0,Xe=n[m>>2]|0,n[m>>2]=n[f>>2],n[f>>2]=Xe,Nd(oe),f=n[O>>2]|0;break}m=f,B=((m-d>>2)+1|0)/-2|0,k=f+(B<<2)|0,d=F-m|0,m=d>>2,m&&(rw(k|0,f|0,d|0)|0,f=n[M>>2]|0),Xe=k+(m<<2)|0,n[O>>2]=Xe,n[M>>2]=f+(B<<2),f=Xe}while(!1);n[f>>2]=n[c>>2],n[O>>2]=(n[O>>2]|0)+4,l=hD(s,Qe,l)|0,Nd(Qe)}while(!1);return C=rt,l|0}function Ne(s){s=s|0;var l=0;do{if(l=s+984|0,o[l>>0]|0)break;o[l>>0]=1,h[s+504>>2]=y(ue),s=n[s+944>>2]|0}while(s|0)}function gt(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-4-f|0)>>>2)<<2)),yt(c))}function mt(s){return s=s|0,n[s+944>>2]|0}function Dt(s){s=s|0,pi(s,(n[s+964>>2]|0)!=0,2832),Ne(s)}function er(s){return s=s|0,(o[s+984>>0]|0)!=0|0}function sn(s,l){s=s|0,l=l|0,wUe(s,l,400)|0&&(br(s|0,l|0,400)|0,Ne(s))}function ei(s){s=s|0;var l=Ze;return l=y(h[s+44>>2]),s=Ot(l)|0,y(s?y(0):l)}function Qi(s){s=s|0;var l=Ze;return l=y(h[s+48>>2]),Ot(l)|0&&(l=o[(n[s+976>>2]|0)+2>>0]|0?y(1):y(0)),y(l)}function Pn(s,l){s=s|0,l=l|0,n[s+980>>2]=l}function fa(s){return s=s|0,n[s+980>>2]|0}function wd(s,l){s=s|0,l=l|0;var c=0;c=s+4|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Ne(s))}function BI(s){return s=s|0,n[s+4>>2]|0}function eo(s,l){s=s|0,l=l|0;var c=0;c=s+8|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Ne(s))}function Bd(s){return s=s|0,n[s+8>>2]|0}function cp(s,l){s=s|0,l=l|0;var c=0;c=s+12|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Ne(s))}function vI(s){return s=s|0,n[s+12>>2]|0}function to(s,l){s=s|0,l=l|0;var c=0;c=s+16|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Ne(s))}function up(s){return s=s|0,n[s+16>>2]|0}function Ap(s,l){s=s|0,l=l|0;var c=0;c=s+20|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Ne(s))}function Ic(s){return s=s|0,n[s+20>>2]|0}function fp(s,l){s=s|0,l=l|0;var c=0;c=s+24|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Ne(s))}function s0(s){return s=s|0,n[s+24>>2]|0}function o0(s,l){s=s|0,l=l|0;var c=0;c=s+28|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Ne(s))}function a0(s){return s=s|0,n[s+28>>2]|0}function vd(s,l){s=s|0,l=l|0;var c=0;c=s+32|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Ne(s))}function Eu(s){return s=s|0,n[s+32>>2]|0}function ro(s,l){s=s|0,l=l|0;var c=0;c=s+36|0,(n[c>>2]|0)!=(l|0)&&(n[c>>2]=l,Ne(s))}function Ga(s){return s=s|0,n[s+36>>2]|0}function pp(s,l){s=s|0,l=y(l);var c=0;c=s+40|0,y(h[c>>2])!=l&&(h[c>>2]=l,Ne(s))}function l0(s,l){s=s|0,l=y(l);var c=0;c=s+44|0,y(h[c>>2])!=l&&(h[c>>2]=l,Ne(s))}function Wa(s,l){s=s|0,l=y(l);var c=0;c=s+48|0,y(h[c>>2])!=l&&(h[c>>2]=l,Ne(s))}function Ya(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ot(l)|0,c=(m^1)&1,f=s+52|0,d=s+56|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Ne(s))}function Dd(s,l){s=s|0,l=y(l);var c=0,f=0;f=s+52|0,c=s+56|0,y(h[f>>2])==l&&(n[c>>2]|0)==2||(h[f>>2]=l,f=Ot(l)|0,n[c>>2]=f?3:2,Ne(s))}function LA(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+52|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function Pd(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Ot(c)|0,f=(m^1)&1,d=s+132+(l<<3)|0,l=s+132+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Ne(s))}function Sd(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Ot(c)|0,f=m?0:2,d=s+132+(l<<3)|0,l=s+132+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Ne(s))}function NA(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=l+132+(c<<3)|0,l=n[f+4>>2]|0,c=s,n[c>>2]=n[f>>2],n[c+4>>2]=l}function OA(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Ot(c)|0,f=(m^1)&1,d=s+60+(l<<3)|0,l=s+60+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Ne(s))}function W(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Ot(c)|0,f=m?0:2,d=s+60+(l<<3)|0,l=s+60+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Ne(s))}function xt(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=l+60+(c<<3)|0,l=n[f+4>>2]|0,c=s,n[c>>2]=n[f>>2],n[c+4>>2]=l}function MA(s,l){s=s|0,l=l|0;var c=0;c=s+60+(l<<3)+4|0,(n[c>>2]|0)!=3&&(h[s+60+(l<<3)>>2]=y(ue),n[c>>2]=3,Ne(s))}function no(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Ot(c)|0,f=(m^1)&1,d=s+204+(l<<3)|0,l=s+204+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Ne(s))}function Cu(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Ot(c)|0,f=m?0:2,d=s+204+(l<<3)|0,l=s+204+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Ne(s))}function dt(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=l+204+(c<<3)|0,l=n[f+4>>2]|0,c=s,n[c>>2]=n[f>>2],n[c+4>>2]=l}function wc(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0,m=0;m=Ot(c)|0,f=(m^1)&1,d=s+276+(l<<3)|0,l=s+276+(l<<3)+4|0,m|y(h[d>>2])==c&&(n[l>>2]|0)==(f|0)||(h[d>>2]=c,n[l>>2]=f,Ne(s))}function xd(s,l){return s=s|0,l=l|0,y(h[s+276+(l<<3)>>2])}function c0(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ot(l)|0,c=(m^1)&1,f=s+348|0,d=s+352|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Ne(s))}function DI(s,l){s=s|0,l=y(l);var c=0,f=0;f=s+348|0,c=s+352|0,y(h[f>>2])==l&&(n[c>>2]|0)==2||(h[f>>2]=l,f=Ot(l)|0,n[c>>2]=f?3:2,Ne(s))}function hp(s){s=s|0;var l=0;l=s+352|0,(n[l>>2]|0)!=3&&(h[s+348>>2]=y(ue),n[l>>2]=3,Ne(s))}function cr(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+348|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function Ni(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ot(l)|0,c=(m^1)&1,f=s+356|0,d=s+360|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Ne(s))}function Iu(s,l){s=s|0,l=y(l);var c=0,f=0;f=s+356|0,c=s+360|0,y(h[f>>2])==l&&(n[c>>2]|0)==2||(h[f>>2]=l,f=Ot(l)|0,n[c>>2]=f?3:2,Ne(s))}function pa(s){s=s|0;var l=0;l=s+360|0,(n[l>>2]|0)!=3&&(h[s+356>>2]=y(ue),n[l>>2]=3,Ne(s))}function u0(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+356|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function Bc(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ot(l)|0,c=(m^1)&1,f=s+364|0,d=s+368|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Ne(s))}function wu(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ot(l)|0,c=m?0:2,f=s+364|0,d=s+368|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Ne(s))}function wt(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+364|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function oi(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ot(l)|0,c=(m^1)&1,f=s+372|0,d=s+376|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Ne(s))}function UA(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ot(l)|0,c=m?0:2,f=s+372|0,d=s+376|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Ne(s))}function ha(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+372|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function Uo(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ot(l)|0,c=(m^1)&1,f=s+380|0,d=s+384|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Ne(s))}function ga(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ot(l)|0,c=m?0:2,f=s+380|0,d=s+384|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Ne(s))}function A0(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+380|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function gp(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ot(l)|0,c=(m^1)&1,f=s+388|0,d=s+392|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Ne(s))}function f0(s,l){s=s|0,l=y(l);var c=0,f=0,d=0,m=0;m=Ot(l)|0,c=m?0:2,f=s+388|0,d=s+392|0,m|y(h[f>>2])==l&&(n[d>>2]|0)==(c|0)||(h[f>>2]=l,n[d>>2]=c,Ne(s))}function bd(s,l){s=s|0,l=l|0;var c=0,f=0;f=l+388|0,c=n[f+4>>2]|0,l=s,n[l>>2]=n[f>>2],n[l+4>>2]=c}function _A(s,l){s=s|0,l=y(l);var c=0;c=s+396|0,y(h[c>>2])!=l&&(h[c>>2]=l,Ne(s))}function p0(s){return s=s|0,y(h[s+396>>2])}function vc(s){return s=s|0,y(h[s+400>>2])}function Dc(s){return s=s|0,y(h[s+404>>2])}function Bu(s){return s=s|0,y(h[s+408>>2])}function gs(s){return s=s|0,y(h[s+412>>2])}function Pc(s){return s=s|0,y(h[s+416>>2])}function On(s){return s=s|0,y(h[s+420>>2])}function ji(s,l){switch(s=s|0,l=l|0,pi(s,(l|0)<6,2918),l|0){case 0:{l=(n[s+496>>2]|0)==2?5:4;break}case 2:{l=(n[s+496>>2]|0)==2?4:5;break}default:}return y(h[s+424+(l<<2)>>2])}function Ci(s,l){switch(s=s|0,l=l|0,pi(s,(l|0)<6,2918),l|0){case 0:{l=(n[s+496>>2]|0)==2?5:4;break}case 2:{l=(n[s+496>>2]|0)==2?4:5;break}default:}return y(h[s+448+(l<<2)>>2])}function HA(s,l){switch(s=s|0,l=l|0,pi(s,(l|0)<6,2918),l|0){case 0:{l=(n[s+496>>2]|0)==2?5:4;break}case 2:{l=(n[s+496>>2]|0)==2?4:5;break}default:}return y(h[s+472+(l<<2)>>2])}function vu(s,l){s=s|0,l=l|0;var c=0,f=Ze;return c=n[s+4>>2]|0,(c|0)==(n[l+4>>2]|0)?c?(f=y(h[s>>2]),s=y(ie(y(f-y(h[l>>2]))))<y(999999974e-13)):s=1:s=0,s|0}function An(s,l){s=y(s),l=y(l);var c=0;return Ot(s)|0?c=Ot(l)|0:c=y(ie(y(s-l)))<y(999999974e-13),c|0}function h0(s,l){s=s|0,l=l|0,g0(s,l)}function g0(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c+4|0,n[f>>2]=0,n[f+4>>2]=0,n[f+8>>2]=0,dc(f|0,s|0,l|0,0),so(s,3,(o[f+11>>0]|0)<0?n[f>>2]|0:f,c),WUe(f),C=c}function Gi(s,l,c,f){s=y(s),l=y(l),c=c|0,f=f|0;var d=Ze;s=y(s*l),d=y(lT(s,y(1)));do if(An(d,y(0))|0)s=y(s-d);else{if(s=y(s-d),An(d,y(1))|0){s=y(s+y(1));break}if(c){s=y(s+y(1));break}f||(d>y(.5)?d=y(1):(f=An(d,y(.5))|0,d=y(f?1:0)),s=y(s+d))}while(!1);return y(s/l)}function Ka(s,l,c,f,d,m,B,k,F,M,O,j,oe){s=s|0,l=y(l),c=c|0,f=y(f),d=d|0,m=y(m),B=B|0,k=y(k),F=y(F),M=y(M),O=y(O),j=y(j),oe=oe|0;var We=0,Oe=Ze,Qe=Ze,rt=Ze,Xe=Ze,ct=Ze,_e=Ze;return F<y(0)|M<y(0)?oe=0:(oe|0&&(Oe=y(h[oe+4>>2]),Oe!=y(0))?(rt=y(Gi(l,Oe,0,0)),Xe=y(Gi(f,Oe,0,0)),Qe=y(Gi(m,Oe,0,0)),Oe=y(Gi(k,Oe,0,0))):(Qe=m,rt=l,Oe=k,Xe=f),(d|0)==(s|0)?We=An(Qe,rt)|0:We=0,(B|0)==(c|0)?oe=An(Oe,Xe)|0:oe=0,!We&&(ct=y(l-O),!(io(s,ct,F)|0))&&!(Du(s,ct,d,F)|0)?We=Pu(s,ct,d,m,F)|0:We=1,!oe&&(_e=y(f-j),!(io(c,_e,M)|0))&&!(Du(c,_e,B,M)|0)?oe=Pu(c,_e,B,k,M)|0:oe=1,oe=We&oe),oe|0}function io(s,l,c){return s=s|0,l=y(l),c=y(c),(s|0)==1?s=An(l,c)|0:s=0,s|0}function Du(s,l,c,f){return s=s|0,l=y(l),c=c|0,f=y(f),(s|0)==2&(c|0)==0?l>=f?s=1:s=An(l,f)|0:s=0,s|0}function Pu(s,l,c,f,d){return s=s|0,l=y(l),c=c|0,f=y(f),d=y(d),(s|0)==2&(c|0)==2&f>l?d<=l?s=1:s=An(l,d)|0:s=0,s|0}function Va(s,l,c,f,d,m,B,k,F,M,O){s=s|0,l=y(l),c=y(c),f=f|0,d=d|0,m=m|0,B=y(B),k=y(k),F=F|0,M=M|0,O=O|0;var j=0,oe=0,We=0,Oe=0,Qe=Ze,rt=Ze,Xe=0,ct=0,_e=0,Ge=0,Nt=0,_r=0,ur=0,Zt=0,kr=0,Or=0,lr=0,Ln=Ze,lo=Ze,co=Ze,uo=0,Ia=0;lr=C,C=C+160|0,Zt=lr+152|0,ur=lr+120|0,_r=lr+104|0,_e=lr+72|0,Oe=lr+56|0,Nt=lr+8|0,ct=lr,Ge=(n[2279]|0)+1|0,n[2279]=Ge,kr=s+984|0,o[kr>>0]|0&&(n[s+512>>2]|0)!=(n[2278]|0)?Xe=4:(n[s+516>>2]|0)==(f|0)?Or=0:Xe=4,(Xe|0)==4&&(n[s+520>>2]=0,n[s+924>>2]=-1,n[s+928>>2]=-1,h[s+932>>2]=y(-1),h[s+936>>2]=y(-1),Or=1);e:do if(n[s+964>>2]|0)if(Qe=y(fn(s,2,B)),rt=y(fn(s,0,B)),j=s+916|0,co=y(h[j>>2]),lo=y(h[s+920>>2]),Ln=y(h[s+932>>2]),Ka(d,l,m,c,n[s+924>>2]|0,co,n[s+928>>2]|0,lo,Ln,y(h[s+936>>2]),Qe,rt,O)|0)Xe=22;else if(We=n[s+520>>2]|0,!We)Xe=21;else for(oe=0;;){if(j=s+524+(oe*24|0)|0,Ln=y(h[j>>2]),lo=y(h[s+524+(oe*24|0)+4>>2]),co=y(h[s+524+(oe*24|0)+16>>2]),Ka(d,l,m,c,n[s+524+(oe*24|0)+8>>2]|0,Ln,n[s+524+(oe*24|0)+12>>2]|0,lo,co,y(h[s+524+(oe*24|0)+20>>2]),Qe,rt,O)|0){Xe=22;break e}if(oe=oe+1|0,oe>>>0>=We>>>0){Xe=21;break}}else{if(F){if(j=s+916|0,!(An(y(h[j>>2]),l)|0)){Xe=21;break}if(!(An(y(h[s+920>>2]),c)|0)){Xe=21;break}if((n[s+924>>2]|0)!=(d|0)){Xe=21;break}j=(n[s+928>>2]|0)==(m|0)?j:0,Xe=22;break}if(We=n[s+520>>2]|0,!We)Xe=21;else for(oe=0;;){if(j=s+524+(oe*24|0)|0,An(y(h[j>>2]),l)|0&&An(y(h[s+524+(oe*24|0)+4>>2]),c)|0&&(n[s+524+(oe*24|0)+8>>2]|0)==(d|0)&&(n[s+524+(oe*24|0)+12>>2]|0)==(m|0)){Xe=22;break e}if(oe=oe+1|0,oe>>>0>=We>>>0){Xe=21;break}}}while(!1);do if((Xe|0)==21)o[11697]|0?(j=0,Xe=28):(j=0,Xe=31);else if((Xe|0)==22){if(oe=(o[11697]|0)!=0,!((j|0)!=0&(Or^1)))if(oe){Xe=28;break}else{Xe=31;break}Oe=j+16|0,n[s+908>>2]=n[Oe>>2],We=j+20|0,n[s+912>>2]=n[We>>2],(o[11698]|0)==0|oe^1||(n[ct>>2]=Sc(Ge)|0,n[ct+4>>2]=Ge,so(s,4,2972,ct),oe=n[s+972>>2]|0,oe|0&&ef[oe&127](s),d=_o(d,F)|0,m=_o(m,F)|0,Ia=+y(h[Oe>>2]),uo=+y(h[We>>2]),n[Nt>>2]=d,n[Nt+4>>2]=m,E[Nt+8>>3]=+l,E[Nt+16>>3]=+c,E[Nt+24>>3]=Ia,E[Nt+32>>3]=uo,n[Nt+40>>2]=M,so(s,4,2989,Nt))}while(!1);return(Xe|0)==28&&(oe=Sc(Ge)|0,n[Oe>>2]=oe,n[Oe+4>>2]=Ge,n[Oe+8>>2]=Or?3047:11699,so(s,4,3038,Oe),oe=n[s+972>>2]|0,oe|0&&ef[oe&127](s),Nt=_o(d,F)|0,Xe=_o(m,F)|0,n[_e>>2]=Nt,n[_e+4>>2]=Xe,E[_e+8>>3]=+l,E[_e+16>>3]=+c,n[_e+24>>2]=M,so(s,4,3049,_e),Xe=31),(Xe|0)==31&&(ds(s,l,c,f,d,m,B,k,F,O),o[11697]|0&&(oe=n[2279]|0,Nt=Sc(oe)|0,n[_r>>2]=Nt,n[_r+4>>2]=oe,n[_r+8>>2]=Or?3047:11699,so(s,4,3083,_r),oe=n[s+972>>2]|0,oe|0&&ef[oe&127](s),Nt=_o(d,F)|0,_r=_o(m,F)|0,uo=+y(h[s+908>>2]),Ia=+y(h[s+912>>2]),n[ur>>2]=Nt,n[ur+4>>2]=_r,E[ur+8>>3]=uo,E[ur+16>>3]=Ia,n[ur+24>>2]=M,so(s,4,3092,ur)),n[s+516>>2]=f,j||(oe=s+520|0,j=n[oe>>2]|0,(j|0)==16&&(o[11697]|0&&so(s,4,3124,Zt),n[oe>>2]=0,j=0),F?j=s+916|0:(n[oe>>2]=j+1,j=s+524+(j*24|0)|0),h[j>>2]=l,h[j+4>>2]=c,n[j+8>>2]=d,n[j+12>>2]=m,n[j+16>>2]=n[s+908>>2],n[j+20>>2]=n[s+912>>2],j=0)),F&&(n[s+416>>2]=n[s+908>>2],n[s+420>>2]=n[s+912>>2],o[s+985>>0]=1,o[kr>>0]=0),n[2279]=(n[2279]|0)+-1,n[s+512>>2]=n[2278],C=lr,Or|(j|0)==0|0}function fn(s,l,c){s=s|0,l=l|0,c=y(c);var f=Ze;return f=y(V(s,l,c)),y(f+y(re(s,l,c)))}function so(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=C,C=C+16|0,d=m,n[d>>2]=f,s?f=n[s+976>>2]|0:f=0,yp(f,s,l,c,d),C=m}function Sc(s){return s=s|0,(s>>>0>60?3201:3201+(60-s)|0)|0}function _o(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;return d=C,C=C+32|0,c=d+12|0,f=d,n[c>>2]=n[254],n[c+4>>2]=n[255],n[c+8>>2]=n[256],n[f>>2]=n[257],n[f+4>>2]=n[258],n[f+8>>2]=n[259],(s|0)>2?s=11699:s=n[(l?f:c)+(s<<2)>>2]|0,C=d,s|0}function ds(s,l,c,f,d,m,B,k,F,M){s=s|0,l=y(l),c=y(c),f=f|0,d=d|0,m=m|0,B=y(B),k=y(k),F=F|0,M=M|0;var O=0,j=0,oe=0,We=0,Oe=Ze,Qe=Ze,rt=Ze,Xe=Ze,ct=Ze,_e=Ze,Ge=Ze,Nt=0,_r=0,ur=0,Zt=Ze,kr=Ze,Or=0,lr=Ze,Ln=0,lo=0,co=0,uo=0,Ia=0,Lp=0,Np=0,kl=0,Op=0,Nu=0,Ou=0,Mp=0,Up=0,_p=0,$r=0,Ql=0,Hp=0,Lc=0,qp=Ze,jp=Ze,Mu=Ze,Uu=Ze,Nc=Ze,Ms=0,rl=0,Go=0,Fl=0,rf=0,nf=Ze,_u=Ze,sf=Ze,of=Ze,Us=Ze,Cs=Ze,Rl=0,Un=Ze,af=Ze,Ao=Ze,Oc=Ze,fo=Ze,Mc=Ze,lf=0,cf=0,Uc=Ze,_s=Ze,Tl=0,uf=0,Af=0,ff=0,Fr=Ze,ri=0,Is=0,po=0,Hs=0,Lr=0,Ar=0,Ll=0,Vt=Ze,pf=0,hi=0;Ll=C,C=C+16|0,Ms=Ll+12|0,rl=Ll+8|0,Go=Ll+4|0,Fl=Ll,pi(s,(d|0)==0|(Ot(l)|0)^1,3326),pi(s,(m|0)==0|(Ot(c)|0)^1,3406),Is=At(s,f)|0,n[s+496>>2]=Is,Lr=hr(2,Is)|0,Ar=hr(0,Is)|0,h[s+440>>2]=y(V(s,Lr,B)),h[s+444>>2]=y(re(s,Lr,B)),h[s+428>>2]=y(V(s,Ar,B)),h[s+436>>2]=y(re(s,Ar,B)),h[s+464>>2]=y(Ir(s,Lr)),h[s+468>>2]=y(Rn(s,Lr)),h[s+452>>2]=y(Ir(s,Ar)),h[s+460>>2]=y(Rn(s,Ar)),h[s+488>>2]=y(ai(s,Lr,B)),h[s+492>>2]=y(ns(s,Lr,B)),h[s+476>>2]=y(ai(s,Ar,B)),h[s+484>>2]=y(ns(s,Ar,B));do if(n[s+964>>2]|0)GA(s,l,c,d,m,B,k);else{if(po=s+948|0,Hs=(n[s+952>>2]|0)-(n[po>>2]|0)>>2,!Hs){lD(s,l,c,d,m,B,k);break}if(!F&&PI(s,l,c,d,m,B,k)|0)break;ee(s),Ql=s+508|0,o[Ql>>0]=0,Lr=hr(n[s+4>>2]|0,Is)|0,Ar=Fd(Lr,Is)|0,ri=ge(Lr)|0,Hp=n[s+8>>2]|0,uf=s+28|0,Lc=(n[uf>>2]|0)!=0,fo=ri?B:k,Uc=ri?k:B,qp=y(Cp(s,Lr,B)),jp=y(SI(s,Lr,B)),Oe=y(Cp(s,Ar,B)),Mc=y(da(s,Lr,B)),_s=y(da(s,Ar,B)),ur=ri?d:m,Tl=ri?m:d,Fr=ri?Mc:_s,ct=ri?_s:Mc,Oc=y(fn(s,2,B)),Xe=y(fn(s,0,B)),Qe=y(y(Kr(s+364|0,B))-Fr),rt=y(y(Kr(s+380|0,B))-Fr),_e=y(y(Kr(s+372|0,k))-ct),Ge=y(y(Kr(s+388|0,k))-ct),Mu=ri?Qe:_e,Uu=ri?rt:Ge,Oc=y(l-Oc),l=y(Oc-Fr),Ot(l)|0?Fr=l:Fr=y(Yn(y(M0(l,rt)),Qe)),af=y(c-Xe),l=y(af-ct),Ot(l)|0?Ao=l:Ao=y(Yn(y(M0(l,Ge)),_e)),Qe=ri?Fr:Ao,Un=ri?Ao:Fr;e:do if((ur|0)==1)for(f=0,j=0;;){if(O=rs(s,j)|0,!f)y(WA(O))>y(0)&&y(Ip(O))>y(0)?f=O:f=0;else if(xI(O)|0){We=0;break e}if(j=j+1|0,j>>>0>=Hs>>>0){We=f;break}}else We=0;while(!1);Nt=We+500|0,_r=We+504|0,f=0,O=0,l=y(0),oe=0;do{if(j=n[(n[po>>2]|0)+(oe<<2)>>2]|0,(n[j+36>>2]|0)==1)Rd(j),o[j+985>>0]=1,o[j+984>>0]=0;else{Su(j),F&&mp(j,At(j,Is)|0,Qe,Un,Fr);do if((n[j+24>>2]|0)!=1)if((j|0)==(We|0)){n[Nt>>2]=n[2278],h[_r>>2]=y(0);break}else{cD(s,j,Fr,d,Ao,Fr,Ao,m,Is,M);break}else O|0&&(n[O+960>>2]=j),n[j+960>>2]=0,O=j,f=f|0?f:j;while(!1);Cs=y(h[j+504>>2]),l=y(l+y(Cs+y(fn(j,Lr,Fr))))}oe=oe+1|0}while((oe|0)!=(Hs|0));for(co=l>Qe,Rl=Lc&((ur|0)==2&co)?1:ur,Ln=(Tl|0)==1,Ia=Ln&(F^1),Lp=(Rl|0)==1,Np=(Rl|0)==2,kl=976+(Lr<<2)|0,Op=(Tl|2|0)==2,_p=Ln&(Lc^1),Nu=1040+(Ar<<2)|0,Ou=1040+(Lr<<2)|0,Mp=976+(Ar<<2)|0,Up=(Tl|0)!=1,co=Lc&((ur|0)!=0&co),lo=s+976|0,Ln=Ln^1,l=Qe,Or=0,uo=0,Cs=y(0),Nc=y(0);;){e:do if(Or>>>0<Hs>>>0)for(_r=n[po>>2]|0,oe=0,Ge=y(0),_e=y(0),rt=y(0),Qe=y(0),j=0,O=0,We=Or;;){if(Nt=n[_r+(We<<2)>>2]|0,(n[Nt+36>>2]|0)!=1&&(n[Nt+940>>2]=uo,(n[Nt+24>>2]|0)!=1)){if(Xe=y(fn(Nt,Lr,Fr)),$r=n[kl>>2]|0,c=y(Kr(Nt+380+($r<<3)|0,fo)),ct=y(h[Nt+504>>2]),c=y(M0(c,ct)),c=y(Yn(y(Kr(Nt+364+($r<<3)|0,fo)),c)),Lc&(oe|0)!=0&y(Xe+y(_e+c))>l){m=oe,Xe=Ge,ur=We;break e}Xe=y(Xe+c),c=y(_e+Xe),Xe=y(Ge+Xe),xI(Nt)|0&&(rt=y(rt+y(WA(Nt))),Qe=y(Qe-y(ct*y(Ip(Nt))))),O|0&&(n[O+960>>2]=Nt),n[Nt+960>>2]=0,oe=oe+1|0,O=Nt,j=j|0?j:Nt}else Xe=Ge,c=_e;if(We=We+1|0,We>>>0<Hs>>>0)Ge=Xe,_e=c;else{m=oe,ur=We;break}}else m=0,Xe=y(0),rt=y(0),Qe=y(0),j=0,ur=Or;while(!1);$r=rt>y(0)&rt<y(1),Zt=$r?y(1):rt,$r=Qe>y(0)&Qe<y(1),Ge=$r?y(1):Qe;do if(Lp)$r=51;else if(Xe<Mu&((Ot(Mu)|0)^1))l=Mu,$r=51;else if(Xe>Uu&((Ot(Uu)|0)^1))l=Uu,$r=51;else if(o[(n[lo>>2]|0)+3>>0]|0)$r=51;else{if(Zt!=y(0)&&y(WA(s))!=y(0)){$r=53;break}l=Xe,$r=53}while(!1);if(($r|0)==51&&($r=0,Ot(l)|0?$r=53:(kr=y(l-Xe),lr=l)),($r|0)==53&&($r=0,Xe<y(0)?(kr=y(-Xe),lr=l):(kr=y(0),lr=l)),!Ia&&(rf=(j|0)==0,!rf)){oe=n[kl>>2]|0,We=kr<y(0),ct=y(kr/Ge),Nt=kr>y(0),_e=y(kr/Zt),rt=y(0),Xe=y(0),l=y(0),O=j;do c=y(Kr(O+380+(oe<<3)|0,fo)),Qe=y(Kr(O+364+(oe<<3)|0,fo)),Qe=y(M0(c,y(Yn(Qe,y(h[O+504>>2]))))),We?(c=y(Qe*y(Ip(O))),c!=y(-0)&&(Vt=y(Qe-y(ct*c)),nf=y(Mn(O,Lr,Vt,lr,Fr)),Vt!=nf)&&(rt=y(rt-y(nf-Qe)),l=y(l+c))):Nt&&(_u=y(WA(O)),_u!=y(0))&&(Vt=y(Qe+y(_e*_u)),sf=y(Mn(O,Lr,Vt,lr,Fr)),Vt!=sf)&&(rt=y(rt-y(sf-Qe)),Xe=y(Xe-_u)),O=n[O+960>>2]|0;while(O|0);if(l=y(Ge+l),Qe=y(kr+rt),rf)l=y(0);else{ct=y(Zt+Xe),We=n[kl>>2]|0,Nt=Qe<y(0),_r=l==y(0),_e=y(Qe/l),oe=Qe>y(0),ct=y(Qe/ct),l=y(0);do{Vt=y(Kr(j+380+(We<<3)|0,fo)),rt=y(Kr(j+364+(We<<3)|0,fo)),rt=y(M0(Vt,y(Yn(rt,y(h[j+504>>2]))))),Nt?(Vt=y(rt*y(Ip(j))),Qe=y(-Vt),Vt!=y(-0)?(Vt=y(_e*Qe),Qe=y(Mn(j,Lr,y(rt+(_r?Qe:Vt)),lr,Fr))):Qe=rt):oe&&(of=y(WA(j)),of!=y(0))?Qe=y(Mn(j,Lr,y(rt+y(ct*of)),lr,Fr)):Qe=rt,l=y(l-y(Qe-rt)),Xe=y(fn(j,Lr,Fr)),c=y(fn(j,Ar,Fr)),Qe=y(Qe+Xe),h[rl>>2]=Qe,n[Fl>>2]=1,rt=y(h[j+396>>2]);e:do if(Ot(rt)|0){O=Ot(Un)|0;do if(!O){if(co|(Ns(j,Ar,Un)|0|Ln)||(Wi(s,j)|0)!=4||(n[(za(j,Ar)|0)+4>>2]|0)==3||(n[(Ja(j,Ar)|0)+4>>2]|0)==3)break;h[Ms>>2]=Un,n[Go>>2]=1;break e}while(!1);if(Ns(j,Ar,Un)|0){O=n[j+992+(n[Mp>>2]<<2)>>2]|0,Vt=y(c+y(Kr(O,Un))),h[Ms>>2]=Vt,O=Up&(n[O+4>>2]|0)==2,n[Go>>2]=((Ot(Vt)|0|O)^1)&1;break}else{h[Ms>>2]=Un,n[Go>>2]=O?0:2;break}}else Vt=y(Qe-Xe),Zt=y(Vt/rt),Vt=y(rt*Vt),n[Go>>2]=1,h[Ms>>2]=y(c+(ri?Zt:Vt));while(!1);xc(j,Lr,lr,Fr,Fl,rl),xc(j,Ar,Un,Fr,Go,Ms);do if(!(Ns(j,Ar,Un)|0)&&(Wi(s,j)|0)==4){if((n[(za(j,Ar)|0)+4>>2]|0)==3){O=0;break}O=(n[(Ja(j,Ar)|0)+4>>2]|0)!=3}else O=0;while(!1);Vt=y(h[rl>>2]),Zt=y(h[Ms>>2]),pf=n[Fl>>2]|0,hi=n[Go>>2]|0,Va(j,ri?Vt:Zt,ri?Zt:Vt,Is,ri?pf:hi,ri?hi:pf,Fr,Ao,F&(O^1),3488,M)|0,o[Ql>>0]=o[Ql>>0]|o[j+508>>0],j=n[j+960>>2]|0}while(j|0)}}else l=y(0);if(l=y(kr+l),hi=l<y(0)&1,o[Ql>>0]=hi|u[Ql>>0],Np&l>y(0)?(O=n[kl>>2]|0,n[s+364+(O<<3)+4>>2]|0&&(Us=y(Kr(s+364+(O<<3)|0,fo)),Us>=y(0))?Qe=y(Yn(y(0),y(Us-y(lr-l)))):Qe=y(0)):Qe=l,Nt=Or>>>0<ur>>>0,Nt){We=n[po>>2]|0,oe=Or,O=0;do j=n[We+(oe<<2)>>2]|0,n[j+24>>2]|0||(O=((n[(za(j,Lr)|0)+4>>2]|0)==3&1)+O|0,O=O+((n[(Ja(j,Lr)|0)+4>>2]|0)==3&1)|0),oe=oe+1|0;while((oe|0)!=(ur|0));O?(Xe=y(0),c=y(0)):$r=101}else $r=101;e:do if(($r|0)==101)switch($r=0,Hp|0){case 1:{O=0,Xe=y(Qe*y(.5)),c=y(0);break e}case 2:{O=0,Xe=Qe,c=y(0);break e}case 3:{if(m>>>0<=1){O=0,Xe=y(0),c=y(0);break e}c=y((m+-1|0)>>>0),O=0,Xe=y(0),c=y(y(Yn(Qe,y(0)))/c);break e}case 5:{c=y(Qe/y((m+1|0)>>>0)),O=0,Xe=c;break e}case 4:{c=y(Qe/y(m>>>0)),O=0,Xe=y(c*y(.5));break e}default:{O=0,Xe=y(0),c=y(0);break e}}while(!1);if(l=y(qp+Xe),Nt){rt=y(Qe/y(O|0)),oe=n[po>>2]|0,j=Or,Qe=y(0);do{O=n[oe+(j<<2)>>2]|0;e:do if((n[O+36>>2]|0)!=1){switch(n[O+24>>2]|0){case 1:{if(Ho(O,Lr)|0){if(!F)break e;Vt=y(YA(O,Lr,lr)),Vt=y(Vt+y(Ir(s,Lr))),Vt=y(Vt+y(V(O,Lr,Fr))),h[O+400+(n[Ou>>2]<<2)>>2]=Vt;break e}break}case 0:if(hi=(n[(za(O,Lr)|0)+4>>2]|0)==3,Vt=y(rt+l),l=hi?Vt:l,F&&(hi=O+400+(n[Ou>>2]<<2)|0,h[hi>>2]=y(l+y(h[hi>>2]))),hi=(n[(Ja(O,Lr)|0)+4>>2]|0)==3,Vt=y(rt+l),l=hi?Vt:l,Ia){Vt=y(c+y(fn(O,Lr,Fr))),Qe=Un,l=y(l+y(Vt+y(h[O+504>>2])));break e}else{l=y(l+y(c+y(KA(O,Lr,Fr)))),Qe=y(Yn(Qe,y(KA(O,Ar,Fr))));break e}default:}F&&(Vt=y(Xe+y(Ir(s,Lr))),hi=O+400+(n[Ou>>2]<<2)|0,h[hi>>2]=y(Vt+y(h[hi>>2])))}while(!1);j=j+1|0}while((j|0)!=(ur|0))}else Qe=y(0);if(c=y(jp+l),Op?Xe=y(y(Mn(s,Ar,y(_s+Qe),Uc,B))-_s):Xe=Un,rt=y(y(Mn(s,Ar,y(_s+(_p?Un:Qe)),Uc,B))-_s),Nt&F){j=Or;do{oe=n[(n[po>>2]|0)+(j<<2)>>2]|0;do if((n[oe+36>>2]|0)!=1){if((n[oe+24>>2]|0)==1){if(Ho(oe,Ar)|0){if(Vt=y(YA(oe,Ar,Un)),Vt=y(Vt+y(Ir(s,Ar))),Vt=y(Vt+y(V(oe,Ar,Fr))),O=n[Nu>>2]|0,h[oe+400+(O<<2)>>2]=Vt,!(Ot(Vt)|0))break}else O=n[Nu>>2]|0;Vt=y(Ir(s,Ar)),h[oe+400+(O<<2)>>2]=y(Vt+y(V(oe,Ar,Fr)));break}O=Wi(s,oe)|0;do if((O|0)==4){if((n[(za(oe,Ar)|0)+4>>2]|0)==3){$r=139;break}if((n[(Ja(oe,Ar)|0)+4>>2]|0)==3){$r=139;break}if(Ns(oe,Ar,Un)|0){l=Oe;break}pf=n[oe+908+(n[kl>>2]<<2)>>2]|0,n[Ms>>2]=pf,l=y(h[oe+396>>2]),hi=Ot(l)|0,Qe=(n[D>>2]=pf,y(h[D>>2])),hi?l=rt:(kr=y(fn(oe,Ar,Fr)),Vt=y(Qe/l),l=y(l*Qe),l=y(kr+(ri?Vt:l))),h[rl>>2]=l,h[Ms>>2]=y(y(fn(oe,Lr,Fr))+Qe),n[Go>>2]=1,n[Fl>>2]=1,xc(oe,Lr,lr,Fr,Go,Ms),xc(oe,Ar,Un,Fr,Fl,rl),l=y(h[Ms>>2]),kr=y(h[rl>>2]),Vt=ri?l:kr,l=ri?kr:l,hi=((Ot(Vt)|0)^1)&1,Va(oe,Vt,l,Is,hi,((Ot(l)|0)^1)&1,Fr,Ao,1,3493,M)|0,l=Oe}else $r=139;while(!1);e:do if(($r|0)==139){$r=0,l=y(Xe-y(KA(oe,Ar,Fr)));do if((n[(za(oe,Ar)|0)+4>>2]|0)==3){if((n[(Ja(oe,Ar)|0)+4>>2]|0)!=3)break;l=y(Oe+y(Yn(y(0),y(l*y(.5)))));break e}while(!1);if((n[(Ja(oe,Ar)|0)+4>>2]|0)==3){l=Oe;break}if((n[(za(oe,Ar)|0)+4>>2]|0)==3){l=y(Oe+y(Yn(y(0),l)));break}switch(O|0){case 1:{l=Oe;break e}case 2:{l=y(Oe+y(l*y(.5)));break e}default:{l=y(Oe+l);break e}}}while(!1);Vt=y(Cs+l),hi=oe+400+(n[Nu>>2]<<2)|0,h[hi>>2]=y(Vt+y(h[hi>>2]))}while(!1);j=j+1|0}while((j|0)!=(ur|0))}if(Cs=y(Cs+rt),Nc=y(Yn(Nc,c)),m=uo+1|0,ur>>>0>=Hs>>>0)break;l=lr,Or=ur,uo=m}do if(F){if(O=m>>>0>1,!O&&!(HF(s)|0))break;if(!(Ot(Un)|0)){l=y(Un-Cs);e:do switch(n[s+12>>2]|0){case 3:{Oe=y(Oe+l),_e=y(0);break}case 2:{Oe=y(Oe+y(l*y(.5))),_e=y(0);break}case 4:{Un>Cs?_e=y(l/y(m>>>0)):_e=y(0);break}case 7:if(Un>Cs){Oe=y(Oe+y(l/y(m<<1>>>0))),_e=y(l/y(m>>>0)),_e=O?_e:y(0);break e}else{Oe=y(Oe+y(l*y(.5))),_e=y(0);break e}case 6:{_e=y(l/y(uo>>>0)),_e=Un>Cs&O?_e:y(0);break}default:_e=y(0)}while(!1);if(m|0)for(Nt=1040+(Ar<<2)|0,_r=976+(Ar<<2)|0,We=0,j=0;;){e:do if(j>>>0<Hs>>>0)for(Qe=y(0),rt=y(0),l=y(0),oe=j;;){O=n[(n[po>>2]|0)+(oe<<2)>>2]|0;do if((n[O+36>>2]|0)!=1&&!(n[O+24>>2]|0)){if((n[O+940>>2]|0)!=(We|0))break e;if(qF(O,Ar)|0&&(Vt=y(h[O+908+(n[_r>>2]<<2)>>2]),l=y(Yn(l,y(Vt+y(fn(O,Ar,Fr)))))),(Wi(s,O)|0)!=5)break;Us=y(m0(O)),Us=y(Us+y(V(O,0,Fr))),Vt=y(h[O+912>>2]),Vt=y(y(Vt+y(fn(O,0,Fr)))-Us),Us=y(Yn(rt,Us)),Vt=y(Yn(Qe,Vt)),Qe=Vt,rt=Us,l=y(Yn(l,y(Us+Vt)))}while(!1);if(O=oe+1|0,O>>>0<Hs>>>0)oe=O;else{oe=O;break}}else rt=y(0),l=y(0),oe=j;while(!1);if(ct=y(_e+l),c=Oe,Oe=y(Oe+ct),j>>>0<oe>>>0){Xe=y(c+rt),O=j;do{j=n[(n[po>>2]|0)+(O<<2)>>2]|0;e:do if((n[j+36>>2]|0)!=1&&!(n[j+24>>2]|0))switch(Wi(s,j)|0){case 1:{Vt=y(c+y(V(j,Ar,Fr))),h[j+400+(n[Nt>>2]<<2)>>2]=Vt;break e}case 3:{Vt=y(y(Oe-y(re(j,Ar,Fr)))-y(h[j+908+(n[_r>>2]<<2)>>2])),h[j+400+(n[Nt>>2]<<2)>>2]=Vt;break e}case 2:{Vt=y(c+y(y(ct-y(h[j+908+(n[_r>>2]<<2)>>2]))*y(.5))),h[j+400+(n[Nt>>2]<<2)>>2]=Vt;break e}case 4:{if(Vt=y(c+y(V(j,Ar,Fr))),h[j+400+(n[Nt>>2]<<2)>>2]=Vt,Ns(j,Ar,Un)|0||(ri?(Qe=y(h[j+908>>2]),l=y(Qe+y(fn(j,Lr,Fr))),rt=ct):(rt=y(h[j+912>>2]),rt=y(rt+y(fn(j,Ar,Fr))),l=ct,Qe=y(h[j+908>>2])),An(l,Qe)|0&&An(rt,y(h[j+912>>2]))|0))break e;Va(j,l,rt,Is,1,1,Fr,Ao,1,3501,M)|0;break e}case 5:{h[j+404>>2]=y(y(Xe-y(m0(j)))+y(YA(j,0,Un)));break e}default:break e}while(!1);O=O+1|0}while((O|0)!=(oe|0))}if(We=We+1|0,(We|0)==(m|0))break;j=oe}}}while(!1);if(h[s+908>>2]=y(Mn(s,2,Oc,B,B)),h[s+912>>2]=y(Mn(s,0,af,k,B)),Rl|0&&(lf=n[s+32>>2]|0,cf=(Rl|0)==2,!(cf&(lf|0)!=2))?cf&(lf|0)==2&&(l=y(Mc+lr),l=y(Yn(y(M0(l,y(y0(s,Lr,Nc,fo)))),Mc)),$r=198):(l=y(Mn(s,Lr,Nc,fo,B)),$r=198),($r|0)==198&&(h[s+908+(n[976+(Lr<<2)>>2]<<2)>>2]=l),Tl|0&&(Af=n[s+32>>2]|0,ff=(Tl|0)==2,!(ff&(Af|0)!=2))?ff&(Af|0)==2&&(l=y(_s+Un),l=y(Yn(y(M0(l,y(y0(s,Ar,y(_s+Cs),Uc)))),_s)),$r=204):(l=y(Mn(s,Ar,y(_s+Cs),Uc,B)),$r=204),($r|0)==204&&(h[s+908+(n[976+(Ar<<2)>>2]<<2)>>2]=l),F){if((n[uf>>2]|0)==2){j=976+(Ar<<2)|0,oe=1040+(Ar<<2)|0,O=0;do We=rs(s,O)|0,n[We+24>>2]|0||(pf=n[j>>2]|0,Vt=y(h[s+908+(pf<<2)>>2]),hi=We+400+(n[oe>>2]<<2)|0,Vt=y(Vt-y(h[hi>>2])),h[hi>>2]=y(Vt-y(h[We+908+(pf<<2)>>2]))),O=O+1|0;while((O|0)!=(Hs|0))}if(f|0){O=ri?Rl:d;do jF(s,f,Fr,O,Ao,Is,M),f=n[f+960>>2]|0;while(f|0)}if(O=(Lr|2|0)==3,j=(Ar|2|0)==3,O|j){f=0;do oe=n[(n[po>>2]|0)+(f<<2)>>2]|0,(n[oe+36>>2]|0)!=1&&(O&&bI(s,oe,Lr),j&&bI(s,oe,Ar)),f=f+1|0;while((f|0)!=(Hs|0))}}}while(!1);C=Ll}function dp(s,l){s=s|0,l=y(l);var c=0;ua(s,l>=y(0),3147),c=l==y(0),h[s+4>>2]=c?y(0):l}function qA(s,l,c,f){s=s|0,l=y(l),c=y(c),f=f|0;var d=Ze,m=Ze,B=0,k=0,F=0;n[2278]=(n[2278]|0)+1,Su(s),Ns(s,2,l)|0?(d=y(Kr(n[s+992>>2]|0,l)),F=1,d=y(d+y(fn(s,2,l)))):(d=y(Kr(s+380|0,l)),d>=y(0)?F=2:(F=((Ot(l)|0)^1)&1,d=l)),Ns(s,0,c)|0?(m=y(Kr(n[s+996>>2]|0,c)),k=1,m=y(m+y(fn(s,0,l)))):(m=y(Kr(s+388|0,c)),m>=y(0)?k=2:(k=((Ot(c)|0)^1)&1,m=c)),B=s+976|0,Va(s,d,m,f,F,k,l,c,1,3189,n[B>>2]|0)|0&&(mp(s,n[s+496>>2]|0,l,c,l),jA(s,y(h[(n[B>>2]|0)+4>>2]),y(0),y(0)),o[11696]|0)&&h0(s,7)}function Su(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0;k=C,C=C+32|0,B=k+24|0,m=k+16|0,f=k+8|0,d=k,c=0;do l=s+380+(c<<3)|0,n[s+380+(c<<3)+4>>2]|0&&(F=l,M=n[F+4>>2]|0,O=f,n[O>>2]=n[F>>2],n[O+4>>2]=M,O=s+364+(c<<3)|0,M=n[O+4>>2]|0,F=d,n[F>>2]=n[O>>2],n[F+4>>2]=M,n[m>>2]=n[f>>2],n[m+4>>2]=n[f+4>>2],n[B>>2]=n[d>>2],n[B+4>>2]=n[d+4>>2],vu(m,B)|0)||(l=s+348+(c<<3)|0),n[s+992+(c<<2)>>2]=l,c=c+1|0;while((c|0)!=2);C=k}function Ns(s,l,c){s=s|0,l=l|0,c=y(c);var f=0;switch(s=n[s+992+(n[976+(l<<2)>>2]<<2)>>2]|0,n[s+4>>2]|0){case 0:case 3:{s=0;break}case 1:{y(h[s>>2])<y(0)?s=0:f=5;break}case 2:{y(h[s>>2])<y(0)?s=0:s=(Ot(c)|0)^1;break}default:f=5}return(f|0)==5&&(s=1),s|0}function Kr(s,l){switch(s=s|0,l=y(l),n[s+4>>2]|0){case 2:{l=y(y(y(h[s>>2])*l)/y(100));break}case 1:{l=y(h[s>>2]);break}default:l=y(ue)}return y(l)}function mp(s,l,c,f,d){s=s|0,l=l|0,c=y(c),f=y(f),d=y(d);var m=0,B=Ze;l=n[s+944>>2]|0?l:1,m=hr(n[s+4>>2]|0,l)|0,l=Fd(m,l)|0,c=y(uD(s,m,c)),f=y(uD(s,l,f)),B=y(c+y(V(s,m,d))),h[s+400+(n[1040+(m<<2)>>2]<<2)>>2]=B,c=y(c+y(re(s,m,d))),h[s+400+(n[1e3+(m<<2)>>2]<<2)>>2]=c,c=y(f+y(V(s,l,d))),h[s+400+(n[1040+(l<<2)>>2]<<2)>>2]=c,d=y(f+y(re(s,l,d))),h[s+400+(n[1e3+(l<<2)>>2]<<2)>>2]=d}function jA(s,l,c,f){s=s|0,l=y(l),c=y(c),f=y(f);var d=0,m=0,B=Ze,k=Ze,F=0,M=0,O=Ze,j=0,oe=Ze,We=Ze,Oe=Ze,Qe=Ze;if(l!=y(0)&&(d=s+400|0,Qe=y(h[d>>2]),m=s+404|0,Oe=y(h[m>>2]),j=s+416|0,We=y(h[j>>2]),M=s+420|0,B=y(h[M>>2]),oe=y(Qe+c),O=y(Oe+f),f=y(oe+We),k=y(O+B),F=(n[s+988>>2]|0)==1,h[d>>2]=y(Gi(Qe,l,0,F)),h[m>>2]=y(Gi(Oe,l,0,F)),c=y(lT(y(We*l),y(1))),An(c,y(0))|0?m=0:m=(An(c,y(1))|0)^1,c=y(lT(y(B*l),y(1))),An(c,y(0))|0?d=0:d=(An(c,y(1))|0)^1,Qe=y(Gi(f,l,F&m,F&(m^1))),h[j>>2]=y(Qe-y(Gi(oe,l,0,F))),Qe=y(Gi(k,l,F&d,F&(d^1))),h[M>>2]=y(Qe-y(Gi(O,l,0,F))),m=(n[s+952>>2]|0)-(n[s+948>>2]|0)>>2,m|0)){d=0;do jA(rs(s,d)|0,l,oe,O),d=d+1|0;while((d|0)!=(m|0))}}function kd(s,l,c,f,d){switch(s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,c|0){case 5:case 0:{s=M7(n[489]|0,f,d)|0;break}default:s=HUe(f,d)|0}return s|0}function d0(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;d=C,C=C+16|0,m=d,n[m>>2]=f,yp(s,0,l,c,m),C=d}function yp(s,l,c,f,d){if(s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,s=s|0?s:956,sW[n[s+8>>2]&1](s,l,c,f,d)|0,(c|0)==5)Tt();else return}function xl(s,l,c){s=s|0,l=l|0,c=c|0,o[s+l>>0]=c&1}function Qd(s,l){s=s|0,l=l|0;var c=0,f=0;n[s>>2]=0,n[s+4>>2]=0,n[s+8>>2]=0,c=l+4|0,f=(n[c>>2]|0)-(n[l>>2]|0)>>2,f|0&&(Ep(s,f),bt(s,n[l>>2]|0,n[c>>2]|0,f))}function Ep(s,l){s=s|0,l=l|0;var c=0;if((L(s)|0)>>>0<l>>>0&&Zr(s),l>>>0>1073741823)Tt();else{c=Yt(l<<2)|0,n[s+4>>2]=c,n[s>>2]=c,n[s+8>>2]=c+(l<<2);return}}function bt(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,f=s+4|0,s=c-l|0,(s|0)>0&&(br(n[f>>2]|0,l|0,s|0)|0,n[f>>2]=(n[f>>2]|0)+(s>>>2<<2))}function L(s){return s=s|0,1073741823}function V(s,l,c){return s=s|0,l=l|0,c=y(c),ge(l)|0&&n[s+96>>2]|0?s=s+92|0:s=vn(s+60|0,n[1040+(l<<2)>>2]|0,992)|0,y(Ye(s,c))}function re(s,l,c){return s=s|0,l=l|0,c=y(c),ge(l)|0&&n[s+104>>2]|0?s=s+100|0:s=vn(s+60|0,n[1e3+(l<<2)>>2]|0,992)|0,y(Ye(s,c))}function ge(s){return s=s|0,(s|1|0)==3|0}function Ye(s,l){return s=s|0,l=y(l),(n[s+4>>2]|0)==3?l=y(0):l=y(Kr(s,l)),y(l)}function At(s,l){return s=s|0,l=l|0,s=n[s>>2]|0,(s|0?s:(l|0)>1?l:1)|0}function hr(s,l){s=s|0,l=l|0;var c=0;e:do if((l|0)==2){switch(s|0){case 2:{s=3;break e}case 3:break;default:{c=4;break e}}s=2}else c=4;while(!1);return s|0}function Ir(s,l){s=s|0,l=l|0;var c=Ze;return ge(l)|0&&n[s+312>>2]|0&&(c=y(h[s+308>>2]),c>=y(0))||(c=y(Yn(y(h[(vn(s+276|0,n[1040+(l<<2)>>2]|0,992)|0)>>2]),y(0)))),y(c)}function Rn(s,l){s=s|0,l=l|0;var c=Ze;return ge(l)|0&&n[s+320>>2]|0&&(c=y(h[s+316>>2]),c>=y(0))||(c=y(Yn(y(h[(vn(s+276|0,n[1e3+(l<<2)>>2]|0,992)|0)>>2]),y(0)))),y(c)}function ai(s,l,c){s=s|0,l=l|0,c=y(c);var f=Ze;return ge(l)|0&&n[s+240>>2]|0&&(f=y(Kr(s+236|0,c)),f>=y(0))||(f=y(Yn(y(Kr(vn(s+204|0,n[1040+(l<<2)>>2]|0,992)|0,c)),y(0)))),y(f)}function ns(s,l,c){s=s|0,l=l|0,c=y(c);var f=Ze;return ge(l)|0&&n[s+248>>2]|0&&(f=y(Kr(s+244|0,c)),f>=y(0))||(f=y(Yn(y(Kr(vn(s+204|0,n[1e3+(l<<2)>>2]|0,992)|0,c)),y(0)))),y(f)}function GA(s,l,c,f,d,m,B){s=s|0,l=y(l),c=y(c),f=f|0,d=d|0,m=y(m),B=y(B);var k=Ze,F=Ze,M=Ze,O=Ze,j=Ze,oe=Ze,We=0,Oe=0,Qe=0;Qe=C,C=C+16|0,We=Qe,Oe=s+964|0,pi(s,(n[Oe>>2]|0)!=0,3519),k=y(da(s,2,l)),F=y(da(s,0,l)),M=y(fn(s,2,l)),O=y(fn(s,0,l)),Ot(l)|0?j=l:j=y(Yn(y(0),y(y(l-M)-k))),Ot(c)|0?oe=c:oe=y(Yn(y(0),y(y(c-O)-F))),(f|0)==1&(d|0)==1?(h[s+908>>2]=y(Mn(s,2,y(l-M),m,m)),l=y(Mn(s,0,y(c-O),B,m))):(oW[n[Oe>>2]&1](We,s,j,f,oe,d),j=y(k+y(h[We>>2])),oe=y(l-M),h[s+908>>2]=y(Mn(s,2,(f|2|0)==2?j:oe,m,m)),oe=y(F+y(h[We+4>>2])),l=y(c-O),l=y(Mn(s,0,(d|2|0)==2?oe:l,B,m))),h[s+912>>2]=l,C=Qe}function lD(s,l,c,f,d,m,B){s=s|0,l=y(l),c=y(c),f=f|0,d=d|0,m=y(m),B=y(B);var k=Ze,F=Ze,M=Ze,O=Ze;M=y(da(s,2,m)),k=y(da(s,0,m)),O=y(fn(s,2,m)),F=y(fn(s,0,m)),l=y(l-O),h[s+908>>2]=y(Mn(s,2,(f|2|0)==2?M:l,m,m)),c=y(c-F),h[s+912>>2]=y(Mn(s,0,(d|2|0)==2?k:c,B,m))}function PI(s,l,c,f,d,m,B){s=s|0,l=y(l),c=y(c),f=f|0,d=d|0,m=y(m),B=y(B);var k=0,F=Ze,M=Ze;return k=(f|0)==2,!(l<=y(0)&k)&&!(c<=y(0)&(d|0)==2)&&!((f|0)==1&(d|0)==1)?s=0:(F=y(fn(s,0,m)),M=y(fn(s,2,m)),k=l<y(0)&k|(Ot(l)|0),l=y(l-M),h[s+908>>2]=y(Mn(s,2,k?y(0):l,m,m)),l=y(c-F),k=c<y(0)&(d|0)==2|(Ot(c)|0),h[s+912>>2]=y(Mn(s,0,k?y(0):l,B,m)),s=1),s|0}function Fd(s,l){return s=s|0,l=l|0,E0(s)|0?s=hr(2,l)|0:s=0,s|0}function Cp(s,l,c){return s=s|0,l=l|0,c=y(c),c=y(ai(s,l,c)),y(c+y(Ir(s,l)))}function SI(s,l,c){return s=s|0,l=l|0,c=y(c),c=y(ns(s,l,c)),y(c+y(Rn(s,l)))}function da(s,l,c){s=s|0,l=l|0,c=y(c);var f=Ze;return f=y(Cp(s,l,c)),y(f+y(SI(s,l,c)))}function xI(s){return s=s|0,n[s+24>>2]|0?s=0:y(WA(s))!=y(0)?s=1:s=y(Ip(s))!=y(0),s|0}function WA(s){s=s|0;var l=Ze;if(n[s+944>>2]|0){if(l=y(h[s+44>>2]),Ot(l)|0)return l=y(h[s+40>>2]),s=l>y(0)&((Ot(l)|0)^1),y(s?l:y(0))}else l=y(0);return y(l)}function Ip(s){s=s|0;var l=Ze,c=0,f=Ze;do if(n[s+944>>2]|0){if(l=y(h[s+48>>2]),Ot(l)|0){if(c=o[(n[s+976>>2]|0)+2>>0]|0,!(c<<24>>24)&&(f=y(h[s+40>>2]),f<y(0)&((Ot(f)|0)^1))){l=y(-f);break}l=c<<24>>24?y(1):y(0)}}else l=y(0);while(!1);return y(l)}function Rd(s){s=s|0;var l=0,c=0;if(sm(s+400|0,0,540)|0,o[s+985>>0]=1,ee(s),c=Di(s)|0,c|0){l=s+948|0,s=0;do Rd(n[(n[l>>2]|0)+(s<<2)>>2]|0),s=s+1|0;while((s|0)!=(c|0))}}function cD(s,l,c,f,d,m,B,k,F,M){s=s|0,l=l|0,c=y(c),f=f|0,d=y(d),m=y(m),B=y(B),k=k|0,F=F|0,M=M|0;var O=0,j=Ze,oe=0,We=0,Oe=Ze,Qe=Ze,rt=0,Xe=Ze,ct=0,_e=Ze,Ge=0,Nt=0,_r=0,ur=0,Zt=0,kr=0,Or=0,lr=0,Ln=0,lo=0;Ln=C,C=C+16|0,_r=Ln+12|0,ur=Ln+8|0,Zt=Ln+4|0,kr=Ln,lr=hr(n[s+4>>2]|0,F)|0,Ge=ge(lr)|0,j=y(Kr(GF(l)|0,Ge?m:B)),Nt=Ns(l,2,m)|0,Or=Ns(l,0,B)|0;do if(!(Ot(j)|0)&&!(Ot(Ge?c:d)|0)){if(O=l+504|0,!(Ot(y(h[O>>2]))|0)&&(!(kI(n[l+976>>2]|0,0)|0)||(n[l+500>>2]|0)==(n[2278]|0)))break;h[O>>2]=y(Yn(j,y(da(l,lr,m))))}else oe=7;while(!1);do if((oe|0)==7){if(ct=Ge^1,!(ct|Nt^1)){B=y(Kr(n[l+992>>2]|0,m)),h[l+504>>2]=y(Yn(B,y(da(l,2,m))));break}if(!(Ge|Or^1)){B=y(Kr(n[l+996>>2]|0,B)),h[l+504>>2]=y(Yn(B,y(da(l,0,m))));break}h[_r>>2]=y(ue),h[ur>>2]=y(ue),n[Zt>>2]=0,n[kr>>2]=0,Xe=y(fn(l,2,m)),_e=y(fn(l,0,m)),Nt?(Oe=y(Xe+y(Kr(n[l+992>>2]|0,m))),h[_r>>2]=Oe,n[Zt>>2]=1,We=1):(We=0,Oe=y(ue)),Or?(j=y(_e+y(Kr(n[l+996>>2]|0,B))),h[ur>>2]=j,n[kr>>2]=1,O=1):(O=0,j=y(ue)),oe=n[s+32>>2]|0,Ge&(oe|0)==2?oe=2:Ot(Oe)|0&&!(Ot(c)|0)&&(h[_r>>2]=c,n[Zt>>2]=2,We=2,Oe=c),!((oe|0)==2&ct)&&Ot(j)|0&&!(Ot(d)|0)&&(h[ur>>2]=d,n[kr>>2]=2,O=2,j=d),Qe=y(h[l+396>>2]),rt=Ot(Qe)|0;do if(rt)oe=We;else{if((We|0)==1&ct){h[ur>>2]=y(y(Oe-Xe)/Qe),n[kr>>2]=1,O=1,oe=1;break}Ge&(O|0)==1?(h[_r>>2]=y(Qe*y(j-_e)),n[Zt>>2]=1,O=1,oe=1):oe=We}while(!1);lo=Ot(c)|0,We=(Wi(s,l)|0)!=4,!(Ge|Nt|((f|0)!=1|lo)|(We|(oe|0)==1))&&(h[_r>>2]=c,n[Zt>>2]=1,!rt)&&(h[ur>>2]=y(y(c-Xe)/Qe),n[kr>>2]=1,O=1),!(Or|ct|((k|0)!=1|(Ot(d)|0))|(We|(O|0)==1))&&(h[ur>>2]=d,n[kr>>2]=1,!rt)&&(h[_r>>2]=y(Qe*y(d-_e)),n[Zt>>2]=1),xc(l,2,m,m,Zt,_r),xc(l,0,B,m,kr,ur),c=y(h[_r>>2]),d=y(h[ur>>2]),Va(l,c,d,F,n[Zt>>2]|0,n[kr>>2]|0,m,B,0,3565,M)|0,B=y(h[l+908+(n[976+(lr<<2)>>2]<<2)>>2]),h[l+504>>2]=y(Yn(B,y(da(l,lr,m))))}while(!1);n[l+500>>2]=n[2278],C=Ln}function Mn(s,l,c,f,d){return s=s|0,l=l|0,c=y(c),f=y(f),d=y(d),f=y(y0(s,l,c,f)),y(Yn(f,y(da(s,l,d))))}function Wi(s,l){return s=s|0,l=l|0,l=l+20|0,l=n[(n[l>>2]|0?l:s+16|0)>>2]|0,(l|0)==5&&E0(n[s+4>>2]|0)|0&&(l=1),l|0}function za(s,l){return s=s|0,l=l|0,ge(l)|0&&n[s+96>>2]|0?l=4:l=n[1040+(l<<2)>>2]|0,s+60+(l<<3)|0}function Ja(s,l){return s=s|0,l=l|0,ge(l)|0&&n[s+104>>2]|0?l=5:l=n[1e3+(l<<2)>>2]|0,s+60+(l<<3)|0}function xc(s,l,c,f,d,m){switch(s=s|0,l=l|0,c=y(c),f=y(f),d=d|0,m=m|0,c=y(Kr(s+380+(n[976+(l<<2)>>2]<<3)|0,c)),c=y(c+y(fn(s,l,f))),n[d>>2]|0){case 2:case 1:{d=Ot(c)|0,f=y(h[m>>2]),h[m>>2]=d|f<c?f:c;break}case 0:{Ot(c)|0||(n[d>>2]=2,h[m>>2]=c);break}default:}}function Ho(s,l){return s=s|0,l=l|0,s=s+132|0,ge(l)|0&&n[(vn(s,4,948)|0)+4>>2]|0?s=1:s=(n[(vn(s,n[1040+(l<<2)>>2]|0,948)|0)+4>>2]|0)!=0,s|0}function YA(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0;return s=s+132|0,ge(l)|0&&(f=vn(s,4,948)|0,(n[f+4>>2]|0)!=0)?d=4:(f=vn(s,n[1040+(l<<2)>>2]|0,948)|0,n[f+4>>2]|0?d=4:c=y(0)),(d|0)==4&&(c=y(Kr(f,c))),y(c)}function KA(s,l,c){s=s|0,l=l|0,c=y(c);var f=Ze;return f=y(h[s+908+(n[976+(l<<2)>>2]<<2)>>2]),f=y(f+y(V(s,l,c))),y(f+y(re(s,l,c)))}function HF(s){s=s|0;var l=0,c=0,f=0;e:do if(E0(n[s+4>>2]|0)|0)l=0;else if((n[s+16>>2]|0)!=5)if(c=Di(s)|0,!c)l=0;else for(l=0;;){if(f=rs(s,l)|0,!(n[f+24>>2]|0)&&(n[f+20>>2]|0)==5){l=1;break e}if(l=l+1|0,l>>>0>=c>>>0){l=0;break}}else l=1;while(!1);return l|0}function qF(s,l){s=s|0,l=l|0;var c=Ze;return c=y(h[s+908+(n[976+(l<<2)>>2]<<2)>>2]),c>=y(0)&((Ot(c)|0)^1)|0}function m0(s){s=s|0;var l=Ze,c=0,f=0,d=0,m=0,B=0,k=0,F=Ze;if(c=n[s+968>>2]|0,c)F=y(h[s+908>>2]),l=y(h[s+912>>2]),l=y(tW[c&0](s,F,l)),pi(s,(Ot(l)|0)^1,3573);else{m=Di(s)|0;do if(m|0){for(c=0,d=0;;){if(f=rs(s,d)|0,n[f+940>>2]|0){B=8;break}if((n[f+24>>2]|0)!=1)if(k=(Wi(s,f)|0)==5,k){c=f;break}else c=c|0?c:f;if(d=d+1|0,d>>>0>=m>>>0){B=8;break}}if((B|0)==8&&!c)break;return l=y(m0(c)),y(l+y(h[c+404>>2]))}while(!1);l=y(h[s+912>>2])}return y(l)}function y0(s,l,c,f){s=s|0,l=l|0,c=y(c),f=y(f);var d=Ze,m=0;return E0(l)|0?(l=1,m=3):ge(l)|0?(l=0,m=3):(f=y(ue),d=y(ue)),(m|0)==3&&(d=y(Kr(s+364+(l<<3)|0,f)),f=y(Kr(s+380+(l<<3)|0,f))),m=f<c&(f>=y(0)&((Ot(f)|0)^1)),c=m?f:c,m=d>=y(0)&((Ot(d)|0)^1)&c<d,y(m?d:c)}function jF(s,l,c,f,d,m,B){s=s|0,l=l|0,c=y(c),f=f|0,d=y(d),m=m|0,B=B|0;var k=Ze,F=Ze,M=0,O=0,j=Ze,oe=Ze,We=Ze,Oe=0,Qe=0,rt=0,Xe=0,ct=Ze,_e=0;rt=hr(n[s+4>>2]|0,m)|0,Oe=Fd(rt,m)|0,Qe=ge(rt)|0,j=y(fn(l,2,c)),oe=y(fn(l,0,c)),Ns(l,2,c)|0?k=y(j+y(Kr(n[l+992>>2]|0,c))):Ho(l,2)|0&&Td(l,2)|0?(k=y(h[s+908>>2]),F=y(Ir(s,2)),F=y(k-y(F+y(Rn(s,2)))),k=y(YA(l,2,c)),k=y(Mn(l,2,y(F-y(k+y(wp(l,2,c)))),c,c))):k=y(ue),Ns(l,0,d)|0?F=y(oe+y(Kr(n[l+996>>2]|0,d))):Ho(l,0)|0&&Td(l,0)|0?(F=y(h[s+912>>2]),ct=y(Ir(s,0)),ct=y(F-y(ct+y(Rn(s,0)))),F=y(YA(l,0,d)),F=y(Mn(l,0,y(ct-y(F+y(wp(l,0,d)))),d,c))):F=y(ue),M=Ot(k)|0,O=Ot(F)|0;do if(M^O&&(We=y(h[l+396>>2]),!(Ot(We)|0)))if(M){k=y(j+y(y(F-oe)*We));break}else{ct=y(oe+y(y(k-j)/We)),F=O?ct:F;break}while(!1);O=Ot(k)|0,M=Ot(F)|0,O|M&&(_e=(O^1)&1,f=c>y(0)&((f|0)!=0&O),k=Qe?k:f?c:k,Va(l,k,F,m,Qe?_e:f?2:_e,O&(M^1)&1,k,F,0,3623,B)|0,k=y(h[l+908>>2]),k=y(k+y(fn(l,2,c))),F=y(h[l+912>>2]),F=y(F+y(fn(l,0,c)))),Va(l,k,F,m,1,1,k,F,1,3635,B)|0,Td(l,rt)|0&&!(Ho(l,rt)|0)?(_e=n[976+(rt<<2)>>2]|0,ct=y(h[s+908+(_e<<2)>>2]),ct=y(ct-y(h[l+908+(_e<<2)>>2])),ct=y(ct-y(Rn(s,rt))),ct=y(ct-y(re(l,rt,c))),ct=y(ct-y(wp(l,rt,Qe?c:d))),h[l+400+(n[1040+(rt<<2)>>2]<<2)>>2]=ct):Xe=21;do if((Xe|0)==21){if(!(Ho(l,rt)|0)&&(n[s+8>>2]|0)==1){_e=n[976+(rt<<2)>>2]|0,ct=y(h[s+908+(_e<<2)>>2]),ct=y(y(ct-y(h[l+908+(_e<<2)>>2]))*y(.5)),h[l+400+(n[1040+(rt<<2)>>2]<<2)>>2]=ct;break}!(Ho(l,rt)|0)&&(n[s+8>>2]|0)==2&&(_e=n[976+(rt<<2)>>2]|0,ct=y(h[s+908+(_e<<2)>>2]),ct=y(ct-y(h[l+908+(_e<<2)>>2])),h[l+400+(n[1040+(rt<<2)>>2]<<2)>>2]=ct)}while(!1);Td(l,Oe)|0&&!(Ho(l,Oe)|0)?(_e=n[976+(Oe<<2)>>2]|0,ct=y(h[s+908+(_e<<2)>>2]),ct=y(ct-y(h[l+908+(_e<<2)>>2])),ct=y(ct-y(Rn(s,Oe))),ct=y(ct-y(re(l,Oe,c))),ct=y(ct-y(wp(l,Oe,Qe?d:c))),h[l+400+(n[1040+(Oe<<2)>>2]<<2)>>2]=ct):Xe=30;do if((Xe|0)==30&&!(Ho(l,Oe)|0)){if((Wi(s,l)|0)==2){_e=n[976+(Oe<<2)>>2]|0,ct=y(h[s+908+(_e<<2)>>2]),ct=y(y(ct-y(h[l+908+(_e<<2)>>2]))*y(.5)),h[l+400+(n[1040+(Oe<<2)>>2]<<2)>>2]=ct;break}_e=(Wi(s,l)|0)==3,_e^(n[s+28>>2]|0)==2&&(_e=n[976+(Oe<<2)>>2]|0,ct=y(h[s+908+(_e<<2)>>2]),ct=y(ct-y(h[l+908+(_e<<2)>>2])),h[l+400+(n[1040+(Oe<<2)>>2]<<2)>>2]=ct)}while(!1)}function bI(s,l,c){s=s|0,l=l|0,c=c|0;var f=Ze,d=0;d=n[976+(c<<2)>>2]|0,f=y(h[l+908+(d<<2)>>2]),f=y(y(h[s+908+(d<<2)>>2])-f),f=y(f-y(h[l+400+(n[1040+(c<<2)>>2]<<2)>>2])),h[l+400+(n[1e3+(c<<2)>>2]<<2)>>2]=f}function E0(s){return s=s|0,(s|1|0)==1|0}function GF(s){s=s|0;var l=Ze;switch(n[s+56>>2]|0){case 0:case 3:{l=y(h[s+40>>2]),l>y(0)&((Ot(l)|0)^1)?s=o[(n[s+976>>2]|0)+2>>0]|0?1056:992:s=1056;break}default:s=s+52|0}return s|0}function kI(s,l){return s=s|0,l=l|0,(o[s+l>>0]|0)!=0|0}function Td(s,l){return s=s|0,l=l|0,s=s+132|0,ge(l)|0&&n[(vn(s,5,948)|0)+4>>2]|0?s=1:s=(n[(vn(s,n[1e3+(l<<2)>>2]|0,948)|0)+4>>2]|0)!=0,s|0}function wp(s,l,c){s=s|0,l=l|0,c=y(c);var f=0,d=0;return s=s+132|0,ge(l)|0&&(f=vn(s,5,948)|0,(n[f+4>>2]|0)!=0)?d=4:(f=vn(s,n[1e3+(l<<2)>>2]|0,948)|0,n[f+4>>2]|0?d=4:c=y(0)),(d|0)==4&&(c=y(Kr(f,c))),y(c)}function uD(s,l,c){return s=s|0,l=l|0,c=y(c),Ho(s,l)|0?c=y(YA(s,l,c)):c=y(-y(wp(s,l,c))),y(c)}function AD(s){return s=y(s),h[D>>2]=s,n[D>>2]|0|0}function Ld(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>1073741823)Tt();else{d=Yt(l<<2)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<2)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<2)}function fD(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>2)<<2)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function Nd(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-4-l|0)>>>2)<<2)),s=n[s>>2]|0,s|0&&yt(s)}function pD(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;if(B=s+4|0,k=n[B>>2]|0,d=k-f|0,m=d>>2,s=l+(m<<2)|0,s>>>0<c>>>0){f=k;do n[f>>2]=n[s>>2],s=s+4|0,f=(n[B>>2]|0)+4|0,n[B>>2]=f;while(s>>>0<c>>>0)}m|0&&rw(k+(0-m<<2)|0,l|0,d|0)|0}function hD(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0;return k=l+4|0,F=n[k>>2]|0,d=n[s>>2]|0,B=c,m=B-d|0,f=F+(0-(m>>2)<<2)|0,n[k>>2]=f,(m|0)>0&&br(f|0,d|0,m|0)|0,d=s+4|0,m=l+8|0,f=(n[d>>2]|0)-B|0,(f|0)>0&&(br(n[m>>2]|0,c|0,f|0)|0,n[m>>2]=(n[m>>2]|0)+(f>>>2<<2)),B=n[s>>2]|0,n[s>>2]=n[k>>2],n[k>>2]=B,B=n[d>>2]|0,n[d>>2]=n[m>>2],n[m>>2]=B,B=s+8|0,c=l+12|0,s=n[B>>2]|0,n[B>>2]=n[c>>2],n[c>>2]=s,n[l>>2]=n[k>>2],F|0}function QI(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;if(B=n[l>>2]|0,m=n[c>>2]|0,(B|0)!=(m|0)){d=s+8|0,c=((m+-4-B|0)>>>2)+1|0,s=B,f=n[d>>2]|0;do n[f>>2]=n[s>>2],f=(n[d>>2]|0)+4|0,n[d>>2]=f,s=s+4|0;while((s|0)!=(m|0));n[l>>2]=B+(c<<2)}}function FI(){Oo()}function gD(){var s=0;return s=Yt(4)|0,RI(s),s|0}function RI(s){s=s|0,n[s>>2]=Sl()|0}function dD(s){s=s|0,s|0&&(C0(s),yt(s))}function C0(s){s=s|0,it(n[s>>2]|0)}function WF(s,l,c){s=s|0,l=l|0,c=c|0,xl(n[s>>2]|0,l,c)}function Od(s,l){s=s|0,l=y(l),dp(n[s>>2]|0,l)}function Md(s,l){return s=s|0,l=l|0,kI(n[s>>2]|0,l)|0}function Ud(){var s=0;return s=Yt(8)|0,I0(s,0),s|0}function I0(s,l){s=s|0,l=l|0,l?l=Mo(n[l>>2]|0)|0:l=qi()|0,n[s>>2]=l,n[s+4>>2]=0,Pn(l,s)}function _d(s){s=s|0;var l=0;return l=Yt(8)|0,I0(l,s),l|0}function w0(s){s=s|0,s|0&&(Hd(s),yt(s))}function Hd(s){s=s|0;var l=0;Dl(n[s>>2]|0),l=s+4|0,s=n[l>>2]|0,n[l>>2]=0,s|0&&(xu(s),yt(s))}function xu(s){s=s|0,bu(s)}function bu(s){s=s|0,s=n[s>>2]|0,s|0&&sa(s|0)}function TI(s){return s=s|0,fa(s)|0}function LI(s){s=s|0;var l=0,c=0;c=s+4|0,l=n[c>>2]|0,n[c>>2]=0,l|0&&(xu(l),yt(l)),Pl(n[s>>2]|0)}function qd(s,l){s=s|0,l=l|0,sn(n[s>>2]|0,n[l>>2]|0)}function YF(s,l){s=s|0,l=l|0,fp(n[s>>2]|0,l)}function KF(s,l,c){s=s|0,l=l|0,c=+c,Pd(n[s>>2]|0,l,y(c))}function jd(s,l,c){s=s|0,l=l|0,c=+c,Sd(n[s>>2]|0,l,y(c))}function NI(s,l){s=s|0,l=l|0,cp(n[s>>2]|0,l)}function OI(s,l){s=s|0,l=l|0,to(n[s>>2]|0,l)}function Sr(s,l){s=s|0,l=l|0,Ap(n[s>>2]|0,l)}function Os(s,l){s=s|0,l=l|0,wd(n[s>>2]|0,l)}function Oi(s,l){s=s|0,l=l|0,o0(n[s>>2]|0,l)}function ms(s,l){s=s|0,l=l|0,eo(n[s>>2]|0,l)}function VA(s,l,c){s=s|0,l=l|0,c=+c,OA(n[s>>2]|0,l,y(c))}function MI(s,l,c){s=s|0,l=l|0,c=+c,W(n[s>>2]|0,l,y(c))}function is(s,l){s=s|0,l=l|0,MA(n[s>>2]|0,l)}function Gd(s,l){s=s|0,l=l|0,vd(n[s>>2]|0,l)}function Bp(s,l){s=s|0,l=l|0,ro(n[s>>2]|0,l)}function B0(s,l){s=s|0,l=+l,pp(n[s>>2]|0,y(l))}function vp(s,l){s=s|0,l=+l,Ya(n[s>>2]|0,y(l))}function UI(s,l){s=s|0,l=+l,Dd(n[s>>2]|0,y(l))}function _I(s,l){s=s|0,l=+l,l0(n[s>>2]|0,y(l))}function HI(s,l){s=s|0,l=+l,Wa(n[s>>2]|0,y(l))}function qI(s,l){s=s|0,l=+l,c0(n[s>>2]|0,y(l))}function ku(s,l){s=s|0,l=+l,DI(n[s>>2]|0,y(l))}function ir(s){s=s|0,hp(n[s>>2]|0)}function Wd(s,l){s=s|0,l=+l,Ni(n[s>>2]|0,y(l))}function jI(s,l){s=s|0,l=+l,Iu(n[s>>2]|0,y(l))}function bl(s){s=s|0,pa(n[s>>2]|0)}function Qu(s,l){s=s|0,l=+l,Bc(n[s>>2]|0,y(l))}function v0(s,l){s=s|0,l=+l,wu(n[s>>2]|0,y(l))}function D0(s,l){s=s|0,l=+l,oi(n[s>>2]|0,y(l))}function GI(s,l){s=s|0,l=+l,UA(n[s>>2]|0,y(l))}function WI(s,l){s=s|0,l=+l,Uo(n[s>>2]|0,y(l))}function bc(s,l){s=s|0,l=+l,ga(n[s>>2]|0,y(l))}function P0(s,l){s=s|0,l=+l,gp(n[s>>2]|0,y(l))}function YI(s,l){s=s|0,l=+l,f0(n[s>>2]|0,y(l))}function Yd(s,l){s=s|0,l=+l,_A(n[s>>2]|0,y(l))}function kc(s,l,c){s=s|0,l=l|0,c=+c,wc(n[s>>2]|0,l,y(c))}function Kd(s,l,c){s=s|0,l=l|0,c=+c,no(n[s>>2]|0,l,y(c))}function S0(s,l,c){s=s|0,l=l|0,c=+c,Cu(n[s>>2]|0,l,y(c))}function x0(s){return s=s|0,s0(n[s>>2]|0)|0}function oo(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;f=C,C=C+16|0,d=f,NA(d,n[l>>2]|0,c),ss(s,d),C=f}function ss(s,l){s=s|0,l=l|0,Xa(s,n[l+4>>2]|0,+y(h[l>>2]))}function Xa(s,l,c){s=s|0,l=l|0,c=+c,n[s>>2]=l,E[s+8>>3]=c}function Vd(s){return s=s|0,vI(n[s>>2]|0)|0}function qo(s){return s=s|0,up(n[s>>2]|0)|0}function mD(s){return s=s|0,Ic(n[s>>2]|0)|0}function Dp(s){return s=s|0,BI(n[s>>2]|0)|0}function KI(s){return s=s|0,a0(n[s>>2]|0)|0}function VF(s){return s=s|0,Bd(n[s>>2]|0)|0}function yD(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;f=C,C=C+16|0,d=f,xt(d,n[l>>2]|0,c),ss(s,d),C=f}function ED(s){return s=s|0,Eu(n[s>>2]|0)|0}function zd(s){return s=s|0,Ga(n[s>>2]|0)|0}function VI(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,LA(f,n[l>>2]|0),ss(s,f),C=c}function Pp(s){return s=s|0,+ +y(ei(n[s>>2]|0))}function CD(s){return s=s|0,+ +y(Qi(n[s>>2]|0))}function ID(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,cr(f,n[l>>2]|0),ss(s,f),C=c}function b0(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,u0(f,n[l>>2]|0),ss(s,f),C=c}function zF(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,wt(f,n[l>>2]|0),ss(s,f),C=c}function JF(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,ha(f,n[l>>2]|0),ss(s,f),C=c}function wD(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,A0(f,n[l>>2]|0),ss(s,f),C=c}function BD(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,bd(f,n[l>>2]|0),ss(s,f),C=c}function zA(s){return s=s|0,+ +y(p0(n[s>>2]|0))}function XF(s,l){return s=s|0,l=l|0,+ +y(xd(n[s>>2]|0,l))}function ZF(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;f=C,C=C+16|0,d=f,dt(d,n[l>>2]|0,c),ss(s,d),C=f}function Qc(s,l,c){s=s|0,l=l|0,c=c|0,ar(n[s>>2]|0,n[l>>2]|0,c)}function $F(s,l){s=s|0,l=l|0,yu(n[s>>2]|0,n[l>>2]|0)}function vD(s){return s=s|0,Di(n[s>>2]|0)|0}function eR(s){return s=s|0,s=mt(n[s>>2]|0)|0,s?s=TI(s)|0:s=0,s|0}function DD(s,l){return s=s|0,l=l|0,s=rs(n[s>>2]|0,l)|0,s?s=TI(s)|0:s=0,s|0}function Fu(s,l){s=s|0,l=l|0;var c=0,f=0;f=Yt(4)|0,PD(f,l),c=s+4|0,l=n[c>>2]|0,n[c>>2]=f,l|0&&(xu(l),yt(l)),vt(n[s>>2]|0,1)}function PD(s,l){s=s|0,l=l|0,iR(s,l)}function tR(s,l,c,f,d,m){s=s|0,l=l|0,c=y(c),f=f|0,d=y(d),m=m|0;var B=0,k=0;B=C,C=C+16|0,k=B,SD(k,fa(l)|0,+c,f,+d,m),h[s>>2]=y(+E[k>>3]),h[s+4>>2]=y(+E[k+8>>3]),C=B}function SD(s,l,c,f,d,m){s=s|0,l=l|0,c=+c,f=f|0,d=+d,m=m|0;var B=0,k=0,F=0,M=0,O=0;B=C,C=C+32|0,O=B+8|0,M=B+20|0,F=B,k=B+16|0,E[O>>3]=c,n[M>>2]=f,E[F>>3]=d,n[k>>2]=m,Jd(s,n[l+4>>2]|0,O,M,F,k),C=B}function Jd(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0;B=C,C=C+16|0,k=B,$a(k),l=ys(l)|0,xD(s,l,+E[c>>3],n[f>>2]|0,+E[d>>3],n[m>>2]|0),el(k),C=B}function ys(s){return s=s|0,n[s>>2]|0}function xD(s,l,c,f,d,m){s=s|0,l=l|0,c=+c,f=f|0,d=+d,m=m|0;var B=0;B=jo(zI()|0)|0,c=+ma(c),f=Xd(f)|0,d=+ma(d),rR(s,qn(0,B|0,l|0,+c,f|0,+d,Xd(m)|0)|0)}function zI(){var s=0;return o[7608]|0||(XI(9120),s=7608,n[s>>2]=1,n[s+4>>2]=0),9120}function jo(s){return s=s|0,n[s+8>>2]|0}function ma(s){return s=+s,+ +Ru(s)}function Xd(s){return s=s|0,k0(s)|0}function rR(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;d=C,C=C+32|0,c=d,f=l,f&1?(ya(c,0),ia(f|0,c|0)|0,JI(s,c),nR(c)):(n[s>>2]=n[l>>2],n[s+4>>2]=n[l+4>>2],n[s+8>>2]=n[l+8>>2],n[s+12>>2]=n[l+12>>2]),C=d}function ya(s,l){s=s|0,l=l|0,Fc(s,l),n[s+8>>2]=0,o[s+24>>0]=0}function JI(s,l){s=s|0,l=l|0,l=l+8|0,n[s>>2]=n[l>>2],n[s+4>>2]=n[l+4>>2],n[s+8>>2]=n[l+8>>2],n[s+12>>2]=n[l+12>>2]}function nR(s){s=s|0,o[s+24>>0]=0}function Fc(s,l){s=s|0,l=l|0,n[s>>2]=l}function k0(s){return s=s|0,s|0}function Ru(s){return s=+s,+s}function XI(s){s=s|0,ao(s,ZI()|0,4)}function ZI(){return 1064}function ao(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c,n[s+8>>2]=ki(l|0,c+1|0)|0}function iR(s,l){s=s|0,l=l|0,l=n[l>>2]|0,n[s>>2]=l,hc(l|0)}function bD(s){s=s|0;var l=0,c=0;c=s+4|0,l=n[c>>2]|0,n[c>>2]=0,l|0&&(xu(l),yt(l)),vt(n[s>>2]|0,0)}function kD(s){s=s|0,Dt(n[s>>2]|0)}function Zd(s){return s=s|0,er(n[s>>2]|0)|0}function sR(s,l,c,f){s=s|0,l=+l,c=+c,f=f|0,qA(n[s>>2]|0,y(l),y(c),f)}function oR(s){return s=s|0,+ +y(vc(n[s>>2]|0))}function v(s){return s=s|0,+ +y(Bu(n[s>>2]|0))}function P(s){return s=s|0,+ +y(Dc(n[s>>2]|0))}function Q(s){return s=s|0,+ +y(gs(n[s>>2]|0))}function H(s){return s=s|0,+ +y(Pc(n[s>>2]|0))}function Y(s){return s=s|0,+ +y(On(n[s>>2]|0))}function ne(s,l){s=s|0,l=l|0,E[s>>3]=+y(vc(n[l>>2]|0)),E[s+8>>3]=+y(Bu(n[l>>2]|0)),E[s+16>>3]=+y(Dc(n[l>>2]|0)),E[s+24>>3]=+y(gs(n[l>>2]|0)),E[s+32>>3]=+y(Pc(n[l>>2]|0)),E[s+40>>3]=+y(On(n[l>>2]|0))}function Be(s,l){return s=s|0,l=l|0,+ +y(ji(n[s>>2]|0,l))}function Ue(s,l){return s=s|0,l=l|0,+ +y(Ci(n[s>>2]|0,l))}function ft(s,l){return s=s|0,l=l|0,+ +y(HA(n[s>>2]|0,l))}function jt(){return Dn()|0}function wr(){Tr(),Xt(),jn(),li(),Ea(),$e()}function Tr(){SLe(11713,4938,1)}function Xt(){YTe(10448)}function jn(){STe(10408)}function li(){JRe(10324)}function Ea(){iFe(10096)}function $e(){je(9132)}function je(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0,We=0,Oe=0,Qe=0,rt=0,Xe=0,ct=0,_e=0,Ge=0,Nt=0,_r=0,ur=0,Zt=0,kr=0,Or=0,lr=0,Ln=0,lo=0,co=0,uo=0,Ia=0,Lp=0,Np=0,kl=0,Op=0,Nu=0,Ou=0,Mp=0,Up=0,_p=0,$r=0,Ql=0,Hp=0,Lc=0,qp=0,jp=0,Mu=0,Uu=0,Nc=0,Ms=0,rl=0,Go=0,Fl=0,rf=0,nf=0,_u=0,sf=0,of=0,Us=0,Cs=0,Rl=0,Un=0,af=0,Ao=0,Oc=0,fo=0,Mc=0,lf=0,cf=0,Uc=0,_s=0,Tl=0,uf=0,Af=0,ff=0,Fr=0,ri=0,Is=0,po=0,Hs=0,Lr=0,Ar=0,Ll=0;l=C,C=C+672|0,c=l+656|0,Ll=l+648|0,Ar=l+640|0,Lr=l+632|0,Hs=l+624|0,po=l+616|0,Is=l+608|0,ri=l+600|0,Fr=l+592|0,ff=l+584|0,Af=l+576|0,uf=l+568|0,Tl=l+560|0,_s=l+552|0,Uc=l+544|0,cf=l+536|0,lf=l+528|0,Mc=l+520|0,fo=l+512|0,Oc=l+504|0,Ao=l+496|0,af=l+488|0,Un=l+480|0,Rl=l+472|0,Cs=l+464|0,Us=l+456|0,of=l+448|0,sf=l+440|0,_u=l+432|0,nf=l+424|0,rf=l+416|0,Fl=l+408|0,Go=l+400|0,rl=l+392|0,Ms=l+384|0,Nc=l+376|0,Uu=l+368|0,Mu=l+360|0,jp=l+352|0,qp=l+344|0,Lc=l+336|0,Hp=l+328|0,Ql=l+320|0,$r=l+312|0,_p=l+304|0,Up=l+296|0,Mp=l+288|0,Ou=l+280|0,Nu=l+272|0,Op=l+264|0,kl=l+256|0,Np=l+248|0,Lp=l+240|0,Ia=l+232|0,uo=l+224|0,co=l+216|0,lo=l+208|0,Ln=l+200|0,lr=l+192|0,Or=l+184|0,kr=l+176|0,Zt=l+168|0,ur=l+160|0,_r=l+152|0,Nt=l+144|0,Ge=l+136|0,_e=l+128|0,ct=l+120|0,Xe=l+112|0,rt=l+104|0,Qe=l+96|0,Oe=l+88|0,We=l+80|0,oe=l+72|0,j=l+64|0,O=l+56|0,M=l+48|0,F=l+40|0,k=l+32|0,B=l+24|0,m=l+16|0,d=l+8|0,f=l,pt(s,3646),Jt(s,3651,2)|0,Br(s,3665,2)|0,Wn(s,3682,18)|0,n[Ll>>2]=19,n[Ll+4>>2]=0,n[c>>2]=n[Ll>>2],n[c+4>>2]=n[Ll+4>>2],xr(s,3690,c)|0,n[Ar>>2]=1,n[Ar+4>>2]=0,n[c>>2]=n[Ar>>2],n[c+4>>2]=n[Ar+4>>2],Sn(s,3696,c)|0,n[Lr>>2]=2,n[Lr+4>>2]=0,n[c>>2]=n[Lr>>2],n[c+4>>2]=n[Lr+4>>2],Tn(s,3706,c)|0,n[Hs>>2]=1,n[Hs+4>>2]=0,n[c>>2]=n[Hs>>2],n[c+4>>2]=n[Hs+4>>2],Yr(s,3722,c)|0,n[po>>2]=2,n[po+4>>2]=0,n[c>>2]=n[po>>2],n[c+4>>2]=n[po+4>>2],Yr(s,3734,c)|0,n[Is>>2]=3,n[Is+4>>2]=0,n[c>>2]=n[Is>>2],n[c+4>>2]=n[Is+4>>2],Tn(s,3753,c)|0,n[ri>>2]=4,n[ri+4>>2]=0,n[c>>2]=n[ri>>2],n[c+4>>2]=n[ri+4>>2],Tn(s,3769,c)|0,n[Fr>>2]=5,n[Fr+4>>2]=0,n[c>>2]=n[Fr>>2],n[c+4>>2]=n[Fr+4>>2],Tn(s,3783,c)|0,n[ff>>2]=6,n[ff+4>>2]=0,n[c>>2]=n[ff>>2],n[c+4>>2]=n[ff+4>>2],Tn(s,3796,c)|0,n[Af>>2]=7,n[Af+4>>2]=0,n[c>>2]=n[Af>>2],n[c+4>>2]=n[Af+4>>2],Tn(s,3813,c)|0,n[uf>>2]=8,n[uf+4>>2]=0,n[c>>2]=n[uf>>2],n[c+4>>2]=n[uf+4>>2],Tn(s,3825,c)|0,n[Tl>>2]=3,n[Tl+4>>2]=0,n[c>>2]=n[Tl>>2],n[c+4>>2]=n[Tl+4>>2],Yr(s,3843,c)|0,n[_s>>2]=4,n[_s+4>>2]=0,n[c>>2]=n[_s>>2],n[c+4>>2]=n[_s+4>>2],Yr(s,3853,c)|0,n[Uc>>2]=9,n[Uc+4>>2]=0,n[c>>2]=n[Uc>>2],n[c+4>>2]=n[Uc+4>>2],Tn(s,3870,c)|0,n[cf>>2]=10,n[cf+4>>2]=0,n[c>>2]=n[cf>>2],n[c+4>>2]=n[cf+4>>2],Tn(s,3884,c)|0,n[lf>>2]=11,n[lf+4>>2]=0,n[c>>2]=n[lf>>2],n[c+4>>2]=n[lf+4>>2],Tn(s,3896,c)|0,n[Mc>>2]=1,n[Mc+4>>2]=0,n[c>>2]=n[Mc>>2],n[c+4>>2]=n[Mc+4>>2],ti(s,3907,c)|0,n[fo>>2]=2,n[fo+4>>2]=0,n[c>>2]=n[fo>>2],n[c+4>>2]=n[fo+4>>2],ti(s,3915,c)|0,n[Oc>>2]=3,n[Oc+4>>2]=0,n[c>>2]=n[Oc>>2],n[c+4>>2]=n[Oc+4>>2],ti(s,3928,c)|0,n[Ao>>2]=4,n[Ao+4>>2]=0,n[c>>2]=n[Ao>>2],n[c+4>>2]=n[Ao+4>>2],ti(s,3948,c)|0,n[af>>2]=5,n[af+4>>2]=0,n[c>>2]=n[af>>2],n[c+4>>2]=n[af+4>>2],ti(s,3960,c)|0,n[Un>>2]=6,n[Un+4>>2]=0,n[c>>2]=n[Un>>2],n[c+4>>2]=n[Un+4>>2],ti(s,3974,c)|0,n[Rl>>2]=7,n[Rl+4>>2]=0,n[c>>2]=n[Rl>>2],n[c+4>>2]=n[Rl+4>>2],ti(s,3983,c)|0,n[Cs>>2]=20,n[Cs+4>>2]=0,n[c>>2]=n[Cs>>2],n[c+4>>2]=n[Cs+4>>2],xr(s,3999,c)|0,n[Us>>2]=8,n[Us+4>>2]=0,n[c>>2]=n[Us>>2],n[c+4>>2]=n[Us+4>>2],ti(s,4012,c)|0,n[of>>2]=9,n[of+4>>2]=0,n[c>>2]=n[of>>2],n[c+4>>2]=n[of+4>>2],ti(s,4022,c)|0,n[sf>>2]=21,n[sf+4>>2]=0,n[c>>2]=n[sf>>2],n[c+4>>2]=n[sf+4>>2],xr(s,4039,c)|0,n[_u>>2]=10,n[_u+4>>2]=0,n[c>>2]=n[_u>>2],n[c+4>>2]=n[_u+4>>2],ti(s,4053,c)|0,n[nf>>2]=11,n[nf+4>>2]=0,n[c>>2]=n[nf>>2],n[c+4>>2]=n[nf+4>>2],ti(s,4065,c)|0,n[rf>>2]=12,n[rf+4>>2]=0,n[c>>2]=n[rf>>2],n[c+4>>2]=n[rf+4>>2],ti(s,4084,c)|0,n[Fl>>2]=13,n[Fl+4>>2]=0,n[c>>2]=n[Fl>>2],n[c+4>>2]=n[Fl+4>>2],ti(s,4097,c)|0,n[Go>>2]=14,n[Go+4>>2]=0,n[c>>2]=n[Go>>2],n[c+4>>2]=n[Go+4>>2],ti(s,4117,c)|0,n[rl>>2]=15,n[rl+4>>2]=0,n[c>>2]=n[rl>>2],n[c+4>>2]=n[rl+4>>2],ti(s,4129,c)|0,n[Ms>>2]=16,n[Ms+4>>2]=0,n[c>>2]=n[Ms>>2],n[c+4>>2]=n[Ms+4>>2],ti(s,4148,c)|0,n[Nc>>2]=17,n[Nc+4>>2]=0,n[c>>2]=n[Nc>>2],n[c+4>>2]=n[Nc+4>>2],ti(s,4161,c)|0,n[Uu>>2]=18,n[Uu+4>>2]=0,n[c>>2]=n[Uu>>2],n[c+4>>2]=n[Uu+4>>2],ti(s,4181,c)|0,n[Mu>>2]=5,n[Mu+4>>2]=0,n[c>>2]=n[Mu>>2],n[c+4>>2]=n[Mu+4>>2],Yr(s,4196,c)|0,n[jp>>2]=6,n[jp+4>>2]=0,n[c>>2]=n[jp>>2],n[c+4>>2]=n[jp+4>>2],Yr(s,4206,c)|0,n[qp>>2]=7,n[qp+4>>2]=0,n[c>>2]=n[qp>>2],n[c+4>>2]=n[qp+4>>2],Yr(s,4217,c)|0,n[Lc>>2]=3,n[Lc+4>>2]=0,n[c>>2]=n[Lc>>2],n[c+4>>2]=n[Lc+4>>2],Rc(s,4235,c)|0,n[Hp>>2]=1,n[Hp+4>>2]=0,n[c>>2]=n[Hp>>2],n[c+4>>2]=n[Hp+4>>2],aR(s,4251,c)|0,n[Ql>>2]=4,n[Ql+4>>2]=0,n[c>>2]=n[Ql>>2],n[c+4>>2]=n[Ql+4>>2],Rc(s,4263,c)|0,n[$r>>2]=5,n[$r+4>>2]=0,n[c>>2]=n[$r>>2],n[c+4>>2]=n[$r+4>>2],Rc(s,4279,c)|0,n[_p>>2]=6,n[_p+4>>2]=0,n[c>>2]=n[_p>>2],n[c+4>>2]=n[_p+4>>2],Rc(s,4293,c)|0,n[Up>>2]=7,n[Up+4>>2]=0,n[c>>2]=n[Up>>2],n[c+4>>2]=n[Up+4>>2],Rc(s,4306,c)|0,n[Mp>>2]=8,n[Mp+4>>2]=0,n[c>>2]=n[Mp>>2],n[c+4>>2]=n[Mp+4>>2],Rc(s,4323,c)|0,n[Ou>>2]=9,n[Ou+4>>2]=0,n[c>>2]=n[Ou>>2],n[c+4>>2]=n[Ou+4>>2],Rc(s,4335,c)|0,n[Nu>>2]=2,n[Nu+4>>2]=0,n[c>>2]=n[Nu>>2],n[c+4>>2]=n[Nu+4>>2],aR(s,4353,c)|0,n[Op>>2]=12,n[Op+4>>2]=0,n[c>>2]=n[Op>>2],n[c+4>>2]=n[Op+4>>2],Q0(s,4363,c)|0,n[kl>>2]=1,n[kl+4>>2]=0,n[c>>2]=n[kl>>2],n[c+4>>2]=n[kl+4>>2],JA(s,4376,c)|0,n[Np>>2]=2,n[Np+4>>2]=0,n[c>>2]=n[Np>>2],n[c+4>>2]=n[Np+4>>2],JA(s,4388,c)|0,n[Lp>>2]=13,n[Lp+4>>2]=0,n[c>>2]=n[Lp>>2],n[c+4>>2]=n[Lp+4>>2],Q0(s,4402,c)|0,n[Ia>>2]=14,n[Ia+4>>2]=0,n[c>>2]=n[Ia>>2],n[c+4>>2]=n[Ia+4>>2],Q0(s,4411,c)|0,n[uo>>2]=15,n[uo+4>>2]=0,n[c>>2]=n[uo>>2],n[c+4>>2]=n[uo+4>>2],Q0(s,4421,c)|0,n[co>>2]=16,n[co+4>>2]=0,n[c>>2]=n[co>>2],n[c+4>>2]=n[co+4>>2],Q0(s,4433,c)|0,n[lo>>2]=17,n[lo+4>>2]=0,n[c>>2]=n[lo>>2],n[c+4>>2]=n[lo+4>>2],Q0(s,4446,c)|0,n[Ln>>2]=18,n[Ln+4>>2]=0,n[c>>2]=n[Ln>>2],n[c+4>>2]=n[Ln+4>>2],Q0(s,4458,c)|0,n[lr>>2]=3,n[lr+4>>2]=0,n[c>>2]=n[lr>>2],n[c+4>>2]=n[lr+4>>2],JA(s,4471,c)|0,n[Or>>2]=1,n[Or+4>>2]=0,n[c>>2]=n[Or>>2],n[c+4>>2]=n[Or+4>>2],QD(s,4486,c)|0,n[kr>>2]=10,n[kr+4>>2]=0,n[c>>2]=n[kr>>2],n[c+4>>2]=n[kr+4>>2],Rc(s,4496,c)|0,n[Zt>>2]=11,n[Zt+4>>2]=0,n[c>>2]=n[Zt>>2],n[c+4>>2]=n[Zt+4>>2],Rc(s,4508,c)|0,n[ur>>2]=3,n[ur+4>>2]=0,n[c>>2]=n[ur>>2],n[c+4>>2]=n[ur+4>>2],aR(s,4519,c)|0,n[_r>>2]=4,n[_r+4>>2]=0,n[c>>2]=n[_r>>2],n[c+4>>2]=n[_r+4>>2],Lve(s,4530,c)|0,n[Nt>>2]=19,n[Nt+4>>2]=0,n[c>>2]=n[Nt>>2],n[c+4>>2]=n[Nt+4>>2],Nve(s,4542,c)|0,n[Ge>>2]=12,n[Ge+4>>2]=0,n[c>>2]=n[Ge>>2],n[c+4>>2]=n[Ge+4>>2],Ove(s,4554,c)|0,n[_e>>2]=13,n[_e+4>>2]=0,n[c>>2]=n[_e>>2],n[c+4>>2]=n[_e+4>>2],Mve(s,4568,c)|0,n[ct>>2]=2,n[ct+4>>2]=0,n[c>>2]=n[ct>>2],n[c+4>>2]=n[ct+4>>2],Uve(s,4578,c)|0,n[Xe>>2]=20,n[Xe+4>>2]=0,n[c>>2]=n[Xe>>2],n[c+4>>2]=n[Xe+4>>2],_ve(s,4587,c)|0,n[rt>>2]=22,n[rt+4>>2]=0,n[c>>2]=n[rt>>2],n[c+4>>2]=n[rt+4>>2],xr(s,4602,c)|0,n[Qe>>2]=23,n[Qe+4>>2]=0,n[c>>2]=n[Qe>>2],n[c+4>>2]=n[Qe+4>>2],xr(s,4619,c)|0,n[Oe>>2]=14,n[Oe+4>>2]=0,n[c>>2]=n[Oe>>2],n[c+4>>2]=n[Oe+4>>2],Hve(s,4629,c)|0,n[We>>2]=1,n[We+4>>2]=0,n[c>>2]=n[We>>2],n[c+4>>2]=n[We+4>>2],qve(s,4637,c)|0,n[oe>>2]=4,n[oe+4>>2]=0,n[c>>2]=n[oe>>2],n[c+4>>2]=n[oe+4>>2],JA(s,4653,c)|0,n[j>>2]=5,n[j+4>>2]=0,n[c>>2]=n[j>>2],n[c+4>>2]=n[j+4>>2],JA(s,4669,c)|0,n[O>>2]=6,n[O+4>>2]=0,n[c>>2]=n[O>>2],n[c+4>>2]=n[O+4>>2],JA(s,4686,c)|0,n[M>>2]=7,n[M+4>>2]=0,n[c>>2]=n[M>>2],n[c+4>>2]=n[M+4>>2],JA(s,4701,c)|0,n[F>>2]=8,n[F+4>>2]=0,n[c>>2]=n[F>>2],n[c+4>>2]=n[F+4>>2],JA(s,4719,c)|0,n[k>>2]=9,n[k+4>>2]=0,n[c>>2]=n[k>>2],n[c+4>>2]=n[k+4>>2],JA(s,4736,c)|0,n[B>>2]=21,n[B+4>>2]=0,n[c>>2]=n[B>>2],n[c+4>>2]=n[B+4>>2],jve(s,4754,c)|0,n[m>>2]=2,n[m+4>>2]=0,n[c>>2]=n[m>>2],n[c+4>>2]=n[m+4>>2],QD(s,4772,c)|0,n[d>>2]=3,n[d+4>>2]=0,n[c>>2]=n[d>>2],n[c+4>>2]=n[d+4>>2],QD(s,4790,c)|0,n[f>>2]=4,n[f+4>>2]=0,n[c>>2]=n[f>>2],n[c+4>>2]=n[f+4>>2],QD(s,4808,c)|0,C=l}function pt(s,l){s=s|0,l=l|0;var c=0;c=zQe()|0,n[s>>2]=c,JQe(c,l),Fp(n[s>>2]|0)}function Jt(s,l,c){return s=s|0,l=l|0,c=c|0,LQe(s,mn(l)|0,c,0),s|0}function Br(s,l,c){return s=s|0,l=l|0,c=c|0,EQe(s,mn(l)|0,c,0),s|0}function Wn(s,l,c){return s=s|0,l=l|0,c=c|0,sQe(s,mn(l)|0,c,0),s|0}function xr(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],jke(s,l,d),C=f,s|0}function Sn(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],vke(s,l,d),C=f,s|0}function Tn(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],lke(s,l,d),C=f,s|0}function Yr(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Ybe(s,l,d),C=f,s|0}function ti(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],kbe(s,l,d),C=f,s|0}function Rc(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],hbe(s,l,d),C=f,s|0}function aR(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Zxe(s,l,d),C=f,s|0}function Q0(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],vxe(s,l,d),C=f,s|0}function JA(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],lxe(s,l,d),C=f,s|0}function QD(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],YSe(s,l,d),C=f,s|0}function Lve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],kSe(s,l,d),C=f,s|0}function Nve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],hSe(s,l,d),C=f,s|0}function Ove(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],$Pe(s,l,d),C=f,s|0}function Mve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],MPe(s,l,d),C=f,s|0}function Uve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],IPe(s,l,d),C=f,s|0}function _ve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],iPe(s,l,d),C=f,s|0}function Hve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],qDe(s,l,d),C=f,s|0}function qve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],vDe(s,l,d),C=f,s|0}function jve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Gve(s,l,d),C=f,s|0}function Gve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Wve(s,c,d,1),C=f}function mn(s){return s=s|0,s|0}function Wve(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=lR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=Yve(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,Kve(m,f)|0,f),C=d}function lR(){var s=0,l=0;if(o[7616]|0||(LG(9136),pr(24,9136,U|0)|0,l=7616,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9136)|0)){s=9136,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));LG(9136)}return 9136}function Yve(s){return s=s|0,0}function Kve(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=lR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],TG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(Jve(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function yn(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0,F=0,M=0,O=0,j=0,oe=0,We=0;B=C,C=C+32|0,oe=B+24|0,j=B+20|0,F=B+16|0,O=B+12|0,M=B+8|0,k=B+4|0,We=B,n[j>>2]=l,n[F>>2]=c,n[O>>2]=f,n[M>>2]=d,n[k>>2]=m,m=s+28|0,n[We>>2]=n[m>>2],n[oe>>2]=n[We>>2],Vve(s+24|0,oe,j,O,M,F,k)|0,n[m>>2]=n[n[m>>2]>>2],C=B}function Vve(s,l,c,f,d,m,B){return s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,B=B|0,s=zve(l)|0,l=Yt(24)|0,RG(l+4|0,n[c>>2]|0,n[f>>2]|0,n[d>>2]|0,n[m>>2]|0,n[B>>2]|0),n[l>>2]=n[s>>2],n[s>>2]=l,l|0}function zve(s){return s=s|0,n[s>>2]|0}function RG(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,n[s>>2]=l,n[s+4>>2]=c,n[s+8>>2]=f,n[s+12>>2]=d,n[s+16>>2]=m}function dr(s,l){return s=s|0,l=l|0,l|s|0}function TG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function Jve(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=Xve(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,Zve(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],TG(m,f,c),n[F>>2]=(n[F>>2]|0)+12,$ve(s,k),eDe(k),C=M;return}}function Xve(s){return s=s|0,357913941}function Zve(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function $ve(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function eDe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function LG(s){s=s|0,nDe(s)}function tDe(s){s=s|0,rDe(s+24|0)}function Nr(s){return s=s|0,n[s>>2]|0}function rDe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function nDe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,3,l,iDe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function zr(){return 9228}function iDe(){return 1140}function sDe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=oDe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=aDe(l,f)|0,C=c,l|0}function Jr(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,n[s>>2]=l,n[s+4>>2]=c,n[s+8>>2]=f,n[s+12>>2]=d,n[s+16>>2]=m}function oDe(s){return s=s|0,(n[(lR()|0)+24>>2]|0)+(s*12|0)|0}function aDe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;return d=C,C=C+48|0,f=d,c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),tf[c&31](f,s),f=lDe(f)|0,C=d,f|0}function lDe(s){s=s|0;var l=0,c=0,f=0,d=0;return d=C,C=C+32|0,l=d+12|0,c=d,f=cR(NG()|0)|0,f?(uR(l,f),AR(c,l),cDe(s,c),s=fR(l)|0):s=uDe(s)|0,C=d,s|0}function NG(){var s=0;return o[7632]|0||(CDe(9184),pr(25,9184,U|0)|0,s=7632,n[s>>2]=1,n[s+4>>2]=0),9184}function cR(s){return s=s|0,n[s+36>>2]|0}function uR(s,l){s=s|0,l=l|0,n[s>>2]=l,n[s+4>>2]=s,n[s+8>>2]=0}function AR(s,l){s=s|0,l=l|0,n[s>>2]=n[l>>2],n[s+4>>2]=n[l+4>>2],n[s+8>>2]=0}function cDe(s,l){s=s|0,l=l|0,hDe(l,s,s+8|0,s+16|0,s+24|0,s+32|0,s+40|0)|0}function fR(s){return s=s|0,n[(n[s+4>>2]|0)+8>>2]|0}function uDe(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0,F=0;F=C,C=C+16|0,c=F+4|0,f=F,d=Za(8)|0,m=d,B=Yt(48)|0,k=B,l=k+48|0;do n[k>>2]=n[s>>2],k=k+4|0,s=s+4|0;while((k|0)<(l|0));return l=m+4|0,n[l>>2]=B,k=Yt(8)|0,B=n[l>>2]|0,n[f>>2]=0,n[c>>2]=n[f>>2],OG(k,B,c),n[d>>2]=k,C=F,m|0}function OG(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,c=Yt(16)|0,n[c+4>>2]=0,n[c+8>>2]=0,n[c>>2]=1092,n[c+12>>2]=l,n[s+4>>2]=c}function ADe(s){s=s|0,im(s),yt(s)}function fDe(s){s=s|0,s=n[s+12>>2]|0,s|0&&yt(s)}function pDe(s){s=s|0,yt(s)}function hDe(s,l,c,f,d,m,B){return s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,B=B|0,m=gDe(n[s>>2]|0,l,c,f,d,m,B)|0,B=s+4|0,n[(n[B>>2]|0)+8>>2]=m,n[(n[B>>2]|0)+8>>2]|0}function gDe(s,l,c,f,d,m,B){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,B=B|0;var k=0,F=0;return k=C,C=C+16|0,F=k,$a(F),s=ys(s)|0,B=dDe(s,+E[l>>3],+E[c>>3],+E[f>>3],+E[d>>3],+E[m>>3],+E[B>>3])|0,el(F),C=k,B|0}function dDe(s,l,c,f,d,m,B){s=s|0,l=+l,c=+c,f=+f,d=+d,m=+m,B=+B;var k=0;return k=jo(mDe()|0)|0,l=+ma(l),c=+ma(c),f=+ma(f),d=+ma(d),m=+ma(m),Ts(0,k|0,s|0,+l,+c,+f,+d,+m,+ +ma(B))|0}function mDe(){var s=0;return o[7624]|0||(yDe(9172),s=7624,n[s>>2]=1,n[s+4>>2]=0),9172}function yDe(s){s=s|0,ao(s,EDe()|0,6)}function EDe(){return 1112}function CDe(s){s=s|0,Sp(s)}function IDe(s){s=s|0,MG(s+24|0),UG(s+16|0)}function MG(s){s=s|0,BDe(s)}function UG(s){s=s|0,wDe(s)}function wDe(s){s=s|0;var l=0,c=0;if(l=n[s>>2]|0,l|0)do c=l,l=n[l>>2]|0,yt(c);while(l|0);n[s>>2]=0}function BDe(s){s=s|0;var l=0,c=0;if(l=n[s>>2]|0,l|0)do c=l,l=n[l>>2]|0,yt(c);while(l|0);n[s>>2]=0}function Sp(s){s=s|0;var l=0;n[s+16>>2]=0,n[s+20>>2]=0,l=s+24|0,n[l>>2]=0,n[s+28>>2]=l,n[s+36>>2]=0,o[s+40>>0]=0,o[s+41>>0]=0}function vDe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],DDe(s,c,d,0),C=f}function DDe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=pR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=PDe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,SDe(m,f)|0,f),C=d}function pR(){var s=0,l=0;if(o[7640]|0||(HG(9232),pr(26,9232,U|0)|0,l=7640,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9232)|0)){s=9232,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));HG(9232)}return 9232}function PDe(s){return s=s|0,0}function SDe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=pR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],_G(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(xDe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function _G(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function xDe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=bDe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,kDe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],_G(m,f,c),n[F>>2]=(n[F>>2]|0)+12,QDe(s,k),FDe(k),C=M;return}}function bDe(s){return s=s|0,357913941}function kDe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function QDe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function FDe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function HG(s){s=s|0,LDe(s)}function RDe(s){s=s|0,TDe(s+24|0)}function TDe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function LDe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,1,l,NDe()|0,3),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function NDe(){return 1144}function ODe(s,l,c,f,d){s=s|0,l=l|0,c=+c,f=+f,d=d|0;var m=0,B=0,k=0,F=0;m=C,C=C+16|0,B=m+8|0,k=m,F=MDe(s)|0,s=n[F+4>>2]|0,n[k>>2]=n[F>>2],n[k+4>>2]=s,n[B>>2]=n[k>>2],n[B+4>>2]=n[k+4>>2],UDe(l,B,c,f,d),C=m}function MDe(s){return s=s|0,(n[(pR()|0)+24>>2]|0)+(s*12|0)|0}function UDe(s,l,c,f,d){s=s|0,l=l|0,c=+c,f=+f,d=d|0;var m=0,B=0,k=0,F=0,M=0;M=C,C=C+16|0,B=M+2|0,k=M+1|0,F=M,m=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(m=n[(n[s>>2]|0)+m>>2]|0),Tu(B,c),c=+Lu(B,c),Tu(k,f),f=+Lu(k,f),XA(F,d),F=ZA(F,d)|0,rW[m&1](s,c,f,F),C=M}function Tu(s,l){s=s|0,l=+l}function Lu(s,l){return s=s|0,l=+l,+ +HDe(l)}function XA(s,l){s=s|0,l=l|0}function ZA(s,l){return s=s|0,l=l|0,_De(l)|0}function _De(s){return s=s|0,s|0}function HDe(s){return s=+s,+s}function qDe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],jDe(s,c,d,1),C=f}function jDe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=hR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=GDe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,WDe(m,f)|0,f),C=d}function hR(){var s=0,l=0;if(o[7648]|0||(jG(9268),pr(27,9268,U|0)|0,l=7648,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9268)|0)){s=9268,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));jG(9268)}return 9268}function GDe(s){return s=s|0,0}function WDe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=hR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],qG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(YDe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function qG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function YDe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=KDe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,VDe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],qG(m,f,c),n[F>>2]=(n[F>>2]|0)+12,zDe(s,k),JDe(k),C=M;return}}function KDe(s){return s=s|0,357913941}function VDe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function zDe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function JDe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function jG(s){s=s|0,$De(s)}function XDe(s){s=s|0,ZDe(s+24|0)}function ZDe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function $De(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,4,l,ePe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function ePe(){return 1160}function tPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=rPe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=nPe(l,f)|0,C=c,l|0}function rPe(s){return s=s|0,(n[(hR()|0)+24>>2]|0)+(s*12|0)|0}function nPe(s,l){s=s|0,l=l|0;var c=0;return c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),GG(_0[c&31](s)|0)|0}function GG(s){return s=s|0,s&1|0}function iPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],sPe(s,c,d,0),C=f}function sPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=gR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=oPe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,aPe(m,f)|0,f),C=d}function gR(){var s=0,l=0;if(o[7656]|0||(YG(9304),pr(28,9304,U|0)|0,l=7656,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9304)|0)){s=9304,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));YG(9304)}return 9304}function oPe(s){return s=s|0,0}function aPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=gR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],WG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(lPe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function WG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function lPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=cPe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,uPe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],WG(m,f,c),n[F>>2]=(n[F>>2]|0)+12,APe(s,k),fPe(k),C=M;return}}function cPe(s){return s=s|0,357913941}function uPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function APe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function fPe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function YG(s){s=s|0,gPe(s)}function pPe(s){s=s|0,hPe(s+24|0)}function hPe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function gPe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,5,l,dPe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function dPe(){return 1164}function mPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=yPe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],EPe(l,d,c),C=f}function yPe(s){return s=s|0,(n[(gR()|0)+24>>2]|0)+(s*12|0)|0}function EPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),xp(d,c),c=bp(d,c)|0,tf[f&31](s,c),kp(d),C=m}function xp(s,l){s=s|0,l=l|0,CPe(s,l)}function bp(s,l){return s=s|0,l=l|0,s|0}function kp(s){s=s|0,xu(s)}function CPe(s,l){s=s|0,l=l|0,dR(s,l)}function dR(s,l){s=s|0,l=l|0,n[s>>2]=l}function IPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],wPe(s,c,d,0),C=f}function wPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=mR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=BPe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,vPe(m,f)|0,f),C=d}function mR(){var s=0,l=0;if(o[7664]|0||(VG(9340),pr(29,9340,U|0)|0,l=7664,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9340)|0)){s=9340,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));VG(9340)}return 9340}function BPe(s){return s=s|0,0}function vPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=mR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],KG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(DPe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function KG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function DPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=PPe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,SPe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],KG(m,f,c),n[F>>2]=(n[F>>2]|0)+12,xPe(s,k),bPe(k),C=M;return}}function PPe(s){return s=s|0,357913941}function SPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function xPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function bPe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function VG(s){s=s|0,FPe(s)}function kPe(s){s=s|0,QPe(s+24|0)}function QPe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function FPe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,4,l,RPe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function RPe(){return 1180}function TPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=LPe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],c=NPe(l,d,c)|0,C=f,c|0}function LPe(s){return s=s|0,(n[(mR()|0)+24>>2]|0)+(s*12|0)|0}function NPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;return m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),F0(d,c),d=R0(d,c)|0,d=FD(pT[f&15](s,d)|0)|0,C=m,d|0}function F0(s,l){s=s|0,l=l|0}function R0(s,l){return s=s|0,l=l|0,OPe(l)|0}function FD(s){return s=s|0,s|0}function OPe(s){return s=s|0,s|0}function MPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],UPe(s,c,d,0),C=f}function UPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=yR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=_Pe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,HPe(m,f)|0,f),C=d}function yR(){var s=0,l=0;if(o[7672]|0||(JG(9376),pr(30,9376,U|0)|0,l=7672,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9376)|0)){s=9376,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));JG(9376)}return 9376}function _Pe(s){return s=s|0,0}function HPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=yR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],zG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(qPe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function zG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function qPe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=jPe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,GPe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],zG(m,f,c),n[F>>2]=(n[F>>2]|0)+12,WPe(s,k),YPe(k),C=M;return}}function jPe(s){return s=s|0,357913941}function GPe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function WPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function YPe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function JG(s){s=s|0,zPe(s)}function KPe(s){s=s|0,VPe(s+24|0)}function VPe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function zPe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,5,l,XG()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function XG(){return 1196}function JPe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=XPe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=ZPe(l,f)|0,C=c,l|0}function XPe(s){return s=s|0,(n[(yR()|0)+24>>2]|0)+(s*12|0)|0}function ZPe(s,l){s=s|0,l=l|0;var c=0;return c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),FD(_0[c&31](s)|0)|0}function $Pe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],eSe(s,c,d,1),C=f}function eSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=ER()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=tSe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,rSe(m,f)|0,f),C=d}function ER(){var s=0,l=0;if(o[7680]|0||($G(9412),pr(31,9412,U|0)|0,l=7680,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9412)|0)){s=9412,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));$G(9412)}return 9412}function tSe(s){return s=s|0,0}function rSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=ER()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],ZG(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(nSe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function ZG(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function nSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=iSe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,sSe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],ZG(m,f,c),n[F>>2]=(n[F>>2]|0)+12,oSe(s,k),aSe(k),C=M;return}}function iSe(s){return s=s|0,357913941}function sSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function oSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function aSe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function $G(s){s=s|0,uSe(s)}function lSe(s){s=s|0,cSe(s+24|0)}function cSe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function uSe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,6,l,e5()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function e5(){return 1200}function ASe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=fSe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=pSe(l,f)|0,C=c,l|0}function fSe(s){return s=s|0,(n[(ER()|0)+24>>2]|0)+(s*12|0)|0}function pSe(s,l){s=s|0,l=l|0;var c=0;return c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),RD(_0[c&31](s)|0)|0}function RD(s){return s=s|0,s|0}function hSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],gSe(s,c,d,0),C=f}function gSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=CR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=dSe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,mSe(m,f)|0,f),C=d}function CR(){var s=0,l=0;if(o[7688]|0||(r5(9448),pr(32,9448,U|0)|0,l=7688,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9448)|0)){s=9448,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));r5(9448)}return 9448}function dSe(s){return s=s|0,0}function mSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=CR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],t5(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(ySe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function t5(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function ySe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=ESe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,CSe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],t5(m,f,c),n[F>>2]=(n[F>>2]|0)+12,ISe(s,k),wSe(k),C=M;return}}function ESe(s){return s=s|0,357913941}function CSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function ISe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function wSe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function r5(s){s=s|0,DSe(s)}function BSe(s){s=s|0,vSe(s+24|0)}function vSe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function DSe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,6,l,n5()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function n5(){return 1204}function PSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=SSe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],xSe(l,d,c),C=f}function SSe(s){return s=s|0,(n[(CR()|0)+24>>2]|0)+(s*12|0)|0}function xSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),IR(d,c),d=wR(d,c)|0,tf[f&31](s,d),C=m}function IR(s,l){s=s|0,l=l|0}function wR(s,l){return s=s|0,l=l|0,bSe(l)|0}function bSe(s){return s=s|0,s|0}function kSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],QSe(s,c,d,0),C=f}function QSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=BR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=FSe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,RSe(m,f)|0,f),C=d}function BR(){var s=0,l=0;if(o[7696]|0||(s5(9484),pr(33,9484,U|0)|0,l=7696,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9484)|0)){s=9484,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));s5(9484)}return 9484}function FSe(s){return s=s|0,0}function RSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=BR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],i5(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(TSe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function i5(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function TSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=LSe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,NSe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],i5(m,f,c),n[F>>2]=(n[F>>2]|0)+12,OSe(s,k),MSe(k),C=M;return}}function LSe(s){return s=s|0,357913941}function NSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function OSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function MSe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function s5(s){s=s|0,HSe(s)}function USe(s){s=s|0,_Se(s+24|0)}function _Se(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function HSe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,1,l,qSe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function qSe(){return 1212}function jSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+16|0,m=d+8|0,B=d,k=GSe(s)|0,s=n[k+4>>2]|0,n[B>>2]=n[k>>2],n[B+4>>2]=s,n[m>>2]=n[B>>2],n[m+4>>2]=n[B+4>>2],WSe(l,m,c,f),C=d}function GSe(s){return s=s|0,(n[(BR()|0)+24>>2]|0)+(s*12|0)|0}function WSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;k=C,C=C+16|0,m=k+1|0,B=k,d=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(d=n[(n[s>>2]|0)+d>>2]|0),IR(m,c),m=wR(m,c)|0,F0(B,f),B=R0(B,f)|0,sw[d&15](s,m,B),C=k}function YSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],KSe(s,c,d,1),C=f}function KSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=vR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=VSe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,zSe(m,f)|0,f),C=d}function vR(){var s=0,l=0;if(o[7704]|0||(a5(9520),pr(34,9520,U|0)|0,l=7704,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9520)|0)){s=9520,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));a5(9520)}return 9520}function VSe(s){return s=s|0,0}function zSe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=vR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],o5(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(JSe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function o5(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function JSe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=XSe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,ZSe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],o5(m,f,c),n[F>>2]=(n[F>>2]|0)+12,$Se(s,k),exe(k),C=M;return}}function XSe(s){return s=s|0,357913941}function ZSe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function $Se(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function exe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function a5(s){s=s|0,nxe(s)}function txe(s){s=s|0,rxe(s+24|0)}function rxe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function nxe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,1,l,ixe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function ixe(){return 1224}function sxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;return d=C,C=C+16|0,m=d+8|0,B=d,k=oxe(s)|0,s=n[k+4>>2]|0,n[B>>2]=n[k>>2],n[B+4>>2]=s,n[m>>2]=n[B>>2],n[m+4>>2]=n[B+4>>2],f=+axe(l,m,c),C=d,+f}function oxe(s){return s=s|0,(n[(vR()|0)+24>>2]|0)+(s*12|0)|0}function axe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),XA(d,c),d=ZA(d,c)|0,B=+Ru(+iW[f&7](s,d)),C=m,+B}function lxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],cxe(s,c,d,1),C=f}function cxe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=DR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=uxe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,Axe(m,f)|0,f),C=d}function DR(){var s=0,l=0;if(o[7712]|0||(c5(9556),pr(35,9556,U|0)|0,l=7712,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9556)|0)){s=9556,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));c5(9556)}return 9556}function uxe(s){return s=s|0,0}function Axe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=DR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],l5(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(fxe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function l5(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function fxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=pxe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,hxe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],l5(m,f,c),n[F>>2]=(n[F>>2]|0)+12,gxe(s,k),dxe(k),C=M;return}}function pxe(s){return s=s|0,357913941}function hxe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function gxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function dxe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function c5(s){s=s|0,Exe(s)}function mxe(s){s=s|0,yxe(s+24|0)}function yxe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function Exe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,5,l,Cxe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Cxe(){return 1232}function Ixe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=wxe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],c=+Bxe(l,d),C=f,+c}function wxe(s){return s=s|0,(n[(DR()|0)+24>>2]|0)+(s*12|0)|0}function Bxe(s,l){s=s|0,l=l|0;var c=0;return c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),+ +Ru(+nW[c&15](s))}function vxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Dxe(s,c,d,1),C=f}function Dxe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=PR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=Pxe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,Sxe(m,f)|0,f),C=d}function PR(){var s=0,l=0;if(o[7720]|0||(A5(9592),pr(36,9592,U|0)|0,l=7720,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9592)|0)){s=9592,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));A5(9592)}return 9592}function Pxe(s){return s=s|0,0}function Sxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=PR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],u5(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(xxe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function u5(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function xxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=bxe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,kxe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],u5(m,f,c),n[F>>2]=(n[F>>2]|0)+12,Qxe(s,k),Fxe(k),C=M;return}}function bxe(s){return s=s|0,357913941}function kxe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function Qxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function Fxe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function A5(s){s=s|0,Lxe(s)}function Rxe(s){s=s|0,Txe(s+24|0)}function Txe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function Lxe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,7,l,Nxe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Nxe(){return 1276}function Oxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=Mxe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=Uxe(l,f)|0,C=c,l|0}function Mxe(s){return s=s|0,(n[(PR()|0)+24>>2]|0)+(s*12|0)|0}function Uxe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;return d=C,C=C+16|0,f=d,c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),tf[c&31](f,s),f=f5(f)|0,C=d,f|0}function f5(s){s=s|0;var l=0,c=0,f=0,d=0;return d=C,C=C+32|0,l=d+12|0,c=d,f=cR(p5()|0)|0,f?(uR(l,f),AR(c,l),_xe(s,c),s=fR(l)|0):s=Hxe(s)|0,C=d,s|0}function p5(){var s=0;return o[7736]|0||(Xxe(9640),pr(25,9640,U|0)|0,s=7736,n[s>>2]=1,n[s+4>>2]=0),9640}function _xe(s,l){s=s|0,l=l|0,Wxe(l,s,s+8|0)|0}function Hxe(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0;return c=C,C=C+16|0,d=c+4|0,B=c,f=Za(8)|0,l=f,k=Yt(16)|0,n[k>>2]=n[s>>2],n[k+4>>2]=n[s+4>>2],n[k+8>>2]=n[s+8>>2],n[k+12>>2]=n[s+12>>2],m=l+4|0,n[m>>2]=k,s=Yt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],SR(s,m,d),n[f>>2]=s,C=c,l|0}function SR(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,c=Yt(16)|0,n[c+4>>2]=0,n[c+8>>2]=0,n[c>>2]=1244,n[c+12>>2]=l,n[s+4>>2]=c}function qxe(s){s=s|0,im(s),yt(s)}function jxe(s){s=s|0,s=n[s+12>>2]|0,s|0&&yt(s)}function Gxe(s){s=s|0,yt(s)}function Wxe(s,l,c){return s=s|0,l=l|0,c=c|0,l=Yxe(n[s>>2]|0,l,c)|0,c=s+4|0,n[(n[c>>2]|0)+8>>2]=l,n[(n[c>>2]|0)+8>>2]|0}function Yxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;return f=C,C=C+16|0,d=f,$a(d),s=ys(s)|0,c=Kxe(s,n[l>>2]|0,+E[c>>3])|0,el(d),C=f,c|0}function Kxe(s,l,c){s=s|0,l=l|0,c=+c;var f=0;return f=jo(Vxe()|0)|0,l=Xd(l)|0,pc(0,f|0,s|0,l|0,+ +ma(c))|0}function Vxe(){var s=0;return o[7728]|0||(zxe(9628),s=7728,n[s>>2]=1,n[s+4>>2]=0),9628}function zxe(s){s=s|0,ao(s,Jxe()|0,2)}function Jxe(){return 1264}function Xxe(s){s=s|0,Sp(s)}function Zxe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],$xe(s,c,d,1),C=f}function $xe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=xR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=ebe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,tbe(m,f)|0,f),C=d}function xR(){var s=0,l=0;if(o[7744]|0||(g5(9684),pr(37,9684,U|0)|0,l=7744,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9684)|0)){s=9684,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));g5(9684)}return 9684}function ebe(s){return s=s|0,0}function tbe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=xR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],h5(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(rbe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function h5(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function rbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=nbe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,ibe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],h5(m,f,c),n[F>>2]=(n[F>>2]|0)+12,sbe(s,k),obe(k),C=M;return}}function nbe(s){return s=s|0,357913941}function ibe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function sbe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function obe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function g5(s){s=s|0,cbe(s)}function abe(s){s=s|0,lbe(s+24|0)}function lbe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function cbe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,5,l,ube()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function ube(){return 1280}function Abe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=fbe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],c=pbe(l,d,c)|0,C=f,c|0}function fbe(s){return s=s|0,(n[(xR()|0)+24>>2]|0)+(s*12|0)|0}function pbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return B=C,C=C+32|0,d=B,m=B+16|0,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),XA(m,c),m=ZA(m,c)|0,sw[f&15](d,s,m),m=f5(d)|0,C=B,m|0}function hbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],gbe(s,c,d,1),C=f}function gbe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=bR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=dbe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,mbe(m,f)|0,f),C=d}function bR(){var s=0,l=0;if(o[7752]|0||(m5(9720),pr(38,9720,U|0)|0,l=7752,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9720)|0)){s=9720,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));m5(9720)}return 9720}function dbe(s){return s=s|0,0}function mbe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=bR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],d5(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(ybe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function d5(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function ybe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=Ebe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,Cbe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],d5(m,f,c),n[F>>2]=(n[F>>2]|0)+12,Ibe(s,k),wbe(k),C=M;return}}function Ebe(s){return s=s|0,357913941}function Cbe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function Ibe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function wbe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function m5(s){s=s|0,Dbe(s)}function Bbe(s){s=s|0,vbe(s+24|0)}function vbe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function Dbe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,8,l,Pbe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Pbe(){return 1288}function Sbe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;return c=C,C=C+16|0,f=c+8|0,d=c,m=xbe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],l=bbe(l,f)|0,C=c,l|0}function xbe(s){return s=s|0,(n[(bR()|0)+24>>2]|0)+(s*12|0)|0}function bbe(s,l){s=s|0,l=l|0;var c=0;return c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),k0(_0[c&31](s)|0)|0}function kbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Qbe(s,c,d,0),C=f}function Qbe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=kR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=Fbe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,Rbe(m,f)|0,f),C=d}function kR(){var s=0,l=0;if(o[7760]|0||(E5(9756),pr(39,9756,U|0)|0,l=7760,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9756)|0)){s=9756,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));E5(9756)}return 9756}function Fbe(s){return s=s|0,0}function Rbe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=kR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],y5(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(Tbe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function y5(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function Tbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=Lbe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,Nbe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],y5(m,f,c),n[F>>2]=(n[F>>2]|0)+12,Obe(s,k),Mbe(k),C=M;return}}function Lbe(s){return s=s|0,357913941}function Nbe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function Obe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function Mbe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function E5(s){s=s|0,Hbe(s)}function Ube(s){s=s|0,_be(s+24|0)}function _be(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function Hbe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,8,l,qbe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function qbe(){return 1292}function jbe(s,l,c){s=s|0,l=l|0,c=+c;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=Gbe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Wbe(l,d,c),C=f}function Gbe(s){return s=s|0,(n[(kR()|0)+24>>2]|0)+(s*12|0)|0}function Wbe(s,l,c){s=s|0,l=l|0,c=+c;var f=0,d=0,m=0;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),Tu(d,c),c=+Lu(d,c),eW[f&31](s,c),C=m}function Ybe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Kbe(s,c,d,0),C=f}function Kbe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=QR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=Vbe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,zbe(m,f)|0,f),C=d}function QR(){var s=0,l=0;if(o[7768]|0||(I5(9792),pr(40,9792,U|0)|0,l=7768,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9792)|0)){s=9792,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));I5(9792)}return 9792}function Vbe(s){return s=s|0,0}function zbe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=QR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],C5(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(Jbe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function C5(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function Jbe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=Xbe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,Zbe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],C5(m,f,c),n[F>>2]=(n[F>>2]|0)+12,$be(s,k),eke(k),C=M;return}}function Xbe(s){return s=s|0,357913941}function Zbe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function $be(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function eke(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function I5(s){s=s|0,nke(s)}function tke(s){s=s|0,rke(s+24|0)}function rke(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function nke(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,1,l,ike()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function ike(){return 1300}function ske(s,l,c,f){s=s|0,l=l|0,c=c|0,f=+f;var d=0,m=0,B=0,k=0;d=C,C=C+16|0,m=d+8|0,B=d,k=oke(s)|0,s=n[k+4>>2]|0,n[B>>2]=n[k>>2],n[B+4>>2]=s,n[m>>2]=n[B>>2],n[m+4>>2]=n[B+4>>2],ake(l,m,c,f),C=d}function oke(s){return s=s|0,(n[(QR()|0)+24>>2]|0)+(s*12|0)|0}function ake(s,l,c,f){s=s|0,l=l|0,c=c|0,f=+f;var d=0,m=0,B=0,k=0;k=C,C=C+16|0,m=k+1|0,B=k,d=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(d=n[(n[s>>2]|0)+d>>2]|0),XA(m,c),m=ZA(m,c)|0,Tu(B,f),f=+Lu(B,f),lW[d&15](s,m,f),C=k}function lke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],cke(s,c,d,0),C=f}function cke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=FR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=uke(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,Ake(m,f)|0,f),C=d}function FR(){var s=0,l=0;if(o[7776]|0||(B5(9828),pr(41,9828,U|0)|0,l=7776,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9828)|0)){s=9828,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));B5(9828)}return 9828}function uke(s){return s=s|0,0}function Ake(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=FR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],w5(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(fke(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function w5(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function fke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=pke(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,hke(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],w5(m,f,c),n[F>>2]=(n[F>>2]|0)+12,gke(s,k),dke(k),C=M;return}}function pke(s){return s=s|0,357913941}function hke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function gke(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function dke(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function B5(s){s=s|0,Eke(s)}function mke(s){s=s|0,yke(s+24|0)}function yke(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function Eke(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,7,l,Cke()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Cke(){return 1312}function Ike(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=wke(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Bke(l,d,c),C=f}function wke(s){return s=s|0,(n[(FR()|0)+24>>2]|0)+(s*12|0)|0}function Bke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),XA(d,c),d=ZA(d,c)|0,tf[f&31](s,d),C=m}function vke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Dke(s,c,d,0),C=f}function Dke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=RR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=Pke(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,Ske(m,f)|0,f),C=d}function RR(){var s=0,l=0;if(o[7784]|0||(D5(9864),pr(42,9864,U|0)|0,l=7784,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9864)|0)){s=9864,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));D5(9864)}return 9864}function Pke(s){return s=s|0,0}function Ske(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=RR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],v5(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(xke(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function v5(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function xke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=bke(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,kke(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],v5(m,f,c),n[F>>2]=(n[F>>2]|0)+12,Qke(s,k),Fke(k),C=M;return}}function bke(s){return s=s|0,357913941}function kke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function Qke(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function Fke(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function D5(s){s=s|0,Lke(s)}function Rke(s){s=s|0,Tke(s+24|0)}function Tke(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function Lke(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,8,l,Nke()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function Nke(){return 1320}function Oke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=Mke(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Uke(l,d,c),C=f}function Mke(s){return s=s|0,(n[(RR()|0)+24>>2]|0)+(s*12|0)|0}function Uke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),_ke(d,c),d=Hke(d,c)|0,tf[f&31](s,d),C=m}function _ke(s,l){s=s|0,l=l|0}function Hke(s,l){return s=s|0,l=l|0,qke(l)|0}function qke(s){return s=s|0,s|0}function jke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],Gke(s,c,d,0),C=f}function Gke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=TR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=Wke(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,Yke(m,f)|0,f),C=d}function TR(){var s=0,l=0;if(o[7792]|0||(S5(9900),pr(43,9900,U|0)|0,l=7792,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9900)|0)){s=9900,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));S5(9900)}return 9900}function Wke(s){return s=s|0,0}function Yke(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=TR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],P5(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(Kke(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function P5(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function Kke(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=Vke(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,zke(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],P5(m,f,c),n[F>>2]=(n[F>>2]|0)+12,Jke(s,k),Xke(k),C=M;return}}function Vke(s){return s=s|0,357913941}function zke(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function Jke(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function Xke(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function S5(s){s=s|0,eQe(s)}function Zke(s){s=s|0,$ke(s+24|0)}function $ke(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function eQe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,22,l,tQe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function tQe(){return 1344}function rQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0;c=C,C=C+16|0,f=c+8|0,d=c,m=nQe(s)|0,s=n[m+4>>2]|0,n[d>>2]=n[m>>2],n[d+4>>2]=s,n[f>>2]=n[d>>2],n[f+4>>2]=n[d+4>>2],iQe(l,f),C=c}function nQe(s){return s=s|0,(n[(TR()|0)+24>>2]|0)+(s*12|0)|0}function iQe(s,l){s=s|0,l=l|0;var c=0;c=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(c=n[(n[s>>2]|0)+c>>2]|0),ef[c&127](s)}function sQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=LR()|0,s=oQe(c)|0,yn(m,l,d,s,aQe(c,f)|0,f)}function LR(){var s=0,l=0;if(o[7800]|0||(b5(9936),pr(44,9936,U|0)|0,l=7800,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9936)|0)){s=9936,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));b5(9936)}return 9936}function oQe(s){return s=s|0,s|0}function aQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=LR()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(x5(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(lQe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function x5(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function lQe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=cQe(s)|0,f>>>0<B>>>0)Zr(s);else{F=n[s>>2]|0,O=(n[s+8>>2]|0)-F|0,M=O>>2,uQe(d,O>>3>>>0<f>>>1>>>0?M>>>0<B>>>0?B:M:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,x5(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,AQe(s,d),fQe(d),C=k;return}}function cQe(s){return s=s|0,536870911}function uQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Yt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function AQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function fQe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function b5(s){s=s|0,gQe(s)}function pQe(s){s=s|0,hQe(s+24|0)}function hQe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function gQe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,23,l,n5()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function dQe(s,l){s=s|0,l=l|0,yQe(n[(mQe(s)|0)>>2]|0,l)}function mQe(s){return s=s|0,(n[(LR()|0)+24>>2]|0)+(s<<3)|0}function yQe(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,IR(f,l),l=wR(f,l)|0,ef[s&127](l),C=c}function EQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=NR()|0,s=CQe(c)|0,yn(m,l,d,s,IQe(c,f)|0,f)}function NR(){var s=0,l=0;if(o[7808]|0||(Q5(9972),pr(45,9972,U|0)|0,l=7808,n[l>>2]=1,n[l+4>>2]=0),!(Nr(9972)|0)){s=9972,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));Q5(9972)}return 9972}function CQe(s){return s=s|0,s|0}function IQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=NR()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(k5(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(wQe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function k5(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function wQe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=BQe(s)|0,f>>>0<B>>>0)Zr(s);else{F=n[s>>2]|0,O=(n[s+8>>2]|0)-F|0,M=O>>2,vQe(d,O>>3>>>0<f>>>1>>>0?M>>>0<B>>>0?B:M:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,k5(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,DQe(s,d),PQe(d),C=k;return}}function BQe(s){return s=s|0,536870911}function vQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Yt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function DQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function PQe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function Q5(s){s=s|0,bQe(s)}function SQe(s){s=s|0,xQe(s+24|0)}function xQe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function bQe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,9,l,kQe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function kQe(){return 1348}function QQe(s,l){return s=s|0,l=l|0,RQe(n[(FQe(s)|0)>>2]|0,l)|0}function FQe(s){return s=s|0,(n[(NR()|0)+24>>2]|0)+(s<<3)|0}function RQe(s,l){s=s|0,l=l|0;var c=0,f=0;return c=C,C=C+16|0,f=c,F5(f,l),l=R5(f,l)|0,l=FD(_0[s&31](l)|0)|0,C=c,l|0}function F5(s,l){s=s|0,l=l|0}function R5(s,l){return s=s|0,l=l|0,TQe(l)|0}function TQe(s){return s=s|0,s|0}function LQe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=OR()|0,s=NQe(c)|0,yn(m,l,d,s,OQe(c,f)|0,f)}function OR(){var s=0,l=0;if(o[7816]|0||(L5(10008),pr(46,10008,U|0)|0,l=7816,n[l>>2]=1,n[l+4>>2]=0),!(Nr(10008)|0)){s=10008,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));L5(10008)}return 10008}function NQe(s){return s=s|0,s|0}function OQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=OR()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(T5(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(MQe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function T5(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function MQe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=UQe(s)|0,f>>>0<B>>>0)Zr(s);else{F=n[s>>2]|0,O=(n[s+8>>2]|0)-F|0,M=O>>2,_Qe(d,O>>3>>>0<f>>>1>>>0?M>>>0<B>>>0?B:M:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,T5(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,HQe(s,d),qQe(d),C=k;return}}function UQe(s){return s=s|0,536870911}function _Qe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Yt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function HQe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function qQe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function L5(s){s=s|0,WQe(s)}function jQe(s){s=s|0,GQe(s+24|0)}function GQe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function WQe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,15,l,XG()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function YQe(s){return s=s|0,VQe(n[(KQe(s)|0)>>2]|0)|0}function KQe(s){return s=s|0,(n[(OR()|0)+24>>2]|0)+(s<<3)|0}function VQe(s){return s=s|0,FD(KD[s&7]()|0)|0}function zQe(){var s=0;return o[7832]|0||(nFe(10052),pr(25,10052,U|0)|0,s=7832,n[s>>2]=1,n[s+4>>2]=0),10052}function JQe(s,l){s=s|0,l=l|0,n[s>>2]=XQe()|0,n[s+4>>2]=ZQe()|0,n[s+12>>2]=l,n[s+8>>2]=$Qe()|0,n[s+32>>2]=2}function XQe(){return 11709}function ZQe(){return 1188}function $Qe(){return TD()|0}function eFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Qp(f,896)|0)==512?c|0&&(tFe(c),yt(c)):l|0&&(Hd(l),yt(l))}function Qp(s,l){return s=s|0,l=l|0,l&s|0}function tFe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Rp(s)}function TD(){var s=0;return o[7824]|0||(n[2511]=rFe()|0,n[2512]=0,s=7824,n[s>>2]=1,n[s+4>>2]=0),10044}function rFe(){return 0}function nFe(s){s=s|0,Sp(s)}function iFe(s){s=s|0;var l=0,c=0,f=0,d=0,m=0;l=C,C=C+32|0,c=l+24|0,m=l+16|0,d=l+8|0,f=l,sFe(s,4827),oFe(s,4834,3)|0,aFe(s,3682,47)|0,n[m>>2]=9,n[m+4>>2]=0,n[c>>2]=n[m>>2],n[c+4>>2]=n[m+4>>2],lFe(s,4841,c)|0,n[d>>2]=1,n[d+4>>2]=0,n[c>>2]=n[d>>2],n[c+4>>2]=n[d+4>>2],cFe(s,4871,c)|0,n[f>>2]=10,n[f+4>>2]=0,n[c>>2]=n[f>>2],n[c+4>>2]=n[f+4>>2],uFe(s,4891,c)|0,C=l}function sFe(s,l){s=s|0,l=l|0;var c=0;c=qRe()|0,n[s>>2]=c,jRe(c,l),Fp(n[s>>2]|0)}function oFe(s,l,c){return s=s|0,l=l|0,c=c|0,PRe(s,mn(l)|0,c,0),s|0}function aFe(s,l,c){return s=s|0,l=l|0,c=c|0,ARe(s,mn(l)|0,c,0),s|0}function lFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],YFe(s,l,d),C=f,s|0}function cFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],SFe(s,l,d),C=f,s|0}function uFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=n[c+4>>2]|0,n[m>>2]=n[c>>2],n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],AFe(s,l,d),C=f,s|0}function AFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],fFe(s,c,d,1),C=f}function fFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=MR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=pFe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,hFe(m,f)|0,f),C=d}function MR(){var s=0,l=0;if(o[7840]|0||(O5(10100),pr(48,10100,U|0)|0,l=7840,n[l>>2]=1,n[l+4>>2]=0),!(Nr(10100)|0)){s=10100,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));O5(10100)}return 10100}function pFe(s){return s=s|0,0}function hFe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=MR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],N5(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(gFe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function N5(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function gFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=dFe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,mFe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],N5(m,f,c),n[F>>2]=(n[F>>2]|0)+12,yFe(s,k),EFe(k),C=M;return}}function dFe(s){return s=s|0,357913941}function mFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function yFe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function EFe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function O5(s){s=s|0,wFe(s)}function CFe(s){s=s|0,IFe(s+24|0)}function IFe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function wFe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,6,l,BFe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function BFe(){return 1364}function vFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;return f=C,C=C+16|0,d=f+8|0,m=f,B=DFe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],c=PFe(l,d,c)|0,C=f,c|0}function DFe(s){return s=s|0,(n[(MR()|0)+24>>2]|0)+(s*12|0)|0}function PFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;return m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),XA(d,c),d=ZA(d,c)|0,d=GG(pT[f&15](s,d)|0)|0,C=m,d|0}function SFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],xFe(s,c,d,0),C=f}function xFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=UR()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=bFe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,kFe(m,f)|0,f),C=d}function UR(){var s=0,l=0;if(o[7848]|0||(U5(10136),pr(49,10136,U|0)|0,l=7848,n[l>>2]=1,n[l+4>>2]=0),!(Nr(10136)|0)){s=10136,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));U5(10136)}return 10136}function bFe(s){return s=s|0,0}function kFe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=UR()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],M5(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(QFe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function M5(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function QFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=FFe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,RFe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],M5(m,f,c),n[F>>2]=(n[F>>2]|0)+12,TFe(s,k),LFe(k),C=M;return}}function FFe(s){return s=s|0,357913941}function RFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function TFe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function LFe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function U5(s){s=s|0,MFe(s)}function NFe(s){s=s|0,OFe(s+24|0)}function OFe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function MFe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,9,l,UFe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function UFe(){return 1372}function _Fe(s,l,c){s=s|0,l=l|0,c=+c;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,d=f+8|0,m=f,B=HFe(s)|0,s=n[B+4>>2]|0,n[m>>2]=n[B>>2],n[m+4>>2]=s,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],qFe(l,d,c),C=f}function HFe(s){return s=s|0,(n[(UR()|0)+24>>2]|0)+(s*12|0)|0}function qFe(s,l,c){s=s|0,l=l|0,c=+c;var f=0,d=0,m=0,B=Ze;m=C,C=C+16|0,d=m,f=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(f=n[(n[s>>2]|0)+f>>2]|0),jFe(d,c),B=y(GFe(d,c)),$7[f&1](s,B),C=m}function jFe(s,l){s=s|0,l=+l}function GFe(s,l){return s=s|0,l=+l,y(WFe(l))}function WFe(s){return s=+s,y(s)}function YFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,d=f+8|0,m=f,k=n[c>>2]|0,B=n[c+4>>2]|0,c=mn(l)|0,n[m>>2]=k,n[m+4>>2]=B,n[d>>2]=n[m>>2],n[d+4>>2]=n[m+4>>2],KFe(s,c,d,0),C=f}function KFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0,F=0,M=0,O=0;d=C,C=C+32|0,m=d+16|0,O=d+8|0,k=d,M=n[c>>2]|0,F=n[c+4>>2]|0,B=n[s>>2]|0,s=_R()|0,n[O>>2]=M,n[O+4>>2]=F,n[m>>2]=n[O>>2],n[m+4>>2]=n[O+4>>2],c=VFe(m)|0,n[k>>2]=M,n[k+4>>2]=F,n[m>>2]=n[k>>2],n[m+4>>2]=n[k+4>>2],yn(B,l,s,c,zFe(m,f)|0,f),C=d}function _R(){var s=0,l=0;if(o[7856]|0||(H5(10172),pr(50,10172,U|0)|0,l=7856,n[l>>2]=1,n[l+4>>2]=0),!(Nr(10172)|0)){s=10172,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));H5(10172)}return 10172}function VFe(s){return s=s|0,0}function zFe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0;return O=C,C=C+32|0,d=O+24|0,B=O+16|0,k=O,F=O+8|0,m=n[s>>2]|0,f=n[s+4>>2]|0,n[k>>2]=m,n[k+4>>2]=f,j=_R()|0,M=j+24|0,s=dr(l,4)|0,n[F>>2]=s,l=j+28|0,c=n[l>>2]|0,c>>>0<(n[j+32>>2]|0)>>>0?(n[B>>2]=m,n[B+4>>2]=f,n[d>>2]=n[B>>2],n[d+4>>2]=n[B+4>>2],_5(c,d,s),s=(n[l>>2]|0)+12|0,n[l>>2]=s):(JFe(M,k,F),s=n[l>>2]|0),C=O,((s-(n[M>>2]|0)|0)/12|0)+-1|0}function _5(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=n[l+4>>2]|0,n[s>>2]=n[l>>2],n[s+4>>2]=f,n[s+8>>2]=c}function JFe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;if(M=C,C=C+48|0,f=M+32|0,B=M+24|0,k=M,F=s+4|0,d=(((n[F>>2]|0)-(n[s>>2]|0)|0)/12|0)+1|0,m=XFe(s)|0,m>>>0<d>>>0)Zr(s);else{O=n[s>>2]|0,oe=((n[s+8>>2]|0)-O|0)/12|0,j=oe<<1,ZFe(k,oe>>>0<m>>>1>>>0?j>>>0<d>>>0?d:j:m,((n[F>>2]|0)-O|0)/12|0,s+8|0),F=k+8|0,m=n[F>>2]|0,d=n[l+4>>2]|0,c=n[c>>2]|0,n[B>>2]=n[l>>2],n[B+4>>2]=d,n[f>>2]=n[B>>2],n[f+4>>2]=n[B+4>>2],_5(m,f,c),n[F>>2]=(n[F>>2]|0)+12,$Fe(s,k),eRe(k),C=M;return}}function XFe(s){return s=s|0,357913941}function ZFe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>357913941)Tt();else{d=Yt(l*12|0)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c*12|0)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l*12|0)}function $Fe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(((d|0)/-12|0)*12|0)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function eRe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~(((f+-12-l|0)>>>0)/12|0)*12|0)),s=n[s>>2]|0,s|0&&yt(s)}function H5(s){s=s|0,nRe(s)}function tRe(s){s=s|0,rRe(s+24|0)}function rRe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~(((l+-12-f|0)>>>0)/12|0)*12|0)),yt(c))}function nRe(s){s=s|0;var l=0;l=zr()|0,Jr(s,2,3,l,iRe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function iRe(){return 1380}function sRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+16|0,m=d+8|0,B=d,k=oRe(s)|0,s=n[k+4>>2]|0,n[B>>2]=n[k>>2],n[B+4>>2]=s,n[m>>2]=n[B>>2],n[m+4>>2]=n[B+4>>2],aRe(l,m,c,f),C=d}function oRe(s){return s=s|0,(n[(_R()|0)+24>>2]|0)+(s*12|0)|0}function aRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;k=C,C=C+16|0,m=k+1|0,B=k,d=n[l>>2]|0,l=n[l+4>>2]|0,s=s+(l>>1)|0,l&1&&(d=n[(n[s>>2]|0)+d>>2]|0),XA(m,c),m=ZA(m,c)|0,lRe(B,f),B=cRe(B,f)|0,sw[d&15](s,m,B),C=k}function lRe(s,l){s=s|0,l=l|0}function cRe(s,l){return s=s|0,l=l|0,uRe(l)|0}function uRe(s){return s=s|0,(s|0)!=0|0}function ARe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=HR()|0,s=fRe(c)|0,yn(m,l,d,s,pRe(c,f)|0,f)}function HR(){var s=0,l=0;if(o[7864]|0||(j5(10208),pr(51,10208,U|0)|0,l=7864,n[l>>2]=1,n[l+4>>2]=0),!(Nr(10208)|0)){s=10208,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));j5(10208)}return 10208}function fRe(s){return s=s|0,s|0}function pRe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=HR()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(q5(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(hRe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function q5(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function hRe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=gRe(s)|0,f>>>0<B>>>0)Zr(s);else{F=n[s>>2]|0,O=(n[s+8>>2]|0)-F|0,M=O>>2,dRe(d,O>>3>>>0<f>>>1>>>0?M>>>0<B>>>0?B:M:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,q5(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,mRe(s,d),yRe(d),C=k;return}}function gRe(s){return s=s|0,536870911}function dRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Yt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function mRe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function yRe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function j5(s){s=s|0,IRe(s)}function ERe(s){s=s|0,CRe(s+24|0)}function CRe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function IRe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,24,l,wRe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function wRe(){return 1392}function BRe(s,l){s=s|0,l=l|0,DRe(n[(vRe(s)|0)>>2]|0,l)}function vRe(s){return s=s|0,(n[(HR()|0)+24>>2]|0)+(s<<3)|0}function DRe(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,F5(f,l),l=R5(f,l)|0,ef[s&127](l),C=c}function PRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=qR()|0,s=SRe(c)|0,yn(m,l,d,s,xRe(c,f)|0,f)}function qR(){var s=0,l=0;if(o[7872]|0||(W5(10244),pr(52,10244,U|0)|0,l=7872,n[l>>2]=1,n[l+4>>2]=0),!(Nr(10244)|0)){s=10244,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));W5(10244)}return 10244}function SRe(s){return s=s|0,s|0}function xRe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=qR()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(G5(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(bRe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function G5(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function bRe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=kRe(s)|0,f>>>0<B>>>0)Zr(s);else{F=n[s>>2]|0,O=(n[s+8>>2]|0)-F|0,M=O>>2,QRe(d,O>>3>>>0<f>>>1>>>0?M>>>0<B>>>0?B:M:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,G5(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,FRe(s,d),RRe(d),C=k;return}}function kRe(s){return s=s|0,536870911}function QRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Yt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function FRe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function RRe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function W5(s){s=s|0,NRe(s)}function TRe(s){s=s|0,LRe(s+24|0)}function LRe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function NRe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,16,l,ORe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function ORe(){return 1400}function MRe(s){return s=s|0,_Re(n[(URe(s)|0)>>2]|0)|0}function URe(s){return s=s|0,(n[(qR()|0)+24>>2]|0)+(s<<3)|0}function _Re(s){return s=s|0,HRe(KD[s&7]()|0)|0}function HRe(s){return s=s|0,s|0}function qRe(){var s=0;return o[7880]|0||(zRe(10280),pr(25,10280,U|0)|0,s=7880,n[s>>2]=1,n[s+4>>2]=0),10280}function jRe(s,l){s=s|0,l=l|0,n[s>>2]=GRe()|0,n[s+4>>2]=WRe()|0,n[s+12>>2]=l,n[s+8>>2]=YRe()|0,n[s+32>>2]=4}function GRe(){return 11711}function WRe(){return 1356}function YRe(){return TD()|0}function KRe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Qp(f,896)|0)==512?c|0&&(VRe(c),yt(c)):l|0&&(C0(l),yt(l))}function VRe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Rp(s)}function zRe(s){s=s|0,Sp(s)}function JRe(s){s=s|0,XRe(s,4920),ZRe(s)|0,$Re(s)|0}function XRe(s,l){s=s|0,l=l|0;var c=0;c=p5()|0,n[s>>2]=c,CTe(c,l),Fp(n[s>>2]|0)}function ZRe(s){s=s|0;var l=0;return l=n[s>>2]|0,T0(l,uTe()|0),s|0}function $Re(s){s=s|0;var l=0;return l=n[s>>2]|0,T0(l,eTe()|0),s|0}function eTe(){var s=0;return o[7888]|0||(Y5(10328),pr(53,10328,U|0)|0,s=7888,n[s>>2]=1,n[s+4>>2]=0),Nr(10328)|0||Y5(10328),10328}function T0(s,l){s=s|0,l=l|0,yn(s,0,l,0,0,0)}function Y5(s){s=s|0,nTe(s),L0(s,10)}function tTe(s){s=s|0,rTe(s+24|0)}function rTe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function nTe(s){s=s|0;var l=0;l=zr()|0,Jr(s,5,1,l,aTe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function iTe(s,l,c){s=s|0,l=l|0,c=+c,sTe(s,l,c)}function L0(s,l){s=s|0,l=l|0,n[s+20>>2]=l}function sTe(s,l,c){s=s|0,l=l|0,c=+c;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+16|0,m=f+8|0,k=f+13|0,d=f,B=f+12|0,XA(k,l),n[m>>2]=ZA(k,l)|0,Tu(B,c),E[d>>3]=+Lu(B,c),oTe(s,m,d),C=f}function oTe(s,l,c){s=s|0,l=l|0,c=c|0,Xa(s+8|0,n[l>>2]|0,+E[c>>3]),o[s+24>>0]=1}function aTe(){return 1404}function lTe(s,l){return s=s|0,l=+l,cTe(s,l)|0}function cTe(s,l){s=s|0,l=+l;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return f=C,C=C+16|0,m=f+4|0,B=f+8|0,k=f,d=Za(8)|0,c=d,F=Yt(16)|0,XA(m,s),s=ZA(m,s)|0,Tu(B,l),Xa(F,s,+Lu(B,l)),B=c+4|0,n[B>>2]=F,s=Yt(8)|0,B=n[B>>2]|0,n[k>>2]=0,n[m>>2]=n[k>>2],SR(s,B,m),n[d>>2]=s,C=f,c|0}function uTe(){var s=0;return o[7896]|0||(K5(10364),pr(54,10364,U|0)|0,s=7896,n[s>>2]=1,n[s+4>>2]=0),Nr(10364)|0||K5(10364),10364}function K5(s){s=s|0,pTe(s),L0(s,55)}function ATe(s){s=s|0,fTe(s+24|0)}function fTe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function pTe(s){s=s|0;var l=0;l=zr()|0,Jr(s,5,4,l,mTe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function hTe(s){s=s|0,gTe(s)}function gTe(s){s=s|0,dTe(s)}function dTe(s){s=s|0,V5(s+8|0),o[s+24>>0]=1}function V5(s){s=s|0,n[s>>2]=0,E[s+8>>3]=0}function mTe(){return 1424}function yTe(){return ETe()|0}function ETe(){var s=0,l=0,c=0,f=0,d=0,m=0,B=0;return l=C,C=C+16|0,d=l+4|0,B=l,c=Za(8)|0,s=c,f=Yt(16)|0,V5(f),m=s+4|0,n[m>>2]=f,f=Yt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],SR(f,m,d),n[c>>2]=f,C=l,s|0}function CTe(s,l){s=s|0,l=l|0,n[s>>2]=ITe()|0,n[s+4>>2]=wTe()|0,n[s+12>>2]=l,n[s+8>>2]=BTe()|0,n[s+32>>2]=5}function ITe(){return 11710}function wTe(){return 1416}function BTe(){return LD()|0}function vTe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Qp(f,896)|0)==512?c|0&&(DTe(c),yt(c)):l|0&&yt(l)}function DTe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Rp(s)}function LD(){var s=0;return o[7904]|0||(n[2600]=PTe()|0,n[2601]=0,s=7904,n[s>>2]=1,n[s+4>>2]=0),10400}function PTe(){return n[357]|0}function STe(s){s=s|0,xTe(s,4926),bTe(s)|0}function xTe(s,l){s=s|0,l=l|0;var c=0;c=NG()|0,n[s>>2]=c,_Te(c,l),Fp(n[s>>2]|0)}function bTe(s){s=s|0;var l=0;return l=n[s>>2]|0,T0(l,kTe()|0),s|0}function kTe(){var s=0;return o[7912]|0||(z5(10412),pr(56,10412,U|0)|0,s=7912,n[s>>2]=1,n[s+4>>2]=0),Nr(10412)|0||z5(10412),10412}function z5(s){s=s|0,RTe(s),L0(s,57)}function QTe(s){s=s|0,FTe(s+24|0)}function FTe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function RTe(s){s=s|0;var l=0;l=zr()|0,Jr(s,5,5,l,OTe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function TTe(s){s=s|0,LTe(s)}function LTe(s){s=s|0,NTe(s)}function NTe(s){s=s|0;var l=0,c=0;l=s+8|0,c=l+48|0;do n[l>>2]=0,l=l+4|0;while((l|0)<(c|0));o[s+56>>0]=1}function OTe(){return 1432}function MTe(){return UTe()|0}function UTe(){var s=0,l=0,c=0,f=0,d=0,m=0,B=0,k=0;B=C,C=C+16|0,s=B+4|0,l=B,c=Za(8)|0,f=c,d=Yt(48)|0,m=d,k=m+48|0;do n[m>>2]=0,m=m+4|0;while((m|0)<(k|0));return m=f+4|0,n[m>>2]=d,k=Yt(8)|0,m=n[m>>2]|0,n[l>>2]=0,n[s>>2]=n[l>>2],OG(k,m,s),n[c>>2]=k,C=B,f|0}function _Te(s,l){s=s|0,l=l|0,n[s>>2]=HTe()|0,n[s+4>>2]=qTe()|0,n[s+12>>2]=l,n[s+8>>2]=jTe()|0,n[s+32>>2]=6}function HTe(){return 11704}function qTe(){return 1436}function jTe(){return LD()|0}function GTe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Qp(f,896)|0)==512?c|0&&(WTe(c),yt(c)):l|0&&yt(l)}function WTe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Rp(s)}function YTe(s){s=s|0,KTe(s,4933),VTe(s)|0,zTe(s)|0}function KTe(s,l){s=s|0,l=l|0;var c=0;c=ELe()|0,n[s>>2]=c,CLe(c,l),Fp(n[s>>2]|0)}function VTe(s){s=s|0;var l=0;return l=n[s>>2]|0,T0(l,cLe()|0),s|0}function zTe(s){s=s|0;var l=0;return l=n[s>>2]|0,T0(l,JTe()|0),s|0}function JTe(){var s=0;return o[7920]|0||(J5(10452),pr(58,10452,U|0)|0,s=7920,n[s>>2]=1,n[s+4>>2]=0),Nr(10452)|0||J5(10452),10452}function J5(s){s=s|0,$Te(s),L0(s,1)}function XTe(s){s=s|0,ZTe(s+24|0)}function ZTe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function $Te(s){s=s|0;var l=0;l=zr()|0,Jr(s,5,1,l,nLe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function eLe(s,l,c){s=s|0,l=+l,c=+c,tLe(s,l,c)}function tLe(s,l,c){s=s|0,l=+l,c=+c;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+32|0,m=f+8|0,k=f+17|0,d=f,B=f+16|0,Tu(k,l),E[m>>3]=+Lu(k,l),Tu(B,c),E[d>>3]=+Lu(B,c),rLe(s,m,d),C=f}function rLe(s,l,c){s=s|0,l=l|0,c=c|0,X5(s+8|0,+E[l>>3],+E[c>>3]),o[s+24>>0]=1}function X5(s,l,c){s=s|0,l=+l,c=+c,E[s>>3]=l,E[s+8>>3]=c}function nLe(){return 1472}function iLe(s,l){return s=+s,l=+l,sLe(s,l)|0}function sLe(s,l){s=+s,l=+l;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return f=C,C=C+16|0,B=f+4|0,k=f+8|0,F=f,d=Za(8)|0,c=d,m=Yt(16)|0,Tu(B,s),s=+Lu(B,s),Tu(k,l),X5(m,s,+Lu(k,l)),k=c+4|0,n[k>>2]=m,m=Yt(8)|0,k=n[k>>2]|0,n[F>>2]=0,n[B>>2]=n[F>>2],Z5(m,k,B),n[d>>2]=m,C=f,c|0}function Z5(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,c=Yt(16)|0,n[c+4>>2]=0,n[c+8>>2]=0,n[c>>2]=1452,n[c+12>>2]=l,n[s+4>>2]=c}function oLe(s){s=s|0,im(s),yt(s)}function aLe(s){s=s|0,s=n[s+12>>2]|0,s|0&&yt(s)}function lLe(s){s=s|0,yt(s)}function cLe(){var s=0;return o[7928]|0||($5(10488),pr(59,10488,U|0)|0,s=7928,n[s>>2]=1,n[s+4>>2]=0),Nr(10488)|0||$5(10488),10488}function $5(s){s=s|0,fLe(s),L0(s,60)}function uLe(s){s=s|0,ALe(s+24|0)}function ALe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function fLe(s){s=s|0;var l=0;l=zr()|0,Jr(s,5,6,l,dLe()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function pLe(s){s=s|0,hLe(s)}function hLe(s){s=s|0,gLe(s)}function gLe(s){s=s|0,e7(s+8|0),o[s+24>>0]=1}function e7(s){s=s|0,n[s>>2]=0,n[s+4>>2]=0,n[s+8>>2]=0,n[s+12>>2]=0}function dLe(){return 1492}function mLe(){return yLe()|0}function yLe(){var s=0,l=0,c=0,f=0,d=0,m=0,B=0;return l=C,C=C+16|0,d=l+4|0,B=l,c=Za(8)|0,s=c,f=Yt(16)|0,e7(f),m=s+4|0,n[m>>2]=f,f=Yt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],Z5(f,m,d),n[c>>2]=f,C=l,s|0}function ELe(){var s=0;return o[7936]|0||(PLe(10524),pr(25,10524,U|0)|0,s=7936,n[s>>2]=1,n[s+4>>2]=0),10524}function CLe(s,l){s=s|0,l=l|0,n[s>>2]=ILe()|0,n[s+4>>2]=wLe()|0,n[s+12>>2]=l,n[s+8>>2]=BLe()|0,n[s+32>>2]=7}function ILe(){return 11700}function wLe(){return 1484}function BLe(){return LD()|0}function vLe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Qp(f,896)|0)==512?c|0&&(DLe(c),yt(c)):l|0&&yt(l)}function DLe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Rp(s)}function PLe(s){s=s|0,Sp(s)}function SLe(s,l,c){s=s|0,l=l|0,c=c|0,s=mn(l)|0,l=xLe(c)|0,c=bLe(c,0)|0,sNe(s,l,c,jR()|0,0)}function xLe(s){return s=s|0,s|0}function bLe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=jR()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(r7(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(NLe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function jR(){var s=0,l=0;if(o[7944]|0||(t7(10568),pr(61,10568,U|0)|0,l=7944,n[l>>2]=1,n[l+4>>2]=0),!(Nr(10568)|0)){s=10568,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));t7(10568)}return 10568}function t7(s){s=s|0,FLe(s)}function kLe(s){s=s|0,QLe(s+24|0)}function QLe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function FLe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,17,l,e5()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function RLe(s){return s=s|0,LLe(n[(TLe(s)|0)>>2]|0)|0}function TLe(s){return s=s|0,(n[(jR()|0)+24>>2]|0)+(s<<3)|0}function LLe(s){return s=s|0,RD(KD[s&7]()|0)|0}function r7(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function NLe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=OLe(s)|0,f>>>0<B>>>0)Zr(s);else{F=n[s>>2]|0,O=(n[s+8>>2]|0)-F|0,M=O>>2,MLe(d,O>>3>>>0<f>>>1>>>0?M>>>0<B>>>0?B:M:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,r7(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,ULe(s,d),_Le(d),C=k;return}}function OLe(s){return s=s|0,536870911}function MLe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Yt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function ULe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function _Le(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function HLe(){qLe()}function qLe(){jLe(10604)}function jLe(s){s=s|0,GLe(s,4955)}function GLe(s,l){s=s|0,l=l|0;var c=0;c=WLe()|0,n[s>>2]=c,YLe(c,l),Fp(n[s>>2]|0)}function WLe(){var s=0;return o[7952]|0||(tNe(10612),pr(25,10612,U|0)|0,s=7952,n[s>>2]=1,n[s+4>>2]=0),10612}function YLe(s,l){s=s|0,l=l|0,n[s>>2]=JLe()|0,n[s+4>>2]=XLe()|0,n[s+12>>2]=l,n[s+8>>2]=ZLe()|0,n[s+32>>2]=8}function Fp(s){s=s|0;var l=0,c=0;l=C,C=C+16|0,c=l,$d()|0,n[c>>2]=s,KLe(10608,c),C=l}function $d(){return o[11714]|0||(n[2652]=0,pr(62,10608,U|0)|0,o[11714]=1),10608}function KLe(s,l){s=s|0,l=l|0;var c=0;c=Yt(8)|0,n[c+4>>2]=n[l>>2],n[c>>2]=n[s>>2],n[s>>2]=c}function VLe(s){s=s|0,zLe(s)}function zLe(s){s=s|0;var l=0,c=0;if(l=n[s>>2]|0,l|0)do c=l,l=n[l>>2]|0,yt(c);while(l|0);n[s>>2]=0}function JLe(){return 11715}function XLe(){return 1496}function ZLe(){return TD()|0}function $Le(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Qp(f,896)|0)==512?c|0&&(eNe(c),yt(c)):l|0&&yt(l)}function eNe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Rp(s)}function tNe(s){s=s|0,Sp(s)}function rNe(s,l){s=s|0,l=l|0;var c=0,f=0;$d()|0,c=n[2652]|0;e:do if(c|0){for(;f=n[c+4>>2]|0,!(f|0&&!(O7(GR(f)|0,s)|0));)if(c=n[c>>2]|0,!c)break e;nNe(f,l)}while(!1)}function GR(s){return s=s|0,n[s+12>>2]|0}function nNe(s,l){s=s|0,l=l|0;var c=0;s=s+36|0,c=n[s>>2]|0,c|0&&(xu(c),yt(c)),c=Yt(4)|0,PD(c,l),n[s>>2]=c}function WR(){return o[11716]|0||(n[2664]=0,pr(63,10656,U|0)|0,o[11716]=1),10656}function n7(){var s=0;return o[11717]|0?s=n[2665]|0:(iNe(),n[2665]=1504,o[11717]=1,s=1504),s|0}function iNe(){o[11740]|0||(o[11718]=dr(dr(8,0)|0,0)|0,o[11719]=dr(dr(0,0)|0,0)|0,o[11720]=dr(dr(0,16)|0,0)|0,o[11721]=dr(dr(8,0)|0,0)|0,o[11722]=dr(dr(0,0)|0,0)|0,o[11723]=dr(dr(8,0)|0,0)|0,o[11724]=dr(dr(0,0)|0,0)|0,o[11725]=dr(dr(8,0)|0,0)|0,o[11726]=dr(dr(0,0)|0,0)|0,o[11727]=dr(dr(8,0)|0,0)|0,o[11728]=dr(dr(0,0)|0,0)|0,o[11729]=dr(dr(0,0)|0,32)|0,o[11730]=dr(dr(0,0)|0,32)|0,o[11740]=1)}function i7(){return 1572}function sNe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,F=0,M=0,O=0;m=C,C=C+32|0,O=m+16|0,M=m+12|0,F=m+8|0,k=m+4|0,B=m,n[O>>2]=s,n[M>>2]=l,n[F>>2]=c,n[k>>2]=f,n[B>>2]=d,WR()|0,oNe(10656,O,M,F,k,B),C=m}function oNe(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0;B=Yt(24)|0,RG(B+4|0,n[l>>2]|0,n[c>>2]|0,n[f>>2]|0,n[d>>2]|0,n[m>>2]|0),n[B>>2]=n[s>>2],n[s>>2]=B}function s7(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0,We=0,Oe=0,Qe=0,rt=0,Xe=0,ct=0;if(ct=C,C=C+32|0,Oe=ct+20|0,Qe=ct+8|0,rt=ct+4|0,Xe=ct,l=n[l>>2]|0,l|0){We=Oe+4|0,F=Oe+8|0,M=Qe+4|0,O=Qe+8|0,j=Qe+8|0,oe=Oe+8|0;do{if(B=l+4|0,k=YR(B)|0,k|0){if(d=$I(k)|0,n[Oe>>2]=0,n[We>>2]=0,n[F>>2]=0,f=(ew(k)|0)+1|0,aNe(Oe,f),f|0)for(;f=f+-1|0,Tc(Qe,n[d>>2]|0),m=n[We>>2]|0,m>>>0<(n[oe>>2]|0)>>>0?(n[m>>2]=n[Qe>>2],n[We>>2]=(n[We>>2]|0)+4):KR(Oe,Qe),f;)d=d+4|0;f=tw(k)|0,n[Qe>>2]=0,n[M>>2]=0,n[O>>2]=0;e:do if(n[f>>2]|0)for(d=0,m=0;;){if((d|0)==(m|0)?lNe(Qe,f):(n[d>>2]=n[f>>2],n[M>>2]=(n[M>>2]|0)+4),f=f+4|0,!(n[f>>2]|0))break e;d=n[M>>2]|0,m=n[j>>2]|0}while(!1);n[rt>>2]=ND(B)|0,n[Xe>>2]=Nr(k)|0,cNe(c,s,rt,Xe,Oe,Qe),VR(Qe),$A(Oe)}l=n[l>>2]|0}while(l|0)}C=ct}function YR(s){return s=s|0,n[s+12>>2]|0}function $I(s){return s=s|0,n[s+12>>2]|0}function ew(s){return s=s|0,n[s+16>>2]|0}function aNe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;d=C,C=C+32|0,c=d,f=n[s>>2]|0,(n[s+8>>2]|0)-f>>2>>>0<l>>>0&&(p7(c,l,(n[s+4>>2]|0)-f>>2,s+8|0),h7(s,c),g7(c)),C=d}function KR(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0;if(B=C,C=C+32|0,c=B,f=s+4|0,d=((n[f>>2]|0)-(n[s>>2]|0)>>2)+1|0,m=f7(s)|0,m>>>0<d>>>0)Zr(s);else{k=n[s>>2]|0,M=(n[s+8>>2]|0)-k|0,F=M>>1,p7(c,M>>2>>>0<m>>>1>>>0?F>>>0<d>>>0?d:F:m,(n[f>>2]|0)-k>>2,s+8|0),m=c+8|0,n[n[m>>2]>>2]=n[l>>2],n[m>>2]=(n[m>>2]|0)+4,h7(s,c),g7(c),C=B;return}}function tw(s){return s=s|0,n[s+8>>2]|0}function lNe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0;if(B=C,C=C+32|0,c=B,f=s+4|0,d=((n[f>>2]|0)-(n[s>>2]|0)>>2)+1|0,m=A7(s)|0,m>>>0<d>>>0)Zr(s);else{k=n[s>>2]|0,M=(n[s+8>>2]|0)-k|0,F=M>>1,xNe(c,M>>2>>>0<m>>>1>>>0?F>>>0<d>>>0?d:F:m,(n[f>>2]|0)-k>>2,s+8|0),m=c+8|0,n[n[m>>2]>>2]=n[l>>2],n[m>>2]=(n[m>>2]|0)+4,bNe(s,c),kNe(c),C=B;return}}function ND(s){return s=s|0,n[s>>2]|0}function cNe(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,uNe(s,l,c,f,d,m)}function VR(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-4-f|0)>>>2)<<2)),yt(c))}function $A(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-4-f|0)>>>2)<<2)),yt(c))}function uNe(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0,F=0,M=0,O=0,j=0;B=C,C=C+48|0,O=B+40|0,k=B+32|0,j=B+24|0,F=B+12|0,M=B,$a(k),s=ys(s)|0,n[j>>2]=n[l>>2],c=n[c>>2]|0,f=n[f>>2]|0,zR(F,d),ANe(M,m),n[O>>2]=n[j>>2],fNe(s,O,c,f,F,M),VR(M),$A(F),el(k),C=B}function zR(s,l){s=s|0,l=l|0;var c=0,f=0;n[s>>2]=0,n[s+4>>2]=0,n[s+8>>2]=0,c=l+4|0,f=(n[c>>2]|0)-(n[l>>2]|0)>>2,f|0&&(PNe(s,f),SNe(s,n[l>>2]|0,n[c>>2]|0,f))}function ANe(s,l){s=s|0,l=l|0;var c=0,f=0;n[s>>2]=0,n[s+4>>2]=0,n[s+8>>2]=0,c=l+4|0,f=(n[c>>2]|0)-(n[l>>2]|0)>>2,f|0&&(vNe(s,f),DNe(s,n[l>>2]|0,n[c>>2]|0,f))}function fNe(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0,F=0,M=0,O=0,j=0;B=C,C=C+32|0,O=B+28|0,j=B+24|0,k=B+12|0,F=B,M=jo(pNe()|0)|0,n[j>>2]=n[l>>2],n[O>>2]=n[j>>2],l=N0(O)|0,c=o7(c)|0,f=JR(f)|0,n[k>>2]=n[d>>2],O=d+4|0,n[k+4>>2]=n[O>>2],j=d+8|0,n[k+8>>2]=n[j>>2],n[j>>2]=0,n[O>>2]=0,n[d>>2]=0,d=XR(k)|0,n[F>>2]=n[m>>2],O=m+4|0,n[F+4>>2]=n[O>>2],j=m+8|0,n[F+8>>2]=n[j>>2],n[j>>2]=0,n[O>>2]=0,n[m>>2]=0,gc(0,M|0,s|0,l|0,c|0,f|0,d|0,hNe(F)|0)|0,VR(F),$A(k),C=B}function pNe(){var s=0;return o[7968]|0||(wNe(10708),s=7968,n[s>>2]=1,n[s+4>>2]=0),10708}function N0(s){return s=s|0,l7(s)|0}function o7(s){return s=s|0,a7(s)|0}function JR(s){return s=s|0,RD(s)|0}function XR(s){return s=s|0,dNe(s)|0}function hNe(s){return s=s|0,gNe(s)|0}function gNe(s){s=s|0;var l=0,c=0,f=0;if(f=(n[s+4>>2]|0)-(n[s>>2]|0)|0,c=f>>2,f=Za(f+4|0)|0,n[f>>2]=c,c|0){l=0;do n[f+4+(l<<2)>>2]=a7(n[(n[s>>2]|0)+(l<<2)>>2]|0)|0,l=l+1|0;while((l|0)!=(c|0))}return f|0}function a7(s){return s=s|0,s|0}function dNe(s){s=s|0;var l=0,c=0,f=0;if(f=(n[s+4>>2]|0)-(n[s>>2]|0)|0,c=f>>2,f=Za(f+4|0)|0,n[f>>2]=c,c|0){l=0;do n[f+4+(l<<2)>>2]=l7((n[s>>2]|0)+(l<<2)|0)|0,l=l+1|0;while((l|0)!=(c|0))}return f|0}function l7(s){s=s|0;var l=0,c=0,f=0,d=0;return d=C,C=C+32|0,l=d+12|0,c=d,f=cR(c7()|0)|0,f?(uR(l,f),AR(c,l),Z4e(s,c),s=fR(l)|0):s=mNe(s)|0,C=d,s|0}function c7(){var s=0;return o[7960]|0||(INe(10664),pr(25,10664,U|0)|0,s=7960,n[s>>2]=1,n[s+4>>2]=0),10664}function mNe(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0;return c=C,C=C+16|0,d=c+4|0,B=c,f=Za(8)|0,l=f,k=Yt(4)|0,n[k>>2]=n[s>>2],m=l+4|0,n[m>>2]=k,s=Yt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],u7(s,m,d),n[f>>2]=s,C=c,l|0}function u7(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,c=Yt(16)|0,n[c+4>>2]=0,n[c+8>>2]=0,n[c>>2]=1656,n[c+12>>2]=l,n[s+4>>2]=c}function yNe(s){s=s|0,im(s),yt(s)}function ENe(s){s=s|0,s=n[s+12>>2]|0,s|0&&yt(s)}function CNe(s){s=s|0,yt(s)}function INe(s){s=s|0,Sp(s)}function wNe(s){s=s|0,ao(s,BNe()|0,5)}function BNe(){return 1676}function vNe(s,l){s=s|0,l=l|0;var c=0;if((A7(s)|0)>>>0<l>>>0&&Zr(s),l>>>0>1073741823)Tt();else{c=Yt(l<<2)|0,n[s+4>>2]=c,n[s>>2]=c,n[s+8>>2]=c+(l<<2);return}}function DNe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,f=s+4|0,s=c-l|0,(s|0)>0&&(br(n[f>>2]|0,l|0,s|0)|0,n[f>>2]=(n[f>>2]|0)+(s>>>2<<2))}function A7(s){return s=s|0,1073741823}function PNe(s,l){s=s|0,l=l|0;var c=0;if((f7(s)|0)>>>0<l>>>0&&Zr(s),l>>>0>1073741823)Tt();else{c=Yt(l<<2)|0,n[s+4>>2]=c,n[s>>2]=c,n[s+8>>2]=c+(l<<2);return}}function SNe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,f=s+4|0,s=c-l|0,(s|0)>0&&(br(n[f>>2]|0,l|0,s|0)|0,n[f>>2]=(n[f>>2]|0)+(s>>>2<<2))}function f7(s){return s=s|0,1073741823}function xNe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>1073741823)Tt();else{d=Yt(l<<2)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<2)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<2)}function bNe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>2)<<2)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function kNe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-4-l|0)>>>2)<<2)),s=n[s>>2]|0,s|0&&yt(s)}function p7(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>1073741823)Tt();else{d=Yt(l<<2)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<2)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<2)}function h7(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>2)<<2)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function g7(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-4-l|0)>>>2)<<2)),s=n[s>>2]|0,s|0&&yt(s)}function QNe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0,We=0,Oe=0,Qe=0;if(Qe=C,C=C+32|0,O=Qe+20|0,j=Qe+12|0,M=Qe+16|0,oe=Qe+4|0,We=Qe,Oe=Qe+8|0,k=n7()|0,m=n[k>>2]|0,B=n[m>>2]|0,B|0)for(F=n[k+8>>2]|0,k=n[k+4>>2]|0;Tc(O,B),FNe(s,O,k,F),m=m+4|0,B=n[m>>2]|0,B;)F=F+1|0,k=k+1|0;if(m=i7()|0,B=n[m>>2]|0,B|0)do Tc(O,B),n[j>>2]=n[m+4>>2],RNe(l,O,j),m=m+8|0,B=n[m>>2]|0;while(B|0);if(m=n[($d()|0)>>2]|0,m|0)do l=n[m+4>>2]|0,Tc(O,n[(em(l)|0)>>2]|0),n[j>>2]=GR(l)|0,TNe(c,O,j),m=n[m>>2]|0;while(m|0);if(Tc(M,0),m=WR()|0,n[O>>2]=n[M>>2],s7(O,m,d),m=n[($d()|0)>>2]|0,m|0){s=O+4|0,l=O+8|0,c=O+8|0;do{if(F=n[m+4>>2]|0,Tc(j,n[(em(F)|0)>>2]|0),LNe(oe,d7(F)|0),B=n[oe>>2]|0,B|0){n[O>>2]=0,n[s>>2]=0,n[l>>2]=0;do Tc(We,n[(em(n[B+4>>2]|0)|0)>>2]|0),k=n[s>>2]|0,k>>>0<(n[c>>2]|0)>>>0?(n[k>>2]=n[We>>2],n[s>>2]=(n[s>>2]|0)+4):KR(O,We),B=n[B>>2]|0;while(B|0);NNe(f,j,O),$A(O)}n[Oe>>2]=n[j>>2],M=m7(F)|0,n[O>>2]=n[Oe>>2],s7(O,M,d),UG(oe),m=n[m>>2]|0}while(m|0)}C=Qe}function FNe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,VNe(s,l,c,f)}function RNe(s,l,c){s=s|0,l=l|0,c=c|0,KNe(s,l,c)}function em(s){return s=s|0,s|0}function TNe(s,l,c){s=s|0,l=l|0,c=c|0,jNe(s,l,c)}function d7(s){return s=s|0,s+16|0}function LNe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;if(m=C,C=C+16|0,d=m+8|0,c=m,n[s>>2]=0,f=n[l>>2]|0,n[d>>2]=f,n[c>>2]=s,c=qNe(c)|0,f|0){if(f=Yt(12)|0,B=(y7(d)|0)+4|0,s=n[B+4>>2]|0,l=f+4|0,n[l>>2]=n[B>>2],n[l+4>>2]=s,l=n[n[d>>2]>>2]|0,n[d>>2]=l,!l)s=f;else for(l=f;s=Yt(12)|0,F=(y7(d)|0)+4|0,k=n[F+4>>2]|0,B=s+4|0,n[B>>2]=n[F>>2],n[B+4>>2]=k,n[l>>2]=s,B=n[n[d>>2]>>2]|0,n[d>>2]=B,B;)l=s;n[s>>2]=n[c>>2],n[c>>2]=f}C=m}function NNe(s,l,c){s=s|0,l=l|0,c=c|0,ONe(s,l,c)}function m7(s){return s=s|0,s+24|0}function ONe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+32|0,B=f+24|0,d=f+16|0,k=f+12|0,m=f,$a(d),s=ys(s)|0,n[k>>2]=n[l>>2],zR(m,c),n[B>>2]=n[k>>2],MNe(s,B,m),$A(m),el(d),C=f}function MNe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=C,C=C+32|0,B=f+16|0,k=f+12|0,d=f,m=jo(UNe()|0)|0,n[k>>2]=n[l>>2],n[B>>2]=n[k>>2],l=N0(B)|0,n[d>>2]=n[c>>2],B=c+4|0,n[d+4>>2]=n[B>>2],k=c+8|0,n[d+8>>2]=n[k>>2],n[k>>2]=0,n[B>>2]=0,n[c>>2]=0,hs(0,m|0,s|0,l|0,XR(d)|0)|0,$A(d),C=f}function UNe(){var s=0;return o[7976]|0||(_Ne(10720),s=7976,n[s>>2]=1,n[s+4>>2]=0),10720}function _Ne(s){s=s|0,ao(s,HNe()|0,2)}function HNe(){return 1732}function qNe(s){return s=s|0,n[s>>2]|0}function y7(s){return s=s|0,n[s>>2]|0}function jNe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+32|0,m=f+16|0,d=f+8|0,B=f,$a(d),s=ys(s)|0,n[B>>2]=n[l>>2],c=n[c>>2]|0,n[m>>2]=n[B>>2],E7(s,m,c),el(d),C=f}function E7(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+16|0,m=f+4|0,B=f,d=jo(GNe()|0)|0,n[B>>2]=n[l>>2],n[m>>2]=n[B>>2],l=N0(m)|0,hs(0,d|0,s|0,l|0,o7(c)|0)|0,C=f}function GNe(){var s=0;return o[7984]|0||(WNe(10732),s=7984,n[s>>2]=1,n[s+4>>2]=0),10732}function WNe(s){s=s|0,ao(s,YNe()|0,2)}function YNe(){return 1744}function KNe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;f=C,C=C+32|0,m=f+16|0,d=f+8|0,B=f,$a(d),s=ys(s)|0,n[B>>2]=n[l>>2],c=n[c>>2]|0,n[m>>2]=n[B>>2],E7(s,m,c),el(d),C=f}function VNe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+32|0,B=d+16|0,m=d+8|0,k=d,$a(m),s=ys(s)|0,n[k>>2]=n[l>>2],c=o[c>>0]|0,f=o[f>>0]|0,n[B>>2]=n[k>>2],zNe(s,B,c,f),el(m),C=d}function zNe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+16|0,B=d+4|0,k=d,m=jo(JNe()|0)|0,n[k>>2]=n[l>>2],n[B>>2]=n[k>>2],l=N0(B)|0,c=tm(c)|0,vi(0,m|0,s|0,l|0,c|0,tm(f)|0)|0,C=d}function JNe(){var s=0;return o[7992]|0||(ZNe(10744),s=7992,n[s>>2]=1,n[s+4>>2]=0),10744}function tm(s){return s=s|0,XNe(s)|0}function XNe(s){return s=s|0,s&255|0}function ZNe(s){s=s|0,ao(s,$Ne()|0,3)}function $Ne(){return 1756}function eOe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;switch(oe=C,C=C+32|0,k=oe+8|0,F=oe+4|0,M=oe+20|0,O=oe,dR(s,0),f=X4e(l)|0,n[k>>2]=0,j=k+4|0,n[j>>2]=0,n[k+8>>2]=0,f<<24>>24){case 0:{o[M>>0]=0,tOe(F,c,M),OD(s,F)|0,bu(F);break}case 8:{j=nT(l)|0,o[M>>0]=8,Tc(O,n[j+4>>2]|0),rOe(F,c,M,O,j+8|0),OD(s,F)|0,bu(F);break}case 9:{if(m=nT(l)|0,l=n[m+4>>2]|0,l|0)for(B=k+8|0,d=m+12|0;l=l+-1|0,Tc(F,n[d>>2]|0),f=n[j>>2]|0,f>>>0<(n[B>>2]|0)>>>0?(n[f>>2]=n[F>>2],n[j>>2]=(n[j>>2]|0)+4):KR(k,F),l;)d=d+4|0;o[M>>0]=9,Tc(O,n[m+8>>2]|0),nOe(F,c,M,O,k),OD(s,F)|0,bu(F);break}default:j=nT(l)|0,o[M>>0]=f,Tc(O,n[j+4>>2]|0),iOe(F,c,M,O),OD(s,F)|0,bu(F)}$A(k),C=oe}function tOe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;f=C,C=C+16|0,d=f,$a(d),l=ys(l)|0,mOe(s,l,o[c>>0]|0),el(d),C=f}function OD(s,l){s=s|0,l=l|0;var c=0;return c=n[s>>2]|0,c|0&&sa(c|0),n[s>>2]=n[l>>2],n[l>>2]=0,s|0}function rOe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,F=0;m=C,C=C+32|0,k=m+16|0,B=m+8|0,F=m,$a(B),l=ys(l)|0,c=o[c>>0]|0,n[F>>2]=n[f>>2],d=n[d>>2]|0,n[k>>2]=n[F>>2],pOe(s,l,c,k,d),el(B),C=m}function nOe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,F=0,M=0;m=C,C=C+32|0,F=m+24|0,B=m+16|0,M=m+12|0,k=m,$a(B),l=ys(l)|0,c=o[c>>0]|0,n[M>>2]=n[f>>2],zR(k,d),n[F>>2]=n[M>>2],cOe(s,l,c,F,k),$A(k),el(B),C=m}function iOe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+32|0,B=d+16|0,m=d+8|0,k=d,$a(m),l=ys(l)|0,c=o[c>>0]|0,n[k>>2]=n[f>>2],n[B>>2]=n[k>>2],sOe(s,l,c,B),el(m),C=d}function sOe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0,B=0,k=0;d=C,C=C+16|0,m=d+4|0,k=d,B=jo(oOe()|0)|0,c=tm(c)|0,n[k>>2]=n[f>>2],n[m>>2]=n[k>>2],MD(s,hs(0,B|0,l|0,c|0,N0(m)|0)|0),C=d}function oOe(){var s=0;return o[8e3]|0||(aOe(10756),s=8e3,n[s>>2]=1,n[s+4>>2]=0),10756}function MD(s,l){s=s|0,l=l|0,dR(s,l)}function aOe(s){s=s|0,ao(s,lOe()|0,2)}function lOe(){return 1772}function cOe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,F=0,M=0;m=C,C=C+32|0,F=m+16|0,M=m+12|0,B=m,k=jo(uOe()|0)|0,c=tm(c)|0,n[M>>2]=n[f>>2],n[F>>2]=n[M>>2],f=N0(F)|0,n[B>>2]=n[d>>2],F=d+4|0,n[B+4>>2]=n[F>>2],M=d+8|0,n[B+8>>2]=n[M>>2],n[M>>2]=0,n[F>>2]=0,n[d>>2]=0,MD(s,vi(0,k|0,l|0,c|0,f|0,XR(B)|0)|0),$A(B),C=m}function uOe(){var s=0;return o[8008]|0||(AOe(10768),s=8008,n[s>>2]=1,n[s+4>>2]=0),10768}function AOe(s){s=s|0,ao(s,fOe()|0,3)}function fOe(){return 1784}function pOe(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,F=0;m=C,C=C+16|0,k=m+4|0,F=m,B=jo(hOe()|0)|0,c=tm(c)|0,n[F>>2]=n[f>>2],n[k>>2]=n[F>>2],f=N0(k)|0,MD(s,vi(0,B|0,l|0,c|0,f|0,JR(d)|0)|0),C=m}function hOe(){var s=0;return o[8016]|0||(gOe(10780),s=8016,n[s>>2]=1,n[s+4>>2]=0),10780}function gOe(s){s=s|0,ao(s,dOe()|0,3)}function dOe(){return 1800}function mOe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;f=jo(yOe()|0)|0,MD(s,un(0,f|0,l|0,tm(c)|0)|0)}function yOe(){var s=0;return o[8024]|0||(EOe(10792),s=8024,n[s>>2]=1,n[s+4>>2]=0),10792}function EOe(s){s=s|0,ao(s,COe()|0,1)}function COe(){return 1816}function IOe(){wOe(),BOe(),vOe()}function wOe(){n[2702]=K7(65536)|0}function BOe(){GOe(10856)}function vOe(){DOe(10816)}function DOe(s){s=s|0,POe(s,5044),SOe(s)|0}function POe(s,l){s=s|0,l=l|0;var c=0;c=c7()|0,n[s>>2]=c,MOe(c,l),Fp(n[s>>2]|0)}function SOe(s){s=s|0;var l=0;return l=n[s>>2]|0,T0(l,xOe()|0),s|0}function xOe(){var s=0;return o[8032]|0||(C7(10820),pr(64,10820,U|0)|0,s=8032,n[s>>2]=1,n[s+4>>2]=0),Nr(10820)|0||C7(10820),10820}function C7(s){s=s|0,QOe(s),L0(s,25)}function bOe(s){s=s|0,kOe(s+24|0)}function kOe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function QOe(s){s=s|0;var l=0;l=zr()|0,Jr(s,5,18,l,LOe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function FOe(s,l){s=s|0,l=l|0,ROe(s,l)}function ROe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;c=C,C=C+16|0,f=c,d=c+4|0,F0(d,l),n[f>>2]=R0(d,l)|0,TOe(s,f),C=c}function TOe(s,l){s=s|0,l=l|0,I7(s+4|0,n[l>>2]|0),o[s+8>>0]=1}function I7(s,l){s=s|0,l=l|0,n[s>>2]=l}function LOe(){return 1824}function NOe(s){return s=s|0,OOe(s)|0}function OOe(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0;return c=C,C=C+16|0,d=c+4|0,B=c,f=Za(8)|0,l=f,k=Yt(4)|0,F0(d,s),I7(k,R0(d,s)|0),m=l+4|0,n[m>>2]=k,s=Yt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],u7(s,m,d),n[f>>2]=s,C=c,l|0}function Za(s){s=s|0;var l=0,c=0;return s=s+7&-8,s>>>0<=32768&&(l=n[2701]|0,s>>>0<=(65536-l|0)>>>0)?(c=(n[2702]|0)+l|0,n[2701]=l+s,s=c):(s=K7(s+8|0)|0,n[s>>2]=n[2703],n[2703]=s,s=s+8|0),s|0}function MOe(s,l){s=s|0,l=l|0,n[s>>2]=UOe()|0,n[s+4>>2]=_Oe()|0,n[s+12>>2]=l,n[s+8>>2]=HOe()|0,n[s+32>>2]=9}function UOe(){return 11744}function _Oe(){return 1832}function HOe(){return LD()|0}function qOe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Qp(f,896)|0)==512?c|0&&(jOe(c),yt(c)):l|0&&yt(l)}function jOe(s){s=s|0,s=n[s+4>>2]|0,s|0&&Rp(s)}function GOe(s){s=s|0,WOe(s,5052),YOe(s)|0,KOe(s,5058,26)|0,VOe(s,5069,1)|0,zOe(s,5077,10)|0,JOe(s,5087,19)|0,XOe(s,5094,27)|0}function WOe(s,l){s=s|0,l=l|0;var c=0;c=j4e()|0,n[s>>2]=c,G4e(c,l),Fp(n[s>>2]|0)}function YOe(s){s=s|0;var l=0;return l=n[s>>2]|0,T0(l,b4e()|0),s|0}function KOe(s,l,c){return s=s|0,l=l|0,c=c|0,A4e(s,mn(l)|0,c,0),s|0}function VOe(s,l,c){return s=s|0,l=l|0,c=c|0,JMe(s,mn(l)|0,c,0),s|0}function zOe(s,l,c){return s=s|0,l=l|0,c=c|0,xMe(s,mn(l)|0,c,0),s|0}function JOe(s,l,c){return s=s|0,l=l|0,c=c|0,pMe(s,mn(l)|0,c,0),s|0}function w7(s,l){s=s|0,l=l|0;var c=0,f=0;e:for(;;){for(c=n[2703]|0;;){if((c|0)==(l|0))break e;if(f=n[c>>2]|0,n[2703]=f,!c)c=f;else break}yt(c)}n[2701]=s}function XOe(s,l,c){return s=s|0,l=l|0,c=c|0,ZOe(s,mn(l)|0,c,0),s|0}function ZOe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=ZR()|0,s=$Oe(c)|0,yn(m,l,d,s,eMe(c,f)|0,f)}function ZR(){var s=0,l=0;if(o[8040]|0||(v7(10860),pr(65,10860,U|0)|0,l=8040,n[l>>2]=1,n[l+4>>2]=0),!(Nr(10860)|0)){s=10860,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));v7(10860)}return 10860}function $Oe(s){return s=s|0,s|0}function eMe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=ZR()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(B7(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(tMe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function B7(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function tMe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=rMe(s)|0,f>>>0<B>>>0)Zr(s);else{F=n[s>>2]|0,O=(n[s+8>>2]|0)-F|0,M=O>>2,nMe(d,O>>3>>>0<f>>>1>>>0?M>>>0<B>>>0?B:M:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,B7(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,iMe(s,d),sMe(d),C=k;return}}function rMe(s){return s=s|0,536870911}function nMe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Yt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function iMe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function sMe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function v7(s){s=s|0,lMe(s)}function oMe(s){s=s|0,aMe(s+24|0)}function aMe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function lMe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,11,l,cMe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function cMe(){return 1840}function uMe(s,l,c){s=s|0,l=l|0,c=c|0,fMe(n[(AMe(s)|0)>>2]|0,l,c)}function AMe(s){return s=s|0,(n[(ZR()|0)+24>>2]|0)+(s<<3)|0}function fMe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;f=C,C=C+16|0,m=f+1|0,d=f,F0(m,l),l=R0(m,l)|0,F0(d,c),c=R0(d,c)|0,tf[s&31](l,c),C=f}function pMe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=$R()|0,s=hMe(c)|0,yn(m,l,d,s,gMe(c,f)|0,f)}function $R(){var s=0,l=0;if(o[8048]|0||(P7(10896),pr(66,10896,U|0)|0,l=8048,n[l>>2]=1,n[l+4>>2]=0),!(Nr(10896)|0)){s=10896,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));P7(10896)}return 10896}function hMe(s){return s=s|0,s|0}function gMe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=$R()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(D7(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(dMe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function D7(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function dMe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=mMe(s)|0,f>>>0<B>>>0)Zr(s);else{F=n[s>>2]|0,O=(n[s+8>>2]|0)-F|0,M=O>>2,yMe(d,O>>3>>>0<f>>>1>>>0?M>>>0<B>>>0?B:M:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,D7(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,EMe(s,d),CMe(d),C=k;return}}function mMe(s){return s=s|0,536870911}function yMe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Yt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function EMe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function CMe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function P7(s){s=s|0,BMe(s)}function IMe(s){s=s|0,wMe(s+24|0)}function wMe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function BMe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,11,l,vMe()|0,1),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function vMe(){return 1852}function DMe(s,l){return s=s|0,l=l|0,SMe(n[(PMe(s)|0)>>2]|0,l)|0}function PMe(s){return s=s|0,(n[($R()|0)+24>>2]|0)+(s<<3)|0}function SMe(s,l){s=s|0,l=l|0;var c=0,f=0;return c=C,C=C+16|0,f=c,F0(f,l),l=R0(f,l)|0,l=RD(_0[s&31](l)|0)|0,C=c,l|0}function xMe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=eT()|0,s=bMe(c)|0,yn(m,l,d,s,kMe(c,f)|0,f)}function eT(){var s=0,l=0;if(o[8056]|0||(x7(10932),pr(67,10932,U|0)|0,l=8056,n[l>>2]=1,n[l+4>>2]=0),!(Nr(10932)|0)){s=10932,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));x7(10932)}return 10932}function bMe(s){return s=s|0,s|0}function kMe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=eT()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(S7(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(QMe(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function S7(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function QMe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=FMe(s)|0,f>>>0<B>>>0)Zr(s);else{F=n[s>>2]|0,O=(n[s+8>>2]|0)-F|0,M=O>>2,RMe(d,O>>3>>>0<f>>>1>>>0?M>>>0<B>>>0?B:M:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,S7(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,TMe(s,d),LMe(d),C=k;return}}function FMe(s){return s=s|0,536870911}function RMe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Yt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function TMe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function LMe(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function x7(s){s=s|0,MMe(s)}function NMe(s){s=s|0,OMe(s+24|0)}function OMe(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function MMe(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,7,l,UMe()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function UMe(){return 1860}function _Me(s,l,c){return s=s|0,l=l|0,c=c|0,qMe(n[(HMe(s)|0)>>2]|0,l,c)|0}function HMe(s){return s=s|0,(n[(eT()|0)+24>>2]|0)+(s<<3)|0}function qMe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0;return f=C,C=C+32|0,B=f+12|0,m=f+8|0,k=f,F=f+16|0,d=f+4|0,jMe(F,l),GMe(k,F,l),xp(d,c),c=bp(d,c)|0,n[B>>2]=n[k>>2],sw[s&15](m,B,c),c=WMe(m)|0,bu(m),kp(d),C=f,c|0}function jMe(s,l){s=s|0,l=l|0}function GMe(s,l,c){s=s|0,l=l|0,c=c|0,YMe(s,c)}function WMe(s){return s=s|0,ys(s)|0}function YMe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0;d=C,C=C+16|0,c=d,f=l,f&1?(KMe(c,0),ia(f|0,c|0)|0,VMe(s,c),zMe(c)):n[s>>2]=n[l>>2],C=d}function KMe(s,l){s=s|0,l=l|0,Fc(s,l),n[s+4>>2]=0,o[s+8>>0]=0}function VMe(s,l){s=s|0,l=l|0,n[s>>2]=n[l+4>>2]}function zMe(s){s=s|0,o[s+8>>0]=0}function JMe(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=tT()|0,s=XMe(c)|0,yn(m,l,d,s,ZMe(c,f)|0,f)}function tT(){var s=0,l=0;if(o[8064]|0||(k7(10968),pr(68,10968,U|0)|0,l=8064,n[l>>2]=1,n[l+4>>2]=0),!(Nr(10968)|0)){s=10968,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));k7(10968)}return 10968}function XMe(s){return s=s|0,s|0}function ZMe(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=tT()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(b7(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):($Me(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function b7(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function $Me(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=e4e(s)|0,f>>>0<B>>>0)Zr(s);else{F=n[s>>2]|0,O=(n[s+8>>2]|0)-F|0,M=O>>2,t4e(d,O>>3>>>0<f>>>1>>>0?M>>>0<B>>>0?B:M:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,b7(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,r4e(s,d),n4e(d),C=k;return}}function e4e(s){return s=s|0,536870911}function t4e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Yt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function r4e(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function n4e(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function k7(s){s=s|0,o4e(s)}function i4e(s){s=s|0,s4e(s+24|0)}function s4e(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function o4e(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,1,l,a4e()|0,5),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function a4e(){return 1872}function l4e(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,u4e(n[(c4e(s)|0)>>2]|0,l,c,f,d,m)}function c4e(s){return s=s|0,(n[(tT()|0)+24>>2]|0)+(s<<3)|0}function u4e(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0,F=0,M=0,O=0,j=0;B=C,C=C+32|0,k=B+16|0,F=B+12|0,M=B+8|0,O=B+4|0,j=B,xp(k,l),l=bp(k,l)|0,xp(F,c),c=bp(F,c)|0,xp(M,f),f=bp(M,f)|0,xp(O,d),d=bp(O,d)|0,xp(j,m),m=bp(j,m)|0,Z7[s&1](l,c,f,d,m),kp(j),kp(O),kp(M),kp(F),kp(k),C=B}function A4e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;m=n[s>>2]|0,d=rT()|0,s=f4e(c)|0,yn(m,l,d,s,p4e(c,f)|0,f)}function rT(){var s=0,l=0;if(o[8072]|0||(F7(11004),pr(69,11004,U|0)|0,l=8072,n[l>>2]=1,n[l+4>>2]=0),!(Nr(11004)|0)){s=11004,l=s+36|0;do n[s>>2]=0,s=s+4|0;while((s|0)<(l|0));F7(11004)}return 11004}function f4e(s){return s=s|0,s|0}function p4e(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0,k=0,F=0;return k=C,C=C+16|0,d=k,m=k+4|0,n[d>>2]=s,F=rT()|0,B=F+24|0,l=dr(l,4)|0,n[m>>2]=l,c=F+28|0,f=n[c>>2]|0,f>>>0<(n[F+32>>2]|0)>>>0?(Q7(f,s,l),l=(n[c>>2]|0)+8|0,n[c>>2]=l):(h4e(B,d,m),l=n[c>>2]|0),C=k,(l-(n[B>>2]|0)>>3)+-1|0}function Q7(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,n[s+4>>2]=c}function h4e(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0;if(k=C,C=C+32|0,d=k,m=s+4|0,B=((n[m>>2]|0)-(n[s>>2]|0)>>3)+1|0,f=g4e(s)|0,f>>>0<B>>>0)Zr(s);else{F=n[s>>2]|0,O=(n[s+8>>2]|0)-F|0,M=O>>2,d4e(d,O>>3>>>0<f>>>1>>>0?M>>>0<B>>>0?B:M:f,(n[m>>2]|0)-F>>3,s+8|0),B=d+8|0,Q7(n[B>>2]|0,n[l>>2]|0,n[c>>2]|0),n[B>>2]=(n[B>>2]|0)+8,m4e(s,d),y4e(d),C=k;return}}function g4e(s){return s=s|0,536870911}function d4e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0;n[s+12>>2]=0,n[s+16>>2]=f;do if(l)if(l>>>0>536870911)Tt();else{d=Yt(l<<3)|0;break}else d=0;while(!1);n[s>>2]=d,f=d+(c<<3)|0,n[s+8>>2]=f,n[s+4>>2]=f,n[s+12>>2]=d+(l<<3)}function m4e(s,l){s=s|0,l=l|0;var c=0,f=0,d=0,m=0,B=0;f=n[s>>2]|0,B=s+4|0,m=l+4|0,d=(n[B>>2]|0)-f|0,c=(n[m>>2]|0)+(0-(d>>3)<<3)|0,n[m>>2]=c,(d|0)>0?(br(c|0,f|0,d|0)|0,f=m,c=n[m>>2]|0):f=m,m=n[s>>2]|0,n[s>>2]=c,n[f>>2]=m,m=l+8|0,d=n[B>>2]|0,n[B>>2]=n[m>>2],n[m>>2]=d,m=s+8|0,B=l+12|0,s=n[m>>2]|0,n[m>>2]=n[B>>2],n[B>>2]=s,n[l>>2]=n[f>>2]}function y4e(s){s=s|0;var l=0,c=0,f=0;l=n[s+4>>2]|0,c=s+8|0,f=n[c>>2]|0,(f|0)!=(l|0)&&(n[c>>2]=f+(~((f+-8-l|0)>>>3)<<3)),s=n[s>>2]|0,s|0&&yt(s)}function F7(s){s=s|0,I4e(s)}function E4e(s){s=s|0,C4e(s+24|0)}function C4e(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function I4e(s){s=s|0;var l=0;l=zr()|0,Jr(s,1,12,l,w4e()|0,2),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function w4e(){return 1896}function B4e(s,l,c){s=s|0,l=l|0,c=c|0,D4e(n[(v4e(s)|0)>>2]|0,l,c)}function v4e(s){return s=s|0,(n[(rT()|0)+24>>2]|0)+(s<<3)|0}function D4e(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;f=C,C=C+16|0,m=f+4|0,d=f,P4e(m,l),l=S4e(m,l)|0,xp(d,c),c=bp(d,c)|0,tf[s&31](l,c),kp(d),C=f}function P4e(s,l){s=s|0,l=l|0}function S4e(s,l){return s=s|0,l=l|0,x4e(l)|0}function x4e(s){return s=s|0,s|0}function b4e(){var s=0;return o[8080]|0||(R7(11040),pr(70,11040,U|0)|0,s=8080,n[s>>2]=1,n[s+4>>2]=0),Nr(11040)|0||R7(11040),11040}function R7(s){s=s|0,F4e(s),L0(s,71)}function k4e(s){s=s|0,Q4e(s+24|0)}function Q4e(s){s=s|0;var l=0,c=0,f=0;c=n[s>>2]|0,f=c,c|0&&(s=s+4|0,l=n[s>>2]|0,(l|0)!=(c|0)&&(n[s>>2]=l+(~((l+-8-f|0)>>>3)<<3)),yt(c))}function F4e(s){s=s|0;var l=0;l=zr()|0,Jr(s,5,7,l,N4e()|0,0),n[s+24>>2]=0,n[s+28>>2]=0,n[s+32>>2]=0}function R4e(s){s=s|0,T4e(s)}function T4e(s){s=s|0,L4e(s)}function L4e(s){s=s|0,o[s+8>>0]=1}function N4e(){return 1936}function O4e(){return M4e()|0}function M4e(){var s=0,l=0,c=0,f=0,d=0,m=0,B=0;return l=C,C=C+16|0,d=l+4|0,B=l,c=Za(8)|0,s=c,m=s+4|0,n[m>>2]=Yt(1)|0,f=Yt(8)|0,m=n[m>>2]|0,n[B>>2]=0,n[d>>2]=n[B>>2],U4e(f,m,d),n[c>>2]=f,C=l,s|0}function U4e(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]=l,c=Yt(16)|0,n[c+4>>2]=0,n[c+8>>2]=0,n[c>>2]=1916,n[c+12>>2]=l,n[s+4>>2]=c}function _4e(s){s=s|0,im(s),yt(s)}function H4e(s){s=s|0,s=n[s+12>>2]|0,s|0&&yt(s)}function q4e(s){s=s|0,yt(s)}function j4e(){var s=0;return o[8088]|0||(J4e(11076),pr(25,11076,U|0)|0,s=8088,n[s>>2]=1,n[s+4>>2]=0),11076}function G4e(s,l){s=s|0,l=l|0,n[s>>2]=W4e()|0,n[s+4>>2]=Y4e()|0,n[s+12>>2]=l,n[s+8>>2]=K4e()|0,n[s+32>>2]=10}function W4e(){return 11745}function Y4e(){return 1940}function K4e(){return TD()|0}function V4e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,(Qp(f,896)|0)==512?c|0&&(z4e(c),yt(c)):l|0&&yt(l)}function z4e(s){s=s|0,s=n[s+4>>2]|0,s|0&&Rp(s)}function J4e(s){s=s|0,Sp(s)}function Tc(s,l){s=s|0,l=l|0,n[s>>2]=l}function nT(s){return s=s|0,n[s>>2]|0}function X4e(s){return s=s|0,o[n[s>>2]>>0]|0}function Z4e(s,l){s=s|0,l=l|0;var c=0,f=0;c=C,C=C+16|0,f=c,n[f>>2]=n[s>>2],$4e(l,f)|0,C=c}function $4e(s,l){s=s|0,l=l|0;var c=0;return c=eUe(n[s>>2]|0,l)|0,l=s+4|0,n[(n[l>>2]|0)+8>>2]=c,n[(n[l>>2]|0)+8>>2]|0}function eUe(s,l){s=s|0,l=l|0;var c=0,f=0;return c=C,C=C+16|0,f=c,$a(f),s=ys(s)|0,l=tUe(s,n[l>>2]|0)|0,el(f),C=c,l|0}function $a(s){s=s|0,n[s>>2]=n[2701],n[s+4>>2]=n[2703]}function tUe(s,l){s=s|0,l=l|0;var c=0;return c=jo(rUe()|0)|0,un(0,c|0,s|0,JR(l)|0)|0}function el(s){s=s|0,w7(n[s>>2]|0,n[s+4>>2]|0)}function rUe(){var s=0;return o[8096]|0||(nUe(11120),s=8096,n[s>>2]=1,n[s+4>>2]=0),11120}function nUe(s){s=s|0,ao(s,iUe()|0,1)}function iUe(){return 1948}function sUe(){oUe()}function oUe(){var s=0,l=0,c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0,We=0,Oe=0,Qe=0;if(Oe=C,C=C+16|0,O=Oe+4|0,j=Oe,Ro(65536,10804,n[2702]|0,10812),c=n7()|0,l=n[c>>2]|0,s=n[l>>2]|0,s|0)for(f=n[c+8>>2]|0,c=n[c+4>>2]|0;du(s|0,u[c>>0]|0|0,o[f>>0]|0),l=l+4|0,s=n[l>>2]|0,s;)f=f+1|0,c=c+1|0;if(s=i7()|0,l=n[s>>2]|0,l|0)do QA(l|0,n[s+4>>2]|0),s=s+8|0,l=n[s>>2]|0;while(l|0);QA(aUe()|0,5167),M=$d()|0,s=n[M>>2]|0;e:do if(s|0){do lUe(n[s+4>>2]|0),s=n[s>>2]|0;while(s|0);if(s=n[M>>2]|0,s|0){F=M;do{for(;d=s,s=n[s>>2]|0,d=n[d+4>>2]|0,!!(cUe(d)|0);)if(n[j>>2]=F,n[O>>2]=n[j>>2],uUe(M,O)|0,!s)break e;if(AUe(d),F=n[F>>2]|0,l=T7(d)|0,m=Bi()|0,B=C,C=C+((1*(l<<2)|0)+15&-16)|0,k=C,C=C+((1*(l<<2)|0)+15&-16)|0,l=n[(d7(d)|0)>>2]|0,l|0)for(c=B,f=k;n[c>>2]=n[(em(n[l+4>>2]|0)|0)>>2],n[f>>2]=n[l+8>>2],l=n[l>>2]|0,l;)c=c+4|0,f=f+4|0;Qe=em(d)|0,l=fUe(d)|0,c=T7(d)|0,f=pUe(d)|0,Il(Qe|0,l|0,B|0,k|0,c|0,f|0,GR(d)|0),kA(m|0)}while(s|0)}}while(!1);if(s=n[(WR()|0)>>2]|0,s|0)do Qe=s+4|0,M=YR(Qe)|0,d=tw(M)|0,m=$I(M)|0,B=(ew(M)|0)+1|0,k=UD(M)|0,F=L7(Qe)|0,M=Nr(M)|0,O=ND(Qe)|0,j=iT(Qe)|0,mc(0,d|0,m|0,B|0,k|0,F|0,M|0,O|0,j|0,sT(Qe)|0),s=n[s>>2]|0;while(s|0);s=n[($d()|0)>>2]|0;e:do if(s|0){t:for(;;){if(l=n[s+4>>2]|0,l|0&&(oe=n[(em(l)|0)>>2]|0,We=n[(m7(l)|0)>>2]|0,We|0)){c=We;do{l=c+4|0,f=YR(l)|0;r:do if(f|0)switch(Nr(f)|0){case 0:break t;case 4:case 3:case 2:{k=tw(f)|0,F=$I(f)|0,M=(ew(f)|0)+1|0,O=UD(f)|0,j=Nr(f)|0,Qe=ND(l)|0,mc(oe|0,k|0,F|0,M|0,O|0,0,j|0,Qe|0,iT(l)|0,sT(l)|0);break r}case 1:{B=tw(f)|0,k=$I(f)|0,F=(ew(f)|0)+1|0,M=UD(f)|0,O=L7(l)|0,j=Nr(f)|0,Qe=ND(l)|0,mc(oe|0,B|0,k|0,F|0,M|0,O|0,j|0,Qe|0,iT(l)|0,sT(l)|0);break r}case 5:{M=tw(f)|0,O=$I(f)|0,j=(ew(f)|0)+1|0,Qe=UD(f)|0,mc(oe|0,M|0,O|0,j|0,Qe|0,hUe(f)|0,Nr(f)|0,0,0,0);break r}default:break r}while(!1);c=n[c>>2]|0}while(c|0)}if(s=n[s>>2]|0,!s)break e}Tt()}while(!1);we(),C=Oe}function aUe(){return 11703}function lUe(s){s=s|0,o[s+40>>0]=0}function cUe(s){return s=s|0,(o[s+40>>0]|0)!=0|0}function uUe(s,l){return s=s|0,l=l|0,l=gUe(l)|0,s=n[l>>2]|0,n[l>>2]=n[s>>2],yt(s),n[l>>2]|0}function AUe(s){s=s|0,o[s+40>>0]=1}function T7(s){return s=s|0,n[s+20>>2]|0}function fUe(s){return s=s|0,n[s+8>>2]|0}function pUe(s){return s=s|0,n[s+32>>2]|0}function UD(s){return s=s|0,n[s+4>>2]|0}function L7(s){return s=s|0,n[s+4>>2]|0}function iT(s){return s=s|0,n[s+8>>2]|0}function sT(s){return s=s|0,n[s+16>>2]|0}function hUe(s){return s=s|0,n[s+20>>2]|0}function gUe(s){return s=s|0,n[s>>2]|0}function _D(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0,We=0,Oe=0,Qe=0,rt=0,Xe=0,ct=0,_e=0,Ge=0,Nt=0;Nt=C,C=C+16|0,oe=Nt;do if(s>>>0<245){if(M=s>>>0<11?16:s+11&-8,s=M>>>3,j=n[2783]|0,c=j>>>s,c&3|0)return l=(c&1^1)+s|0,s=11172+(l<<1<<2)|0,c=s+8|0,f=n[c>>2]|0,d=f+8|0,m=n[d>>2]|0,(s|0)==(m|0)?n[2783]=j&~(1<<l):(n[m+12>>2]=s,n[c>>2]=m),Ge=l<<3,n[f+4>>2]=Ge|3,Ge=f+Ge+4|0,n[Ge>>2]=n[Ge>>2]|1,Ge=d,C=Nt,Ge|0;if(O=n[2785]|0,M>>>0>O>>>0){if(c|0)return l=2<<s,l=c<<s&(l|0-l),l=(l&0-l)+-1|0,B=l>>>12&16,l=l>>>B,c=l>>>5&8,l=l>>>c,d=l>>>2&4,l=l>>>d,s=l>>>1&2,l=l>>>s,f=l>>>1&1,f=(c|B|d|s|f)+(l>>>f)|0,l=11172+(f<<1<<2)|0,s=l+8|0,d=n[s>>2]|0,B=d+8|0,c=n[B>>2]|0,(l|0)==(c|0)?(s=j&~(1<<f),n[2783]=s):(n[c+12>>2]=l,n[s>>2]=c,s=j),m=(f<<3)-M|0,n[d+4>>2]=M|3,f=d+M|0,n[f+4>>2]=m|1,n[f+m>>2]=m,O|0&&(d=n[2788]|0,l=O>>>3,c=11172+(l<<1<<2)|0,l=1<<l,s&l?(s=c+8|0,l=n[s>>2]|0):(n[2783]=s|l,l=c,s=c+8|0),n[s>>2]=d,n[l+12>>2]=d,n[d+8>>2]=l,n[d+12>>2]=c),n[2785]=m,n[2788]=f,Ge=B,C=Nt,Ge|0;if(k=n[2784]|0,k){if(c=(k&0-k)+-1|0,B=c>>>12&16,c=c>>>B,m=c>>>5&8,c=c>>>m,F=c>>>2&4,c=c>>>F,f=c>>>1&2,c=c>>>f,s=c>>>1&1,s=n[11436+((m|B|F|f|s)+(c>>>s)<<2)>>2]|0,c=(n[s+4>>2]&-8)-M|0,f=n[s+16+(((n[s+16>>2]|0)==0&1)<<2)>>2]|0,!f)F=s,m=c;else{do B=(n[f+4>>2]&-8)-M|0,F=B>>>0<c>>>0,c=F?B:c,s=F?f:s,f=n[f+16+(((n[f+16>>2]|0)==0&1)<<2)>>2]|0;while(f|0);F=s,m=c}if(B=F+M|0,F>>>0<B>>>0){d=n[F+24>>2]|0,l=n[F+12>>2]|0;do if((l|0)==(F|0)){if(s=F+20|0,l=n[s>>2]|0,!l&&(s=F+16|0,l=n[s>>2]|0,!l)){c=0;break}for(;;){if(c=l+20|0,f=n[c>>2]|0,f|0){l=f,s=c;continue}if(c=l+16|0,f=n[c>>2]|0,f)l=f,s=c;else break}n[s>>2]=0,c=l}else c=n[F+8>>2]|0,n[c+12>>2]=l,n[l+8>>2]=c,c=l;while(!1);do if(d|0){if(l=n[F+28>>2]|0,s=11436+(l<<2)|0,(F|0)==(n[s>>2]|0)){if(n[s>>2]=c,!c){n[2784]=k&~(1<<l);break}}else if(n[d+16+(((n[d+16>>2]|0)!=(F|0)&1)<<2)>>2]=c,!c)break;n[c+24>>2]=d,l=n[F+16>>2]|0,l|0&&(n[c+16>>2]=l,n[l+24>>2]=c),l=n[F+20>>2]|0,l|0&&(n[c+20>>2]=l,n[l+24>>2]=c)}while(!1);return m>>>0<16?(Ge=m+M|0,n[F+4>>2]=Ge|3,Ge=F+Ge+4|0,n[Ge>>2]=n[Ge>>2]|1):(n[F+4>>2]=M|3,n[B+4>>2]=m|1,n[B+m>>2]=m,O|0&&(f=n[2788]|0,l=O>>>3,c=11172+(l<<1<<2)|0,l=1<<l,j&l?(s=c+8|0,l=n[s>>2]|0):(n[2783]=j|l,l=c,s=c+8|0),n[s>>2]=f,n[l+12>>2]=f,n[f+8>>2]=l,n[f+12>>2]=c),n[2785]=m,n[2788]=B),Ge=F+8|0,C=Nt,Ge|0}else j=M}else j=M}else j=M}else if(s>>>0<=4294967231)if(s=s+11|0,M=s&-8,F=n[2784]|0,F){f=0-M|0,s=s>>>8,s?M>>>0>16777215?k=31:(j=(s+1048320|0)>>>16&8,_e=s<<j,O=(_e+520192|0)>>>16&4,_e=_e<<O,k=(_e+245760|0)>>>16&2,k=14-(O|j|k)+(_e<<k>>>15)|0,k=M>>>(k+7|0)&1|k<<1):k=0,c=n[11436+(k<<2)>>2]|0;e:do if(!c)c=0,s=0,_e=57;else for(s=0,B=M<<((k|0)==31?0:25-(k>>>1)|0),m=0;;){if(d=(n[c+4>>2]&-8)-M|0,d>>>0<f>>>0)if(d)s=c,f=d;else{s=c,f=0,d=c,_e=61;break e}if(d=n[c+20>>2]|0,c=n[c+16+(B>>>31<<2)>>2]|0,m=(d|0)==0|(d|0)==(c|0)?m:d,d=(c|0)==0,d){c=m,_e=57;break}else B=B<<((d^1)&1)}while(!1);if((_e|0)==57){if((c|0)==0&(s|0)==0){if(s=2<<k,s=F&(s|0-s),!s){j=M;break}j=(s&0-s)+-1|0,B=j>>>12&16,j=j>>>B,m=j>>>5&8,j=j>>>m,k=j>>>2&4,j=j>>>k,O=j>>>1&2,j=j>>>O,c=j>>>1&1,s=0,c=n[11436+((m|B|k|O|c)+(j>>>c)<<2)>>2]|0}c?(d=c,_e=61):(k=s,B=f)}if((_e|0)==61)for(;;)if(_e=0,c=(n[d+4>>2]&-8)-M|0,j=c>>>0<f>>>0,c=j?c:f,s=j?d:s,d=n[d+16+(((n[d+16>>2]|0)==0&1)<<2)>>2]|0,d)f=c,_e=61;else{k=s,B=c;break}if(k|0&&B>>>0<((n[2785]|0)-M|0)>>>0){if(m=k+M|0,k>>>0>=m>>>0)return Ge=0,C=Nt,Ge|0;d=n[k+24>>2]|0,l=n[k+12>>2]|0;do if((l|0)==(k|0)){if(s=k+20|0,l=n[s>>2]|0,!l&&(s=k+16|0,l=n[s>>2]|0,!l)){l=0;break}for(;;){if(c=l+20|0,f=n[c>>2]|0,f|0){l=f,s=c;continue}if(c=l+16|0,f=n[c>>2]|0,f)l=f,s=c;else break}n[s>>2]=0}else Ge=n[k+8>>2]|0,n[Ge+12>>2]=l,n[l+8>>2]=Ge;while(!1);do if(d){if(s=n[k+28>>2]|0,c=11436+(s<<2)|0,(k|0)==(n[c>>2]|0)){if(n[c>>2]=l,!l){f=F&~(1<<s),n[2784]=f;break}}else if(n[d+16+(((n[d+16>>2]|0)!=(k|0)&1)<<2)>>2]=l,!l){f=F;break}n[l+24>>2]=d,s=n[k+16>>2]|0,s|0&&(n[l+16>>2]=s,n[s+24>>2]=l),s=n[k+20>>2]|0,s&&(n[l+20>>2]=s,n[s+24>>2]=l),f=F}else f=F;while(!1);do if(B>>>0>=16){if(n[k+4>>2]=M|3,n[m+4>>2]=B|1,n[m+B>>2]=B,l=B>>>3,B>>>0<256){c=11172+(l<<1<<2)|0,s=n[2783]|0,l=1<<l,s&l?(s=c+8|0,l=n[s>>2]|0):(n[2783]=s|l,l=c,s=c+8|0),n[s>>2]=m,n[l+12>>2]=m,n[m+8>>2]=l,n[m+12>>2]=c;break}if(l=B>>>8,l?B>>>0>16777215?l=31:(_e=(l+1048320|0)>>>16&8,Ge=l<<_e,ct=(Ge+520192|0)>>>16&4,Ge=Ge<<ct,l=(Ge+245760|0)>>>16&2,l=14-(ct|_e|l)+(Ge<<l>>>15)|0,l=B>>>(l+7|0)&1|l<<1):l=0,c=11436+(l<<2)|0,n[m+28>>2]=l,s=m+16|0,n[s+4>>2]=0,n[s>>2]=0,s=1<<l,!(f&s)){n[2784]=f|s,n[c>>2]=m,n[m+24>>2]=c,n[m+12>>2]=m,n[m+8>>2]=m;break}for(s=B<<((l|0)==31?0:25-(l>>>1)|0),c=n[c>>2]|0;;){if((n[c+4>>2]&-8|0)==(B|0)){_e=97;break}if(f=c+16+(s>>>31<<2)|0,l=n[f>>2]|0,l)s=s<<1,c=l;else{_e=96;break}}if((_e|0)==96){n[f>>2]=m,n[m+24>>2]=c,n[m+12>>2]=m,n[m+8>>2]=m;break}else if((_e|0)==97){_e=c+8|0,Ge=n[_e>>2]|0,n[Ge+12>>2]=m,n[_e>>2]=m,n[m+8>>2]=Ge,n[m+12>>2]=c,n[m+24>>2]=0;break}}else Ge=B+M|0,n[k+4>>2]=Ge|3,Ge=k+Ge+4|0,n[Ge>>2]=n[Ge>>2]|1;while(!1);return Ge=k+8|0,C=Nt,Ge|0}else j=M}else j=M;else j=-1;while(!1);if(c=n[2785]|0,c>>>0>=j>>>0)return l=c-j|0,s=n[2788]|0,l>>>0>15?(Ge=s+j|0,n[2788]=Ge,n[2785]=l,n[Ge+4>>2]=l|1,n[Ge+l>>2]=l,n[s+4>>2]=j|3):(n[2785]=0,n[2788]=0,n[s+4>>2]=c|3,Ge=s+c+4|0,n[Ge>>2]=n[Ge>>2]|1),Ge=s+8|0,C=Nt,Ge|0;if(B=n[2786]|0,B>>>0>j>>>0)return ct=B-j|0,n[2786]=ct,Ge=n[2789]|0,_e=Ge+j|0,n[2789]=_e,n[_e+4>>2]=ct|1,n[Ge+4>>2]=j|3,Ge=Ge+8|0,C=Nt,Ge|0;if(n[2901]|0?s=n[2903]|0:(n[2903]=4096,n[2902]=4096,n[2904]=-1,n[2905]=-1,n[2906]=0,n[2894]=0,s=oe&-16^1431655768,n[oe>>2]=s,n[2901]=s,s=4096),k=j+48|0,F=j+47|0,m=s+F|0,d=0-s|0,M=m&d,M>>>0<=j>>>0||(s=n[2893]|0,s|0&&(O=n[2891]|0,oe=O+M|0,oe>>>0<=O>>>0|oe>>>0>s>>>0)))return Ge=0,C=Nt,Ge|0;e:do if(n[2894]&4)l=0,_e=133;else{c=n[2789]|0;t:do if(c){for(f=11580;s=n[f>>2]|0,!(s>>>0<=c>>>0&&(Qe=f+4|0,(s+(n[Qe>>2]|0)|0)>>>0>c>>>0));)if(s=n[f+8>>2]|0,s)f=s;else{_e=118;break t}if(l=m-B&d,l>>>0<2147483647)if(s=Tp(l|0)|0,(s|0)==((n[f>>2]|0)+(n[Qe>>2]|0)|0)){if((s|0)!=-1){B=l,m=s,_e=135;break e}}else f=s,_e=126;else l=0}else _e=118;while(!1);do if((_e|0)==118)if(c=Tp(0)|0,(c|0)!=-1&&(l=c,We=n[2902]|0,Oe=We+-1|0,l=(Oe&l|0?(Oe+l&0-We)-l|0:0)+M|0,We=n[2891]|0,Oe=l+We|0,l>>>0>j>>>0&l>>>0<2147483647)){if(Qe=n[2893]|0,Qe|0&&Oe>>>0<=We>>>0|Oe>>>0>Qe>>>0){l=0;break}if(s=Tp(l|0)|0,(s|0)==(c|0)){B=l,m=c,_e=135;break e}else f=s,_e=126}else l=0;while(!1);do if((_e|0)==126){if(c=0-l|0,!(k>>>0>l>>>0&(l>>>0<2147483647&(f|0)!=-1)))if((f|0)==-1){l=0;break}else{B=l,m=f,_e=135;break e}if(s=n[2903]|0,s=F-l+s&0-s,s>>>0>=2147483647){B=l,m=f,_e=135;break e}if((Tp(s|0)|0)==-1){Tp(c|0)|0,l=0;break}else{B=s+l|0,m=f,_e=135;break e}}while(!1);n[2894]=n[2894]|4,_e=133}while(!1);if((_e|0)==133&&M>>>0<2147483647&&(ct=Tp(M|0)|0,Qe=Tp(0)|0,rt=Qe-ct|0,Xe=rt>>>0>(j+40|0)>>>0,!((ct|0)==-1|Xe^1|ct>>>0<Qe>>>0&((ct|0)!=-1&(Qe|0)!=-1)^1))&&(B=Xe?rt:l,m=ct,_e=135),(_e|0)==135){l=(n[2891]|0)+B|0,n[2891]=l,l>>>0>(n[2892]|0)>>>0&&(n[2892]=l),F=n[2789]|0;do if(F){for(l=11580;;){if(s=n[l>>2]|0,c=l+4|0,f=n[c>>2]|0,(m|0)==(s+f|0)){_e=145;break}if(d=n[l+8>>2]|0,d)l=d;else break}if((_e|0)==145&&!(n[l+12>>2]&8|0)&&F>>>0<m>>>0&F>>>0>=s>>>0){n[c>>2]=f+B,Ge=F+8|0,Ge=Ge&7|0?0-Ge&7:0,_e=F+Ge|0,Ge=(n[2786]|0)+(B-Ge)|0,n[2789]=_e,n[2786]=Ge,n[_e+4>>2]=Ge|1,n[_e+Ge+4>>2]=40,n[2790]=n[2905];break}for(m>>>0<(n[2787]|0)>>>0&&(n[2787]=m),c=m+B|0,l=11580;;){if((n[l>>2]|0)==(c|0)){_e=153;break}if(s=n[l+8>>2]|0,s)l=s;else break}if((_e|0)==153&&!(n[l+12>>2]&8|0)){n[l>>2]=m,O=l+4|0,n[O>>2]=(n[O>>2]|0)+B,O=m+8|0,O=m+(O&7|0?0-O&7:0)|0,l=c+8|0,l=c+(l&7|0?0-l&7:0)|0,M=O+j|0,k=l-O-j|0,n[O+4>>2]=j|3;do if((l|0)!=(F|0)){if((l|0)==(n[2788]|0)){Ge=(n[2785]|0)+k|0,n[2785]=Ge,n[2788]=M,n[M+4>>2]=Ge|1,n[M+Ge>>2]=Ge;break}if(s=n[l+4>>2]|0,(s&3|0)==1){B=s&-8,f=s>>>3;e:do if(s>>>0<256)if(s=n[l+8>>2]|0,c=n[l+12>>2]|0,(c|0)==(s|0)){n[2783]=n[2783]&~(1<<f);break}else{n[s+12>>2]=c,n[c+8>>2]=s;break}else{m=n[l+24>>2]|0,s=n[l+12>>2]|0;do if((s|0)==(l|0)){if(f=l+16|0,c=f+4|0,s=n[c>>2]|0,!s)if(s=n[f>>2]|0,s)c=f;else{s=0;break}for(;;){if(f=s+20|0,d=n[f>>2]|0,d|0){s=d,c=f;continue}if(f=s+16|0,d=n[f>>2]|0,d)s=d,c=f;else break}n[c>>2]=0}else Ge=n[l+8>>2]|0,n[Ge+12>>2]=s,n[s+8>>2]=Ge;while(!1);if(!m)break;c=n[l+28>>2]|0,f=11436+(c<<2)|0;do if((l|0)!=(n[f>>2]|0)){if(n[m+16+(((n[m+16>>2]|0)!=(l|0)&1)<<2)>>2]=s,!s)break e}else{if(n[f>>2]=s,s|0)break;n[2784]=n[2784]&~(1<<c);break e}while(!1);if(n[s+24>>2]=m,c=l+16|0,f=n[c>>2]|0,f|0&&(n[s+16>>2]=f,n[f+24>>2]=s),c=n[c+4>>2]|0,!c)break;n[s+20>>2]=c,n[c+24>>2]=s}while(!1);l=l+B|0,d=B+k|0}else d=k;if(l=l+4|0,n[l>>2]=n[l>>2]&-2,n[M+4>>2]=d|1,n[M+d>>2]=d,l=d>>>3,d>>>0<256){c=11172+(l<<1<<2)|0,s=n[2783]|0,l=1<<l,s&l?(s=c+8|0,l=n[s>>2]|0):(n[2783]=s|l,l=c,s=c+8|0),n[s>>2]=M,n[l+12>>2]=M,n[M+8>>2]=l,n[M+12>>2]=c;break}l=d>>>8;do if(!l)l=0;else{if(d>>>0>16777215){l=31;break}_e=(l+1048320|0)>>>16&8,Ge=l<<_e,ct=(Ge+520192|0)>>>16&4,Ge=Ge<<ct,l=(Ge+245760|0)>>>16&2,l=14-(ct|_e|l)+(Ge<<l>>>15)|0,l=d>>>(l+7|0)&1|l<<1}while(!1);if(f=11436+(l<<2)|0,n[M+28>>2]=l,s=M+16|0,n[s+4>>2]=0,n[s>>2]=0,s=n[2784]|0,c=1<<l,!(s&c)){n[2784]=s|c,n[f>>2]=M,n[M+24>>2]=f,n[M+12>>2]=M,n[M+8>>2]=M;break}for(s=d<<((l|0)==31?0:25-(l>>>1)|0),c=n[f>>2]|0;;){if((n[c+4>>2]&-8|0)==(d|0)){_e=194;break}if(f=c+16+(s>>>31<<2)|0,l=n[f>>2]|0,l)s=s<<1,c=l;else{_e=193;break}}if((_e|0)==193){n[f>>2]=M,n[M+24>>2]=c,n[M+12>>2]=M,n[M+8>>2]=M;break}else if((_e|0)==194){_e=c+8|0,Ge=n[_e>>2]|0,n[Ge+12>>2]=M,n[_e>>2]=M,n[M+8>>2]=Ge,n[M+12>>2]=c,n[M+24>>2]=0;break}}else Ge=(n[2786]|0)+k|0,n[2786]=Ge,n[2789]=M,n[M+4>>2]=Ge|1;while(!1);return Ge=O+8|0,C=Nt,Ge|0}for(l=11580;s=n[l>>2]|0,!(s>>>0<=F>>>0&&(Ge=s+(n[l+4>>2]|0)|0,Ge>>>0>F>>>0));)l=n[l+8>>2]|0;d=Ge+-47|0,s=d+8|0,s=d+(s&7|0?0-s&7:0)|0,d=F+16|0,s=s>>>0<d>>>0?F:s,l=s+8|0,c=m+8|0,c=c&7|0?0-c&7:0,_e=m+c|0,c=B+-40-c|0,n[2789]=_e,n[2786]=c,n[_e+4>>2]=c|1,n[_e+c+4>>2]=40,n[2790]=n[2905],c=s+4|0,n[c>>2]=27,n[l>>2]=n[2895],n[l+4>>2]=n[2896],n[l+8>>2]=n[2897],n[l+12>>2]=n[2898],n[2895]=m,n[2896]=B,n[2898]=0,n[2897]=l,l=s+24|0;do _e=l,l=l+4|0,n[l>>2]=7;while((_e+8|0)>>>0<Ge>>>0);if((s|0)!=(F|0)){if(m=s-F|0,n[c>>2]=n[c>>2]&-2,n[F+4>>2]=m|1,n[s>>2]=m,l=m>>>3,m>>>0<256){c=11172+(l<<1<<2)|0,s=n[2783]|0,l=1<<l,s&l?(s=c+8|0,l=n[s>>2]|0):(n[2783]=s|l,l=c,s=c+8|0),n[s>>2]=F,n[l+12>>2]=F,n[F+8>>2]=l,n[F+12>>2]=c;break}if(l=m>>>8,l?m>>>0>16777215?c=31:(_e=(l+1048320|0)>>>16&8,Ge=l<<_e,ct=(Ge+520192|0)>>>16&4,Ge=Ge<<ct,c=(Ge+245760|0)>>>16&2,c=14-(ct|_e|c)+(Ge<<c>>>15)|0,c=m>>>(c+7|0)&1|c<<1):c=0,f=11436+(c<<2)|0,n[F+28>>2]=c,n[F+20>>2]=0,n[d>>2]=0,l=n[2784]|0,s=1<<c,!(l&s)){n[2784]=l|s,n[f>>2]=F,n[F+24>>2]=f,n[F+12>>2]=F,n[F+8>>2]=F;break}for(s=m<<((c|0)==31?0:25-(c>>>1)|0),c=n[f>>2]|0;;){if((n[c+4>>2]&-8|0)==(m|0)){_e=216;break}if(f=c+16+(s>>>31<<2)|0,l=n[f>>2]|0,l)s=s<<1,c=l;else{_e=215;break}}if((_e|0)==215){n[f>>2]=F,n[F+24>>2]=c,n[F+12>>2]=F,n[F+8>>2]=F;break}else if((_e|0)==216){_e=c+8|0,Ge=n[_e>>2]|0,n[Ge+12>>2]=F,n[_e>>2]=F,n[F+8>>2]=Ge,n[F+12>>2]=c,n[F+24>>2]=0;break}}}else{Ge=n[2787]|0,(Ge|0)==0|m>>>0<Ge>>>0&&(n[2787]=m),n[2895]=m,n[2896]=B,n[2898]=0,n[2792]=n[2901],n[2791]=-1,l=0;do Ge=11172+(l<<1<<2)|0,n[Ge+12>>2]=Ge,n[Ge+8>>2]=Ge,l=l+1|0;while((l|0)!=32);Ge=m+8|0,Ge=Ge&7|0?0-Ge&7:0,_e=m+Ge|0,Ge=B+-40-Ge|0,n[2789]=_e,n[2786]=Ge,n[_e+4>>2]=Ge|1,n[_e+Ge+4>>2]=40,n[2790]=n[2905]}while(!1);if(l=n[2786]|0,l>>>0>j>>>0)return ct=l-j|0,n[2786]=ct,Ge=n[2789]|0,_e=Ge+j|0,n[2789]=_e,n[_e+4>>2]=ct|1,n[Ge+4>>2]=j|3,Ge=Ge+8|0,C=Nt,Ge|0}return n[(rm()|0)>>2]=12,Ge=0,C=Nt,Ge|0}function HD(s){s=s|0;var l=0,c=0,f=0,d=0,m=0,B=0,k=0,F=0;if(s){c=s+-8|0,d=n[2787]|0,s=n[s+-4>>2]|0,l=s&-8,F=c+l|0;do if(s&1)k=c,B=c;else{if(f=n[c>>2]|0,!(s&3)||(B=c+(0-f)|0,m=f+l|0,B>>>0<d>>>0))return;if((B|0)==(n[2788]|0)){if(s=F+4|0,l=n[s>>2]|0,(l&3|0)!=3){k=B,l=m;break}n[2785]=m,n[s>>2]=l&-2,n[B+4>>2]=m|1,n[B+m>>2]=m;return}if(c=f>>>3,f>>>0<256)if(s=n[B+8>>2]|0,l=n[B+12>>2]|0,(l|0)==(s|0)){n[2783]=n[2783]&~(1<<c),k=B,l=m;break}else{n[s+12>>2]=l,n[l+8>>2]=s,k=B,l=m;break}d=n[B+24>>2]|0,s=n[B+12>>2]|0;do if((s|0)==(B|0)){if(c=B+16|0,l=c+4|0,s=n[l>>2]|0,!s)if(s=n[c>>2]|0,s)l=c;else{s=0;break}for(;;){if(c=s+20|0,f=n[c>>2]|0,f|0){s=f,l=c;continue}if(c=s+16|0,f=n[c>>2]|0,f)s=f,l=c;else break}n[l>>2]=0}else k=n[B+8>>2]|0,n[k+12>>2]=s,n[s+8>>2]=k;while(!1);if(d){if(l=n[B+28>>2]|0,c=11436+(l<<2)|0,(B|0)==(n[c>>2]|0)){if(n[c>>2]=s,!s){n[2784]=n[2784]&~(1<<l),k=B,l=m;break}}else if(n[d+16+(((n[d+16>>2]|0)!=(B|0)&1)<<2)>>2]=s,!s){k=B,l=m;break}n[s+24>>2]=d,l=B+16|0,c=n[l>>2]|0,c|0&&(n[s+16>>2]=c,n[c+24>>2]=s),l=n[l+4>>2]|0,l?(n[s+20>>2]=l,n[l+24>>2]=s,k=B,l=m):(k=B,l=m)}else k=B,l=m}while(!1);if(!(B>>>0>=F>>>0)&&(s=F+4|0,f=n[s>>2]|0,!!(f&1))){if(f&2)n[s>>2]=f&-2,n[k+4>>2]=l|1,n[B+l>>2]=l,d=l;else{if(s=n[2788]|0,(F|0)==(n[2789]|0)){if(F=(n[2786]|0)+l|0,n[2786]=F,n[2789]=k,n[k+4>>2]=F|1,(k|0)!=(s|0))return;n[2788]=0,n[2785]=0;return}if((F|0)==(s|0)){F=(n[2785]|0)+l|0,n[2785]=F,n[2788]=B,n[k+4>>2]=F|1,n[B+F>>2]=F;return}d=(f&-8)+l|0,c=f>>>3;do if(f>>>0<256)if(l=n[F+8>>2]|0,s=n[F+12>>2]|0,(s|0)==(l|0)){n[2783]=n[2783]&~(1<<c);break}else{n[l+12>>2]=s,n[s+8>>2]=l;break}else{m=n[F+24>>2]|0,s=n[F+12>>2]|0;do if((s|0)==(F|0)){if(c=F+16|0,l=c+4|0,s=n[l>>2]|0,!s)if(s=n[c>>2]|0,s)l=c;else{c=0;break}for(;;){if(c=s+20|0,f=n[c>>2]|0,f|0){s=f,l=c;continue}if(c=s+16|0,f=n[c>>2]|0,f)s=f,l=c;else break}n[l>>2]=0,c=s}else c=n[F+8>>2]|0,n[c+12>>2]=s,n[s+8>>2]=c,c=s;while(!1);if(m|0){if(s=n[F+28>>2]|0,l=11436+(s<<2)|0,(F|0)==(n[l>>2]|0)){if(n[l>>2]=c,!c){n[2784]=n[2784]&~(1<<s);break}}else if(n[m+16+(((n[m+16>>2]|0)!=(F|0)&1)<<2)>>2]=c,!c)break;n[c+24>>2]=m,s=F+16|0,l=n[s>>2]|0,l|0&&(n[c+16>>2]=l,n[l+24>>2]=c),s=n[s+4>>2]|0,s|0&&(n[c+20>>2]=s,n[s+24>>2]=c)}}while(!1);if(n[k+4>>2]=d|1,n[B+d>>2]=d,(k|0)==(n[2788]|0)){n[2785]=d;return}}if(s=d>>>3,d>>>0<256){c=11172+(s<<1<<2)|0,l=n[2783]|0,s=1<<s,l&s?(l=c+8|0,s=n[l>>2]|0):(n[2783]=l|s,s=c,l=c+8|0),n[l>>2]=k,n[s+12>>2]=k,n[k+8>>2]=s,n[k+12>>2]=c;return}s=d>>>8,s?d>>>0>16777215?s=31:(B=(s+1048320|0)>>>16&8,F=s<<B,m=(F+520192|0)>>>16&4,F=F<<m,s=(F+245760|0)>>>16&2,s=14-(m|B|s)+(F<<s>>>15)|0,s=d>>>(s+7|0)&1|s<<1):s=0,f=11436+(s<<2)|0,n[k+28>>2]=s,n[k+20>>2]=0,n[k+16>>2]=0,l=n[2784]|0,c=1<<s;do if(l&c){for(l=d<<((s|0)==31?0:25-(s>>>1)|0),c=n[f>>2]|0;;){if((n[c+4>>2]&-8|0)==(d|0)){s=73;break}if(f=c+16+(l>>>31<<2)|0,s=n[f>>2]|0,s)l=l<<1,c=s;else{s=72;break}}if((s|0)==72){n[f>>2]=k,n[k+24>>2]=c,n[k+12>>2]=k,n[k+8>>2]=k;break}else if((s|0)==73){B=c+8|0,F=n[B>>2]|0,n[F+12>>2]=k,n[B>>2]=k,n[k+8>>2]=F,n[k+12>>2]=c,n[k+24>>2]=0;break}}else n[2784]=l|c,n[f>>2]=k,n[k+24>>2]=f,n[k+12>>2]=k,n[k+8>>2]=k;while(!1);if(F=(n[2791]|0)+-1|0,n[2791]=F,!F)s=11588;else return;for(;s=n[s>>2]|0,s;)s=s+8|0;n[2791]=-1}}}function dUe(){return 11628}function mUe(s){s=s|0;var l=0,c=0;return l=C,C=C+16|0,c=l,n[c>>2]=CUe(n[s+60>>2]|0)|0,s=qD(Ec(6,c|0)|0)|0,C=l,s|0}function N7(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0,We=0;j=C,C=C+48|0,M=j+16|0,m=j,d=j+32|0,k=s+28|0,f=n[k>>2]|0,n[d>>2]=f,F=s+20|0,f=(n[F>>2]|0)-f|0,n[d+4>>2]=f,n[d+8>>2]=l,n[d+12>>2]=c,f=f+c|0,B=s+60|0,n[m>>2]=n[B>>2],n[m+4>>2]=d,n[m+8>>2]=2,m=qD(aa(146,m|0)|0)|0;e:do if((f|0)!=(m|0)){for(l=2;!((m|0)<0);)if(f=f-m|0,We=n[d+4>>2]|0,oe=m>>>0>We>>>0,d=oe?d+8|0:d,l=(oe<<31>>31)+l|0,We=m-(oe?We:0)|0,n[d>>2]=(n[d>>2]|0)+We,oe=d+4|0,n[oe>>2]=(n[oe>>2]|0)-We,n[M>>2]=n[B>>2],n[M+4>>2]=d,n[M+8>>2]=l,m=qD(aa(146,M|0)|0)|0,(f|0)==(m|0)){O=3;break e}n[s+16>>2]=0,n[k>>2]=0,n[F>>2]=0,n[s>>2]=n[s>>2]|32,(l|0)==2?c=0:c=c-(n[d+4>>2]|0)|0}else O=3;while(!1);return(O|0)==3&&(We=n[s+44>>2]|0,n[s+16>>2]=We+(n[s+48>>2]|0),n[k>>2]=We,n[F>>2]=We),C=j,c|0}function yUe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;return d=C,C=C+32|0,m=d,f=d+20|0,n[m>>2]=n[s+60>>2],n[m+4>>2]=0,n[m+8>>2]=l,n[m+12>>2]=f,n[m+16>>2]=c,(qD(oa(140,m|0)|0)|0)<0?(n[f>>2]=-1,s=-1):s=n[f>>2]|0,C=d,s|0}function qD(s){return s=s|0,s>>>0>4294963200&&(n[(rm()|0)>>2]=0-s,s=-1),s|0}function rm(){return(EUe()|0)+64|0}function EUe(){return oT()|0}function oT(){return 2084}function CUe(s){return s=s|0,s|0}function IUe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;return d=C,C=C+32|0,f=d,n[s+36>>2]=1,!(n[s>>2]&64|0)&&(n[f>>2]=n[s+60>>2],n[f+4>>2]=21523,n[f+8>>2]=d+16,Ls(54,f|0)|0)&&(o[s+75>>0]=-1),f=N7(s,l,c)|0,C=d,f|0}function O7(s,l){s=s|0,l=l|0;var c=0,f=0;if(c=o[s>>0]|0,f=o[l>>0]|0,!(c<<24>>24)||c<<24>>24!=f<<24>>24)s=f;else{do s=s+1|0,l=l+1|0,c=o[s>>0]|0,f=o[l>>0]|0;while(!(!(c<<24>>24)||c<<24>>24!=f<<24>>24));s=f}return(c&255)-(s&255)|0}function wUe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0;e:do if(!c)s=0;else{for(;f=o[s>>0]|0,d=o[l>>0]|0,f<<24>>24==d<<24>>24;)if(c=c+-1|0,c)s=s+1|0,l=l+1|0;else{s=0;break e}s=(f&255)-(d&255)|0}while(!1);return s|0}function M7(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0,We=0,Oe=0,Qe=0;Qe=C,C=C+224|0,O=Qe+120|0,j=Qe+80|0,We=Qe,Oe=Qe+136|0,f=j,d=f+40|0;do n[f>>2]=0,f=f+4|0;while((f|0)<(d|0));return n[O>>2]=n[c>>2],(aT(0,l,O,We,j)|0)<0?c=-1:((n[s+76>>2]|0)>-1?oe=BUe(s)|0:oe=0,c=n[s>>2]|0,M=c&32,(o[s+74>>0]|0)<1&&(n[s>>2]=c&-33),f=s+48|0,n[f>>2]|0?c=aT(s,l,O,We,j)|0:(d=s+44|0,m=n[d>>2]|0,n[d>>2]=Oe,B=s+28|0,n[B>>2]=Oe,k=s+20|0,n[k>>2]=Oe,n[f>>2]=80,F=s+16|0,n[F>>2]=Oe+80,c=aT(s,l,O,We,j)|0,m&&(YD[n[s+36>>2]&7](s,0,0)|0,c=n[k>>2]|0?c:-1,n[d>>2]=m,n[f>>2]=0,n[F>>2]=0,n[B>>2]=0,n[k>>2]=0)),f=n[s>>2]|0,n[s>>2]=f|M,oe|0&&vUe(s),c=f&32|0?-1:c),C=Qe,c|0}function aT(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0,We=0,Oe=0,Qe=0,rt=0,Xe=0,ct=0,_e=0,Ge=0,Nt=0,_r=0,ur=0,Zt=0,kr=0,Or=0,lr=0;lr=C,C=C+64|0,ur=lr+16|0,Zt=lr,Nt=lr+24|0,kr=lr+8|0,Or=lr+20|0,n[ur>>2]=l,ct=(s|0)!=0,_e=Nt+40|0,Ge=_e,Nt=Nt+39|0,_r=kr+4|0,B=0,m=0,O=0;e:for(;;){do if((m|0)>-1)if((B|0)>(2147483647-m|0)){n[(rm()|0)>>2]=75,m=-1;break}else{m=B+m|0;break}while(!1);if(B=o[l>>0]|0,B<<24>>24)k=l;else{Xe=87;break}t:for(;;){switch(B<<24>>24){case 37:{B=k,Xe=9;break t}case 0:{B=k;break t}default:}rt=k+1|0,n[ur>>2]=rt,B=o[rt>>0]|0,k=rt}t:do if((Xe|0)==9)for(;;){if(Xe=0,(o[k+1>>0]|0)!=37)break t;if(B=B+1|0,k=k+2|0,n[ur>>2]=k,(o[k>>0]|0)==37)Xe=9;else break}while(!1);if(B=B-l|0,ct&&os(s,l,B),B|0){l=k;continue}F=k+1|0,B=(o[F>>0]|0)+-48|0,B>>>0<10?(rt=(o[k+2>>0]|0)==36,Qe=rt?B:-1,O=rt?1:O,F=rt?k+3|0:F):Qe=-1,n[ur>>2]=F,B=o[F>>0]|0,k=(B<<24>>24)+-32|0;t:do if(k>>>0<32)for(M=0,j=B;;){if(B=1<<k,!(B&75913)){B=j;break t}if(M=B|M,F=F+1|0,n[ur>>2]=F,B=o[F>>0]|0,k=(B<<24>>24)+-32|0,k>>>0>=32)break;j=B}else M=0;while(!1);if(B<<24>>24==42){if(k=F+1|0,B=(o[k>>0]|0)+-48|0,B>>>0<10&&(o[F+2>>0]|0)==36)n[d+(B<<2)>>2]=10,B=n[f+((o[k>>0]|0)+-48<<3)>>2]|0,O=1,F=F+3|0;else{if(O|0){m=-1;break}ct?(O=(n[c>>2]|0)+3&-4,B=n[O>>2]|0,n[c>>2]=O+4,O=0,F=k):(B=0,O=0,F=k)}n[ur>>2]=F,rt=(B|0)<0,B=rt?0-B|0:B,M=rt?M|8192:M}else{if(B=U7(ur)|0,(B|0)<0){m=-1;break}F=n[ur>>2]|0}do if((o[F>>0]|0)==46){if((o[F+1>>0]|0)!=42){n[ur>>2]=F+1,k=U7(ur)|0,F=n[ur>>2]|0;break}if(j=F+2|0,k=(o[j>>0]|0)+-48|0,k>>>0<10&&(o[F+3>>0]|0)==36){n[d+(k<<2)>>2]=10,k=n[f+((o[j>>0]|0)+-48<<3)>>2]|0,F=F+4|0,n[ur>>2]=F;break}if(O|0){m=-1;break e}ct?(rt=(n[c>>2]|0)+3&-4,k=n[rt>>2]|0,n[c>>2]=rt+4):k=0,n[ur>>2]=j,F=j}else k=-1;while(!1);for(Oe=0;;){if(((o[F>>0]|0)+-65|0)>>>0>57){m=-1;break e}if(rt=F+1|0,n[ur>>2]=rt,j=o[(o[F>>0]|0)+-65+(5178+(Oe*58|0))>>0]|0,oe=j&255,(oe+-1|0)>>>0<8)Oe=oe,F=rt;else break}if(!(j<<24>>24)){m=-1;break}We=(Qe|0)>-1;do if(j<<24>>24==19)if(We){m=-1;break e}else Xe=49;else{if(We){n[d+(Qe<<2)>>2]=oe,We=f+(Qe<<3)|0,Qe=n[We+4>>2]|0,Xe=Zt,n[Xe>>2]=n[We>>2],n[Xe+4>>2]=Qe,Xe=49;break}if(!ct){m=0;break e}_7(Zt,oe,c)}while(!1);if((Xe|0)==49&&(Xe=0,!ct)){B=0,l=rt;continue}F=o[F>>0]|0,F=(Oe|0)!=0&(F&15|0)==3?F&-33:F,We=M&-65537,Qe=M&8192|0?We:M;t:do switch(F|0){case 110:switch((Oe&255)<<24>>24){case 0:{n[n[Zt>>2]>>2]=m,B=0,l=rt;continue e}case 1:{n[n[Zt>>2]>>2]=m,B=0,l=rt;continue e}case 2:{B=n[Zt>>2]|0,n[B>>2]=m,n[B+4>>2]=((m|0)<0)<<31>>31,B=0,l=rt;continue e}case 3:{a[n[Zt>>2]>>1]=m,B=0,l=rt;continue e}case 4:{o[n[Zt>>2]>>0]=m,B=0,l=rt;continue e}case 6:{n[n[Zt>>2]>>2]=m,B=0,l=rt;continue e}case 7:{B=n[Zt>>2]|0,n[B>>2]=m,n[B+4>>2]=((m|0)<0)<<31>>31,B=0,l=rt;continue e}default:{B=0,l=rt;continue e}}case 112:{F=120,k=k>>>0>8?k:8,l=Qe|8,Xe=61;break}case 88:case 120:{l=Qe,Xe=61;break}case 111:{F=Zt,l=n[F>>2]|0,F=n[F+4>>2]|0,oe=PUe(l,F,_e)|0,We=Ge-oe|0,M=0,j=5642,k=(Qe&8|0)==0|(k|0)>(We|0)?k:We+1|0,We=Qe,Xe=67;break}case 105:case 100:if(F=Zt,l=n[F>>2]|0,F=n[F+4>>2]|0,(F|0)<0){l=jD(0,0,l|0,F|0)|0,F=Ce,M=Zt,n[M>>2]=l,n[M+4>>2]=F,M=1,j=5642,Xe=66;break t}else{M=(Qe&2049|0)!=0&1,j=Qe&2048|0?5643:Qe&1|0?5644:5642,Xe=66;break t}case 117:{F=Zt,M=0,j=5642,l=n[F>>2]|0,F=n[F+4>>2]|0,Xe=66;break}case 99:{o[Nt>>0]=n[Zt>>2],l=Nt,M=0,j=5642,oe=_e,F=1,k=We;break}case 109:{F=SUe(n[(rm()|0)>>2]|0)|0,Xe=71;break}case 115:{F=n[Zt>>2]|0,F=F|0?F:5652,Xe=71;break}case 67:{n[kr>>2]=n[Zt>>2],n[_r>>2]=0,n[Zt>>2]=kr,oe=-1,F=kr,Xe=75;break}case 83:{l=n[Zt>>2]|0,k?(oe=k,F=l,Xe=75):(Es(s,32,B,0,Qe),l=0,Xe=84);break}case 65:case 71:case 70:case 69:case 97:case 103:case 102:case 101:{B=bUe(s,+E[Zt>>3],B,k,Qe,F)|0,l=rt;continue e}default:M=0,j=5642,oe=_e,F=k,k=Qe}while(!1);t:do if((Xe|0)==61)Qe=Zt,Oe=n[Qe>>2]|0,Qe=n[Qe+4>>2]|0,oe=DUe(Oe,Qe,_e,F&32)|0,j=(l&8|0)==0|(Oe|0)==0&(Qe|0)==0,M=j?0:2,j=j?5642:5642+(F>>4)|0,We=l,l=Oe,F=Qe,Xe=67;else if((Xe|0)==66)oe=nm(l,F,_e)|0,We=Qe,Xe=67;else if((Xe|0)==71)Xe=0,Qe=xUe(F,0,k)|0,Oe=(Qe|0)==0,l=F,M=0,j=5642,oe=Oe?F+k|0:Qe,F=Oe?k:Qe-F|0,k=We;else if((Xe|0)==75){for(Xe=0,j=F,l=0,k=0;M=n[j>>2]|0,!(!M||(k=H7(Or,M)|0,(k|0)<0|k>>>0>(oe-l|0)>>>0));)if(l=k+l|0,oe>>>0>l>>>0)j=j+4|0;else break;if((k|0)<0){m=-1;break e}if(Es(s,32,B,l,Qe),!l)l=0,Xe=84;else for(M=0;;){if(k=n[F>>2]|0,!k){Xe=84;break t}if(k=H7(Or,k)|0,M=k+M|0,(M|0)>(l|0)){Xe=84;break t}if(os(s,Or,k),M>>>0>=l>>>0){Xe=84;break}else F=F+4|0}}while(!1);if((Xe|0)==67)Xe=0,F=(l|0)!=0|(F|0)!=0,Qe=(k|0)!=0|F,F=((F^1)&1)+(Ge-oe)|0,l=Qe?oe:_e,oe=_e,F=Qe?(k|0)>(F|0)?k:F:k,k=(k|0)>-1?We&-65537:We;else if((Xe|0)==84){Xe=0,Es(s,32,B,l,Qe^8192),B=(B|0)>(l|0)?B:l,l=rt;continue}Oe=oe-l|0,We=(F|0)<(Oe|0)?Oe:F,Qe=We+M|0,B=(B|0)<(Qe|0)?Qe:B,Es(s,32,B,Qe,k),os(s,j,M),Es(s,48,B,Qe,k^65536),Es(s,48,We,Oe,0),os(s,l,Oe),Es(s,32,B,Qe,k^8192),l=rt}e:do if((Xe|0)==87&&!s)if(!O)m=0;else{for(m=1;l=n[d+(m<<2)>>2]|0,!!l;)if(_7(f+(m<<3)|0,l,c),m=m+1|0,(m|0)>=10){m=1;break e}for(;;){if(n[d+(m<<2)>>2]|0){m=-1;break e}if(m=m+1|0,(m|0)>=10){m=1;break}}}while(!1);return C=lr,m|0}function BUe(s){return s=s|0,0}function vUe(s){s=s|0}function os(s,l,c){s=s|0,l=l|0,c=c|0,n[s>>2]&32||MUe(l,c,s)|0}function U7(s){s=s|0;var l=0,c=0,f=0;if(c=n[s>>2]|0,f=(o[c>>0]|0)+-48|0,f>>>0<10){l=0;do l=f+(l*10|0)|0,c=c+1|0,n[s>>2]=c,f=(o[c>>0]|0)+-48|0;while(f>>>0<10)}else l=0;return l|0}function _7(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;e:do if(l>>>0<=20)do switch(l|0){case 9:{f=(n[c>>2]|0)+3&-4,l=n[f>>2]|0,n[c>>2]=f+4,n[s>>2]=l;break e}case 10:{f=(n[c>>2]|0)+3&-4,l=n[f>>2]|0,n[c>>2]=f+4,f=s,n[f>>2]=l,n[f+4>>2]=((l|0)<0)<<31>>31;break e}case 11:{f=(n[c>>2]|0)+3&-4,l=n[f>>2]|0,n[c>>2]=f+4,f=s,n[f>>2]=l,n[f+4>>2]=0;break e}case 12:{f=(n[c>>2]|0)+7&-8,l=f,d=n[l>>2]|0,l=n[l+4>>2]|0,n[c>>2]=f+8,f=s,n[f>>2]=d,n[f+4>>2]=l;break e}case 13:{d=(n[c>>2]|0)+3&-4,f=n[d>>2]|0,n[c>>2]=d+4,f=(f&65535)<<16>>16,d=s,n[d>>2]=f,n[d+4>>2]=((f|0)<0)<<31>>31;break e}case 14:{d=(n[c>>2]|0)+3&-4,f=n[d>>2]|0,n[c>>2]=d+4,d=s,n[d>>2]=f&65535,n[d+4>>2]=0;break e}case 15:{d=(n[c>>2]|0)+3&-4,f=n[d>>2]|0,n[c>>2]=d+4,f=(f&255)<<24>>24,d=s,n[d>>2]=f,n[d+4>>2]=((f|0)<0)<<31>>31;break e}case 16:{d=(n[c>>2]|0)+3&-4,f=n[d>>2]|0,n[c>>2]=d+4,d=s,n[d>>2]=f&255,n[d+4>>2]=0;break e}case 17:{d=(n[c>>2]|0)+7&-8,m=+E[d>>3],n[c>>2]=d+8,E[s>>3]=m;break e}case 18:{d=(n[c>>2]|0)+7&-8,m=+E[d>>3],n[c>>2]=d+8,E[s>>3]=m;break e}default:break e}while(!1);while(!1)}function DUe(s,l,c,f){if(s=s|0,l=l|0,c=c|0,f=f|0,!((s|0)==0&(l|0)==0))do c=c+-1|0,o[c>>0]=u[5694+(s&15)>>0]|0|f,s=GD(s|0,l|0,4)|0,l=Ce;while(!((s|0)==0&(l|0)==0));return c|0}function PUe(s,l,c){if(s=s|0,l=l|0,c=c|0,!((s|0)==0&(l|0)==0))do c=c+-1|0,o[c>>0]=s&7|48,s=GD(s|0,l|0,3)|0,l=Ce;while(!((s|0)==0&(l|0)==0));return c|0}function nm(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;if(l>>>0>0|(l|0)==0&s>>>0>4294967295){for(;f=AT(s|0,l|0,10,0)|0,c=c+-1|0,o[c>>0]=f&255|48,f=s,s=uT(s|0,l|0,10,0)|0,l>>>0>9|(l|0)==9&f>>>0>4294967295;)l=Ce;l=s}else l=s;if(l)for(;c=c+-1|0,o[c>>0]=(l>>>0)%10|0|48,!(l>>>0<10);)l=(l>>>0)/10|0;return c|0}function SUe(s){return s=s|0,TUe(s,n[(RUe()|0)+188>>2]|0)|0}function xUe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;m=l&255,f=(c|0)!=0;e:do if(f&(s&3|0)!=0)for(d=l&255;;){if((o[s>>0]|0)==d<<24>>24){B=6;break e}if(s=s+1|0,c=c+-1|0,f=(c|0)!=0,!(f&(s&3|0)!=0)){B=5;break}}else B=5;while(!1);(B|0)==5&&(f?B=6:c=0);e:do if((B|0)==6&&(d=l&255,(o[s>>0]|0)!=d<<24>>24)){f=He(m,16843009)|0;t:do if(c>>>0>3){for(;m=n[s>>2]^f,!((m&-2139062144^-2139062144)&m+-16843009|0);)if(s=s+4|0,c=c+-4|0,c>>>0<=3){B=11;break t}}else B=11;while(!1);if((B|0)==11&&!c){c=0;break}for(;;){if((o[s>>0]|0)==d<<24>>24)break e;if(s=s+1|0,c=c+-1|0,!c){c=0;break}}}while(!1);return(c|0?s:0)|0}function Es(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0;if(B=C,C=C+256|0,m=B,(c|0)>(f|0)&(d&73728|0)==0){if(d=c-f|0,sm(m|0,l|0,(d>>>0<256?d:256)|0)|0,d>>>0>255){l=c-f|0;do os(s,m,256),d=d+-256|0;while(d>>>0>255);d=l&255}os(s,m,d)}C=B}function H7(s,l){return s=s|0,l=l|0,s?s=QUe(s,l,0)|0:s=0,s|0}function bUe(s,l,c,f,d,m){s=s|0,l=+l,c=c|0,f=f|0,d=d|0,m=m|0;var B=0,k=0,F=0,M=0,O=0,j=0,oe=0,We=0,Oe=0,Qe=0,rt=0,Xe=0,ct=0,_e=0,Ge=0,Nt=0,_r=0,ur=0,Zt=0,kr=0,Or=0,lr=0,Ln=0;Ln=C,C=C+560|0,F=Ln+8|0,rt=Ln,lr=Ln+524|0,Or=lr,M=Ln+512|0,n[rt>>2]=0,kr=M+12|0,q7(l)|0,(Ce|0)<0?(l=-l,ur=1,_r=5659):(ur=(d&2049|0)!=0&1,_r=d&2048|0?5662:d&1|0?5665:5660),q7(l)|0,Zt=Ce&2146435072;do if(Zt>>>0<2146435072|(Zt|0)==2146435072&!1){if(We=+kUe(l,rt)*2,B=We!=0,B&&(n[rt>>2]=(n[rt>>2]|0)+-1),ct=m|32,(ct|0)==97){Oe=m&32,oe=Oe|0?_r+9|0:_r,j=ur|2,B=12-f|0;do if(f>>>0>11|(B|0)==0)l=We;else{l=8;do B=B+-1|0,l=l*16;while(B|0);if((o[oe>>0]|0)==45){l=-(l+(-We-l));break}else{l=We+l-l;break}}while(!1);k=n[rt>>2]|0,B=(k|0)<0?0-k|0:k,B=nm(B,((B|0)<0)<<31>>31,kr)|0,(B|0)==(kr|0)&&(B=M+11|0,o[B>>0]=48),o[B+-1>>0]=(k>>31&2)+43,O=B+-2|0,o[O>>0]=m+15,M=(f|0)<1,F=(d&8|0)==0,B=lr;do Zt=~~l,k=B+1|0,o[B>>0]=u[5694+Zt>>0]|Oe,l=(l-+(Zt|0))*16,(k-Or|0)==1&&!(F&(M&l==0))?(o[k>>0]=46,B=B+2|0):B=k;while(l!=0);Zt=B-Or|0,Or=kr-O|0,kr=(f|0)!=0&(Zt+-2|0)<(f|0)?f+2|0:Zt,B=Or+j+kr|0,Es(s,32,c,B,d),os(s,oe,j),Es(s,48,c,B,d^65536),os(s,lr,Zt),Es(s,48,kr-Zt|0,0,0),os(s,O,Or),Es(s,32,c,B,d^8192);break}k=(f|0)<0?6:f,B?(B=(n[rt>>2]|0)+-28|0,n[rt>>2]=B,l=We*268435456):(l=We,B=n[rt>>2]|0),Zt=(B|0)<0?F:F+288|0,F=Zt;do Ge=~~l>>>0,n[F>>2]=Ge,F=F+4|0,l=(l-+(Ge>>>0))*1e9;while(l!=0);if((B|0)>0)for(M=Zt,j=F;;){if(O=(B|0)<29?B:29,B=j+-4|0,B>>>0>=M>>>0){F=0;do _e=V7(n[B>>2]|0,0,O|0)|0,_e=cT(_e|0,Ce|0,F|0,0)|0,Ge=Ce,Xe=AT(_e|0,Ge|0,1e9,0)|0,n[B>>2]=Xe,F=uT(_e|0,Ge|0,1e9,0)|0,B=B+-4|0;while(B>>>0>=M>>>0);F&&(M=M+-4|0,n[M>>2]=F)}for(F=j;!(F>>>0<=M>>>0);)if(B=F+-4|0,!(n[B>>2]|0))F=B;else break;if(B=(n[rt>>2]|0)-O|0,n[rt>>2]=B,(B|0)>0)j=F;else break}else M=Zt;if((B|0)<0){f=((k+25|0)/9|0)+1|0,Qe=(ct|0)==102;do{if(Oe=0-B|0,Oe=(Oe|0)<9?Oe:9,M>>>0<F>>>0){O=(1<<Oe)+-1|0,j=1e9>>>Oe,oe=0,B=M;do Ge=n[B>>2]|0,n[B>>2]=(Ge>>>Oe)+oe,oe=He(Ge&O,j)|0,B=B+4|0;while(B>>>0<F>>>0);B=n[M>>2]|0?M:M+4|0,oe?(n[F>>2]=oe,M=B,B=F+4|0):(M=B,B=F)}else M=n[M>>2]|0?M:M+4|0,B=F;F=Qe?Zt:M,F=(B-F>>2|0)>(f|0)?F+(f<<2)|0:B,B=(n[rt>>2]|0)+Oe|0,n[rt>>2]=B}while((B|0)<0);B=M,f=F}else B=M,f=F;if(Ge=Zt,B>>>0<f>>>0){if(F=(Ge-B>>2)*9|0,O=n[B>>2]|0,O>>>0>=10){M=10;do M=M*10|0,F=F+1|0;while(O>>>0>=M>>>0)}}else F=0;if(Qe=(ct|0)==103,Xe=(k|0)!=0,M=k-((ct|0)!=102?F:0)+((Xe&Qe)<<31>>31)|0,(M|0)<(((f-Ge>>2)*9|0)+-9|0)){if(M=M+9216|0,Oe=Zt+4+(((M|0)/9|0)+-1024<<2)|0,M=((M|0)%9|0)+1|0,(M|0)<9){O=10;do O=O*10|0,M=M+1|0;while((M|0)!=9)}else O=10;if(j=n[Oe>>2]|0,oe=(j>>>0)%(O>>>0)|0,M=(Oe+4|0)==(f|0),M&(oe|0)==0)M=Oe;else if(We=((j>>>0)/(O>>>0)|0)&1|0?9007199254740994:9007199254740992,_e=(O|0)/2|0,l=oe>>>0<_e>>>0?.5:M&(oe|0)==(_e|0)?1:1.5,ur&&(_e=(o[_r>>0]|0)==45,l=_e?-l:l,We=_e?-We:We),M=j-oe|0,n[Oe>>2]=M,We+l!=We){if(_e=M+O|0,n[Oe>>2]=_e,_e>>>0>999999999)for(F=Oe;M=F+-4|0,n[F>>2]=0,M>>>0<B>>>0&&(B=B+-4|0,n[B>>2]=0),_e=(n[M>>2]|0)+1|0,n[M>>2]=_e,_e>>>0>999999999;)F=M;else M=Oe;if(F=(Ge-B>>2)*9|0,j=n[B>>2]|0,j>>>0>=10){O=10;do O=O*10|0,F=F+1|0;while(j>>>0>=O>>>0)}}else M=Oe;M=M+4|0,M=f>>>0>M>>>0?M:f,_e=B}else M=f,_e=B;for(ct=M;;){if(ct>>>0<=_e>>>0){rt=0;break}if(B=ct+-4|0,!(n[B>>2]|0))ct=B;else{rt=1;break}}f=0-F|0;do if(Qe)if(B=((Xe^1)&1)+k|0,(B|0)>(F|0)&(F|0)>-5?(O=m+-1|0,k=B+-1-F|0):(O=m+-2|0,k=B+-1|0),B=d&8,B)Oe=B;else{if(rt&&(Nt=n[ct+-4>>2]|0,(Nt|0)!=0))if((Nt>>>0)%10|0)M=0;else{M=0,B=10;do B=B*10|0,M=M+1|0;while(!((Nt>>>0)%(B>>>0)|0|0))}else M=9;if(B=((ct-Ge>>2)*9|0)+-9|0,(O|32|0)==102){Oe=B-M|0,Oe=(Oe|0)>0?Oe:0,k=(k|0)<(Oe|0)?k:Oe,Oe=0;break}else{Oe=B+F-M|0,Oe=(Oe|0)>0?Oe:0,k=(k|0)<(Oe|0)?k:Oe,Oe=0;break}}else O=m,Oe=d&8;while(!1);if(Qe=k|Oe,j=(Qe|0)!=0&1,oe=(O|32|0)==102,oe)Xe=0,B=(F|0)>0?F:0;else{if(B=(F|0)<0?f:F,B=nm(B,((B|0)<0)<<31>>31,kr)|0,M=kr,(M-B|0)<2)do B=B+-1|0,o[B>>0]=48;while((M-B|0)<2);o[B+-1>>0]=(F>>31&2)+43,B=B+-2|0,o[B>>0]=O,Xe=B,B=M-B|0}if(B=ur+1+k+j+B|0,Es(s,32,c,B,d),os(s,_r,ur),Es(s,48,c,B,d^65536),oe){O=_e>>>0>Zt>>>0?Zt:_e,Oe=lr+9|0,j=Oe,oe=lr+8|0,M=O;do{if(F=nm(n[M>>2]|0,0,Oe)|0,(M|0)==(O|0))(F|0)==(Oe|0)&&(o[oe>>0]=48,F=oe);else if(F>>>0>lr>>>0){sm(lr|0,48,F-Or|0)|0;do F=F+-1|0;while(F>>>0>lr>>>0)}os(s,F,j-F|0),M=M+4|0}while(M>>>0<=Zt>>>0);if(Qe|0&&os(s,5710,1),M>>>0<ct>>>0&(k|0)>0)for(;;){if(F=nm(n[M>>2]|0,0,Oe)|0,F>>>0>lr>>>0){sm(lr|0,48,F-Or|0)|0;do F=F+-1|0;while(F>>>0>lr>>>0)}if(os(s,F,(k|0)<9?k:9),M=M+4|0,F=k+-9|0,M>>>0<ct>>>0&(k|0)>9)k=F;else{k=F;break}}Es(s,48,k+9|0,9,0)}else{if(Qe=rt?ct:_e+4|0,(k|0)>-1){rt=lr+9|0,Oe=(Oe|0)==0,f=rt,j=0-Or|0,oe=lr+8|0,O=_e;do{F=nm(n[O>>2]|0,0,rt)|0,(F|0)==(rt|0)&&(o[oe>>0]=48,F=oe);do if((O|0)==(_e|0)){if(M=F+1|0,os(s,F,1),Oe&(k|0)<1){F=M;break}os(s,5710,1),F=M}else{if(F>>>0<=lr>>>0)break;sm(lr|0,48,F+j|0)|0;do F=F+-1|0;while(F>>>0>lr>>>0)}while(!1);Or=f-F|0,os(s,F,(k|0)>(Or|0)?Or:k),k=k-Or|0,O=O+4|0}while(O>>>0<Qe>>>0&(k|0)>-1)}Es(s,48,k+18|0,18,0),os(s,Xe,kr-Xe|0)}Es(s,32,c,B,d^8192)}else lr=(m&32|0)!=0,B=ur+3|0,Es(s,32,c,B,d&-65537),os(s,_r,ur),os(s,l!=l|!1?lr?5686:5690:lr?5678:5682,3),Es(s,32,c,B,d^8192);while(!1);return C=Ln,((B|0)<(c|0)?c:B)|0}function q7(s){s=+s;var l=0;return E[D>>3]=s,l=n[D>>2]|0,Ce=n[D+4>>2]|0,l|0}function kUe(s,l){return s=+s,l=l|0,+ +j7(s,l)}function j7(s,l){s=+s,l=l|0;var c=0,f=0,d=0;switch(E[D>>3]=s,c=n[D>>2]|0,f=n[D+4>>2]|0,d=GD(c|0,f|0,52)|0,d&2047){case 0:{s!=0?(s=+j7(s*18446744073709552e3,l),c=(n[l>>2]|0)+-64|0):c=0,n[l>>2]=c;break}case 2047:break;default:n[l>>2]=(d&2047)+-1022,n[D>>2]=c,n[D+4>>2]=f&-2146435073|1071644672,s=+E[D>>3]}return+s}function QUe(s,l,c){s=s|0,l=l|0,c=c|0;do if(s){if(l>>>0<128){o[s>>0]=l,s=1;break}if(!(n[n[(FUe()|0)+188>>2]>>2]|0))if((l&-128|0)==57216){o[s>>0]=l,s=1;break}else{n[(rm()|0)>>2]=84,s=-1;break}if(l>>>0<2048){o[s>>0]=l>>>6|192,o[s+1>>0]=l&63|128,s=2;break}if(l>>>0<55296|(l&-8192|0)==57344){o[s>>0]=l>>>12|224,o[s+1>>0]=l>>>6&63|128,o[s+2>>0]=l&63|128,s=3;break}if((l+-65536|0)>>>0<1048576){o[s>>0]=l>>>18|240,o[s+1>>0]=l>>>12&63|128,o[s+2>>0]=l>>>6&63|128,o[s+3>>0]=l&63|128,s=4;break}else{n[(rm()|0)>>2]=84,s=-1;break}}else s=1;while(!1);return s|0}function FUe(){return oT()|0}function RUe(){return oT()|0}function TUe(s,l){s=s|0,l=l|0;var c=0,f=0;for(f=0;;){if((u[5712+f>>0]|0)==(s|0)){s=2;break}if(c=f+1|0,(c|0)==87){c=5800,f=87,s=5;break}else f=c}if((s|0)==2&&(f?(c=5800,s=5):c=5800),(s|0)==5)for(;;){do s=c,c=c+1|0;while(o[s>>0]|0);if(f=f+-1|0,f)s=5;else break}return LUe(c,n[l+20>>2]|0)|0}function LUe(s,l){return s=s|0,l=l|0,NUe(s,l)|0}function NUe(s,l){return s=s|0,l=l|0,l?l=OUe(n[l>>2]|0,n[l+4>>2]|0,s)|0:l=0,(l|0?l:s)|0}function OUe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0;oe=(n[s>>2]|0)+1794895138|0,m=O0(n[s+8>>2]|0,oe)|0,f=O0(n[s+12>>2]|0,oe)|0,d=O0(n[s+16>>2]|0,oe)|0;e:do if(m>>>0<l>>>2>>>0&&(j=l-(m<<2)|0,f>>>0<j>>>0&d>>>0<j>>>0)&&!((d|f)&3|0)){for(j=f>>>2,O=d>>>2,M=0;;){if(k=m>>>1,F=M+k|0,B=F<<1,d=B+j|0,f=O0(n[s+(d<<2)>>2]|0,oe)|0,d=O0(n[s+(d+1<<2)>>2]|0,oe)|0,!(d>>>0<l>>>0&f>>>0<(l-d|0)>>>0)){f=0;break e}if(o[s+(d+f)>>0]|0){f=0;break e}if(f=O7(c,s+d|0)|0,!f)break;if(f=(f|0)<0,(m|0)==1){f=0;break e}else M=f?M:F,m=f?k:m-k|0}f=B+O|0,d=O0(n[s+(f<<2)>>2]|0,oe)|0,f=O0(n[s+(f+1<<2)>>2]|0,oe)|0,f>>>0<l>>>0&d>>>0<(l-f|0)>>>0?f=o[s+(f+d)>>0]|0?0:s+f|0:f=0}else f=0;while(!1);return f|0}function O0(s,l){s=s|0,l=l|0;var c=0;return c=X7(s|0)|0,(l|0?c:s)|0}function MUe(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0,k=0;f=c+16|0,d=n[f>>2]|0,d?m=5:UUe(c)|0?f=0:(d=n[f>>2]|0,m=5);e:do if((m|0)==5){if(k=c+20|0,B=n[k>>2]|0,f=B,(d-B|0)>>>0<l>>>0){f=YD[n[c+36>>2]&7](c,s,l)|0;break}t:do if((o[c+75>>0]|0)>-1){for(B=l;;){if(!B){m=0,d=s;break t}if(d=B+-1|0,(o[s+d>>0]|0)==10)break;B=d}if(f=YD[n[c+36>>2]&7](c,s,B)|0,f>>>0<B>>>0)break e;m=B,d=s+B|0,l=l-B|0,f=n[k>>2]|0}else m=0,d=s;while(!1);br(f|0,d|0,l|0)|0,n[k>>2]=(n[k>>2]|0)+l,f=m+l|0}while(!1);return f|0}function UUe(s){s=s|0;var l=0,c=0;return l=s+74|0,c=o[l>>0]|0,o[l>>0]=c+255|c,l=n[s>>2]|0,l&8?(n[s>>2]=l|32,s=-1):(n[s+8>>2]=0,n[s+4>>2]=0,c=n[s+44>>2]|0,n[s+28>>2]=c,n[s+20>>2]=c,n[s+16>>2]=c+(n[s+48>>2]|0),s=0),s|0}function Yn(s,l){s=y(s),l=y(l);var c=0,f=0;c=G7(s)|0;do if((c&2147483647)>>>0<=2139095040){if(f=G7(l)|0,(f&2147483647)>>>0<=2139095040)if((f^c|0)<0){s=(c|0)<0?l:s;break}else{s=s<l?l:s;break}}else s=l;while(!1);return y(s)}function G7(s){return s=y(s),h[D>>2]=s,n[D>>2]|0|0}function M0(s,l){s=y(s),l=y(l);var c=0,f=0;c=W7(s)|0;do if((c&2147483647)>>>0<=2139095040){if(f=W7(l)|0,(f&2147483647)>>>0<=2139095040)if((f^c|0)<0){s=(c|0)<0?s:l;break}else{s=s<l?s:l;break}}else s=l;while(!1);return y(s)}function W7(s){return s=y(s),h[D>>2]=s,n[D>>2]|0|0}function lT(s,l){s=y(s),l=y(l);var c=0,f=0,d=0,m=0,B=0,k=0,F=0,M=0;m=(h[D>>2]=s,n[D>>2]|0),k=(h[D>>2]=l,n[D>>2]|0),c=m>>>23&255,B=k>>>23&255,F=m&-2147483648,d=k<<1;e:do if(d|0&&!((c|0)==255|((_Ue(l)|0)&2147483647)>>>0>2139095040)){if(f=m<<1,f>>>0<=d>>>0)return l=y(s*y(0)),y((f|0)==(d|0)?l:s);if(c)f=m&8388607|8388608;else{if(c=m<<9,(c|0)>-1){f=c,c=0;do c=c+-1|0,f=f<<1;while((f|0)>-1)}else c=0;f=m<<1-c}if(B)k=k&8388607|8388608;else{if(m=k<<9,(m|0)>-1){d=0;do d=d+-1|0,m=m<<1;while((m|0)>-1)}else d=0;B=d,k=k<<1-d}d=f-k|0,m=(d|0)>-1;t:do if((c|0)>(B|0)){for(;;){if(m)if(d)f=d;else break;if(f=f<<1,c=c+-1|0,d=f-k|0,m=(d|0)>-1,(c|0)<=(B|0))break t}l=y(s*y(0));break e}while(!1);if(m)if(d)f=d;else{l=y(s*y(0));break}if(f>>>0<8388608)do f=f<<1,c=c+-1|0;while(f>>>0<8388608);(c|0)>0?c=f+-8388608|c<<23:c=f>>>(1-c|0),l=(n[D>>2]=c|F,y(h[D>>2]))}else M=3;while(!1);return(M|0)==3&&(l=y(s*l),l=y(l/l)),y(l)}function _Ue(s){return s=y(s),h[D>>2]=s,n[D>>2]|0|0}function HUe(s,l){return s=s|0,l=l|0,M7(n[582]|0,s,l)|0}function Zr(s){s=s|0,Tt()}function im(s){s=s|0}function qUe(s,l){return s=s|0,l=l|0,0}function jUe(s){return s=s|0,(Y7(s+4|0)|0)==-1?(ef[n[(n[s>>2]|0)+8>>2]&127](s),s=1):s=0,s|0}function Y7(s){s=s|0;var l=0;return l=n[s>>2]|0,n[s>>2]=l+-1,l+-1|0}function Rp(s){s=s|0,jUe(s)|0&&GUe(s)}function GUe(s){s=s|0;var l=0;l=s+8|0,n[l>>2]|0&&(Y7(l)|0)!=-1||ef[n[(n[s>>2]|0)+16>>2]&127](s)}function Yt(s){s=s|0;var l=0;for(l=s|0?s:1;s=_D(l)|0,!(s|0);){if(s=YUe()|0,!s){s=0;break}aW[s&0]()}return s|0}function K7(s){return s=s|0,Yt(s)|0}function yt(s){s=s|0,HD(s)}function WUe(s){s=s|0,(o[s+11>>0]|0)<0&&yt(n[s>>2]|0)}function YUe(){var s=0;return s=n[2923]|0,n[2923]=s+0,s|0}function KUe(){}function jD(s,l,c,f){return s=s|0,l=l|0,c=c|0,f=f|0,f=l-f-(c>>>0>s>>>0|0)>>>0,Ce=f,s-c>>>0|0|0}function cT(s,l,c,f){return s=s|0,l=l|0,c=c|0,f=f|0,c=s+c>>>0,Ce=l+f+(c>>>0<s>>>0|0)>>>0,c|0|0}function sm(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0,B=0;if(m=s+c|0,l=l&255,(c|0)>=67){for(;s&3;)o[s>>0]=l,s=s+1|0;for(f=m&-4|0,d=f-64|0,B=l|l<<8|l<<16|l<<24;(s|0)<=(d|0);)n[s>>2]=B,n[s+4>>2]=B,n[s+8>>2]=B,n[s+12>>2]=B,n[s+16>>2]=B,n[s+20>>2]=B,n[s+24>>2]=B,n[s+28>>2]=B,n[s+32>>2]=B,n[s+36>>2]=B,n[s+40>>2]=B,n[s+44>>2]=B,n[s+48>>2]=B,n[s+52>>2]=B,n[s+56>>2]=B,n[s+60>>2]=B,s=s+64|0;for(;(s|0)<(f|0);)n[s>>2]=B,s=s+4|0}for(;(s|0)<(m|0);)o[s>>0]=l,s=s+1|0;return m-c|0}function V7(s,l,c){return s=s|0,l=l|0,c=c|0,(c|0)<32?(Ce=l<<c|(s&(1<<c)-1<<32-c)>>>32-c,s<<c):(Ce=s<<c-32,0)}function GD(s,l,c){return s=s|0,l=l|0,c=c|0,(c|0)<32?(Ce=l>>>c,s>>>c|(l&(1<<c)-1)<<32-c):(Ce=0,l>>>c-32|0)}function br(s,l,c){s=s|0,l=l|0,c=c|0;var f=0,d=0,m=0;if((c|0)>=8192)return FA(s|0,l|0,c|0)|0;if(m=s|0,d=s+c|0,(s&3)==(l&3)){for(;s&3;){if(!c)return m|0;o[s>>0]=o[l>>0]|0,s=s+1|0,l=l+1|0,c=c-1|0}for(c=d&-4|0,f=c-64|0;(s|0)<=(f|0);)n[s>>2]=n[l>>2],n[s+4>>2]=n[l+4>>2],n[s+8>>2]=n[l+8>>2],n[s+12>>2]=n[l+12>>2],n[s+16>>2]=n[l+16>>2],n[s+20>>2]=n[l+20>>2],n[s+24>>2]=n[l+24>>2],n[s+28>>2]=n[l+28>>2],n[s+32>>2]=n[l+32>>2],n[s+36>>2]=n[l+36>>2],n[s+40>>2]=n[l+40>>2],n[s+44>>2]=n[l+44>>2],n[s+48>>2]=n[l+48>>2],n[s+52>>2]=n[l+52>>2],n[s+56>>2]=n[l+56>>2],n[s+60>>2]=n[l+60>>2],s=s+64|0,l=l+64|0;for(;(s|0)<(c|0);)n[s>>2]=n[l>>2],s=s+4|0,l=l+4|0}else for(c=d-4|0;(s|0)<(c|0);)o[s>>0]=o[l>>0]|0,o[s+1>>0]=o[l+1>>0]|0,o[s+2>>0]=o[l+2>>0]|0,o[s+3>>0]=o[l+3>>0]|0,s=s+4|0,l=l+4|0;for(;(s|0)<(d|0);)o[s>>0]=o[l>>0]|0,s=s+1|0,l=l+1|0;return m|0}function z7(s){s=s|0;var l=0;return l=o[N+(s&255)>>0]|0,(l|0)<8?l|0:(l=o[N+(s>>8&255)>>0]|0,(l|0)<8?l+8|0:(l=o[N+(s>>16&255)>>0]|0,(l|0)<8?l+16|0:(o[N+(s>>>24)>>0]|0)+24|0))}function J7(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0;var m=0,B=0,k=0,F=0,M=0,O=0,j=0,oe=0,We=0,Oe=0;if(O=s,F=l,M=F,B=c,oe=f,k=oe,!M)return m=(d|0)!=0,k?m?(n[d>>2]=s|0,n[d+4>>2]=l&0,oe=0,d=0,Ce=oe,d|0):(oe=0,d=0,Ce=oe,d|0):(m&&(n[d>>2]=(O>>>0)%(B>>>0),n[d+4>>2]=0),oe=0,d=(O>>>0)/(B>>>0)>>>0,Ce=oe,d|0);m=(k|0)==0;do if(B){if(!m){if(m=(S(k|0)|0)-(S(M|0)|0)|0,m>>>0<=31){j=m+1|0,k=31-m|0,l=m-31>>31,B=j,s=O>>>(j>>>0)&l|M<<k,l=M>>>(j>>>0)&l,m=0,k=O<<k;break}return d?(n[d>>2]=s|0,n[d+4>>2]=F|l&0,oe=0,d=0,Ce=oe,d|0):(oe=0,d=0,Ce=oe,d|0)}if(m=B-1|0,m&B|0){k=(S(B|0)|0)+33-(S(M|0)|0)|0,Oe=64-k|0,j=32-k|0,F=j>>31,We=k-32|0,l=We>>31,B=k,s=j-1>>31&M>>>(We>>>0)|(M<<j|O>>>(k>>>0))&l,l=l&M>>>(k>>>0),m=O<<Oe&F,k=(M<<Oe|O>>>(We>>>0))&F|O<<j&k-33>>31;break}return d|0&&(n[d>>2]=m&O,n[d+4>>2]=0),(B|0)==1?(We=F|l&0,Oe=s|0|0,Ce=We,Oe|0):(Oe=z7(B|0)|0,We=M>>>(Oe>>>0)|0,Oe=M<<32-Oe|O>>>(Oe>>>0)|0,Ce=We,Oe|0)}else{if(m)return d|0&&(n[d>>2]=(M>>>0)%(B>>>0),n[d+4>>2]=0),We=0,Oe=(M>>>0)/(B>>>0)>>>0,Ce=We,Oe|0;if(!O)return d|0&&(n[d>>2]=0,n[d+4>>2]=(M>>>0)%(k>>>0)),We=0,Oe=(M>>>0)/(k>>>0)>>>0,Ce=We,Oe|0;if(m=k-1|0,!(m&k))return d|0&&(n[d>>2]=s|0,n[d+4>>2]=m&M|l&0),We=0,Oe=M>>>((z7(k|0)|0)>>>0),Ce=We,Oe|0;if(m=(S(k|0)|0)-(S(M|0)|0)|0,m>>>0<=30){l=m+1|0,k=31-m|0,B=l,s=M<<k|O>>>(l>>>0),l=M>>>(l>>>0),m=0,k=O<<k;break}return d?(n[d>>2]=s|0,n[d+4>>2]=F|l&0,We=0,Oe=0,Ce=We,Oe|0):(We=0,Oe=0,Ce=We,Oe|0)}while(!1);if(!B)M=k,F=0,k=0;else{j=c|0|0,O=oe|f&0,M=cT(j|0,O|0,-1,-1)|0,c=Ce,F=k,k=0;do f=F,F=m>>>31|F<<1,m=k|m<<1,f=s<<1|f>>>31|0,oe=s>>>31|l<<1|0,jD(M|0,c|0,f|0,oe|0)|0,Oe=Ce,We=Oe>>31|((Oe|0)<0?-1:0)<<1,k=We&1,s=jD(f|0,oe|0,We&j|0,(((Oe|0)<0?-1:0)>>31|((Oe|0)<0?-1:0)<<1)&O|0)|0,l=Ce,B=B-1|0;while(B|0);M=F,F=0}return B=0,d|0&&(n[d>>2]=s,n[d+4>>2]=l),We=(m|0)>>>31|(M|B)<<1|(B<<1|m>>>31)&0|F,Oe=(m<<1|0)&-2|k,Ce=We,Oe|0}function uT(s,l,c,f){return s=s|0,l=l|0,c=c|0,f=f|0,J7(s,l,c,f,0)|0}function Tp(s){s=s|0;var l=0,c=0;return c=s+15&-16|0,l=n[w>>2]|0,s=l+c|0,(c|0)>0&(s|0)<(l|0)|(s|0)<0?(se()|0,yc(12),-1):(n[w>>2]=s,(s|0)>($()|0)&&!(X()|0)?(n[w>>2]=l,yc(12),-1):l|0)}function rw(s,l,c){s=s|0,l=l|0,c=c|0;var f=0;if((l|0)<(s|0)&(s|0)<(l+c|0)){for(f=s,l=l+c|0,s=s+c|0;(c|0)>0;)s=s-1|0,l=l-1|0,c=c-1|0,o[s>>0]=o[l>>0]|0;s=f}else br(s,l,c)|0;return s|0}function AT(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0;var d=0,m=0;return m=C,C=C+16|0,d=m|0,J7(s,l,c,f,d)|0,C=m,Ce=n[d+4>>2]|0,n[d>>2]|0|0}function X7(s){return s=s|0,(s&255)<<24|(s>>8&255)<<16|(s>>16&255)<<8|s>>>24|0}function VUe(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,Z7[s&1](l|0,c|0,f|0,d|0,m|0)}function zUe(s,l,c){s=s|0,l=l|0,c=y(c),$7[s&1](l|0,y(c))}function JUe(s,l,c){s=s|0,l=l|0,c=+c,eW[s&31](l|0,+c)}function XUe(s,l,c,f){return s=s|0,l=l|0,c=y(c),f=y(f),y(tW[s&0](l|0,y(c),y(f)))}function ZUe(s,l){s=s|0,l=l|0,ef[s&127](l|0)}function $Ue(s,l,c){s=s|0,l=l|0,c=c|0,tf[s&31](l|0,c|0)}function e3e(s,l){return s=s|0,l=l|0,_0[s&31](l|0)|0}function t3e(s,l,c,f,d){s=s|0,l=l|0,c=+c,f=+f,d=d|0,rW[s&1](l|0,+c,+f,d|0)}function r3e(s,l,c,f){s=s|0,l=l|0,c=+c,f=+f,N3e[s&1](l|0,+c,+f)}function n3e(s,l,c,f){return s=s|0,l=l|0,c=c|0,f=f|0,YD[s&7](l|0,c|0,f|0)|0}function i3e(s,l,c,f){return s=s|0,l=l|0,c=c|0,f=f|0,+O3e[s&1](l|0,c|0,f|0)}function s3e(s,l){return s=s|0,l=l|0,+nW[s&15](l|0)}function o3e(s,l,c){return s=s|0,l=l|0,c=+c,M3e[s&1](l|0,+c)|0}function a3e(s,l,c){return s=s|0,l=l|0,c=c|0,pT[s&15](l|0,c|0)|0}function l3e(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=+f,d=+d,m=m|0,U3e[s&1](l|0,c|0,+f,+d,m|0)}function c3e(s,l,c,f,d,m,B){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,B=B|0,_3e[s&1](l|0,c|0,f|0,d|0,m|0,B|0)}function u3e(s,l,c){return s=s|0,l=l|0,c=c|0,+iW[s&7](l|0,c|0)}function A3e(s){return s=s|0,KD[s&7]()|0}function f3e(s,l,c,f,d,m){return s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,sW[s&1](l|0,c|0,f|0,d|0,m|0)|0}function p3e(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=+d,H3e[s&1](l|0,c|0,f|0,+d)}function h3e(s,l,c,f,d,m,B){s=s|0,l=l|0,c=c|0,f=y(f),d=d|0,m=y(m),B=B|0,oW[s&1](l|0,c|0,y(f),d|0,y(m),B|0)}function g3e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,sw[s&15](l|0,c|0,f|0)}function d3e(s){s=s|0,aW[s&0]()}function m3e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=+f,lW[s&15](l|0,c|0,+f)}function y3e(s,l,c){return s=s|0,l=+l,c=+c,q3e[s&1](+l,+c)|0}function E3e(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,hT[s&15](l|0,c|0,f|0,d|0)}function C3e(s,l,c,f,d){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,R(0)}function I3e(s,l){s=s|0,l=y(l),R(1)}function Ca(s,l){s=s|0,l=+l,R(2)}function w3e(s,l,c){return s=s|0,l=y(l),c=y(c),R(3),Ze}function Cr(s){s=s|0,R(4)}function nw(s,l){s=s|0,l=l|0,R(5)}function tl(s){return s=s|0,R(6),0}function B3e(s,l,c,f){s=s|0,l=+l,c=+c,f=f|0,R(7)}function v3e(s,l,c){s=s|0,l=+l,c=+c,R(8)}function D3e(s,l,c){return s=s|0,l=l|0,c=c|0,R(9),0}function P3e(s,l,c){return s=s|0,l=l|0,c=c|0,R(10),0}function U0(s){return s=s|0,R(11),0}function S3e(s,l){return s=s|0,l=+l,R(12),0}function iw(s,l){return s=s|0,l=l|0,R(13),0}function x3e(s,l,c,f,d){s=s|0,l=l|0,c=+c,f=+f,d=d|0,R(14)}function b3e(s,l,c,f,d,m){s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,m=m|0,R(15)}function fT(s,l){return s=s|0,l=l|0,R(16),0}function k3e(){return R(17),0}function Q3e(s,l,c,f,d){return s=s|0,l=l|0,c=c|0,f=f|0,d=d|0,R(18),0}function F3e(s,l,c,f){s=s|0,l=l|0,c=c|0,f=+f,R(19)}function R3e(s,l,c,f,d,m){s=s|0,l=l|0,c=y(c),f=f|0,d=y(d),m=m|0,R(20)}function WD(s,l,c){s=s|0,l=l|0,c=c|0,R(21)}function T3e(){R(22)}function om(s,l,c){s=s|0,l=l|0,c=+c,R(23)}function L3e(s,l){return s=+s,l=+l,R(24),0}function am(s,l,c,f){s=s|0,l=l|0,c=c|0,f=f|0,R(25)}var Z7=[C3e,QNe],$7=[I3e,Od],eW=[Ca,B0,vp,UI,_I,HI,qI,ku,Wd,jI,Qu,v0,D0,GI,WI,bc,P0,YI,Yd,Ca,Ca,Ca,Ca,Ca,Ca,Ca,Ca,Ca,Ca,Ca,Ca,Ca],tW=[w3e],ef=[Cr,im,ADe,fDe,pDe,qxe,jxe,Gxe,oLe,aLe,lLe,yNe,ENe,CNe,_4e,H4e,q4e,qa,w0,LI,ir,bl,bD,kD,tDe,IDe,RDe,XDe,pPe,kPe,KPe,lSe,BSe,USe,txe,mxe,Rxe,abe,Bbe,Ube,tke,mke,Rke,Zke,pQe,SQe,jQe,dD,CFe,NFe,tRe,ERe,TRe,tTe,ATe,hTe,QTe,TTe,XTe,uLe,pLe,kLe,VLe,MG,bOe,oMe,IMe,NMe,i4e,E4e,k4e,R4e,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr,Cr],tf=[nw,qd,YF,NI,OI,Sr,Os,Oi,ms,is,Gd,Bp,VI,ID,b0,zF,JF,wD,BD,$F,Fu,ne,rQe,dQe,BRe,FOe,rNe,w7,nw,nw,nw,nw],_0=[tl,mUe,_d,x0,Vd,qo,mD,Dp,KI,VF,ED,zd,vD,eR,Zd,YQe,MRe,RLe,NOe,Za,tl,tl,tl,tl,tl,tl,tl,tl,tl,tl,tl,tl],rW=[B3e,sR],N3e=[v3e,eLe],YD=[D3e,N7,yUe,IUe,TPe,Abe,vFe,_Me],O3e=[P3e,sxe],nW=[U0,Pp,CD,zA,oR,v,P,Q,H,Y,U0,U0,U0,U0,U0,U0],M3e=[S3e,lTe],pT=[iw,qUe,DD,sDe,tPe,JPe,ASe,Oxe,Sbe,QQe,Md,DMe,iw,iw,iw,iw],U3e=[x3e,ODe],_3e=[b3e,l4e],iW=[fT,XF,Be,Ue,ft,Ixe,fT,fT],KD=[k3e,jt,Ud,gD,yTe,MTe,mLe,O4e],sW=[Q3e,kd],H3e=[F3e,ske],oW=[R3e,tR],sw=[WD,oo,yD,ZF,Qc,mPe,PSe,Ike,Oke,WF,eOe,uMe,B4e,WD,WD,WD],aW=[T3e],lW=[om,KF,jd,VA,MI,kc,Kd,S0,jbe,_Fe,iTe,om,om,om,om,om],q3e=[L3e,iLe],hT=[am,jSe,eFe,sRe,KRe,vTe,GTe,vLe,$Le,qOe,V4e,am,am,am,am,am];return{_llvm_bswap_i32:X7,dynCall_idd:y3e,dynCall_i:A3e,_i64Subtract:jD,___udivdi3:uT,dynCall_vif:zUe,setThrew:No,dynCall_viii:g3e,_bitshift64Lshr:GD,_bitshift64Shl:V7,dynCall_vi:ZUe,dynCall_viiddi:l3e,dynCall_diii:i3e,dynCall_iii:a3e,_memset:sm,_sbrk:Tp,_memcpy:br,__GLOBAL__sub_I_Yoga_cpp:FI,dynCall_vii:$Ue,___uremdi3:AT,dynCall_vid:JUe,stackAlloc:ca,_nbind_init:sUe,getTempRet0:TA,dynCall_di:s3e,dynCall_iid:o3e,setTempRet0:RA,_i64Add:cT,dynCall_fiff:XUe,dynCall_iiii:n3e,_emscripten_get_global_libc:dUe,dynCall_viid:m3e,dynCall_viiid:p3e,dynCall_viififi:h3e,dynCall_ii:e3e,__GLOBAL__sub_I_Binding_cc:IOe,dynCall_viiii:E3e,dynCall_iiiiii:f3e,stackSave:mu,dynCall_viiiii:VUe,__GLOBAL__sub_I_nbind_cc:wr,dynCall_vidd:r3e,_free:HD,runPostSets:KUe,dynCall_viiiiii:c3e,establishStackSpace:dn,_memmove:rw,stackRestore:Bl,_malloc:_D,__GLOBAL__sub_I_common_cc:HLe,dynCall_viddi:t3e,dynCall_dii:u3e,dynCall_v:d3e}}(Module.asmGlobalArg,Module.asmLibraryArg,buffer),_llvm_bswap_i32=Module._llvm_bswap_i32=asm._llvm_bswap_i32,getTempRet0=Module.getTempRet0=asm.getTempRet0,___udivdi3=Module.___udivdi3=asm.___udivdi3,setThrew=Module.setThrew=asm.setThrew,_bitshift64Lshr=Module._bitshift64Lshr=asm._bitshift64Lshr,_bitshift64Shl=Module._bitshift64Shl=asm._bitshift64Shl,_memset=Module._memset=asm._memset,_sbrk=Module._sbrk=asm._sbrk,_memcpy=Module._memcpy=asm._memcpy,stackAlloc=Module.stackAlloc=asm.stackAlloc,___uremdi3=Module.___uremdi3=asm.___uremdi3,_nbind_init=Module._nbind_init=asm._nbind_init,_i64Subtract=Module._i64Subtract=asm._i64Subtract,setTempRet0=Module.setTempRet0=asm.setTempRet0,_i64Add=Module._i64Add=asm._i64Add,_emscripten_get_global_libc=Module._emscripten_get_global_libc=asm._emscripten_get_global_libc,__GLOBAL__sub_I_Yoga_cpp=Module.__GLOBAL__sub_I_Yoga_cpp=asm.__GLOBAL__sub_I_Yoga_cpp,__GLOBAL__sub_I_Binding_cc=Module.__GLOBAL__sub_I_Binding_cc=asm.__GLOBAL__sub_I_Binding_cc,stackSave=Module.stackSave=asm.stackSave,__GLOBAL__sub_I_nbind_cc=Module.__GLOBAL__sub_I_nbind_cc=asm.__GLOBAL__sub_I_nbind_cc,_free=Module._free=asm._free,runPostSets=Module.runPostSets=asm.runPostSets,establishStackSpace=Module.establishStackSpace=asm.establishStackSpace,_memmove=Module._memmove=asm._memmove,stackRestore=Module.stackRestore=asm.stackRestore,_malloc=Module._malloc=asm._malloc,__GLOBAL__sub_I_common_cc=Module.__GLOBAL__sub_I_common_cc=asm.__GLOBAL__sub_I_common_cc,dynCall_viiiii=Module.dynCall_viiiii=asm.dynCall_viiiii,dynCall_vif=Module.dynCall_vif=asm.dynCall_vif,dynCall_vid=Module.dynCall_vid=asm.dynCall_vid,dynCall_fiff=Module.dynCall_fiff=asm.dynCall_fiff,dynCall_vi=Module.dynCall_vi=asm.dynCall_vi,dynCall_vii=Module.dynCall_vii=asm.dynCall_vii,dynCall_ii=Module.dynCall_ii=asm.dynCall_ii,dynCall_viddi=Module.dynCall_viddi=asm.dynCall_viddi,dynCall_vidd=Module.dynCall_vidd=asm.dynCall_vidd,dynCall_iiii=Module.dynCall_iiii=asm.dynCall_iiii,dynCall_diii=Module.dynCall_diii=asm.dynCall_diii,dynCall_di=Module.dynCall_di=asm.dynCall_di,dynCall_iid=Module.dynCall_iid=asm.dynCall_iid,dynCall_iii=Module.dynCall_iii=asm.dynCall_iii,dynCall_viiddi=Module.dynCall_viiddi=asm.dynCall_viiddi,dynCall_viiiiii=Module.dynCall_viiiiii=asm.dynCall_viiiiii,dynCall_dii=Module.dynCall_dii=asm.dynCall_dii,dynCall_i=Module.dynCall_i=asm.dynCall_i,dynCall_iiiiii=Module.dynCall_iiiiii=asm.dynCall_iiiiii,dynCall_viiid=Module.dynCall_viiid=asm.dynCall_viiid,dynCall_viififi=Module.dynCall_viififi=asm.dynCall_viififi,dynCall_viii=Module.dynCall_viii=asm.dynCall_viii,dynCall_v=Module.dynCall_v=asm.dynCall_v,dynCall_viid=Module.dynCall_viid=asm.dynCall_viid,dynCall_idd=Module.dynCall_idd=asm.dynCall_idd,dynCall_viiii=Module.dynCall_viiii=asm.dynCall_viiii;Runtime.stackAlloc=Module.stackAlloc,Runtime.stackSave=Module.stackSave,Runtime.stackRestore=Module.stackRestore,Runtime.establishStackSpace=Module.establishStackSpace,Runtime.setTempRet0=Module.setTempRet0,Runtime.getTempRet0=Module.getTempRet0,Module.asm=asm;function ExitStatus(t){this.name=\"ExitStatus\",this.message=\"Program terminated with exit(\"+t+\")\",this.status=t}ExitStatus.prototype=new Error,ExitStatus.prototype.constructor=ExitStatus;var initialStackTop,preloadStartTime=null,calledMain=!1;dependenciesFulfilled=function t(){Module.calledRun||run(),Module.calledRun||(dependenciesFulfilled=t)},Module.callMain=Module.callMain=function t(e){e=e||[],ensureInitRuntime();var r=e.length+1;function o(){for(var p=0;p<3;p++)a.push(0)}var a=[allocate(intArrayFromString(Module.thisProgram),\"i8\",ALLOC_NORMAL)];o();for(var n=0;n<r-1;n=n+1)a.push(allocate(intArrayFromString(e[n]),\"i8\",ALLOC_NORMAL)),o();a.push(0),a=allocate(a,\"i32\",ALLOC_NORMAL);try{var u=Module._main(r,a,0);exit(u,!0)}catch(p){if(p instanceof ExitStatus)return;if(p==\"SimulateInfiniteLoop\"){Module.noExitRuntime=!0;return}else{var A=p;p&&typeof p==\"object\"&&p.stack&&(A=[p,p.stack]),Module.printErr(\"exception thrown: \"+A),Module.quit(1,p)}}finally{calledMain=!0}};function run(t){if(t=t||Module.arguments,preloadStartTime===null&&(preloadStartTime=Date.now()),runDependencies>0||(preRun(),runDependencies>0)||Module.calledRun)return;function e(){Module.calledRun||(Module.calledRun=!0,!ABORT&&(ensureInitRuntime(),preMain(),Module.onRuntimeInitialized&&Module.onRuntimeInitialized(),Module._main&&shouldRunNow&&Module.callMain(t),postRun()))}Module.setStatus?(Module.setStatus(\"Running...\"),setTimeout(function(){setTimeout(function(){Module.setStatus(\"\")},1),e()},1)):e()}Module.run=Module.run=run;function exit(t,e){e&&Module.noExitRuntime||(Module.noExitRuntime||(ABORT=!0,EXITSTATUS=t,STACKTOP=initialStackTop,exitRuntime(),Module.onExit&&Module.onExit(t)),ENVIRONMENT_IS_NODE&&process.exit(t),Module.quit(t,new ExitStatus(t)))}Module.exit=Module.exit=exit;var abortDecorators=[];function abort(t){Module.onAbort&&Module.onAbort(t),t!==void 0?(Module.print(t),Module.printErr(t),t=JSON.stringify(t)):t=\"\",ABORT=!0,EXITSTATUS=1;var e=`\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.`,r=\"abort(\"+t+\") at \"+stackTrace()+e;throw abortDecorators&&abortDecorators.forEach(function(o){r=o(r,t)}),r}if(Module.abort=Module.abort=abort,Module.preInit)for(typeof Module.preInit==\"function\"&&(Module.preInit=[Module.preInit]);Module.preInit.length>0;)Module.preInit.pop()();var shouldRunNow=!0;Module.noInitialRun&&(shouldRunNow=!1),run()})});var id=_((nKt,SCe)=>{\"use strict\";var byt=DCe(),kyt=PCe(),pq=!1,hq=null;kyt({},function(t,e){if(!pq){if(pq=!0,t)throw t;hq=e}});if(!pq)throw new Error(\"Failed to load the yoga module - it needed to be loaded synchronously, but didn't\");SCe.exports=byt(hq.bind,hq.lib)});var dq=_((iKt,gq)=>{\"use strict\";var xCe=t=>Number.isNaN(t)?!1:t>=4352&&(t<=4447||t===9001||t===9002||11904<=t&&t<=12871&&t!==12351||12880<=t&&t<=19903||19968<=t&&t<=42182||43360<=t&&t<=43388||44032<=t&&t<=55203||63744<=t&&t<=64255||65040<=t&&t<=65049||65072<=t&&t<=65131||65281<=t&&t<=65376||65504<=t&&t<=65510||110592<=t&&t<=110593||127488<=t&&t<=127569||131072<=t&&t<=262141);gq.exports=xCe;gq.exports.default=xCe});var kCe=_((sKt,bCe)=>{\"use strict\";bCe.exports=function(){return/\\uD83C\\uDFF4\\uDB40\\uDC67\\uDB40\\uDC62(?:\\uDB40\\uDC65\\uDB40\\uDC6E\\uDB40\\uDC67|\\uDB40\\uDC73\\uDB40\\uDC63\\uDB40\\uDC74|\\uDB40\\uDC77\\uDB40\\uDC6C\\uDB40\\uDC73)\\uDB40\\uDC7F|\\uD83D\\uDC68(?:\\uD83C\\uDFFC\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68\\uD83C\\uDFFB|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFF\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB-\\uDFFE])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFE\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB-\\uDFFD])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFD\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB\\uDFFC])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\u200D(?:\\u2764\\uFE0F\\u200D(?:\\uD83D\\uDC8B\\u200D)?\\uD83D\\uDC68|(?:\\uD83D[\\uDC68\\uDC69])\\u200D(?:\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC67\\u200D(?:\\uD83D[\\uDC66\\uDC67]))|\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC67\\u200D(?:\\uD83D[\\uDC66\\uDC67])|(?:\\uD83D[\\uDC68\\uDC69])\\u200D(?:\\uD83D[\\uDC66\\uDC67])|[\\u2695\\u2696\\u2708]\\uFE0F|\\uD83D[\\uDC66\\uDC67]|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|(?:\\uD83C\\uDFFB\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFF\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFE\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFD\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFC\\u200D[\\u2695\\u2696\\u2708])\\uFE0F|\\uD83C\\uDFFB\\u200D(?:\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C[\\uDFFB-\\uDFFF])|(?:\\uD83E\\uDDD1\\uD83C\\uDFFB\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1|\\uD83D\\uDC69\\uD83C\\uDFFC\\u200D\\uD83E\\uDD1D\\u200D\\uD83D\\uDC69)\\uD83C\\uDFFB|\\uD83E\\uDDD1(?:\\uD83C\\uDFFF\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1(?:\\uD83C[\\uDFFB-\\uDFFF])|\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1)|(?:\\uD83E\\uDDD1\\uD83C\\uDFFE\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1|\\uD83D\\uDC69\\uD83C\\uDFFF\\u200D\\uD83E\\uDD1D\\u200D(?:\\uD83D[\\uDC68\\uDC69]))(?:\\uD83C[\\uDFFB-\\uDFFE])|(?:\\uD83E\\uDDD1\\uD83C\\uDFFC\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1|\\uD83D\\uDC69\\uD83C\\uDFFD\\u200D\\uD83E\\uDD1D\\u200D\\uD83D\\uDC69)(?:\\uD83C[\\uDFFB\\uDFFC])|\\uD83D\\uDC69(?:\\uD83C\\uDFFE\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB-\\uDFFD\\uDFFF])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFC\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB\\uDFFD-\\uDFFF])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFB\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFC-\\uDFFF])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFD\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB\\uDFFC\\uDFFE\\uDFFF])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\u200D(?:\\u2764\\uFE0F\\u200D(?:\\uD83D\\uDC8B\\u200D(?:\\uD83D[\\uDC68\\uDC69])|\\uD83D[\\uDC68\\uDC69])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFF\\u200D(?:\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD]))|\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D(?:\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC67\\u200D(?:\\uD83D[\\uDC66\\uDC67]))|(?:\\uD83E\\uDDD1\\uD83C\\uDFFD\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1|\\uD83D\\uDC69\\uD83C\\uDFFE\\u200D\\uD83E\\uDD1D\\u200D\\uD83D\\uDC69)(?:\\uD83C[\\uDFFB-\\uDFFD])|\\uD83D\\uDC69\\u200D\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D(?:\\uD83D[\\uDC66\\uDC67])|(?:\\uD83D\\uDC41\\uFE0F\\u200D\\uD83D\\uDDE8|\\uD83D\\uDC69(?:\\uD83C\\uDFFF\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFE\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFC\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFB\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFD\\u200D[\\u2695\\u2696\\u2708]|\\u200D[\\u2695\\u2696\\u2708])|(?:(?:\\u26F9|\\uD83C[\\uDFCB\\uDFCC]|\\uD83D\\uDD75)\\uFE0F|\\uD83D\\uDC6F|\\uD83E[\\uDD3C\\uDDDE\\uDDDF])\\u200D[\\u2640\\u2642]|(?:\\u26F9|\\uD83C[\\uDFCB\\uDFCC]|\\uD83D\\uDD75)(?:\\uD83C[\\uDFFB-\\uDFFF])\\u200D[\\u2640\\u2642]|(?:\\uD83C[\\uDFC3\\uDFC4\\uDFCA]|\\uD83D[\\uDC6E\\uDC71\\uDC73\\uDC77\\uDC81\\uDC82\\uDC86\\uDC87\\uDE45-\\uDE47\\uDE4B\\uDE4D\\uDE4E\\uDEA3\\uDEB4-\\uDEB6]|\\uD83E[\\uDD26\\uDD37-\\uDD39\\uDD3D\\uDD3E\\uDDB8\\uDDB9\\uDDCD-\\uDDCF\\uDDD6-\\uDDDD])(?:(?:\\uD83C[\\uDFFB-\\uDFFF])\\u200D[\\u2640\\u2642]|\\u200D[\\u2640\\u2642])|\\uD83C\\uDFF4\\u200D\\u2620)\\uFE0F|\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\\u200D(?:\\uD83D[\\uDC66\\uDC67])|\\uD83C\\uDFF3\\uFE0F\\u200D\\uD83C\\uDF08|\\uD83D\\uDC15\\u200D\\uD83E\\uDDBA|\\uD83D\\uDC69\\u200D\\uD83D\\uDC66|\\uD83D\\uDC69\\u200D\\uD83D\\uDC67|\\uD83C\\uDDFD\\uD83C\\uDDF0|\\uD83C\\uDDF4\\uD83C\\uDDF2|\\uD83C\\uDDF6\\uD83C\\uDDE6|[#\\*0-9]\\uFE0F\\u20E3|\\uD83C\\uDDE7(?:\\uD83C[\\uDDE6\\uDDE7\\uDDE9-\\uDDEF\\uDDF1-\\uDDF4\\uDDF6-\\uDDF9\\uDDFB\\uDDFC\\uDDFE\\uDDFF])|\\uD83C\\uDDF9(?:\\uD83C[\\uDDE6\\uDDE8\\uDDE9\\uDDEB-\\uDDED\\uDDEF-\\uDDF4\\uDDF7\\uDDF9\\uDDFB\\uDDFC\\uDDFF])|\\uD83C\\uDDEA(?:\\uD83C[\\uDDE6\\uDDE8\\uDDEA\\uDDEC\\uDDED\\uDDF7-\\uDDFA])|\\uD83E\\uDDD1(?:\\uD83C[\\uDFFB-\\uDFFF])|\\uD83C\\uDDF7(?:\\uD83C[\\uDDEA\\uDDF4\\uDDF8\\uDDFA\\uDDFC])|\\uD83D\\uDC69(?:\\uD83C[\\uDFFB-\\uDFFF])|\\uD83C\\uDDF2(?:\\uD83C[\\uDDE6\\uDDE8-\\uDDED\\uDDF0-\\uDDFF])|\\uD83C\\uDDE6(?:\\uD83C[\\uDDE8-\\uDDEC\\uDDEE\\uDDF1\\uDDF2\\uDDF4\\uDDF6-\\uDDFA\\uDDFC\\uDDFD\\uDDFF])|\\uD83C\\uDDF0(?:\\uD83C[\\uDDEA\\uDDEC-\\uDDEE\\uDDF2\\uDDF3\\uDDF5\\uDDF7\\uDDFC\\uDDFE\\uDDFF])|\\uD83C\\uDDED(?:\\uD83C[\\uDDF0\\uDDF2\\uDDF3\\uDDF7\\uDDF9\\uDDFA])|\\uD83C\\uDDE9(?:\\uD83C[\\uDDEA\\uDDEC\\uDDEF\\uDDF0\\uDDF2\\uDDF4\\uDDFF])|\\uD83C\\uDDFE(?:\\uD83C[\\uDDEA\\uDDF9])|\\uD83C\\uDDEC(?:\\uD83C[\\uDDE6\\uDDE7\\uDDE9-\\uDDEE\\uDDF1-\\uDDF3\\uDDF5-\\uDDFA\\uDDFC\\uDDFE])|\\uD83C\\uDDF8(?:\\uD83C[\\uDDE6-\\uDDEA\\uDDEC-\\uDDF4\\uDDF7-\\uDDF9\\uDDFB\\uDDFD-\\uDDFF])|\\uD83C\\uDDEB(?:\\uD83C[\\uDDEE-\\uDDF0\\uDDF2\\uDDF4\\uDDF7])|\\uD83C\\uDDF5(?:\\uD83C[\\uDDE6\\uDDEA-\\uDDED\\uDDF0-\\uDDF3\\uDDF7-\\uDDF9\\uDDFC\\uDDFE])|\\uD83C\\uDDFB(?:\\uD83C[\\uDDE6\\uDDE8\\uDDEA\\uDDEC\\uDDEE\\uDDF3\\uDDFA])|\\uD83C\\uDDF3(?:\\uD83C[\\uDDE6\\uDDE8\\uDDEA-\\uDDEC\\uDDEE\\uDDF1\\uDDF4\\uDDF5\\uDDF7\\uDDFA\\uDDFF])|\\uD83C\\uDDE8(?:\\uD83C[\\uDDE6\\uDDE8\\uDDE9\\uDDEB-\\uDDEE\\uDDF0-\\uDDF5\\uDDF7\\uDDFA-\\uDDFF])|\\uD83C\\uDDF1(?:\\uD83C[\\uDDE6-\\uDDE8\\uDDEE\\uDDF0\\uDDF7-\\uDDFB\\uDDFE])|\\uD83C\\uDDFF(?:\\uD83C[\\uDDE6\\uDDF2\\uDDFC])|\\uD83C\\uDDFC(?:\\uD83C[\\uDDEB\\uDDF8])|\\uD83C\\uDDFA(?:\\uD83C[\\uDDE6\\uDDEC\\uDDF2\\uDDF3\\uDDF8\\uDDFE\\uDDFF])|\\uD83C\\uDDEE(?:\\uD83C[\\uDDE8-\\uDDEA\\uDDF1-\\uDDF4\\uDDF6-\\uDDF9])|\\uD83C\\uDDEF(?:\\uD83C[\\uDDEA\\uDDF2\\uDDF4\\uDDF5])|(?:\\uD83C[\\uDFC3\\uDFC4\\uDFCA]|\\uD83D[\\uDC6E\\uDC71\\uDC73\\uDC77\\uDC81\\uDC82\\uDC86\\uDC87\\uDE45-\\uDE47\\uDE4B\\uDE4D\\uDE4E\\uDEA3\\uDEB4-\\uDEB6]|\\uD83E[\\uDD26\\uDD37-\\uDD39\\uDD3D\\uDD3E\\uDDB8\\uDDB9\\uDDCD-\\uDDCF\\uDDD6-\\uDDDD])(?:\\uD83C[\\uDFFB-\\uDFFF])|(?:\\u26F9|\\uD83C[\\uDFCB\\uDFCC]|\\uD83D\\uDD75)(?:\\uD83C[\\uDFFB-\\uDFFF])|(?:[\\u261D\\u270A-\\u270D]|\\uD83C[\\uDF85\\uDFC2\\uDFC7]|\\uD83D[\\uDC42\\uDC43\\uDC46-\\uDC50\\uDC66\\uDC67\\uDC6B-\\uDC6D\\uDC70\\uDC72\\uDC74-\\uDC76\\uDC78\\uDC7C\\uDC83\\uDC85\\uDCAA\\uDD74\\uDD7A\\uDD90\\uDD95\\uDD96\\uDE4C\\uDE4F\\uDEC0\\uDECC]|\\uD83E[\\uDD0F\\uDD18-\\uDD1C\\uDD1E\\uDD1F\\uDD30-\\uDD36\\uDDB5\\uDDB6\\uDDBB\\uDDD2-\\uDDD5])(?:\\uD83C[\\uDFFB-\\uDFFF])|(?:[\\u231A\\u231B\\u23E9-\\u23EC\\u23F0\\u23F3\\u25FD\\u25FE\\u2614\\u2615\\u2648-\\u2653\\u267F\\u2693\\u26A1\\u26AA\\u26AB\\u26BD\\u26BE\\u26C4\\u26C5\\u26CE\\u26D4\\u26EA\\u26F2\\u26F3\\u26F5\\u26FA\\u26FD\\u2705\\u270A\\u270B\\u2728\\u274C\\u274E\\u2753-\\u2755\\u2757\\u2795-\\u2797\\u27B0\\u27BF\\u2B1B\\u2B1C\\u2B50\\u2B55]|\\uD83C[\\uDC04\\uDCCF\\uDD8E\\uDD91-\\uDD9A\\uDDE6-\\uDDFF\\uDE01\\uDE1A\\uDE2F\\uDE32-\\uDE36\\uDE38-\\uDE3A\\uDE50\\uDE51\\uDF00-\\uDF20\\uDF2D-\\uDF35\\uDF37-\\uDF7C\\uDF7E-\\uDF93\\uDFA0-\\uDFCA\\uDFCF-\\uDFD3\\uDFE0-\\uDFF0\\uDFF4\\uDFF8-\\uDFFF]|\\uD83D[\\uDC00-\\uDC3E\\uDC40\\uDC42-\\uDCFC\\uDCFF-\\uDD3D\\uDD4B-\\uDD4E\\uDD50-\\uDD67\\uDD7A\\uDD95\\uDD96\\uDDA4\\uDDFB-\\uDE4F\\uDE80-\\uDEC5\\uDECC\\uDED0-\\uDED2\\uDED5\\uDEEB\\uDEEC\\uDEF4-\\uDEFA\\uDFE0-\\uDFEB]|\\uD83E[\\uDD0D-\\uDD3A\\uDD3C-\\uDD45\\uDD47-\\uDD71\\uDD73-\\uDD76\\uDD7A-\\uDDA2\\uDDA5-\\uDDAA\\uDDAE-\\uDDCA\\uDDCD-\\uDDFF\\uDE70-\\uDE73\\uDE78-\\uDE7A\\uDE80-\\uDE82\\uDE90-\\uDE95])|(?:[#\\*0-9\\xA9\\xAE\\u203C\\u2049\\u2122\\u2139\\u2194-\\u2199\\u21A9\\u21AA\\u231A\\u231B\\u2328\\u23CF\\u23E9-\\u23F3\\u23F8-\\u23FA\\u24C2\\u25AA\\u25AB\\u25B6\\u25C0\\u25FB-\\u25FE\\u2600-\\u2604\\u260E\\u2611\\u2614\\u2615\\u2618\\u261D\\u2620\\u2622\\u2623\\u2626\\u262A\\u262E\\u262F\\u2638-\\u263A\\u2640\\u2642\\u2648-\\u2653\\u265F\\u2660\\u2663\\u2665\\u2666\\u2668\\u267B\\u267E\\u267F\\u2692-\\u2697\\u2699\\u269B\\u269C\\u26A0\\u26A1\\u26AA\\u26AB\\u26B0\\u26B1\\u26BD\\u26BE\\u26C4\\u26C5\\u26C8\\u26CE\\u26CF\\u26D1\\u26D3\\u26D4\\u26E9\\u26EA\\u26F0-\\u26F5\\u26F7-\\u26FA\\u26FD\\u2702\\u2705\\u2708-\\u270D\\u270F\\u2712\\u2714\\u2716\\u271D\\u2721\\u2728\\u2733\\u2734\\u2744\\u2747\\u274C\\u274E\\u2753-\\u2755\\u2757\\u2763\\u2764\\u2795-\\u2797\\u27A1\\u27B0\\u27BF\\u2934\\u2935\\u2B05-\\u2B07\\u2B1B\\u2B1C\\u2B50\\u2B55\\u3030\\u303D\\u3297\\u3299]|\\uD83C[\\uDC04\\uDCCF\\uDD70\\uDD71\\uDD7E\\uDD7F\\uDD8E\\uDD91-\\uDD9A\\uDDE6-\\uDDFF\\uDE01\\uDE02\\uDE1A\\uDE2F\\uDE32-\\uDE3A\\uDE50\\uDE51\\uDF00-\\uDF21\\uDF24-\\uDF93\\uDF96\\uDF97\\uDF99-\\uDF9B\\uDF9E-\\uDFF0\\uDFF3-\\uDFF5\\uDFF7-\\uDFFF]|\\uD83D[\\uDC00-\\uDCFD\\uDCFF-\\uDD3D\\uDD49-\\uDD4E\\uDD50-\\uDD67\\uDD6F\\uDD70\\uDD73-\\uDD7A\\uDD87\\uDD8A-\\uDD8D\\uDD90\\uDD95\\uDD96\\uDDA4\\uDDA5\\uDDA8\\uDDB1\\uDDB2\\uDDBC\\uDDC2-\\uDDC4\\uDDD1-\\uDDD3\\uDDDC-\\uDDDE\\uDDE1\\uDDE3\\uDDE8\\uDDEF\\uDDF3\\uDDFA-\\uDE4F\\uDE80-\\uDEC5\\uDECB-\\uDED2\\uDED5\\uDEE0-\\uDEE5\\uDEE9\\uDEEB\\uDEEC\\uDEF0\\uDEF3-\\uDEFA\\uDFE0-\\uDFEB]|\\uD83E[\\uDD0D-\\uDD3A\\uDD3C-\\uDD45\\uDD47-\\uDD71\\uDD73-\\uDD76\\uDD7A-\\uDDA2\\uDDA5-\\uDDAA\\uDDAE-\\uDDCA\\uDDCD-\\uDDFF\\uDE70-\\uDE73\\uDE78-\\uDE7A\\uDE80-\\uDE82\\uDE90-\\uDE95])\\uFE0F|(?:[\\u261D\\u26F9\\u270A-\\u270D]|\\uD83C[\\uDF85\\uDFC2-\\uDFC4\\uDFC7\\uDFCA-\\uDFCC]|\\uD83D[\\uDC42\\uDC43\\uDC46-\\uDC50\\uDC66-\\uDC78\\uDC7C\\uDC81-\\uDC83\\uDC85-\\uDC87\\uDC8F\\uDC91\\uDCAA\\uDD74\\uDD75\\uDD7A\\uDD90\\uDD95\\uDD96\\uDE45-\\uDE47\\uDE4B-\\uDE4F\\uDEA3\\uDEB4-\\uDEB6\\uDEC0\\uDECC]|\\uD83E[\\uDD0F\\uDD18-\\uDD1F\\uDD26\\uDD30-\\uDD39\\uDD3C-\\uDD3E\\uDDB5\\uDDB6\\uDDB8\\uDDB9\\uDDBB\\uDDCD-\\uDDCF\\uDDD1-\\uDDDD])/g}});var PB=_((oKt,mq)=>{\"use strict\";var Qyt=pS(),Fyt=dq(),Ryt=kCe(),QCe=t=>{if(typeof t!=\"string\"||t.length===0||(t=Qyt(t),t.length===0))return 0;t=t.replace(Ryt(),\"  \");let e=0;for(let r=0;r<t.length;r++){let o=t.codePointAt(r);o<=31||o>=127&&o<=159||o>=768&&o<=879||(o>65535&&r++,e+=Fyt(o)?2:1)}return e};mq.exports=QCe;mq.exports.default=QCe});var Eq=_((aKt,yq)=>{\"use strict\";var Tyt=PB(),FCe=t=>{let e=0;for(let r of t.split(`\n`))e=Math.max(e,Tyt(r));return e};yq.exports=FCe;yq.exports.default=FCe});var RCe=_(SB=>{\"use strict\";var Lyt=SB&&SB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(SB,\"__esModule\",{value:!0});var Nyt=Lyt(Eq()),Cq={};SB.default=t=>{if(t.length===0)return{width:0,height:0};if(Cq[t])return Cq[t];let e=Nyt.default(t),r=t.split(`\n`).length;return Cq[t]={width:e,height:r},{width:e,height:r}}});var TCe=_(xB=>{\"use strict\";var Oyt=xB&&xB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(xB,\"__esModule\",{value:!0});var In=Oyt(id()),Myt=(t,e)=>{\"position\"in e&&t.setPositionType(e.position===\"absolute\"?In.default.POSITION_TYPE_ABSOLUTE:In.default.POSITION_TYPE_RELATIVE)},Uyt=(t,e)=>{\"marginLeft\"in e&&t.setMargin(In.default.EDGE_START,e.marginLeft||0),\"marginRight\"in e&&t.setMargin(In.default.EDGE_END,e.marginRight||0),\"marginTop\"in e&&t.setMargin(In.default.EDGE_TOP,e.marginTop||0),\"marginBottom\"in e&&t.setMargin(In.default.EDGE_BOTTOM,e.marginBottom||0)},_yt=(t,e)=>{\"paddingLeft\"in e&&t.setPadding(In.default.EDGE_LEFT,e.paddingLeft||0),\"paddingRight\"in e&&t.setPadding(In.default.EDGE_RIGHT,e.paddingRight||0),\"paddingTop\"in e&&t.setPadding(In.default.EDGE_TOP,e.paddingTop||0),\"paddingBottom\"in e&&t.setPadding(In.default.EDGE_BOTTOM,e.paddingBottom||0)},Hyt=(t,e)=>{var r;\"flexGrow\"in e&&t.setFlexGrow((r=e.flexGrow)!==null&&r!==void 0?r:0),\"flexShrink\"in e&&t.setFlexShrink(typeof e.flexShrink==\"number\"?e.flexShrink:1),\"flexDirection\"in e&&(e.flexDirection===\"row\"&&t.setFlexDirection(In.default.FLEX_DIRECTION_ROW),e.flexDirection===\"row-reverse\"&&t.setFlexDirection(In.default.FLEX_DIRECTION_ROW_REVERSE),e.flexDirection===\"column\"&&t.setFlexDirection(In.default.FLEX_DIRECTION_COLUMN),e.flexDirection===\"column-reverse\"&&t.setFlexDirection(In.default.FLEX_DIRECTION_COLUMN_REVERSE)),\"flexBasis\"in e&&(typeof e.flexBasis==\"number\"?t.setFlexBasis(e.flexBasis):typeof e.flexBasis==\"string\"?t.setFlexBasisPercent(Number.parseInt(e.flexBasis,10)):t.setFlexBasis(NaN)),\"alignItems\"in e&&((e.alignItems===\"stretch\"||!e.alignItems)&&t.setAlignItems(In.default.ALIGN_STRETCH),e.alignItems===\"flex-start\"&&t.setAlignItems(In.default.ALIGN_FLEX_START),e.alignItems===\"center\"&&t.setAlignItems(In.default.ALIGN_CENTER),e.alignItems===\"flex-end\"&&t.setAlignItems(In.default.ALIGN_FLEX_END)),\"alignSelf\"in e&&((e.alignSelf===\"auto\"||!e.alignSelf)&&t.setAlignSelf(In.default.ALIGN_AUTO),e.alignSelf===\"flex-start\"&&t.setAlignSelf(In.default.ALIGN_FLEX_START),e.alignSelf===\"center\"&&t.setAlignSelf(In.default.ALIGN_CENTER),e.alignSelf===\"flex-end\"&&t.setAlignSelf(In.default.ALIGN_FLEX_END)),\"justifyContent\"in e&&((e.justifyContent===\"flex-start\"||!e.justifyContent)&&t.setJustifyContent(In.default.JUSTIFY_FLEX_START),e.justifyContent===\"center\"&&t.setJustifyContent(In.default.JUSTIFY_CENTER),e.justifyContent===\"flex-end\"&&t.setJustifyContent(In.default.JUSTIFY_FLEX_END),e.justifyContent===\"space-between\"&&t.setJustifyContent(In.default.JUSTIFY_SPACE_BETWEEN),e.justifyContent===\"space-around\"&&t.setJustifyContent(In.default.JUSTIFY_SPACE_AROUND))},qyt=(t,e)=>{var r,o;\"width\"in e&&(typeof e.width==\"number\"?t.setWidth(e.width):typeof e.width==\"string\"?t.setWidthPercent(Number.parseInt(e.width,10)):t.setWidthAuto()),\"height\"in e&&(typeof e.height==\"number\"?t.setHeight(e.height):typeof e.height==\"string\"?t.setHeightPercent(Number.parseInt(e.height,10)):t.setHeightAuto()),\"minWidth\"in e&&(typeof e.minWidth==\"string\"?t.setMinWidthPercent(Number.parseInt(e.minWidth,10)):t.setMinWidth((r=e.minWidth)!==null&&r!==void 0?r:0)),\"minHeight\"in e&&(typeof e.minHeight==\"string\"?t.setMinHeightPercent(Number.parseInt(e.minHeight,10)):t.setMinHeight((o=e.minHeight)!==null&&o!==void 0?o:0))},jyt=(t,e)=>{\"display\"in e&&t.setDisplay(e.display===\"flex\"?In.default.DISPLAY_FLEX:In.default.DISPLAY_NONE)},Gyt=(t,e)=>{if(\"borderStyle\"in e){let r=typeof e.borderStyle==\"string\"?1:0;t.setBorder(In.default.EDGE_TOP,r),t.setBorder(In.default.EDGE_BOTTOM,r),t.setBorder(In.default.EDGE_LEFT,r),t.setBorder(In.default.EDGE_RIGHT,r)}};xB.default=(t,e={})=>{Myt(t,e),Uyt(t,e),_yt(t,e),Hyt(t,e),qyt(t,e),jyt(t,e),Gyt(t,e)}});var OCe=_((uKt,NCe)=>{\"use strict\";var bB=PB(),Wyt=pS(),Yyt=qw(),wq=new Set([\"\\x1B\",\"\\x9B\"]),Kyt=39,LCe=t=>`${wq.values().next().value}[${t}m`,Vyt=t=>t.split(\" \").map(e=>bB(e)),Iq=(t,e,r)=>{let o=[...e],a=!1,n=bB(Wyt(t[t.length-1]));for(let[u,A]of o.entries()){let p=bB(A);if(n+p<=r?t[t.length-1]+=A:(t.push(A),n=0),wq.has(A))a=!0;else if(a&&A===\"m\"){a=!1;continue}a||(n+=p,n===r&&u<o.length-1&&(t.push(\"\"),n=0))}!n&&t[t.length-1].length>0&&t.length>1&&(t[t.length-2]+=t.pop())},zyt=t=>{let e=t.split(\" \"),r=e.length;for(;r>0&&!(bB(e[r-1])>0);)r--;return r===e.length?t:e.slice(0,r).join(\" \")+e.slice(r).join(\"\")},Jyt=(t,e,r={})=>{if(r.trim!==!1&&t.trim()===\"\")return\"\";let o=\"\",a=\"\",n,u=Vyt(t),A=[\"\"];for(let[p,h]of t.split(\" \").entries()){r.trim!==!1&&(A[A.length-1]=A[A.length-1].trimLeft());let E=bB(A[A.length-1]);if(p!==0&&(E>=e&&(r.wordWrap===!1||r.trim===!1)&&(A.push(\"\"),E=0),(E>0||r.trim===!1)&&(A[A.length-1]+=\" \",E++)),r.hard&&u[p]>e){let w=e-E,D=1+Math.floor((u[p]-w-1)/e);Math.floor((u[p]-1)/e)<D&&A.push(\"\"),Iq(A,h,e);continue}if(E+u[p]>e&&E>0&&u[p]>0){if(r.wordWrap===!1&&E<e){Iq(A,h,e);continue}A.push(\"\")}if(E+u[p]>e&&r.wordWrap===!1){Iq(A,h,e);continue}A[A.length-1]+=h}r.trim!==!1&&(A=A.map(zyt)),o=A.join(`\n`);for(let[p,h]of[...o].entries()){if(a+=h,wq.has(h)){let w=parseFloat(/\\d[^m]*/.exec(o.slice(p,p+4)));n=w===Kyt?null:w}let E=Yyt.codes.get(Number(n));n&&E&&(o[p+1]===`\n`?a+=LCe(E):h===`\n`&&(a+=LCe(n)))}return a};NCe.exports=(t,e,r)=>String(t).normalize().replace(/\\r\\n/g,`\n`).split(`\n`).map(o=>Jyt(o,e,r)).join(`\n`)});var _Ce=_((AKt,UCe)=>{\"use strict\";var MCe=\"[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]\",Xyt=t=>t&&t.exact?new RegExp(`^${MCe}$`):new RegExp(MCe,\"g\");UCe.exports=Xyt});var Bq=_((fKt,GCe)=>{\"use strict\";var Zyt=dq(),$yt=_Ce(),HCe=qw(),jCe=[\"\\x1B\",\"\\x9B\"],vQ=t=>`${jCe[0]}[${t}m`,qCe=(t,e,r)=>{let o=[];t=[...t];for(let a of t){let n=a;a.match(\";\")&&(a=a.split(\";\")[0][0]+\"0\");let u=HCe.codes.get(parseInt(a,10));if(u){let A=t.indexOf(u.toString());A>=0?t.splice(A,1):o.push(vQ(e?u:n))}else if(e){o.push(vQ(0));break}else o.push(vQ(n))}if(e&&(o=o.filter((a,n)=>o.indexOf(a)===n),r!==void 0)){let a=vQ(HCe.codes.get(parseInt(r,10)));o=o.reduce((n,u)=>u===a?[u,...n]:[...n,u],[])}return o.join(\"\")};GCe.exports=(t,e,r)=>{let o=[...t.normalize()],a=[];r=typeof r==\"number\"?r:o.length;let n=!1,u,A=0,p=\"\";for(let[h,E]of o.entries()){let w=!1;if(jCe.includes(E)){let D=/\\d[^m]*/.exec(t.slice(h,h+18));u=D&&D.length>0?D[0]:void 0,A<r&&(n=!0,u!==void 0&&a.push(u))}else n&&E===\"m\"&&(n=!1,w=!0);if(!n&&!w&&++A,!$yt({exact:!0}).test(E)&&Zyt(E.codePointAt())&&++A,A>e&&A<=r)p+=E;else if(A===e&&!n&&u!==void 0)p=qCe(a);else if(A>=r){p+=qCe(a,!0,u);break}}return p}});var YCe=_((pKt,WCe)=>{\"use strict\";var _h=Bq(),eEt=PB();function DQ(t,e,r){if(t.charAt(e)===\" \")return e;for(let o=1;o<=3;o++)if(r){if(t.charAt(e+o)===\" \")return e+o}else if(t.charAt(e-o)===\" \")return e-o;return e}WCe.exports=(t,e,r)=>{r={position:\"end\",preferTruncationOnSpace:!1,...r};let{position:o,space:a,preferTruncationOnSpace:n}=r,u=\"\\u2026\",A=1;if(typeof t!=\"string\")throw new TypeError(`Expected \\`input\\` to be a string, got ${typeof t}`);if(typeof e!=\"number\")throw new TypeError(`Expected \\`columns\\` to be a number, got ${typeof e}`);if(e<1)return\"\";if(e===1)return u;let p=eEt(t);if(p<=e)return t;if(o===\"start\"){if(n){let h=DQ(t,p-e+1,!0);return u+_h(t,h,p).trim()}return a===!0&&(u+=\" \",A=2),u+_h(t,p-e+A,p)}if(o===\"middle\"){a===!0&&(u=\" \"+u+\" \",A=3);let h=Math.floor(e/2);if(n){let E=DQ(t,h),w=DQ(t,p-(e-h)+1,!0);return _h(t,0,E)+u+_h(t,w,p).trim()}return _h(t,0,h)+u+_h(t,p-(e-h)+A,p)}if(o===\"end\"){if(n){let h=DQ(t,e-1);return _h(t,0,h)+u}return a===!0&&(u=\" \"+u,A=2),_h(t,0,e-A)+u}throw new Error(`Expected \\`options.position\\` to be either \\`start\\`, \\`middle\\` or \\`end\\`, got ${o}`)}});var Dq=_(kB=>{\"use strict\";var KCe=kB&&kB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(kB,\"__esModule\",{value:!0});var tEt=KCe(OCe()),rEt=KCe(YCe()),vq={};kB.default=(t,e,r)=>{let o=t+String(e)+String(r);if(vq[o])return vq[o];let a=t;if(r===\"wrap\"&&(a=tEt.default(t,e,{trim:!1,hard:!0})),r.startsWith(\"truncate\")){let n=\"end\";r===\"truncate-middle\"&&(n=\"middle\"),r===\"truncate-start\"&&(n=\"start\"),a=rEt.default(t,e,{position:n})}return vq[o]=a,a}});var Sq=_(Pq=>{\"use strict\";Object.defineProperty(Pq,\"__esModule\",{value:!0});var VCe=t=>{let e=\"\";if(t.childNodes.length>0)for(let r of t.childNodes){let o=\"\";r.nodeName===\"#text\"?o=r.nodeValue:((r.nodeName===\"ink-text\"||r.nodeName===\"ink-virtual-text\")&&(o=VCe(r)),o.length>0&&typeof r.internal_transform==\"function\"&&(o=r.internal_transform(o))),e+=o}return e};Pq.default=VCe});var xq=_(Ei=>{\"use strict\";var QB=Ei&&Ei.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(Ei,\"__esModule\",{value:!0});Ei.setTextNodeValue=Ei.createTextNode=Ei.setStyle=Ei.setAttribute=Ei.removeChildNode=Ei.insertBeforeNode=Ei.appendChildNode=Ei.createNode=Ei.TEXT_NAME=void 0;var nEt=QB(id()),zCe=QB(RCe()),iEt=QB(TCe()),sEt=QB(Dq()),oEt=QB(Sq());Ei.TEXT_NAME=\"#text\";Ei.createNode=t=>{var e;let r={nodeName:t,style:{},attributes:{},childNodes:[],parentNode:null,yogaNode:t===\"ink-virtual-text\"?void 0:nEt.default.Node.create()};return t===\"ink-text\"&&((e=r.yogaNode)===null||e===void 0||e.setMeasureFunc(aEt.bind(null,r))),r};Ei.appendChildNode=(t,e)=>{var r;e.parentNode&&Ei.removeChildNode(e.parentNode,e),e.parentNode=t,t.childNodes.push(e),e.yogaNode&&((r=t.yogaNode)===null||r===void 0||r.insertChild(e.yogaNode,t.yogaNode.getChildCount())),(t.nodeName===\"ink-text\"||t.nodeName===\"ink-virtual-text\")&&PQ(t)};Ei.insertBeforeNode=(t,e,r)=>{var o,a;e.parentNode&&Ei.removeChildNode(e.parentNode,e),e.parentNode=t;let n=t.childNodes.indexOf(r);if(n>=0){t.childNodes.splice(n,0,e),e.yogaNode&&((o=t.yogaNode)===null||o===void 0||o.insertChild(e.yogaNode,n));return}t.childNodes.push(e),e.yogaNode&&((a=t.yogaNode)===null||a===void 0||a.insertChild(e.yogaNode,t.yogaNode.getChildCount())),(t.nodeName===\"ink-text\"||t.nodeName===\"ink-virtual-text\")&&PQ(t)};Ei.removeChildNode=(t,e)=>{var r,o;e.yogaNode&&((o=(r=e.parentNode)===null||r===void 0?void 0:r.yogaNode)===null||o===void 0||o.removeChild(e.yogaNode)),e.parentNode=null;let a=t.childNodes.indexOf(e);a>=0&&t.childNodes.splice(a,1),(t.nodeName===\"ink-text\"||t.nodeName===\"ink-virtual-text\")&&PQ(t)};Ei.setAttribute=(t,e,r)=>{t.attributes[e]=r};Ei.setStyle=(t,e)=>{t.style=e,t.yogaNode&&iEt.default(t.yogaNode,e)};Ei.createTextNode=t=>{let e={nodeName:\"#text\",nodeValue:t,yogaNode:void 0,parentNode:null,style:{}};return Ei.setTextNodeValue(e,t),e};var aEt=function(t,e){var r,o;let a=t.nodeName===\"#text\"?t.nodeValue:oEt.default(t),n=zCe.default(a);if(n.width<=e||n.width>=1&&e>0&&e<1)return n;let u=(o=(r=t.style)===null||r===void 0?void 0:r.textWrap)!==null&&o!==void 0?o:\"wrap\",A=sEt.default(a,e,u);return zCe.default(A)},JCe=t=>{var e;if(!(!t||!t.parentNode))return(e=t.yogaNode)!==null&&e!==void 0?e:JCe(t.parentNode)},PQ=t=>{let e=JCe(t);e?.markDirty()};Ei.setTextNodeValue=(t,e)=>{typeof e!=\"string\"&&(e=String(e)),t.nodeValue=e,PQ(t)}});var tIe=_(FB=>{\"use strict\";var eIe=FB&&FB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(FB,\"__esModule\",{value:!0});var XCe=uq(),lEt=eIe(ECe()),ZCe=eIe(id()),ko=xq(),$Ce=t=>{t?.unsetMeasureFunc(),t?.freeRecursive()};FB.default=lEt.default({schedulePassiveEffects:XCe.unstable_scheduleCallback,cancelPassiveEffects:XCe.unstable_cancelCallback,now:Date.now,getRootHostContext:()=>({isInsideText:!1}),prepareForCommit:()=>null,preparePortalMount:()=>null,clearContainer:()=>!1,shouldDeprioritizeSubtree:()=>!1,resetAfterCommit:t=>{if(t.isStaticDirty){t.isStaticDirty=!1,typeof t.onImmediateRender==\"function\"&&t.onImmediateRender();return}typeof t.onRender==\"function\"&&t.onRender()},getChildHostContext:(t,e)=>{let r=t.isInsideText,o=e===\"ink-text\"||e===\"ink-virtual-text\";return r===o?t:{isInsideText:o}},shouldSetTextContent:()=>!1,createInstance:(t,e,r,o)=>{if(o.isInsideText&&t===\"ink-box\")throw new Error(\"<Box> can\\u2019t be nested inside <Text> component\");let a=t===\"ink-text\"&&o.isInsideText?\"ink-virtual-text\":t,n=ko.createNode(a);for(let[u,A]of Object.entries(e))u!==\"children\"&&(u===\"style\"?ko.setStyle(n,A):u===\"internal_transform\"?n.internal_transform=A:u===\"internal_static\"?n.internal_static=!0:ko.setAttribute(n,u,A));return n},createTextInstance:(t,e,r)=>{if(!r.isInsideText)throw new Error(`Text string \"${t}\" must be rendered inside <Text> component`);return ko.createTextNode(t)},resetTextContent:()=>{},hideTextInstance:t=>{ko.setTextNodeValue(t,\"\")},unhideTextInstance:(t,e)=>{ko.setTextNodeValue(t,e)},getPublicInstance:t=>t,hideInstance:t=>{var e;(e=t.yogaNode)===null||e===void 0||e.setDisplay(ZCe.default.DISPLAY_NONE)},unhideInstance:t=>{var e;(e=t.yogaNode)===null||e===void 0||e.setDisplay(ZCe.default.DISPLAY_FLEX)},appendInitialChild:ko.appendChildNode,appendChild:ko.appendChildNode,insertBefore:ko.insertBeforeNode,finalizeInitialChildren:(t,e,r,o)=>(t.internal_static&&(o.isStaticDirty=!0,o.staticNode=t),!1),supportsMutation:!0,appendChildToContainer:ko.appendChildNode,insertInContainerBefore:ko.insertBeforeNode,removeChildFromContainer:(t,e)=>{ko.removeChildNode(t,e),$Ce(e.yogaNode)},prepareUpdate:(t,e,r,o,a)=>{t.internal_static&&(a.isStaticDirty=!0);let n={},u=Object.keys(o);for(let A of u)if(o[A]!==r[A]){if(A===\"style\"&&typeof o.style==\"object\"&&typeof r.style==\"object\"){let h=o.style,E=r.style,w=Object.keys(h);for(let D of w){if(D===\"borderStyle\"||D===\"borderColor\"){if(typeof n.style!=\"object\"){let b={};n.style=b}n.style.borderStyle=h.borderStyle,n.style.borderColor=h.borderColor}if(h[D]!==E[D]){if(typeof n.style!=\"object\"){let b={};n.style=b}n.style[D]=h[D]}}continue}n[A]=o[A]}return n},commitUpdate:(t,e)=>{for(let[r,o]of Object.entries(e))r!==\"children\"&&(r===\"style\"?ko.setStyle(t,o):r===\"internal_transform\"?t.internal_transform=o:r===\"internal_static\"?t.internal_static=!0:ko.setAttribute(t,r,o))},commitTextUpdate:(t,e,r)=>{ko.setTextNodeValue(t,r)},removeChild:(t,e)=>{ko.removeChildNode(t,e),$Ce(e.yogaNode)}})});var nIe=_((yKt,rIe)=>{\"use strict\";rIe.exports=(t,e=1,r)=>{if(r={indent:\" \",includeEmptyLines:!1,...r},typeof t!=\"string\")throw new TypeError(`Expected \\`input\\` to be a \\`string\\`, got \\`${typeof t}\\``);if(typeof e!=\"number\")throw new TypeError(`Expected \\`count\\` to be a \\`number\\`, got \\`${typeof e}\\``);if(typeof r.indent!=\"string\")throw new TypeError(`Expected \\`options.indent\\` to be a \\`string\\`, got \\`${typeof r.indent}\\``);if(e===0)return t;let o=r.includeEmptyLines?/^/gm:/^(?!\\s*$)/gm;return t.replace(o,r.indent.repeat(e))}});var iIe=_(RB=>{\"use strict\";var cEt=RB&&RB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(RB,\"__esModule\",{value:!0});var SQ=cEt(id());RB.default=t=>t.getComputedWidth()-t.getComputedPadding(SQ.default.EDGE_LEFT)-t.getComputedPadding(SQ.default.EDGE_RIGHT)-t.getComputedBorder(SQ.default.EDGE_LEFT)-t.getComputedBorder(SQ.default.EDGE_RIGHT)});var sIe=_((CKt,uEt)=>{uEt.exports={single:{topLeft:\"\\u250C\",topRight:\"\\u2510\",bottomRight:\"\\u2518\",bottomLeft:\"\\u2514\",vertical:\"\\u2502\",horizontal:\"\\u2500\"},double:{topLeft:\"\\u2554\",topRight:\"\\u2557\",bottomRight:\"\\u255D\",bottomLeft:\"\\u255A\",vertical:\"\\u2551\",horizontal:\"\\u2550\"},round:{topLeft:\"\\u256D\",topRight:\"\\u256E\",bottomRight:\"\\u256F\",bottomLeft:\"\\u2570\",vertical:\"\\u2502\",horizontal:\"\\u2500\"},bold:{topLeft:\"\\u250F\",topRight:\"\\u2513\",bottomRight:\"\\u251B\",bottomLeft:\"\\u2517\",vertical:\"\\u2503\",horizontal:\"\\u2501\"},singleDouble:{topLeft:\"\\u2553\",topRight:\"\\u2556\",bottomRight:\"\\u255C\",bottomLeft:\"\\u2559\",vertical:\"\\u2551\",horizontal:\"\\u2500\"},doubleSingle:{topLeft:\"\\u2552\",topRight:\"\\u2555\",bottomRight:\"\\u255B\",bottomLeft:\"\\u2558\",vertical:\"\\u2502\",horizontal:\"\\u2550\"},classic:{topLeft:\"+\",topRight:\"+\",bottomRight:\"+\",bottomLeft:\"+\",vertical:\"|\",horizontal:\"-\"}}});var aIe=_((IKt,bq)=>{\"use strict\";var oIe=sIe();bq.exports=oIe;bq.exports.default=oIe});var cIe=_((wKt,lIe)=>{\"use strict\";var AEt=(t,e,r)=>{let o=t.indexOf(e);if(o===-1)return t;let a=e.length,n=0,u=\"\";do u+=t.substr(n,o-n)+e+r,n=o+a,o=t.indexOf(e,n);while(o!==-1);return u+=t.substr(n),u},fEt=(t,e,r,o)=>{let a=0,n=\"\";do{let u=t[o-1]===\"\\r\";n+=t.substr(a,(u?o-1:o)-a)+e+(u?`\\r\n`:`\n`)+r,a=o+1,o=t.indexOf(`\n`,a)}while(o!==-1);return n+=t.substr(a),n};lIe.exports={stringReplaceAll:AEt,stringEncaseCRLFWithFirstIndex:fEt}});var hIe=_((BKt,pIe)=>{\"use strict\";var pEt=/(?:\\\\(u(?:[a-f\\d]{4}|\\{[a-f\\d]{1,6}\\})|x[a-f\\d]{2}|.))|(?:\\{(~)?(\\w+(?:\\([^)]*\\))?(?:\\.\\w+(?:\\([^)]*\\))?)*)(?:[ \\t]|(?=\\r?\\n)))|(\\})|((?:.|[\\r\\n\\f])+?)/gi,uIe=/(?:^|\\.)(\\w+)(?:\\(([^)]*)\\))?/g,hEt=/^(['\"])((?:\\\\.|(?!\\1)[^\\\\])*)\\1$/,gEt=/\\\\(u(?:[a-f\\d]{4}|{[a-f\\d]{1,6}})|x[a-f\\d]{2}|.)|([^\\\\])/gi,dEt=new Map([[\"n\",`\n`],[\"r\",\"\\r\"],[\"t\",\"\t\"],[\"b\",\"\\b\"],[\"f\",\"\\f\"],[\"v\",\"\\v\"],[\"0\",\"\\0\"],[\"\\\\\",\"\\\\\"],[\"e\",\"\\x1B\"],[\"a\",\"\\x07\"]]);function fIe(t){let e=t[0]===\"u\",r=t[1]===\"{\";return e&&!r&&t.length===5||t[0]===\"x\"&&t.length===3?String.fromCharCode(parseInt(t.slice(1),16)):e&&r?String.fromCodePoint(parseInt(t.slice(2,-1),16)):dEt.get(t)||t}function mEt(t,e){let r=[],o=e.trim().split(/\\s*,\\s*/g),a;for(let n of o){let u=Number(n);if(!Number.isNaN(u))r.push(u);else if(a=n.match(hEt))r.push(a[2].replace(gEt,(A,p,h)=>p?fIe(p):h));else throw new Error(`Invalid Chalk template style argument: ${n} (in style '${t}')`)}return r}function yEt(t){uIe.lastIndex=0;let e=[],r;for(;(r=uIe.exec(t))!==null;){let o=r[1];if(r[2]){let a=mEt(o,r[2]);e.push([o].concat(a))}else e.push([o])}return e}function AIe(t,e){let r={};for(let a of e)for(let n of a.styles)r[n[0]]=a.inverse?null:n.slice(1);let o=t;for(let[a,n]of Object.entries(r))if(Array.isArray(n)){if(!(a in o))throw new Error(`Unknown Chalk style: ${a}`);o=n.length>0?o[a](...n):o[a]}return o}pIe.exports=(t,e)=>{let r=[],o=[],a=[];if(e.replace(pEt,(n,u,A,p,h,E)=>{if(u)a.push(fIe(u));else if(p){let w=a.join(\"\");a=[],o.push(r.length===0?w:AIe(t,r)(w)),r.push({inverse:A,styles:yEt(p)})}else if(h){if(r.length===0)throw new Error(\"Found extraneous } in Chalk template literal\");o.push(AIe(t,r)(a.join(\"\"))),a=[],r.pop()}else a.push(E)}),o.push(a.join(\"\")),r.length>0){let n=`Chalk template literal is missing ${r.length} closing bracket${r.length===1?\"\":\"s\"} (\\`}\\`)`;throw new Error(n)}return o.join(\"\")}});var FQ=_((vKt,CIe)=>{\"use strict\";var TB=qw(),{stdout:Qq,stderr:Fq}=$L(),{stringReplaceAll:EEt,stringEncaseCRLFWithFirstIndex:CEt}=cIe(),{isArray:xQ}=Array,dIe=[\"ansi\",\"ansi\",\"ansi256\",\"ansi16m\"],DC=Object.create(null),IEt=(t,e={})=>{if(e.level&&!(Number.isInteger(e.level)&&e.level>=0&&e.level<=3))throw new Error(\"The `level` option should be an integer from 0 to 3\");let r=Qq?Qq.level:0;t.level=e.level===void 0?r:e.level},Rq=class{constructor(e){return mIe(e)}},mIe=t=>{let e={};return IEt(e,t),e.template=(...r)=>EIe(e.template,...r),Object.setPrototypeOf(e,bQ.prototype),Object.setPrototypeOf(e.template,e),e.template.constructor=()=>{throw new Error(\"`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.\")},e.template.Instance=Rq,e.template};function bQ(t){return mIe(t)}for(let[t,e]of Object.entries(TB))DC[t]={get(){let r=kQ(this,Tq(e.open,e.close,this._styler),this._isEmpty);return Object.defineProperty(this,t,{value:r}),r}};DC.visible={get(){let t=kQ(this,this._styler,!0);return Object.defineProperty(this,\"visible\",{value:t}),t}};var yIe=[\"rgb\",\"hex\",\"keyword\",\"hsl\",\"hsv\",\"hwb\",\"ansi\",\"ansi256\"];for(let t of yIe)DC[t]={get(){let{level:e}=this;return function(...r){let o=Tq(TB.color[dIe[e]][t](...r),TB.color.close,this._styler);return kQ(this,o,this._isEmpty)}}};for(let t of yIe){let e=\"bg\"+t[0].toUpperCase()+t.slice(1);DC[e]={get(){let{level:r}=this;return function(...o){let a=Tq(TB.bgColor[dIe[r]][t](...o),TB.bgColor.close,this._styler);return kQ(this,a,this._isEmpty)}}}}var wEt=Object.defineProperties(()=>{},{...DC,level:{enumerable:!0,get(){return this._generator.level},set(t){this._generator.level=t}}}),Tq=(t,e,r)=>{let o,a;return r===void 0?(o=t,a=e):(o=r.openAll+t,a=e+r.closeAll),{open:t,close:e,openAll:o,closeAll:a,parent:r}},kQ=(t,e,r)=>{let o=(...a)=>xQ(a[0])&&xQ(a[0].raw)?gIe(o,EIe(o,...a)):gIe(o,a.length===1?\"\"+a[0]:a.join(\" \"));return Object.setPrototypeOf(o,wEt),o._generator=t,o._styler=e,o._isEmpty=r,o},gIe=(t,e)=>{if(t.level<=0||!e)return t._isEmpty?\"\":e;let r=t._styler;if(r===void 0)return e;let{openAll:o,closeAll:a}=r;if(e.indexOf(\"\\x1B\")!==-1)for(;r!==void 0;)e=EEt(e,r.close,r.open),r=r.parent;let n=e.indexOf(`\n`);return n!==-1&&(e=CEt(e,a,o,n)),o+e+a},kq,EIe=(t,...e)=>{let[r]=e;if(!xQ(r)||!xQ(r.raw))return e.join(\" \");let o=e.slice(1),a=[r.raw[0]];for(let n=1;n<r.length;n++)a.push(String(o[n-1]).replace(/[{}\\\\]/g,\"\\\\$&\"),String(r.raw[n]));return kq===void 0&&(kq=hIe()),kq(t,a.join(\"\"))};Object.defineProperties(bQ.prototype,DC);var QQ=bQ();QQ.supportsColor=Qq;QQ.stderr=bQ({level:Fq?Fq.level:0});QQ.stderr.supportsColor=Fq;CIe.exports=QQ});var Lq=_(NB=>{\"use strict\";var BEt=NB&&NB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(NB,\"__esModule\",{value:!0});var LB=BEt(FQ()),vEt=/^(rgb|hsl|hsv|hwb)\\(\\s?(\\d+),\\s?(\\d+),\\s?(\\d+)\\s?\\)$/,DEt=/^(ansi|ansi256)\\(\\s?(\\d+)\\s?\\)$/,RQ=(t,e)=>e===\"foreground\"?t:\"bg\"+t[0].toUpperCase()+t.slice(1);NB.default=(t,e,r)=>{if(!e)return t;if(e in LB.default){let a=RQ(e,r);return LB.default[a](t)}if(e.startsWith(\"#\")){let a=RQ(\"hex\",r);return LB.default[a](e)(t)}if(e.startsWith(\"ansi\")){let a=DEt.exec(e);if(!a)return t;let n=RQ(a[1],r),u=Number(a[2]);return LB.default[n](u)(t)}if(e.startsWith(\"rgb\")||e.startsWith(\"hsl\")||e.startsWith(\"hsv\")||e.startsWith(\"hwb\")){let a=vEt.exec(e);if(!a)return t;let n=RQ(a[1],r),u=Number(a[2]),A=Number(a[3]),p=Number(a[4]);return LB.default[n](u,A,p)(t)}return t}});var wIe=_(OB=>{\"use strict\";var IIe=OB&&OB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(OB,\"__esModule\",{value:!0});var PEt=IIe(aIe()),Nq=IIe(Lq());OB.default=(t,e,r,o)=>{if(typeof r.style.borderStyle==\"string\"){let a=r.yogaNode.getComputedWidth(),n=r.yogaNode.getComputedHeight(),u=r.style.borderColor,A=PEt.default[r.style.borderStyle],p=Nq.default(A.topLeft+A.horizontal.repeat(a-2)+A.topRight,u,\"foreground\"),h=(Nq.default(A.vertical,u,\"foreground\")+`\n`).repeat(n-2),E=Nq.default(A.bottomLeft+A.horizontal.repeat(a-2)+A.bottomRight,u,\"foreground\");o.write(t,e,p,{transformers:[]}),o.write(t,e+1,h,{transformers:[]}),o.write(t+a-1,e+1,h,{transformers:[]}),o.write(t,e+n-1,E,{transformers:[]})}}});var vIe=_(MB=>{\"use strict\";var sd=MB&&MB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(MB,\"__esModule\",{value:!0});var SEt=sd(id()),xEt=sd(Eq()),bEt=sd(nIe()),kEt=sd(Dq()),QEt=sd(iIe()),FEt=sd(Sq()),REt=sd(wIe()),TEt=(t,e)=>{var r;let o=(r=t.childNodes[0])===null||r===void 0?void 0:r.yogaNode;if(o){let a=o.getComputedLeft(),n=o.getComputedTop();e=`\n`.repeat(n)+bEt.default(e,a)}return e},BIe=(t,e,r)=>{var o;let{offsetX:a=0,offsetY:n=0,transformers:u=[],skipStaticElements:A}=r;if(A&&t.internal_static)return;let{yogaNode:p}=t;if(p){if(p.getDisplay()===SEt.default.DISPLAY_NONE)return;let h=a+p.getComputedLeft(),E=n+p.getComputedTop(),w=u;if(typeof t.internal_transform==\"function\"&&(w=[t.internal_transform,...u]),t.nodeName===\"ink-text\"){let D=FEt.default(t);if(D.length>0){let b=xEt.default(D),C=QEt.default(p);if(b>C){let T=(o=t.style.textWrap)!==null&&o!==void 0?o:\"wrap\";D=kEt.default(D,C,T)}D=TEt(t,D),e.write(h,E,D,{transformers:w})}return}if(t.nodeName===\"ink-box\"&&REt.default(h,E,t,e),t.nodeName===\"ink-root\"||t.nodeName===\"ink-box\")for(let D of t.childNodes)BIe(D,e,{offsetX:h,offsetY:E,transformers:w,skipStaticElements:A})}};MB.default=BIe});var SIe=_(UB=>{\"use strict\";var PIe=UB&&UB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(UB,\"__esModule\",{value:!0});var DIe=PIe(Bq()),LEt=PIe(PB()),Oq=class{constructor(e){this.writes=[];let{width:r,height:o}=e;this.width=r,this.height=o}write(e,r,o,a){let{transformers:n}=a;o&&this.writes.push({x:e,y:r,text:o,transformers:n})}get(){let e=[];for(let o=0;o<this.height;o++)e.push(\" \".repeat(this.width));for(let o of this.writes){let{x:a,y:n,text:u,transformers:A}=o,p=u.split(`\n`),h=0;for(let E of p){let w=e[n+h];if(!w)continue;let D=LEt.default(E);for(let b of A)E=b(E);e[n+h]=DIe.default(w,0,a)+E+DIe.default(w,a+D),h++}}return{output:e.map(o=>o.trimRight()).join(`\n`),height:e.length}}};UB.default=Oq});var kIe=_(_B=>{\"use strict\";var Mq=_B&&_B.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(_B,\"__esModule\",{value:!0});var NEt=Mq(id()),xIe=Mq(vIe()),bIe=Mq(SIe());_B.default=(t,e)=>{var r;if(t.yogaNode.setWidth(e),t.yogaNode){t.yogaNode.calculateLayout(void 0,void 0,NEt.default.DIRECTION_LTR);let o=new bIe.default({width:t.yogaNode.getComputedWidth(),height:t.yogaNode.getComputedHeight()});xIe.default(t,o,{skipStaticElements:!0});let a;!((r=t.staticNode)===null||r===void 0)&&r.yogaNode&&(a=new bIe.default({width:t.staticNode.yogaNode.getComputedWidth(),height:t.staticNode.yogaNode.getComputedHeight()}),xIe.default(t.staticNode,a,{skipStaticElements:!1}));let{output:n,height:u}=o.get();return{output:n,outputHeight:u,staticOutput:a?`${a.get().output}\n`:\"\"}}return{output:\"\",outputHeight:0,staticOutput:\"\"}}});var TIe=_((kKt,RIe)=>{\"use strict\";var QIe=ve(\"stream\"),FIe=[\"assert\",\"count\",\"countReset\",\"debug\",\"dir\",\"dirxml\",\"error\",\"group\",\"groupCollapsed\",\"groupEnd\",\"info\",\"log\",\"table\",\"time\",\"timeEnd\",\"timeLog\",\"trace\",\"warn\"],Uq={},OEt=t=>{let e=new QIe.PassThrough,r=new QIe.PassThrough;e.write=a=>t(\"stdout\",a),r.write=a=>t(\"stderr\",a);let o=new console.Console(e,r);for(let a of FIe)Uq[a]=console[a],console[a]=o[a];return()=>{for(let a of FIe)console[a]=Uq[a];Uq={}}};RIe.exports=OEt});var Hq=_(_q=>{\"use strict\";Object.defineProperty(_q,\"__esModule\",{value:!0});_q.default=new WeakMap});var jq=_(qq=>{\"use strict\";Object.defineProperty(qq,\"__esModule\",{value:!0});var MEt=ln(),LIe=MEt.createContext({exit:()=>{}});LIe.displayName=\"InternalAppContext\";qq.default=LIe});var Wq=_(Gq=>{\"use strict\";Object.defineProperty(Gq,\"__esModule\",{value:!0});var UEt=ln(),NIe=UEt.createContext({stdin:void 0,setRawMode:()=>{},isRawModeSupported:!1,internal_exitOnCtrlC:!0});NIe.displayName=\"InternalStdinContext\";Gq.default=NIe});var Kq=_(Yq=>{\"use strict\";Object.defineProperty(Yq,\"__esModule\",{value:!0});var _Et=ln(),OIe=_Et.createContext({stdout:void 0,write:()=>{}});OIe.displayName=\"InternalStdoutContext\";Yq.default=OIe});var zq=_(Vq=>{\"use strict\";Object.defineProperty(Vq,\"__esModule\",{value:!0});var HEt=ln(),MIe=HEt.createContext({stderr:void 0,write:()=>{}});MIe.displayName=\"InternalStderrContext\";Vq.default=MIe});var TQ=_(Jq=>{\"use strict\";Object.defineProperty(Jq,\"__esModule\",{value:!0});var qEt=ln(),UIe=qEt.createContext({activeId:void 0,add:()=>{},remove:()=>{},activate:()=>{},deactivate:()=>{},enableFocus:()=>{},disableFocus:()=>{},focusNext:()=>{},focusPrevious:()=>{},focus:()=>{}});UIe.displayName=\"InternalFocusContext\";Jq.default=UIe});var HIe=_((OKt,_Ie)=>{\"use strict\";var jEt=/[|\\\\{}()[\\]^$+*?.-]/g;_Ie.exports=t=>{if(typeof t!=\"string\")throw new TypeError(\"Expected a string\");return t.replace(jEt,\"\\\\$&\")}});var WIe=_((MKt,GIe)=>{\"use strict\";var GEt=HIe(),WEt=typeof process==\"object\"&&process&&typeof process.cwd==\"function\"?process.cwd():\".\",jIe=[].concat(ve(\"module\").builtinModules,\"bootstrap_node\",\"node\").map(t=>new RegExp(`(?:\\\\((?:node:)?${t}(?:\\\\.js)?:\\\\d+:\\\\d+\\\\)$|^\\\\s*at (?:node:)?${t}(?:\\\\.js)?:\\\\d+:\\\\d+$)`));jIe.push(/\\((?:node:)?internal\\/[^:]+:\\d+:\\d+\\)$/,/\\s*at (?:node:)?internal\\/[^:]+:\\d+:\\d+$/,/\\/\\.node-spawn-wrap-\\w+-\\w+\\/node:\\d+:\\d+\\)?$/);var Xq=class t{constructor(e){e={ignoredPackages:[],...e},\"internals\"in e||(e.internals=t.nodeInternals()),\"cwd\"in e||(e.cwd=WEt),this._cwd=e.cwd.replace(/\\\\/g,\"/\"),this._internals=[].concat(e.internals,YEt(e.ignoredPackages)),this._wrapCallSite=e.wrapCallSite||!1}static nodeInternals(){return[...jIe]}clean(e,r=0){r=\" \".repeat(r),Array.isArray(e)||(e=e.split(`\n`)),!/^\\s*at /.test(e[0])&&/^\\s*at /.test(e[1])&&(e=e.slice(1));let o=!1,a=null,n=[];return e.forEach(u=>{if(u=u.replace(/\\\\/g,\"/\"),this._internals.some(p=>p.test(u)))return;let A=/^\\s*at /.test(u);o?u=u.trimEnd().replace(/^(\\s+)at /,\"$1\"):(u=u.trim(),A&&(u=u.slice(3))),u=u.replace(`${this._cwd}/`,\"\"),u&&(A?(a&&(n.push(a),a=null),n.push(u)):(o=!0,a=u))}),n.map(u=>`${r}${u}\n`).join(\"\")}captureString(e,r=this.captureString){typeof e==\"function\"&&(r=e,e=1/0);let{stackTraceLimit:o}=Error;e&&(Error.stackTraceLimit=e);let a={};Error.captureStackTrace(a,r);let{stack:n}=a;return Error.stackTraceLimit=o,this.clean(n)}capture(e,r=this.capture){typeof e==\"function\"&&(r=e,e=1/0);let{prepareStackTrace:o,stackTraceLimit:a}=Error;Error.prepareStackTrace=(A,p)=>this._wrapCallSite?p.map(this._wrapCallSite):p,e&&(Error.stackTraceLimit=e);let n={};Error.captureStackTrace(n,r);let{stack:u}=n;return Object.assign(Error,{prepareStackTrace:o,stackTraceLimit:a}),u}at(e=this.at){let[r]=this.capture(1,e);if(!r)return{};let o={line:r.getLineNumber(),column:r.getColumnNumber()};qIe(o,r.getFileName(),this._cwd),r.isConstructor()&&(o.constructor=!0),r.isEval()&&(o.evalOrigin=r.getEvalOrigin()),r.isNative()&&(o.native=!0);let a;try{a=r.getTypeName()}catch{}a&&a!==\"Object\"&&a!==\"[object Object]\"&&(o.type=a);let n=r.getFunctionName();n&&(o.function=n);let u=r.getMethodName();return u&&n!==u&&(o.method=u),o}parseLine(e){let r=e&&e.match(KEt);if(!r)return null;let o=r[1]===\"new\",a=r[2],n=r[3],u=r[4],A=Number(r[5]),p=Number(r[6]),h=r[7],E=r[8],w=r[9],D=r[10]===\"native\",b=r[11]===\")\",C,T={};if(E&&(T.line=Number(E)),w&&(T.column=Number(w)),b&&h){let N=0;for(let U=h.length-1;U>0;U--)if(h.charAt(U)===\")\")N++;else if(h.charAt(U)===\"(\"&&h.charAt(U-1)===\" \"&&(N--,N===-1&&h.charAt(U-1)===\" \")){let z=h.slice(0,U-1);h=h.slice(U+1),a+=` (${z}`;break}}if(a){let N=a.match(VEt);N&&(a=N[1],C=N[2])}return qIe(T,h,this._cwd),o&&(T.constructor=!0),n&&(T.evalOrigin=n,T.evalLine=A,T.evalColumn=p,T.evalFile=u&&u.replace(/\\\\/g,\"/\")),D&&(T.native=!0),a&&(T.function=a),C&&a!==C&&(T.method=C),T}};function qIe(t,e,r){e&&(e=e.replace(/\\\\/g,\"/\"),e.startsWith(`${r}/`)&&(e=e.slice(r.length+1)),t.file=e)}function YEt(t){if(t.length===0)return[];let e=t.map(r=>GEt(r));return new RegExp(`[/\\\\\\\\]node_modules[/\\\\\\\\](?:${e.join(\"|\")})[/\\\\\\\\][^:]+:\\\\d+:\\\\d+`)}var KEt=new RegExp(\"^(?:\\\\s*at )?(?:(new) )?(?:(.*?) \\\\()?(?:eval at ([^ ]+) \\\\((.+?):(\\\\d+):(\\\\d+)\\\\), )?(?:(.+?):(\\\\d+):(\\\\d+)|(native))(\\\\)?)$\"),VEt=/^(.*?) \\[as (.*?)\\]$/;GIe.exports=Xq});var KIe=_((UKt,YIe)=>{\"use strict\";YIe.exports=(t,e)=>t.replace(/^\\t+/gm,r=>\" \".repeat(r.length*(e||2)))});var zIe=_((_Kt,VIe)=>{\"use strict\";var zEt=KIe(),JEt=(t,e)=>{let r=[],o=t-e,a=t+e;for(let n=o;n<=a;n++)r.push(n);return r};VIe.exports=(t,e,r)=>{if(typeof t!=\"string\")throw new TypeError(\"Source code is missing.\");if(!e||e<1)throw new TypeError(\"Line number must start from `1`.\");if(t=zEt(t).split(/\\r?\\n/),!(e>t.length))return r={around:3,...r},JEt(e,r.around).filter(o=>t[o-1]!==void 0).map(o=>({line:o,value:t[o-1]}))}});var LQ=_(lu=>{\"use strict\";var XEt=lu&&lu.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),ZEt=lu&&lu.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,\"default\",{enumerable:!0,value:e})}:function(t,e){t.default=e}),$Et=lu&&lu.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!==\"default\"&&Object.hasOwnProperty.call(t,r)&&XEt(e,t,r);return ZEt(e,t),e},eCt=lu&&lu.__rest||function(t,e){var r={};for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&e.indexOf(o)<0&&(r[o]=t[o]);if(t!=null&&typeof Object.getOwnPropertySymbols==\"function\")for(var a=0,o=Object.getOwnPropertySymbols(t);a<o.length;a++)e.indexOf(o[a])<0&&Object.prototype.propertyIsEnumerable.call(t,o[a])&&(r[o[a]]=t[o[a]]);return r};Object.defineProperty(lu,\"__esModule\",{value:!0});var JIe=$Et(ln()),Zq=JIe.forwardRef((t,e)=>{var{children:r}=t,o=eCt(t,[\"children\"]);let a=Object.assign(Object.assign({},o),{marginLeft:o.marginLeft||o.marginX||o.margin||0,marginRight:o.marginRight||o.marginX||o.margin||0,marginTop:o.marginTop||o.marginY||o.margin||0,marginBottom:o.marginBottom||o.marginY||o.margin||0,paddingLeft:o.paddingLeft||o.paddingX||o.padding||0,paddingRight:o.paddingRight||o.paddingX||o.padding||0,paddingTop:o.paddingTop||o.paddingY||o.padding||0,paddingBottom:o.paddingBottom||o.paddingY||o.padding||0});return JIe.default.createElement(\"ink-box\",{ref:e,style:a},r)});Zq.displayName=\"Box\";Zq.defaultProps={flexDirection:\"row\",flexGrow:0,flexShrink:1};lu.default=Zq});var tj=_(HB=>{\"use strict\";var $q=HB&&HB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(HB,\"__esModule\",{value:!0});var tCt=$q(ln()),PC=$q(FQ()),XIe=$q(Lq()),ej=({color:t,backgroundColor:e,dimColor:r,bold:o,italic:a,underline:n,strikethrough:u,inverse:A,wrap:p,children:h})=>{if(h==null)return null;let E=w=>(r&&(w=PC.default.dim(w)),t&&(w=XIe.default(w,t,\"foreground\")),e&&(w=XIe.default(w,e,\"background\")),o&&(w=PC.default.bold(w)),a&&(w=PC.default.italic(w)),n&&(w=PC.default.underline(w)),u&&(w=PC.default.strikethrough(w)),A&&(w=PC.default.inverse(w)),w);return tCt.default.createElement(\"ink-text\",{style:{flexGrow:0,flexShrink:1,flexDirection:\"row\",textWrap:p},internal_transform:E},h)};ej.displayName=\"Text\";ej.defaultProps={dimColor:!1,bold:!1,italic:!1,underline:!1,strikethrough:!1,wrap:\"wrap\"};HB.default=ej});var twe=_(cu=>{\"use strict\";var rCt=cu&&cu.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),nCt=cu&&cu.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,\"default\",{enumerable:!0,value:e})}:function(t,e){t.default=e}),iCt=cu&&cu.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!==\"default\"&&Object.hasOwnProperty.call(t,r)&&rCt(e,t,r);return nCt(e,t),e},qB=cu&&cu.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(cu,\"__esModule\",{value:!0});var ZIe=iCt(ve(\"fs\")),ps=qB(ln()),$Ie=qB(WIe()),sCt=qB(zIe()),zf=qB(LQ()),mA=qB(tj()),ewe=new $Ie.default({cwd:process.cwd(),internals:$Ie.default.nodeInternals()}),oCt=({error:t})=>{let e=t.stack?t.stack.split(`\n`).slice(1):void 0,r=e?ewe.parseLine(e[0]):void 0,o,a=0;if(r?.file&&r?.line&&ZIe.existsSync(r.file)){let n=ZIe.readFileSync(r.file,\"utf8\");if(o=sCt.default(n,r.line),o)for(let{line:u}of o)a=Math.max(a,String(u).length)}return ps.default.createElement(zf.default,{flexDirection:\"column\",padding:1},ps.default.createElement(zf.default,null,ps.default.createElement(mA.default,{backgroundColor:\"red\",color:\"white\"},\" \",\"ERROR\",\" \"),ps.default.createElement(mA.default,null,\" \",t.message)),r&&ps.default.createElement(zf.default,{marginTop:1},ps.default.createElement(mA.default,{dimColor:!0},r.file,\":\",r.line,\":\",r.column)),r&&o&&ps.default.createElement(zf.default,{marginTop:1,flexDirection:\"column\"},o.map(({line:n,value:u})=>ps.default.createElement(zf.default,{key:n},ps.default.createElement(zf.default,{width:a+1},ps.default.createElement(mA.default,{dimColor:n!==r.line,backgroundColor:n===r.line?\"red\":void 0,color:n===r.line?\"white\":void 0},String(n).padStart(a,\" \"),\":\")),ps.default.createElement(mA.default,{key:n,backgroundColor:n===r.line?\"red\":void 0,color:n===r.line?\"white\":void 0},\" \"+u)))),t.stack&&ps.default.createElement(zf.default,{marginTop:1,flexDirection:\"column\"},t.stack.split(`\n`).slice(1).map(n=>{let u=ewe.parseLine(n);return u?ps.default.createElement(zf.default,{key:n},ps.default.createElement(mA.default,{dimColor:!0},\"- \"),ps.default.createElement(mA.default,{dimColor:!0,bold:!0},u.function),ps.default.createElement(mA.default,{dimColor:!0,color:\"gray\"},\" \",\"(\",u.file,\":\",u.line,\":\",u.column,\")\")):ps.default.createElement(zf.default,{key:n},ps.default.createElement(mA.default,{dimColor:!0},\"- \"),ps.default.createElement(mA.default,{dimColor:!0,bold:!0},n))})))};cu.default=oCt});var nwe=_(uu=>{\"use strict\";var aCt=uu&&uu.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),lCt=uu&&uu.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,\"default\",{enumerable:!0,value:e})}:function(t,e){t.default=e}),cCt=uu&&uu.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!==\"default\"&&Object.hasOwnProperty.call(t,r)&&aCt(e,t,r);return lCt(e,t),e},ad=uu&&uu.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(uu,\"__esModule\",{value:!0});var od=cCt(ln()),rwe=ad(Z6()),uCt=ad(jq()),ACt=ad(Wq()),fCt=ad(Kq()),pCt=ad(zq()),hCt=ad(TQ()),gCt=ad(twe()),dCt=\"\t\",mCt=\"\\x1B[Z\",yCt=\"\\x1B\",NQ=class extends od.PureComponent{constructor(){super(...arguments),this.state={isFocusEnabled:!0,activeFocusId:void 0,focusables:[],error:void 0},this.rawModeEnabledCount=0,this.handleSetRawMode=e=>{let{stdin:r}=this.props;if(!this.isRawModeSupported())throw r===process.stdin?new Error(`Raw mode is not supported on the current process.stdin, which Ink uses as input stream by default.\nRead about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported`):new Error(`Raw mode is not supported on the stdin provided to Ink.\nRead about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported`);if(r.setEncoding(\"utf8\"),e){this.rawModeEnabledCount===0&&(r.addListener(\"data\",this.handleInput),r.resume(),r.setRawMode(!0)),this.rawModeEnabledCount++;return}--this.rawModeEnabledCount===0&&(r.setRawMode(!1),r.removeListener(\"data\",this.handleInput),r.pause())},this.handleInput=e=>{e===\"\u0003\"&&this.props.exitOnCtrlC&&this.handleExit(),e===yCt&&this.state.activeFocusId&&this.setState({activeFocusId:void 0}),this.state.isFocusEnabled&&this.state.focusables.length>0&&(e===dCt&&this.focusNext(),e===mCt&&this.focusPrevious())},this.handleExit=e=>{this.isRawModeSupported()&&this.handleSetRawMode(!1),this.props.onExit(e)},this.enableFocus=()=>{this.setState({isFocusEnabled:!0})},this.disableFocus=()=>{this.setState({isFocusEnabled:!1})},this.focus=e=>{this.setState(r=>r.focusables.some(a=>a?.id===e)?{activeFocusId:e}:r)},this.focusNext=()=>{this.setState(e=>{var r;let o=(r=e.focusables[0])===null||r===void 0?void 0:r.id;return{activeFocusId:this.findNextFocusable(e)||o}})},this.focusPrevious=()=>{this.setState(e=>{var r;let o=(r=e.focusables[e.focusables.length-1])===null||r===void 0?void 0:r.id;return{activeFocusId:this.findPreviousFocusable(e)||o}})},this.addFocusable=(e,{autoFocus:r})=>{this.setState(o=>{let a=o.activeFocusId;return!a&&r&&(a=e),{activeFocusId:a,focusables:[...o.focusables,{id:e,isActive:!0}]}})},this.removeFocusable=e=>{this.setState(r=>({activeFocusId:r.activeFocusId===e?void 0:r.activeFocusId,focusables:r.focusables.filter(o=>o.id!==e)}))},this.activateFocusable=e=>{this.setState(r=>({focusables:r.focusables.map(o=>o.id!==e?o:{id:e,isActive:!0})}))},this.deactivateFocusable=e=>{this.setState(r=>({activeFocusId:r.activeFocusId===e?void 0:r.activeFocusId,focusables:r.focusables.map(o=>o.id!==e?o:{id:e,isActive:!1})}))},this.findNextFocusable=e=>{var r;let o=e.focusables.findIndex(a=>a.id===e.activeFocusId);for(let a=o+1;a<e.focusables.length;a++)if(!((r=e.focusables[a])===null||r===void 0)&&r.isActive)return e.focusables[a].id},this.findPreviousFocusable=e=>{var r;let o=e.focusables.findIndex(a=>a.id===e.activeFocusId);for(let a=o-1;a>=0;a--)if(!((r=e.focusables[a])===null||r===void 0)&&r.isActive)return e.focusables[a].id}}static getDerivedStateFromError(e){return{error:e}}isRawModeSupported(){return this.props.stdin.isTTY}render(){return od.default.createElement(uCt.default.Provider,{value:{exit:this.handleExit}},od.default.createElement(ACt.default.Provider,{value:{stdin:this.props.stdin,setRawMode:this.handleSetRawMode,isRawModeSupported:this.isRawModeSupported(),internal_exitOnCtrlC:this.props.exitOnCtrlC}},od.default.createElement(fCt.default.Provider,{value:{stdout:this.props.stdout,write:this.props.writeToStdout}},od.default.createElement(pCt.default.Provider,{value:{stderr:this.props.stderr,write:this.props.writeToStderr}},od.default.createElement(hCt.default.Provider,{value:{activeId:this.state.activeFocusId,add:this.addFocusable,remove:this.removeFocusable,activate:this.activateFocusable,deactivate:this.deactivateFocusable,enableFocus:this.enableFocus,disableFocus:this.disableFocus,focusNext:this.focusNext,focusPrevious:this.focusPrevious,focus:this.focus}},this.state.error?od.default.createElement(gCt.default,{error:this.state.error}):this.props.children)))))}componentDidMount(){rwe.default.hide(this.props.stdout)}componentWillUnmount(){rwe.default.show(this.props.stdout),this.isRawModeSupported()&&this.handleSetRawMode(!1)}componentDidCatch(e){this.handleExit(e)}};uu.default=NQ;NQ.displayName=\"InternalApp\"});var owe=_(Au=>{\"use strict\";var ECt=Au&&Au.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),CCt=Au&&Au.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,\"default\",{enumerable:!0,value:e})}:function(t,e){t.default=e}),ICt=Au&&Au.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!==\"default\"&&Object.hasOwnProperty.call(t,r)&&ECt(e,t,r);return CCt(e,t),e},fu=Au&&Au.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(Au,\"__esModule\",{value:!0});var wCt=fu(ln()),iwe=WM(),BCt=fu(tCe()),vCt=fu(K6()),DCt=fu(aCe()),PCt=fu(cCe()),rj=fu(tIe()),SCt=fu(kIe()),xCt=fu(X6()),bCt=fu(TIe()),kCt=ICt(xq()),QCt=fu(Hq()),FCt=fu(nwe()),SC=process.env.CI===\"false\"?!1:DCt.default,swe=()=>{},nj=class{constructor(e){this.resolveExitPromise=()=>{},this.rejectExitPromise=()=>{},this.unsubscribeExit=()=>{},this.onRender=()=>{if(this.isUnmounted)return;let{output:r,outputHeight:o,staticOutput:a}=SCt.default(this.rootNode,this.options.stdout.columns||80),n=a&&a!==`\n`;if(this.options.debug){n&&(this.fullStaticOutput+=a),this.options.stdout.write(this.fullStaticOutput+r);return}if(SC){n&&this.options.stdout.write(a),this.lastOutput=r;return}if(n&&(this.fullStaticOutput+=a),o>=this.options.stdout.rows){this.options.stdout.write(vCt.default.clearTerminal+this.fullStaticOutput+r),this.lastOutput=r;return}n&&(this.log.clear(),this.options.stdout.write(a),this.log(r)),!n&&r!==this.lastOutput&&this.throttledLog(r),this.lastOutput=r},PCt.default(this),this.options=e,this.rootNode=kCt.createNode(\"ink-root\"),this.rootNode.onRender=e.debug?this.onRender:iwe(this.onRender,32,{leading:!0,trailing:!0}),this.rootNode.onImmediateRender=this.onRender,this.log=BCt.default.create(e.stdout),this.throttledLog=e.debug?this.log:iwe(this.log,void 0,{leading:!0,trailing:!0}),this.isUnmounted=!1,this.lastOutput=\"\",this.fullStaticOutput=\"\",this.container=rj.default.createContainer(this.rootNode,0,!1,null),this.unsubscribeExit=xCt.default(this.unmount,{alwaysLast:!1}),e.patchConsole&&this.patchConsole(),SC||(e.stdout.on(\"resize\",this.onRender),this.unsubscribeResize=()=>{e.stdout.off(\"resize\",this.onRender)})}render(e){let r=wCt.default.createElement(FCt.default,{stdin:this.options.stdin,stdout:this.options.stdout,stderr:this.options.stderr,writeToStdout:this.writeToStdout,writeToStderr:this.writeToStderr,exitOnCtrlC:this.options.exitOnCtrlC,onExit:this.unmount},e);rj.default.updateContainer(r,this.container,null,swe)}writeToStdout(e){if(!this.isUnmounted){if(this.options.debug){this.options.stdout.write(e+this.fullStaticOutput+this.lastOutput);return}if(SC){this.options.stdout.write(e);return}this.log.clear(),this.options.stdout.write(e),this.log(this.lastOutput)}}writeToStderr(e){if(!this.isUnmounted){if(this.options.debug){this.options.stderr.write(e),this.options.stdout.write(this.fullStaticOutput+this.lastOutput);return}if(SC){this.options.stderr.write(e);return}this.log.clear(),this.options.stderr.write(e),this.log(this.lastOutput)}}unmount(e){this.isUnmounted||(this.onRender(),this.unsubscribeExit(),typeof this.restoreConsole==\"function\"&&this.restoreConsole(),typeof this.unsubscribeResize==\"function\"&&this.unsubscribeResize(),SC?this.options.stdout.write(this.lastOutput+`\n`):this.options.debug||this.log.done(),this.isUnmounted=!0,rj.default.updateContainer(null,this.container,null,swe),QCt.default.delete(this.options.stdout),e instanceof Error?this.rejectExitPromise(e):this.resolveExitPromise())}waitUntilExit(){return this.exitPromise||(this.exitPromise=new Promise((e,r)=>{this.resolveExitPromise=e,this.rejectExitPromise=r})),this.exitPromise}clear(){!SC&&!this.options.debug&&this.log.clear()}patchConsole(){this.options.debug||(this.restoreConsole=bCt.default((e,r)=>{e===\"stdout\"&&this.writeToStdout(r),e===\"stderr\"&&(r.startsWith(\"The above error occurred\")||this.writeToStderr(r))}))}};Au.default=nj});var lwe=_(jB=>{\"use strict\";var awe=jB&&jB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(jB,\"__esModule\",{value:!0});var RCt=awe(owe()),OQ=awe(Hq()),TCt=ve(\"stream\"),LCt=(t,e)=>{let r=Object.assign({stdout:process.stdout,stdin:process.stdin,stderr:process.stderr,debug:!1,exitOnCtrlC:!0,patchConsole:!0},NCt(e)),o=OCt(r.stdout,()=>new RCt.default(r));return o.render(t),{rerender:o.render,unmount:()=>o.unmount(),waitUntilExit:o.waitUntilExit,cleanup:()=>OQ.default.delete(r.stdout),clear:o.clear}};jB.default=LCt;var NCt=(t={})=>t instanceof TCt.Stream?{stdout:t,stdin:process.stdin}:t,OCt=(t,e)=>{let r;return OQ.default.has(t)?r=OQ.default.get(t):(r=e(),OQ.default.set(t,r)),r}});var uwe=_(Jf=>{\"use strict\";var MCt=Jf&&Jf.__createBinding||(Object.create?function(t,e,r,o){o===void 0&&(o=r),Object.defineProperty(t,o,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,o){o===void 0&&(o=r),t[o]=e[r]}),UCt=Jf&&Jf.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,\"default\",{enumerable:!0,value:e})}:function(t,e){t.default=e}),_Ct=Jf&&Jf.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!==\"default\"&&Object.hasOwnProperty.call(t,r)&&MCt(e,t,r);return UCt(e,t),e};Object.defineProperty(Jf,\"__esModule\",{value:!0});var GB=_Ct(ln()),cwe=t=>{let{items:e,children:r,style:o}=t,[a,n]=GB.useState(0),u=GB.useMemo(()=>e.slice(a),[e,a]);GB.useLayoutEffect(()=>{n(e.length)},[e.length]);let A=u.map((h,E)=>r(h,a+E)),p=GB.useMemo(()=>Object.assign({position:\"absolute\",flexDirection:\"column\"},o),[o]);return GB.default.createElement(\"ink-box\",{internal_static:!0,style:p},A)};cwe.displayName=\"Static\";Jf.default=cwe});var fwe=_(WB=>{\"use strict\";var HCt=WB&&WB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(WB,\"__esModule\",{value:!0});var qCt=HCt(ln()),Awe=({children:t,transform:e})=>t==null?null:qCt.default.createElement(\"ink-text\",{style:{flexGrow:0,flexShrink:1,flexDirection:\"row\"},internal_transform:e},t);Awe.displayName=\"Transform\";WB.default=Awe});var hwe=_(YB=>{\"use strict\";var jCt=YB&&YB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(YB,\"__esModule\",{value:!0});var GCt=jCt(ln()),pwe=({count:t=1})=>GCt.default.createElement(\"ink-text\",null,`\n`.repeat(t));pwe.displayName=\"Newline\";YB.default=pwe});var mwe=_(KB=>{\"use strict\";var gwe=KB&&KB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(KB,\"__esModule\",{value:!0});var WCt=gwe(ln()),YCt=gwe(LQ()),dwe=()=>WCt.default.createElement(YCt.default,{flexGrow:1});dwe.displayName=\"Spacer\";KB.default=dwe});var MQ=_(VB=>{\"use strict\";var KCt=VB&&VB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(VB,\"__esModule\",{value:!0});var VCt=ln(),zCt=KCt(Wq()),JCt=()=>VCt.useContext(zCt.default);VB.default=JCt});var Ewe=_(zB=>{\"use strict\";var XCt=zB&&zB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(zB,\"__esModule\",{value:!0});var ywe=ln(),ZCt=XCt(MQ()),$Ct=(t,e={})=>{let{stdin:r,setRawMode:o,internal_exitOnCtrlC:a}=ZCt.default();ywe.useEffect(()=>{if(e.isActive!==!1)return o(!0),()=>{o(!1)}},[e.isActive,o]),ywe.useEffect(()=>{if(e.isActive===!1)return;let n=u=>{let A=String(u),p={upArrow:A===\"\\x1B[A\",downArrow:A===\"\\x1B[B\",leftArrow:A===\"\\x1B[D\",rightArrow:A===\"\\x1B[C\",pageDown:A===\"\\x1B[6~\",pageUp:A===\"\\x1B[5~\",return:A===\"\\r\",escape:A===\"\\x1B\",ctrl:!1,shift:!1,tab:A===\"\t\"||A===\"\\x1B[Z\",backspace:A===\"\\b\",delete:A===\"\\x7F\"||A===\"\\x1B[3~\",meta:!1};A<=\"\u001a\"&&!p.return&&(A=String.fromCharCode(A.charCodeAt(0)+97-1),p.ctrl=!0),A.startsWith(\"\\x1B\")&&(A=A.slice(1),p.meta=!0);let h=A>=\"A\"&&A<=\"Z\",E=A>=\"\\u0410\"&&A<=\"\\u042F\";A.length===1&&(h||E)&&(p.shift=!0),p.tab&&A===\"[Z\"&&(p.shift=!0),(p.tab||p.backspace||p.delete)&&(A=\"\"),(!(A===\"c\"&&p.ctrl)||!a)&&t(A,p)};return r?.on(\"data\",n),()=>{r?.off(\"data\",n)}},[e.isActive,r,a,t])};zB.default=$Ct});var Cwe=_(JB=>{\"use strict\";var eIt=JB&&JB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(JB,\"__esModule\",{value:!0});var tIt=ln(),rIt=eIt(jq()),nIt=()=>tIt.useContext(rIt.default);JB.default=nIt});var Iwe=_(XB=>{\"use strict\";var iIt=XB&&XB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(XB,\"__esModule\",{value:!0});var sIt=ln(),oIt=iIt(Kq()),aIt=()=>sIt.useContext(oIt.default);XB.default=aIt});var wwe=_(ZB=>{\"use strict\";var lIt=ZB&&ZB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(ZB,\"__esModule\",{value:!0});var cIt=ln(),uIt=lIt(zq()),AIt=()=>cIt.useContext(uIt.default);ZB.default=AIt});var vwe=_(ev=>{\"use strict\";var Bwe=ev&&ev.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(ev,\"__esModule\",{value:!0});var $B=ln(),fIt=Bwe(TQ()),pIt=Bwe(MQ()),hIt=({isActive:t=!0,autoFocus:e=!1,id:r}={})=>{let{isRawModeSupported:o,setRawMode:a}=pIt.default(),{activeId:n,add:u,remove:A,activate:p,deactivate:h,focus:E}=$B.useContext(fIt.default),w=$B.useMemo(()=>r??Math.random().toString().slice(2,7),[r]);return $B.useEffect(()=>(u(w,{autoFocus:e}),()=>{A(w)}),[w,e]),$B.useEffect(()=>{t?p(w):h(w)},[t,w]),$B.useEffect(()=>{if(!(!o||!t))return a(!0),()=>{a(!1)}},[t]),{isFocused:!!w&&n===w,focus:E}};ev.default=hIt});var Dwe=_(tv=>{\"use strict\";var gIt=tv&&tv.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(tv,\"__esModule\",{value:!0});var dIt=ln(),mIt=gIt(TQ()),yIt=()=>{let t=dIt.useContext(mIt.default);return{enableFocus:t.enableFocus,disableFocus:t.disableFocus,focusNext:t.focusNext,focusPrevious:t.focusPrevious,focus:t.focus}};tv.default=yIt});var Pwe=_(ij=>{\"use strict\";Object.defineProperty(ij,\"__esModule\",{value:!0});ij.default=t=>{var e,r,o,a;return{width:(r=(e=t.yogaNode)===null||e===void 0?void 0:e.getComputedWidth())!==null&&r!==void 0?r:0,height:(a=(o=t.yogaNode)===null||o===void 0?void 0:o.getComputedHeight())!==null&&a!==void 0?a:0}}});var ac=_(zs=>{\"use strict\";Object.defineProperty(zs,\"__esModule\",{value:!0});var EIt=lwe();Object.defineProperty(zs,\"render\",{enumerable:!0,get:function(){return EIt.default}});var CIt=LQ();Object.defineProperty(zs,\"Box\",{enumerable:!0,get:function(){return CIt.default}});var IIt=tj();Object.defineProperty(zs,\"Text\",{enumerable:!0,get:function(){return IIt.default}});var wIt=uwe();Object.defineProperty(zs,\"Static\",{enumerable:!0,get:function(){return wIt.default}});var BIt=fwe();Object.defineProperty(zs,\"Transform\",{enumerable:!0,get:function(){return BIt.default}});var vIt=hwe();Object.defineProperty(zs,\"Newline\",{enumerable:!0,get:function(){return vIt.default}});var DIt=mwe();Object.defineProperty(zs,\"Spacer\",{enumerable:!0,get:function(){return DIt.default}});var PIt=Ewe();Object.defineProperty(zs,\"useInput\",{enumerable:!0,get:function(){return PIt.default}});var SIt=Cwe();Object.defineProperty(zs,\"useApp\",{enumerable:!0,get:function(){return SIt.default}});var xIt=MQ();Object.defineProperty(zs,\"useStdin\",{enumerable:!0,get:function(){return xIt.default}});var bIt=Iwe();Object.defineProperty(zs,\"useStdout\",{enumerable:!0,get:function(){return bIt.default}});var kIt=wwe();Object.defineProperty(zs,\"useStderr\",{enumerable:!0,get:function(){return kIt.default}});var QIt=vwe();Object.defineProperty(zs,\"useFocus\",{enumerable:!0,get:function(){return QIt.default}});var FIt=Dwe();Object.defineProperty(zs,\"useFocusManager\",{enumerable:!0,get:function(){return FIt.default}});var RIt=Pwe();Object.defineProperty(zs,\"measureElement\",{enumerable:!0,get:function(){return RIt.default}})});var oj={};Kt(oj,{Gem:()=>sj});var Swe,ld,sj,UQ=It(()=>{Swe=et(ac()),ld=et(ln()),sj=(0,ld.memo)(({active:t})=>{let e=(0,ld.useMemo)(()=>t?\"\\u25C9\":\"\\u25EF\",[t]),r=(0,ld.useMemo)(()=>t?\"green\":\"yellow\",[t]);return ld.default.createElement(Swe.Text,{color:r},e)})});var bwe={};Kt(bwe,{useKeypress:()=>cd});function cd({active:t},e,r){let{stdin:o}=(0,xwe.useStdin)(),a=(0,_Q.useCallback)((n,u)=>e(n,u),r);(0,_Q.useEffect)(()=>{if(!(!t||!o))return o.on(\"keypress\",a),()=>{o.off(\"keypress\",a)}},[t,a,o])}var xwe,_Q,rv=It(()=>{xwe=et(ac()),_Q=et(ln())});var Qwe={};Kt(Qwe,{FocusRequest:()=>kwe,useFocusRequest:()=>aj});var kwe,aj,lj=It(()=>{rv();kwe=(r=>(r.BEFORE=\"before\",r.AFTER=\"after\",r))(kwe||{}),aj=function({active:t},e,r){cd({active:t},(o,a)=>{a.name===\"tab\"&&(a.shift?e(\"before\"):e(\"after\"))},r)}});var Fwe={};Kt(Fwe,{useListInput:()=>nv});var nv,HQ=It(()=>{rv();nv=function(t,e,{active:r,minus:o,plus:a,set:n,loop:u=!0}){cd({active:r},(A,p)=>{let h=e.indexOf(t);switch(p.name){case o:{let E=h-1;if(u){n(e[(e.length+E)%e.length]);return}if(E<0)return;n(e[E])}break;case a:{let E=h+1;if(u){n(e[E%e.length]);return}if(E>=e.length)return;n(e[E])}break}},[e,t,a,n,u])}});var qQ={};Kt(qQ,{ScrollableItems:()=>TIt});var Hh,Ua,TIt,jQ=It(()=>{Hh=et(ac()),Ua=et(ln());lj();HQ();TIt=({active:t=!0,children:e=[],radius:r=10,size:o=1,loop:a=!0,onFocusRequest:n,willReachEnd:u})=>{let A=N=>{if(N.key===null)throw new Error(\"Expected all children to have a key\");return N.key},p=Ua.default.Children.map(e,N=>A(N)),h=p[0],[E,w]=(0,Ua.useState)(h),D=p.indexOf(E);(0,Ua.useEffect)(()=>{p.includes(E)||w(h)},[e]),(0,Ua.useEffect)(()=>{u&&D>=p.length-2&&u()},[D]),aj({active:t&&!!n},N=>{n?.(N)},[n]),nv(E,p,{active:t,minus:\"up\",plus:\"down\",set:w,loop:a});let b=D-r,C=D+r;C>p.length&&(b-=C-p.length,C=p.length),b<0&&(C+=-b,b=0),C>=p.length&&(C=p.length-1);let T=[];for(let N=b;N<=C;++N){let U=p[N],z=t&&U===E;T.push(Ua.default.createElement(Hh.Box,{key:U,height:o},Ua.default.createElement(Hh.Box,{marginLeft:1,marginRight:1},Ua.default.createElement(Hh.Text,null,z?Ua.default.createElement(Hh.Text,{color:\"cyan\",bold:!0},\">\"):\" \")),Ua.default.createElement(Hh.Box,null,Ua.default.cloneElement(e[N],{active:z}))))}return Ua.default.createElement(Hh.Box,{flexDirection:\"column\",width:\"100%\"},T)}});var Rwe,Xf,Twe,cj,Lwe,uj=It(()=>{Rwe=et(ac()),Xf=et(ln()),Twe=ve(\"readline\"),cj=Xf.default.createContext(null),Lwe=({children:t})=>{let{stdin:e,setRawMode:r}=(0,Rwe.useStdin)();(0,Xf.useEffect)(()=>{r&&r(!0),e&&(0,Twe.emitKeypressEvents)(e)},[e,r]);let[o,a]=(0,Xf.useState)(new Map),n=(0,Xf.useMemo)(()=>({getAll:()=>o,get:u=>o.get(u),set:(u,A)=>a(new Map([...o,[u,A]]))}),[o,a]);return Xf.default.createElement(cj.Provider,{value:n,children:t})}});var Aj={};Kt(Aj,{useMinistore:()=>LIt});function LIt(t,e){let r=(0,GQ.useContext)(cj);if(r===null)throw new Error(\"Expected this hook to run with a ministore context attached\");if(typeof t>\"u\")return r.getAll();let o=(0,GQ.useCallback)(n=>{r.set(t,n)},[t,r.set]),a=r.get(t);return typeof a>\"u\"&&(a=e),[a,o]}var GQ,fj=It(()=>{GQ=et(ln());uj()});var YQ={};Kt(YQ,{renderForm:()=>NIt});async function NIt(t,e,{stdin:r,stdout:o,stderr:a}){let n,u=p=>{let{exit:h}=(0,WQ.useApp)();cd({active:!0},(E,w)=>{w.name===\"return\"&&(n=p,h())},[h,p])},{waitUntilExit:A}=(0,WQ.render)(pj.default.createElement(Lwe,null,pj.default.createElement(t,{...e,useSubmit:u})),{stdin:r,stdout:o,stderr:a});return await A(),n}var WQ,pj,KQ=It(()=>{WQ=et(ac()),pj=et(ln());uj();rv()});var Uwe=_(iv=>{\"use strict\";Object.defineProperty(iv,\"__esModule\",{value:!0});iv.UncontrolledTextInput=void 0;var Owe=ln(),hj=ln(),Nwe=ac(),ud=FQ(),Mwe=({value:t,placeholder:e=\"\",focus:r=!0,mask:o,highlightPastedText:a=!1,showCursor:n=!0,onChange:u,onSubmit:A})=>{let[{cursorOffset:p,cursorWidth:h},E]=hj.useState({cursorOffset:(t||\"\").length,cursorWidth:0});hj.useEffect(()=>{E(T=>{if(!r||!n)return T;let N=t||\"\";return T.cursorOffset>N.length-1?{cursorOffset:N.length,cursorWidth:0}:T})},[t,r,n]);let w=a?h:0,D=o?o.repeat(t.length):t,b=D,C=e?ud.grey(e):void 0;if(n&&r){C=e.length>0?ud.inverse(e[0])+ud.grey(e.slice(1)):ud.inverse(\" \"),b=D.length>0?\"\":ud.inverse(\" \");let T=0;for(let N of D)T>=p-w&&T<=p?b+=ud.inverse(N):b+=N,T++;D.length>0&&p===D.length&&(b+=ud.inverse(\" \"))}return Nwe.useInput((T,N)=>{if(N.upArrow||N.downArrow||N.ctrl&&T===\"c\"||N.tab||N.shift&&N.tab)return;if(N.return){A&&A(t);return}let U=p,z=t,te=0;N.leftArrow?n&&U--:N.rightArrow?n&&U++:N.backspace||N.delete?p>0&&(z=t.slice(0,p-1)+t.slice(p,t.length),U--):(z=t.slice(0,p)+T+t.slice(p,t.length),U+=T.length,T.length>1&&(te=T.length)),p<0&&(U=0),p>t.length&&(U=t.length),E({cursorOffset:U,cursorWidth:te}),z!==t&&u(z)},{isActive:r}),Owe.createElement(Nwe.Text,null,e?D.length>0?b:C:b)};iv.default=Mwe;iv.UncontrolledTextInput=({initialValue:t=\"\",...e})=>{let[r,o]=hj.useState(t);return Owe.createElement(Mwe,Object.assign({},e,{value:r,onChange:o}))}});var qwe={};Kt(qwe,{Pad:()=>gj});var _we,Hwe,gj,dj=It(()=>{_we=et(ac()),Hwe=et(ln()),gj=({length:t,active:e})=>{if(t===0)return null;let r=t>1?` ${\"-\".repeat(t-1)}`:\" \";return Hwe.default.createElement(_we.Text,{dimColor:!e},r)}});var jwe={};Kt(jwe,{ItemOptions:()=>OIt});var ov,qh,OIt,Gwe=It(()=>{ov=et(ac()),qh=et(ln());HQ();UQ();dj();OIt=function({active:t,skewer:e,options:r,value:o,onChange:a,sizes:n=[]}){let u=r.filter(({label:p})=>!!p).map(({value:p})=>p),A=r.findIndex(p=>p.value===o&&p.label!=\"\");return nv(o,u,{active:t,minus:\"left\",plus:\"right\",set:a}),qh.default.createElement(qh.default.Fragment,null,r.map(({label:p},h)=>{let E=h===A,w=n[h]-1||0,D=p.replace(/[\\u001b\\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,\"\"),b=Math.max(0,w-D.length-2);return p?qh.default.createElement(ov.Box,{key:p,width:w,marginLeft:1},qh.default.createElement(ov.Text,{wrap:\"truncate\"},qh.default.createElement(sj,{active:E}),\" \",p),e?qh.default.createElement(gj,{active:t,length:b}):null):qh.default.createElement(ov.Box,{key:`spacer-${h}`,width:w,marginLeft:1})}))}});var s1e=_((xzt,i1e)=>{var Dj;i1e.exports=()=>(typeof Dj>\"u\"&&(Dj=ve(\"zlib\").brotliDecompressSync(Buffer.from(\"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\",\"base64\")).toString()),Dj)});var P1e=_(($zt,D1e)=>{var Tj=Symbol(\"arg flag\"),lc=class t extends Error{constructor(e,r){super(e),this.name=\"ArgError\",this.code=r,Object.setPrototypeOf(this,t.prototype)}};function wv(t,{argv:e=process.argv.slice(2),permissive:r=!1,stopAtPositional:o=!1}={}){if(!t)throw new lc(\"argument specification object is required\",\"ARG_CONFIG_NO_SPEC\");let a={_:[]},n={},u={};for(let A of Object.keys(t)){if(!A)throw new lc(\"argument key cannot be an empty string\",\"ARG_CONFIG_EMPTY_KEY\");if(A[0]!==\"-\")throw new lc(`argument key must start with '-' but found: '${A}'`,\"ARG_CONFIG_NONOPT_KEY\");if(A.length===1)throw new lc(`argument key must have a name; singular '-' keys are not allowed: ${A}`,\"ARG_CONFIG_NONAME_KEY\");if(typeof t[A]==\"string\"){n[A]=t[A];continue}let p=t[A],h=!1;if(Array.isArray(p)&&p.length===1&&typeof p[0]==\"function\"){let[E]=p;p=(w,D,b=[])=>(b.push(E(w,D,b[b.length-1])),b),h=E===Boolean||E[Tj]===!0}else if(typeof p==\"function\")h=p===Boolean||p[Tj]===!0;else throw new lc(`type missing or not a function or valid array type: ${A}`,\"ARG_CONFIG_VAD_TYPE\");if(A[1]!==\"-\"&&A.length>2)throw new lc(`short argument keys (with a single hyphen) must have only one character: ${A}`,\"ARG_CONFIG_SHORTOPT_TOOLONG\");u[A]=[p,h]}for(let A=0,p=e.length;A<p;A++){let h=e[A];if(o&&a._.length>0){a._=a._.concat(e.slice(A));break}if(h===\"--\"){a._=a._.concat(e.slice(A+1));break}if(h.length>1&&h[0]===\"-\"){let E=h[1]===\"-\"||h.length===2?[h]:h.slice(1).split(\"\").map(w=>`-${w}`);for(let w=0;w<E.length;w++){let D=E[w],[b,C]=D[1]===\"-\"?D.split(/=(.*)/,2):[D,void 0],T=b;for(;T in n;)T=n[T];if(!(T in u))if(r){a._.push(D);continue}else throw new lc(`unknown or unexpected option: ${b}`,\"ARG_UNKNOWN_OPTION\");let[N,U]=u[T];if(!U&&w+1<E.length)throw new lc(`option requires argument (but was followed by another short argument): ${b}`,\"ARG_MISSING_REQUIRED_SHORTARG\");if(U)a[T]=N(!0,T,a[T]);else if(C===void 0){if(e.length<A+2||e[A+1].length>1&&e[A+1][0]===\"-\"&&!(e[A+1].match(/^-?\\d*(\\.(?=\\d))?\\d*$/)&&(N===Number||typeof BigInt<\"u\"&&N===BigInt))){let z=b===T?\"\":` (alias for ${T})`;throw new lc(`option requires argument: ${b}${z}`,\"ARG_MISSING_REQUIRED_LONGARG\")}a[T]=N(e[A+1],T,a[T]),++A}else a[T]=N(C,T,a[T])}}else a._.push(h)}return a}wv.flag=t=>(t[Tj]=!0,t);wv.COUNT=wv.flag((t,e,r)=>(r||0)+1);wv.ArgError=lc;D1e.exports=wv});var T1e=_((bJt,R1e)=>{var Mj;R1e.exports=()=>(typeof Mj>\"u\"&&(Mj=ve(\"zlib\").brotliDecompressSync(Buffer.from(\"W7YZIYrAeaAIofn/qpGBmjpZVwDLAvMwf4yXtBPC2k244urd2MomTN2aMogfZ4A7OVKdZytVrWdTrWmYxircma0wGjinrwi97kOIB/rfPvf++/N1nmkwua4pdU0vplRnJ8uTq4/IAsPFlgkUtfMXWn1Nm4s4/1OdO8sUK02YQ8V0UUTasGUTR54r1eZDT0Tg+dfNn2bSIN6Zw+V9selvZoGapDZBTNJtWlu8YiP8VAl4vuaHrmqbStPqWMGWi1ET+Wl8hECbrj9M79f7pp+KJEBcE6TKVEriNY6xXKgoIrpP3yOOwfyPgdESROE7cD251tzuvu9hZjDLwpDcErDkGhpVUc7ZLP5BvGEEUjaLZdHaf3p1wpI/ZW6ndipAYFTca6o+3B9iFWHICDGbsHGBmmPDDNvKKnyOtjGr2X7Xv2gIEIo0IUR9fyzr0RFHe+BekvwQ8A7azu4PX6uXTmr3kyZ3UxuE0AeEwE7s3f0LdIJcvAtlstfAn45Em6li+lMmn6NJtkeT0hrM6hZvhjO5NFsx6OvLtoz8vjLzBCE2tq38M2NRMff1r/HFdUdxSA4v2T8UzNbJfx16WEjKmYryX6bLx1Qi4KkviXx2b7rrUxmOfmjBZgdsdLqS9lR7LqgGoSoMNiKLAWDBhm2OenIXqbIOID+RvwRtjzFzXwcoDeaECP86wI+AHGNpQW3WAPb/lwReQ94/ItDUi2V7l5TD4XFWZ8iKTQ12efZjmhTFHWDF9Oc3y70FuMb4wQ/I8qsKeqfE1WVz8edT8MeF67oUi2PlFO03r1CeI4weV1yCaDPmoUYdmMNiRTHsQSNECB+KvgK4BSAsq0qMdK2hYiFg2XXS+o6wEpuP+WXFzRWVisb+bZhUMBx1Uk4qPk7VZ8D1ygB1KwB3KxGYr3qT58d9K84LMe4xPUVz65JDAAYiPHjF/WO1WnW5lxKhpqd4E8oB11Yhn2lsJJ6wgA1OHsJVhMgWr0L6mnDSCoEJ/1xNAVWu0xJ5jcBdoOkC7MBWt4wKYC6pZnU0L0/ZEun63aneuabhhBNM/ElZOVSwFTXhz7urfvcEdzPZNQ/Af/UI5+TJfwTyaXTx5P/jSTu0EjKokid64RDKPrpo0TiT4Dxz/C4cdmdvrVq1qtz/FZbanctieS8eT23qQvPgR6DcPtLjac8FFkDnsbtRv3C+pjh/rES8pqV/UqOax7pPArrJiAxDeArF7/TOfkGNdm1eRHltB0cWa/gCLLQmvzYGAzaC3oiqmm+BmRNUVYDye1Wrf7CoviG9h2bqkfb3co4TkHVQLpWB3sEWM6KCqxl98ZURki9KaP51AxocQP1YrTb71POvLimJLx1O3wgr+jrKYpnOaVh+kQMsaiNKd6vfUs58mCo8VZtF7aA3vcH2sfIfFG3JJY5egsfZCxbWam6tBq2rYQHOzGsbWIRyw4/RMQqrWdK0s9ucgjMyuOQBxG3s3UxOyQlvchbAK4PqV5NA7+s8i/LQewHL9ps1/11SMtq2rzO/k47/CvLVxu/VF14vKnSYvKDIgBp8YQYOrFJnbSfaKiCf2FTBdai76QQTPskJiOSQEKAGct1m9u99O1y37v5Ryvu1HnEnH4Pyn6/CGWd02gi3lBebEnDS0rjEcssB4poRl5wQ9ZteiikUd3kk9ogUkO3Tho11OUVtIukGJ9kbf5PU/PB8gGMrXP7OdPhPUuXg1usheUW1WSLUHYhseGbnUhLmToxyTdiii6DrmbM7eNWtN+y5AIGRHscz2OE8fUQNxSIQZ6hZlRsj1Hsb4x/m4jOawSTFI9FWpjZH8KZ1VTHRlu6U6l+DXBQ7EpQifgHFdiB5VffK4B1wq+IeaBjTsCQEBJBGq3xSny6qetT4lGrbfAOyCI74QeRBimUsmfY65mHj5ICnp/VFsAnaIZuAeBoI+vCFT6JvJoYsyrhaowcOo2Fj8z6AwYvLzPIj2f5esqLhnzs37MN5yy0LWnrJ0EadFAE9448ipZMWaTuelOG+8tWTQ3mIJ29XtpRgS0H42ei8U0KKuc5VWrPWLE1VGrFv2WZu+lBgfNBbBvu9yXrZH023WvtV9bhXBHIyy3a+EVXAI4JMH4ruzTys/jUtXVFd88jvMX7XmIjMgmHwEML9EdRUI18RZdXYPJUtEveG0iLRQEVPTHGBOa3STqzkApApn4QAndZyYwVctL7PXL24PCvPb3kKHTM3qbZlCZZUQ67o30+MCLu1idSB7Ko1KBlCBuX7kPCxvukHi1g7E0IUnq1iFOilXH+T92MGHQJfO5QsUgulZFfd0vWflcxXZD1lPZzB2XvF5BBbTLmzzHuhnTS4KnEPBGqXf+SofcIfJzD3CpiduYhveczjMRb1sXs46drNeQYTdLHw0oVyb3h0AB+z14AseDdgwCyU4d+RWq5Nk2qyWK9SYulIfQCzl/1IxYA0Zc1tsFTi7hVi4YJ9avMITOFjbT7JvuUggreBddtHy42woEaBtrl3C76tSSb1Jp7dwOMEratJVKxjLFKSOKc883wNPZuelXgSBmyCeRLmvoXVuwk90HGS/5yjGOiiLZDC5owKIhOnKT8u0FziBoIfb0VDK3P/uzPGyLNQ3q8Q88g1jxBae7ZindZet2uyHQxNxWbDk4cm+qnw48xcXQWId5pIu+SfEW1FY8nW5rU6w+smRmIG7Zt+CgiO9WZdMH5f8vmUZyWxck6ptvvszFtk6Zgfq10sHR0nTcxZuli/wscpETEZ2OfhVpXMFE+qsLO165Z7TZA1d1Bqmr2mZ9Hahd9lg7E8mT7YYUz9A1+3YRZ9K32VcOjPJW0L0WaPEFNbMFp8C74yc+9qBPFrVE5wPUCiQUF7VLXdWt+k+DK6uoZck62z4kEpLYA9tvMewEDrnuj6qY3lHSggl2aBf4QLEZf5GTaaaBklz+BsSey9F/Gll7EqpzrlJqi4ohTF1F5wpX0AnsfJVSAxz75XiSfSWwnKPzS9wprGuvH6wzu3HS/Y3D7Hcz4zt94iktY3VoDMBXIVU3ZhurAHW0oIkm+v8uQDLPzAmNcXoq1pGUMzuES7qoV9MvYcM/zWfYGdpY3mnjrlGUvd742zezvatOApsxYwL8mkF56vhqawtH8p17pATe1qqlQZ+5fbn6ir4u9mRFTuGNdjU9Kr4Dhb3NGiE7PFRxRGkDLHna3uExLPv9heaZ4l/IbwwjK5uX0Sz5fHSRBX2lntiN51G2bilyt53ibizDkv5bIKqCsVvYi5gM6npb/DHOxdOYFE7iXKH6x4/AIgZUk12lnNak5nTvZNqEwsJDP5qC3DSDSQdP/yQDL7Mr7VWIfD4/nglnn+Ol3aa5pjLQy7F4R1EP/w8oDypvHrmRGEdr/2ZeD9jc9qczNGvWVs1TOpaG1OWPaZ/FeGyqdqOxLql5sbNtLSLj+RigrA8Zd5Skqj5g9HG0R8woPZ8Isv2DI5UcFB74cxq5VF7XR8O+8rIDoIA0r8ZckbDl+z2XGW8kkGlTnl4bYsVvo2XOPalZQC+nHLDeDUjjrq45/Bu66uR6VaZM7XLQChJ6aOJb1zjVoJjGxl/RvOgbbEsUcg9jN6wHQVxz+YK1o4mIkTd9lr73hDhiGJmnrk09khgnZX1jZgXMvlXZfvu/4UzJMeGKZ8+tUdHXsL27CkrKTeN7GAv03B++NvNl3ScoeZpb00tw8A7uI70mwNEMLH3b4q+AS5/v1K0HXvITE/0J1tw8aOX/dv4NwY7+PyWxCzYkFIV9+BpMl+mrOMqJ+oTDH0P+y5oD0Wls9sLKBWmrBPVIBEusrH9cISnk8TJVBCZ+WuYp4oVjgVYQ74StFhLJkeVX+vnH2MZYLE4hGw/zLr1ixF4S0fuq5t1wlGdZcN3Ryiei/RvIQEttuAPEZ56X9DN3RdN1i7WZrDZ9bA2Y6QFCJL8I4FQNd0LAd8e28SZ97m49v3sySuqZT4X7yiKaymNsJy0h+JmUQ53oKpS7dI2CHicwn4nmdRaVSG8PMxr30O/p0loXp2VDeedkJ9n983Z06Xp9nOmvn+ssww+cEbjRzPuX7J+2BQZM01++bXQh6G+eFM+s+c704+9OtsQZ1bwnCZ08K5ZGvMyav8qbdAspe9+ft/QgINsPYAAJlYbcNG5yK6QACe4MsxLLW1T+2s9RJwn7N3Tlm3rL9ZJqtIYwQhWftRqFrqSbokt46nCJqXwRg36i/q7RjTmNCIrZuJc8Sw7ofcAIbN2ZDTkn/ySLoemB33MehW/gegbYAjaNvCCUK4bJs78glrWaysX9ai9TNgcwvRK4+FvwzKg9P21PWN4KwUt8/awmrBhg4sDYMNFJXeBvQ26BLMj6Rg/N6LrXanZNnMsidv4lcT58XgxA1IXpI0MIdVsux5r5bQtNBw0WVK1kTGNQSUIJuIi6AxVF0l+7Lx1z1dieSEoZA+mkP5Ylq4a4MKkLN8745tnSpG3PmlGA7XNgTGeyhijUEgFAHib//r5F5pPqL9J+peKzxJ0PvdaU8A7PiVnOqt8Pu6x7hdfJVmvd60uU7lShz7MZ+W0V3ifWezK/HicLkkP3nx3fLmVafZkIw19egheY8kUHPI8uHQcuhEaOy4pYcmpxzonwxtTiuhiUZ31qv35CM4SgUk4csI78TrbHYCCkvr9MLRSuVuz4VAfGmKhj+5+RoDKwhxJoV1SdcxbwWZ9nFu5I1jiu+ujtpSJ8igdxbOxoVTQwUXDjVFsEbDPKZ33uPtCS3Gib8Jnl06fKT39gz7DSiesYxjt1f+qlrYdKFPXG/uHojPmMAHfu6cIv1ufCH/3W0Ns9ups/HJL6qfjJsfW1cPRnlj122sQXqMt2P/4lF/vp6Lua1x9e48pQ+bsOaJUoH+HhZJhZfmsdx28stYxUj2zwB0mAiiNCXlG5RdoMnIR50mn9OuiGDweOpOKLuzCXy1d1HK9cvgsWsMRO7sA1xUaW3/Tn0Z/EpnMWIoaOG6Pt1A95uzncpFO7Enftf/+x94/6T13Uj4kwKj2u8jwa+yurOoF2+fO3laYMZon4KElVG18Pp8ThJqb5pfWXmWgMqIOMWeGRPByVkE5rAkv9DainSO805Arfc08Yuqnl7MkN5F1sq8Hm5XxpyQ7TpI8/j4dDEn0fNfBXMuuOhdCkbXBaE7ULhJTnFOAEdOX5hJhi2J2rvT+aE6ovLq0vJNnFfjnDyQUoJXnJ3brh3X+H/ab+10cRRhjOO+582DlAqxvXm8mYdkuEG4ZY97+Cy7fPONOY0jMNgUw8W6VqUAONWnGGV/ugM603iYSnR917qLJjSN5VhxfnuIe+Wu3pnZh4e7L49970k2Uhjfj7fOzjbG+1kWydmutpbBTL+75BFfLbNT0Br502jm6laNDgAoRYm7bBFpnX0GOUtU0n50Si/45IPV/QiRlZXdpDHFrHnUACn0a0rw59DTqVe3G9phSBlM9k3TFNcu3XCemc3uvTQbs9feSU/+HqHeJgTbXexE5ph7KqlM7jtT/Lx5p0+GexQuFZy0MmE7acbsX3twNvmnRztnoJ2CaML1NzRGidjukIutSTdkQ1htxO4xb7rVUTlFkeB7Ek0j7ykrp6ktH2nhoncdd9GzmMW60Fr4hoXPnUmPhe2xaZHTBiTVcytnYLvUWdBY2yX31XT8OeAuQDtVlu8xt5k/5kxrqeze3Up79nMDTqmI+u8BzVVs7J/sqH2w3lpaY4b/ZIGiSpQcMtelbSWb2kgvgITu8BaJvE+PTW/xEW0Q92LdM2O0d1RBY3fqStUpXT9W01PUug9KYgTsV5bzTndaIlS7sUc4DEnhHna/y6aDBELFrV9uSsHb7LFjYnLskmjMK6iW3/PxHXn+jjtnPk9Irst9XEfIykDfZQ9rNloWu1V2g2f9T8ms7ocYu7ckXI6/fj1zLs+D/bh654KaV+DsSbZ2EMB28fcVsnx/WD5P32wZWgLT2qklWDronQiwn9ZlvwLQ8W8j3D6vfGW8XXmj5Wb5PvocCsH4fkKAKXKo1dhiJDJo4EcC65eDgaZPec/bkWU30KVlJxt1+93tJq9eVfbXSJrME1VDqKc0xzxLWuTxB8eWmYLJXubjl7xyoailC9soRMWC+bbTKNSIMgJGpSDjFJ9rg0n7M4gvm1OMC22JOP0aW2U1IgKklcH2dT95bzdPG0293mh2QENp2u7CVj04wlDsec2IiKIMU2JfQKDqHHyanNmf7dTyUOVEzuWDm9iZMDy8Z5QJAcay5RE5QT2M4FJbjqqdWxbBBwe9MkADroHwk8lOsafoJ5iMzyozT0XuCRdoQ8qUMm2KR1LKIVsShLwekNZwxCqxyx2QYWaJ5T+37rKqq6DbHbVqjnVd4JurTVDkmoqwQhNUmv6YkTzZKATehk+2qHmxWZjGOAhCFj4t4jDw/PcvGfteQzOzAsvLJ7s4S9WnC2YHb8Pg6wGPt0sh9KTTPzjvecLHS5z1VhZRUTBs4geXXkTEbFa3rDXUIYpNGQ6KZ5/kbWMHD94uTT7yLBk1G3CZC/CrLVBJEL3iZSmIeK+DkEYxmO2cYoElRYjhlUxuYghY55e5Vu5PYOa/WGF9TEO+z64kKLMjgR8O9Oo8zPujvD/U+2ndy8ftlkY2GSI+aFwhYmgpPBlt82jUsIl166FQAAlzfqUD3S1xH37rs7Nk4ZaDSUIiIBq1VmccU3ky2+bRqWET6ztCozAykITec2lxjil+uPN2vnX7sPMbyOIHuNwZvDGDK9EvjtyJQEGjDdaaNDhjwVNzK62n59toPxVQsrh8DDTZRjINmKe1t5ad3GfXJBKYdAboyfw0KdPWW1mJAgYjxjdX8r4oWpaUgQyQIDk0qOvB3+rqSDbp1Xc49R2h5+5VjcuCIXZxLRHPmuM9dlZOd6+uPWlyGsbS+oPDi7hmn6sQDoT1wPRdycZfgffHe3+896yJJ1q3I0nZjafC4S5yX95xkP165eE65eG65kHWiTpNp+rMPGVedLK4BpCcE5FRbT2Asx8dNMj0gen2zqKCj1r4IpFNt3PM6YntBu1lOx/I3FZPdWsq8Mp2k//n1NxJRYFijdJwfZdlF/P+qZmoT35tfJHjyhS5+rQ0mI/AHBC36sX8Af3HUYizJ+mzNSUB0FWNGbE8PTHfTR2Bs2c3pPnjG6CuesDEHZl/zIviFg4Q1NaTyYs3Y52hAwOZKqgWhHiqXiCRvHCXvWYdnr7dumBTd4iud6Cuu587521YmlLWPveWj0G5RD4KmEykSYK0lAFIkQ/cuTPJzFAAyt24Y8eIomJKGhvE9DrJYv0njUniEddmu8nNRtrVkcvnxhxObJls7KaJNjz9cyCDhNeucjD+RZNldRu+l06d+4rFUPrC2c96sqN1I3ugDleefgtL2wNwIXr5MmMWeq0IeiOUr/F/Ku3rZS4PYzt6+KzZAXSCtZYYI3QBFBxg1JZ8XMwTXZxxVjFzp74LuExmVj7nnqO17MmMfsb9oabFL86NhzE/A1CI6c9s3fSIESs+J1Rzk8LDWTh3tfdwqZcp1scWKFHH6z5nihgdViBZ296XyYdXpLm6p4ztIEgkrsDp2nRwW+CVDb8rQx9qlk65hQmlgstLprc00evMTsmDoW/qxsieeiFOdhgsRarlPKIFVAi35+Z2vC+2wEzF2Crs20DX4z06bhphnjLZ7CY1UNb8z3lz6d4gMPTH+1nSxk/o8l1E/2o/p/1mJVxeco7HjsaLcTMN7lnxXGw86yZCTPD3BUrDZ8LmSalAA+xgQ45ElnJD38Zt3MYt22QrM5HaKgmmcQn+Pt+xxf8EzX6OuBmlbtjyNBl+m7MwkjFnHNHpYCAEhvw5TrjcIIgh8cr51VcLL2rjfE6fiSqTqDiteEVBP2fWg/ka0c+p/0vJqgxp63RgtKxrmyEMruMhXveJTdQIoHec229Y9rm8NQzLLCtgIIYhUr+POyGqlmzrC0hg+5AbvLUViMk+vTD/snwtLly52nDaBwSON6lAMJnULe9iVm7qyCGfwqolXl3hOUWDafo5uVANKrM7QFmXgROb3/WXM0CU5JLdyiaOfiZUtFM0F2xepBtOrqY2TU+yXWVDf8ibQ4ZKiHOLDCrasIvhRqaTXdrycvlCMGCJ15/dlndbxlrbUfXLsBBmoiWPs+u/tZlc/0Pe/1u9vzrv/13eH+993ra3fzkGDDLXL7Dq9sJAbXT9qUaTy4kmXdRtka0k+TKht0nu1xJwLIBMJ2o7Z6D3u34toEnmjl43WhtqK1GlvOhtqftfQMmIN62hMzGGNHI91u216azTS9ttv92v8AmbekGM7GBtrWXa77YRRzqsa06L3ma8LVN40aSn5OMo7ntQeOjY7I2r7kypr5xdpOoeBc2Uda2d6TG7HnXD+sU07bdxS8Hir2i1r4ffw+kTyfxhKLtI1Pp3Qq54J/+z322a++9gJ77HdTf6l3Zg3r+FeEytF2Lxs8soef2Qfs0AKusstlJP9bonsVBZdXVXPunX3r/d+wO9P977es2WfrWN1yq7hA6stWaMJFk91WvPrL8LbaCewyGs6OrVgyhLSyadqTtNt2an6QqdvjJU/5wlvWgn8Cq7DfQVrjDQ9cmsr4DVr25g5QZgmzcA+Po0qP+cxiS9RFpQbS7UqyLFg6FcKzX6OjTn3wLzbR6ibXaKL8+yfBWfxVIV578RI5O8KA9XX/jz3+9qLtP6A4MObx3U57FxxbpZc3zWHhMvzOaOlYyn+TtoHSnbU7v/O65N7FZG+FTNomGWfGcUNDSPyQkbmGt2C12fiOJLugvh+1cXgFA6DtpZouttdgKXrD7GJTVtlNuPGhe7fFb346cuy9XIP96Hs6le8QX26dcpTfAgW4sDh6wT1pjs1/d0STdAZUoX1sb0pcnqSF4rs19TE4Xs5Tqp1/Tkq9WRk3UJ3S5d45Py0HXJ1F/zE866nDi2Bmg+1y2Yeq0Zsk3WRaI1Qx3Pu6sxwjZuo7WbcEWiexiSzKfixKdwfPL+EoM613WZqV478zAc2F8bZxrtYpjralqUkywclVACr+QH/9frtyv9vWQENkrK4xPnzEM8ea3PiKv1bY3bzPAvSrieoSFU+swTSKMZjxihqvk+b0RgAO456joWF0phb16hBbjLVvcyheqcAjQh6detnGLiBvtpCqDU+quKkd75q7b8PRnHuBzuMU39mosB5/pTMfQUM54LbRK8osVZC4X5dHvtKWPRiWFo6LHukj4i3u3WjEW81a/K8fNTTcCCD4YbeeUxA0aMxxqFYdmjBRadsS7TUOns1BeWoXcAKmMqoPD+i5fyXF648uATa+5YgzPqvaD7GS7gRl2ac0+Ei0H5t6dL2kAYvmXyxVTEZJwGqMJ5rejs1ntfVciA3kJiL4ZxS4EKDFN7Tf2ucx49P+idEf7Lbzj2yaItS8JB8HbeC9DXh4r/XVu0ioL4vm+n9O7qucPTpaF8TXuNgL7+Xdj+BMpg5K2fIWwHEHuBN/eCx2mkSloNTX8E5tU9HsJJTC7886uP2ZZ2MOro+p4XhUupEExteB4Ch2Q0tdB2NHqVUoZF/TcJP5N/fof3akRsDd3Yd353pcdXyYe+YBKGyvGfoke1fcyF6p7yqUEQ4n1aOv11tvcgRyeruur3J4YfC+jKOuMzvK0SQ9ArhHDzLGmq2O2pn2S1/sDbaFfUYWUiGuRmm48txX3NJuU+q8A2Rz3026gEMQMY2Hn5LIfKfHQS3/HE420sGvttnL/FBA837M7UM6STsh4bmopEZ2dBWW8YQWJV2elnRF3KjorwRI5CtHzYkT/OfjWhecIanzRCBBIe/LepmuGvzv5yQ94U6IdfUxtXmRA9MMa0uA5B6c2Q7xCviXbOWBiLbxENZtdahRE+gEDExzi7QAYQYfgQ0hR/NVNggA+ioZNcWHKNem0FnbkE4kdL9K5zV3c9v/jpcYaz3zY4q0OGkKr5FfEgl+kPkAhxeHnwGl39qUERhfkIJ5jIDIRIjrsZd649qB0vy8I6oqKjjgMIatxre0o/Pd9oIYwJuEIPV70ysVR43mNo+AtjLF84mWxKzLw4ErqaOzLyfIfCianI+ZNCWbNr4za2EWc9L+wQ7wwgnSrysRJhrmPZCp5s6h8iuA6D6ndHf6Zw8CTSk+yxsTcgmUvJHCSsdDlECty1KVRduLsLF30yYE0xLfYJrcC4OERfMql1EWJJzkc0PalxuJSFutw7jNW8H8I3MZ/Rf7bqgserOSCQmLLcT/WcJIDfUbLgu4smr73pGIILiloo4uBAhAPaKOQP7eicj59VTs/35ZDLX2MPeGcmR56x0hJK/YCH+RCG7Wz74Bla1Y9nWKJyZwGdYauIiv26lMxZRMO3pmY9rDNrIz/DO555odBpXZj7AohGefjE5fn3kSqc/4zVy+pFs1HihJCQLoeqXpR81nR6yAjJfWOpF4I61rc3Tv/xK/2X8q/0i1A1+g/JM304oZr3nGISGxvp7PvoamR4pGUCDKvjfn6cYnrOOWiosAzHrGfsarfaTjXFJ2htEXISk+qqXAmfjKEes1mD6N0TlqnPjYLiQXOyuJWCXcT+CJb27i6ZgDHf2NAt8C5aFERT4R550wtsL4C7H4Ta4oVyc/VOkpNq1PRnbKKx5/tjm72k7UwUc1er6KF30dhQssGugiiBqksUK0s3HwptUik8wGOl/XEsdeig/STdBU0J3W5eJoLDgWoIvzMI8cBQbQcA3L+xgAV3dS0ECxcBd0kKBfWspg8OAGY1yV/yIB58OQ95MM25AEFqWK148NHDV5pqPsZZyLI9tDI0PFTaLTut7dShnIydDmCKbDEGyjRbrQ+WacqVbHnKs1Xn4t3dtqa9ThNWFJ0FfUidGz1WwXm+EQiIuKgCYvGpXVxQPG6qv5BlikjUfwCp6fdL+nvVnmg/FMBpdEDQzWfW2epHp5L7Dw6UN2135woZZ2fO7jUOuybrNE1Jg9cdUUwcEYcHypoOiOQ5fRGHzatGpqS3gEnWdKlNolnb8sV55S3jgxK54t8DLdVPfDgDbypfMBwfoxq41dc0bnOKZwTOdmc7GLv6+sMoEY6oBWlvnOpmc6Ibxu07sPx83StVyUbamL9Ar1PrMXnMsM+32TrDCZ059PS1/HMbLNpu3MMyfJowhmfecitAP4wzP9F53ae95PJxH+46zT/O+eaENUCAgZOCPvvKCPTnATye/qUbpqJhSClEoPkzRSJ20PpVdIJ4ar6HB3+T+GEp/QZofbnKk3j53fINLnJsvtJFiy1hi140f4wWyko7xmEne1Go1beiG1yisoPlLkWjHyklG7yziH0XoAN+05c5w8Nrf9rdJJfLuZjX301GXfKr0+NAh59uXL1Mx5VcfpQv3j1/LPHuydnuKDSgmqQuHzUrfm8SEJlIAwdNPZ4GuWpXFKQdhmHTKgcdTkR7YUPx2+lrupnD+BGtUZ1cKpEJp5eg8uWThRBxXguGqp7Fa0XIgAu8sjGVf/p1k8BiOHXX5T9R4bqouH9d2VyKZKtsp3ZN2Tofscxx/tYvhi4/hRrQK9QJOU2UPBoOMikMwcYAGfhwoh3j/yxNSYwQg6RauGDDPmUl2MUiXoYrXuPfhyB5ZovnATBfS2TAR7lpOMPiTNvSbr5hpdWg2oPprMnIc2kiZsR15TgdbF5Adv+ahIftgVKCNSvDl4mXEVxNgE47YCubEWx69p5g22SbsDM0G9f2k/+OqpVAmNSuIEQ/Vqaj4xy4af7KFcmXZjbhFW5u+EhqLZ9eyeshsR6WU8FXSwy91mzgbdh8K2/lvrhglwWAq+v3lwsiI9annoPIVhQHGz62AqgT6EgKzyiLjHtBceZ2YyXEcZl6IDTcmD5ZY+bY1aOHP8AynIQh1p/uRqkR1nvzPnzAbnB6CvgoGae031B5Jx+pQrbKGJfkttvVTgtBCu2Hotrs/UD92L4ZxQChCyoCqByv/3+hfcPHuk0NBJ+uQQfnxM7bC4rswuiTm6TGqCEjjbzVtEB5uZ00auG3aSMfe/KwaMlqdW5GIRWLKuF74Fi6z9Bw76c2A/jvKLaAnGC6Xt8WKQEIdTpmUu6kAYrsPlazkFPM/MJR06ieGmoV7sxi1QXm9sS9M/REh3V+XV2kJh37/7oknUkB1VQYaNsU7ojX14OgRYPeTJbzqp6cxlYv4mwqmRywPiwi4XoE7vAiOJX5ouDCtCXfo0DpVGKEPW9Z9HoRI0g/nsQIcSeAS5BACRjfPGWQ18NrBNU3Uw8H2rClTwhdKHYMFWWFHMUpS6J8SSoovMCfNGByryoXK57C4KtuWOVel05M1DfKIspR1A3u1xdqrnqWjjnRueFWnlKwY42urV0xdNS3Fkml2HUU3lRFRWB9odyUaOBnYEpDwxeKeIdDxcdd9ezlrKBgd3nf7Ck9JC4OiW/YFO7xcMZlSk2WfZODOx5DMrYOxvjK74K1XAT3U+MR0HluiwR8DaDJHyTNavychuXTpg2xSE701CiGq6raiJ3deCFeWRe+zCFeapDzFazSDnecmnmLj5WNdyV3esGfpgti4VzIq23FFcVFRGBwo5rG4S1XfF7TiROfMgDiQnQnlF6JA6lyRByN1LefSa/pFPbsub4YhOLolrSAjjX+VvH3oO/y3NiW9svMeHCMIoXK2x/9Uly5CAUlIg3S0RFHQrCqHmxx3SxU8M4JNjQgQJJ1pH/hvUvXEj6u3QAjKlWCLPBO+toyX2pHNNev2oIPsLGe+D7ykCyn/Ty9vTHyNhH0CY6IWUa77154g3fMSdSnwCYOk+KMVULGjru3XLRk2muhfyZNxR1P/uRP8eRPeY03KCqVn++oYdHYeftDLKe7y3d8kIRm4AIr54oDxuGDblRgU8G6U9BxrpKzRLKgSFnt/UHdANqO0RVtitGXkcTb6vj3OHvlyP1dRjleE6OExnBSFB/O1AA8R0C7fzzK2oY0iBv2RrY+fiNbH1fn4+HetQsv2iwkfLsbBzdDDDdkA7+LFUH2HqkIRbWn2CQtrZnZnaasgb2/g1YEXRzx0RYwxokcDOV1Lq0w9Tr3XWQ4FvG7tf4SiuZOH9z6lVDPAKSNCynTCztsCwCwwbaP0H6O/yAg47yWUosy8pnct3Trv7+Ua6z858b+v2Vbx91Yf9fe9Wzd1mw9X/c1X/u56sB6uf4s9URbO6+Pdb+6zazf8zewq0dovb/aWUf0btZAfedWsKNfZR6+rUz0TYuxVI1e2MDw8kHiYlBzQyG1SWk5QawOcLUSRwMI009FcBzErsRxwcLp9loOXXG2y7bjs1FNgGYvt2Jmd/XprbFituCngBOjd4chj14i1OnZYeMMZWQyKsKGF3tX1ASAqr50xs9eWR0fc3UIkEaqcAiaPHwy4cK65aXTcE7JIJmDF7HHTU12YFbuIl0evi48j0HUuX+h5IItl6yPFQVUVj6ghEl7v8jaYVTKVIXtRcI9HHtfG48NcLJ4MOq4iKZhbMhZ4OaymQC6qprDwff9/N/SlPJF0SU2NUErqCw7E4KU/5TmuCYF4WDIeM1p6YQtebofS1pN0QDRV252IdEeJd7QW0IPjoXa9aXvJKiOUgkz5Jw6cXoWsAITWEk2pgMH+CHFrXql63b4YcO9q42VsVJaq2PdtBqTNF44Ph3LCpBp08HtlkUz9aEIzTk+eR26UBE+rk0tkHGsv2o0t+i8K4bZaa3fNagzlWIragJE0zXMHy7IBEMhK1jEDDljUW5uuI4VUr6S9YaAZpUe4Gxc6bhurYumNk/QCwKkPQBMIvzhjFAicIQxC9gdgOSMyDipd3nNHAS7ByAzjJGTGJ81SlwT8q2RdyGnUm55jrnllSDyO3sJiM5o8Hz4GYB89gSV1SD/JVlbACLd+jomF9Zhf24q6XkmJL0JHnx3GCp4rRmmYDbDpxT7R3hUihF04i/XeD1w8ykEj7rGiFZSOY+pxcgS+AEFjJ9zBmpvHXPtM+a4YmDs/ro1evIq5lo1c6mXnqch1U7ZRTmRqkduCUsT5PakS38gCBeMSrpSXLQctv3pe9VvaXcYEw9gGXDP+CYAuMmOTBflgpR7ceLPheKvaxnjtb+T3ucv3h3AQg2lalIH8+2Tmu3mZWr0ok2QcyZ3p4QurELcg7d8/A+LjXvhMRHZNvNgZePFhpGOUxUbwnU75Ta0cd998js1wu84PAbJf3lp9iSI//lKRqG+fgoNa/3JZSTvlLynRHlIjCYNUNqjC/OQ7/TkzY95TXOUvKX4ZqkWOsjFfk1xq0KWSP6tfM+N5aKIk51sTPuv723k++E0k87aDXvATsHZv+zGmLJREdbYqlT4G+h5bbWZ/Vb+jU6X2Am9gDmfqQbsZK1GHfLwAfvxHIsqjuBL3ZKu2zvSyra+lZYOxnzkR+GtBxN0ckVJh1s8RNHZo+N2B1B3SAcxbF3Vc4WFTL7ruJsSDYMA6GVLR38Xhl9KLmbFZUgNFve5buXKWC0RkOZain1e5YKe7OOpn/IjY8irpa47hlzzN9GylEMPfwCmxHqrYvDTl7FohLTvXu2hbjaR62nuXLFs/KL6cWT2b0OvgBVv2Fg2AUYuB01ORGCwqgTfWR2VIp1nT0+g1JNyBgksohrL57UqflkDKFHrUbHtRWyEjOppYipQbDCEDjttkHvj1hZkDWK4jIRUmYfIwj+UBqHUNpGMUVM+8tPjk4Rw9FyUk8jWRfEipixfj70DTGOuUs0opiRLLMaAnvRfPnacnaHZzIGWEFzlS828mMwfeau9+Orp1f3lXSffHTFvD8BwkzUF0OYEyin463HBzkN6nByQs8JMswriP5g5WehS4SYyjwVIZcEi3l9JM3Axzbb5RtFvfAD/RIgUCqlbAP0BlJ7pFLq0ozlZ3yrOjtJl9Lu4ZzfELvBRw6zoqgZSu/kJ4pWcf/eN2zV0+ijHSfXTNke72O0pcpj/8+Pcn55EEdYuHneXInCso8+8Zv0M8ZVjA027vuDuiC2fUd8aVNLU50X07PZkTtBf8+nc0Tea+C5MfBSugYnKLWJR3kncEuUwXFiP1JSAr5veUI8qa7ioTShCby0+caFw1LZk3uOyR3m1HgqiROtc6zxCB6ZiaeoinIozcYWqTO6x+jPhnH1bPZHtWirPIOnjNXKCVnhAbFqflyZ1VLSD3dmH40WD4FZJF+UjSwmXiojv4HXCWGbvfG+KFmds9BvAQa6Ix1/crd0/RNGI5KUot4kEm++Nxv32ozG7PiqwXx9Qv+Ssawfn28MAv9qU4DCrd8LH1Gqkorw0BXM9Q4AcXNTWT8Rx238Wz7zTCN8Wb6+H4V0WWkUQcAP/xnqRaBYDnAKKJY3liMiVp7SHln0n7gRrNCqKxE+xQG1ALpnKO5VIYR82U3YFAkBKlAnnV601gO+4fRtw8pKHauhynFFrTQxK8G+4zOiUBClxWWeJ1QaxBArEDJBrq2EOJ/GdoQ8KNe70RUbYpLkY3bfD2HRVxtxg4Rd0F7lACUIDXIe7uGVbE0CNm6VHX+O3IEPya45tNW2AeLXqzpeFzkqWMEruOL9Y35cV1UZZZvshxrALnUaW3PGTupSoZvP+CRVEzUlDVC8yQclUhy0PidnqJ6G2aavL5a57czkWiKPNMZ1YyefiDZlMNJmZtKUc3E+EGYrq4PBm9HC9P2y7ztKdEkhug65bVfGAA6SaPrHHKmCaFwYpKRS0aZtYPWaDjKDDPkVi4DSdVeIe0B+XeEsPW8r3XLj7y6VtWQ43kZ8D4/wW3nG4rtFxWLiGtenmiOpMcj0vgrAFi2ZgB2dGnvpfbzPG4PhNeytzET4Ro2zS9QKCtBWB8Nmp3w41R2tXki5VajJjqfvNtKUPKbwWopbNQAnzu0A9E+u/3LeyukNDXcd0ZiF5iMroX9QtXMAMmyI/J1mQaJd9F5pb8xCiTOej5SKiciyILWMB6raNSfAnIMf3GWMSlyIYO7ssONgNaDTyCLTbgk0lHOuOCp8E8fFfscx/+KWTMpWLysdPfl/DdZhq8knTZ8lNX4vJZXDOy4wmgk0ZToY09zqovLVgKh6uBTCnZhAmV8BATno1QtFg2qLXiq6pKre3cSThQwdEnxCYaJZiBrIsJ+A95NLXHuFLGeWobtNr10IH/Z35+TrGxc9OCto6ZktgAkjP75M/Cz1YWMdQoABzq1dkmkA5U7gm/MSEW4Uy9+KDBdxtZm+pwiIwHcraaBSJgImm2oV9IyUo4wYXWUjwkwEYiNEzjkJw8S3FPvnBR1NuWQOiWQc3AjaZuvhJtEo5mck+daTk9PO+W2efl7FeJmv9qz71G3H/3q/4e4xNSlTCMAxa9sLYuk+AEy9XLt4puqzycsrLSi8jVWGL5QoJECvGDpZ5KOYrD88MY60/vp9nyrulyh6XkiKRA8+Qf8qK0SgBN0X/w2aJEj0A\",\"base64\")).toString()),Mj)});var U1e=_((Gj,Wj)=>{(function(t){Gj&&typeof Gj==\"object\"&&typeof Wj<\"u\"?Wj.exports=t():typeof define==\"function\"&&define.amd?define([],t):typeof window<\"u\"?window.isWindows=t():typeof global<\"u\"?global.isWindows=t():typeof self<\"u\"?self.isWindows=t():this.isWindows=t()})(function(){\"use strict\";return function(){return process&&(process.platform===\"win32\"||/^(msys|cygwin)$/.test(process.env.OSTYPE))}})});var j1e=_((SXt,q1e)=>{\"use strict\";Yj.ifExists=Twt;var FC=ve(\"util\"),cc=ve(\"path\"),_1e=U1e(),Qwt=/^#!\\s*(?:\\/usr\\/bin\\/env)?\\s*([^ \\t]+)(.*)$/,Fwt={createPwshFile:!0,createCmdFile:_1e(),fs:ve(\"fs\")},Rwt=new Map([[\".js\",\"node\"],[\".cjs\",\"node\"],[\".mjs\",\"node\"],[\".cmd\",\"cmd\"],[\".bat\",\"cmd\"],[\".ps1\",\"pwsh\"],[\".sh\",\"sh\"]]);function H1e(t){let e={...Fwt,...t},r=e.fs;return e.fs_={chmod:r.chmod?FC.promisify(r.chmod):async()=>{},mkdir:FC.promisify(r.mkdir),readFile:FC.promisify(r.readFile),stat:FC.promisify(r.stat),unlink:FC.promisify(r.unlink),writeFile:FC.promisify(r.writeFile)},e}async function Yj(t,e,r){let o=H1e(r);await o.fs_.stat(t),await Nwt(t,e,o)}function Twt(t,e,r){return Yj(t,e,r).catch(()=>{})}function Lwt(t,e){return e.fs_.unlink(t).catch(()=>{})}async function Nwt(t,e,r){let o=await Hwt(t,r);return await Owt(e,r),Mwt(t,e,o,r)}function Owt(t,e){return e.fs_.mkdir(cc.dirname(t),{recursive:!0})}function Mwt(t,e,r,o){let a=H1e(o),n=[{generator:Gwt,extension:\"\"}];return a.createCmdFile&&n.push({generator:jwt,extension:\".cmd\"}),a.createPwshFile&&n.push({generator:Wwt,extension:\".ps1\"}),Promise.all(n.map(u=>qwt(t,e+u.extension,r,u.generator,a)))}function Uwt(t,e){return Lwt(t,e)}function _wt(t,e){return Ywt(t,e)}async function Hwt(t,e){let a=(await e.fs_.readFile(t,\"utf8\")).trim().split(/\\r*\\n/)[0].match(Qwt);if(!a){let n=cc.extname(t).toLowerCase();return{program:Rwt.get(n)||null,additionalArgs:\"\"}}return{program:a[1],additionalArgs:a[2]}}async function qwt(t,e,r,o,a){let n=a.preserveSymlinks?\"--preserve-symlinks\":\"\",u=[r.additionalArgs,n].filter(A=>A).join(\" \");return a=Object.assign({},a,{prog:r.program,args:u}),await Uwt(e,a),await a.fs_.writeFile(e,o(t,e,a),\"utf8\"),_wt(e,a)}function jwt(t,e,r){let a=cc.relative(cc.dirname(e),t).split(\"/\").join(\"\\\\\"),n=cc.isAbsolute(a)?`\"${a}\"`:`\"%~dp0\\\\${a}\"`,u,A=r.prog,p=r.args||\"\",h=Kj(r.nodePath).win32;A?(u=`\"%~dp0\\\\${A}.exe\"`,a=n):(A=n,p=\"\",a=\"\");let E=r.progArgs?`${r.progArgs.join(\" \")} `:\"\",w=h?`@SET NODE_PATH=${h}\\r\n`:\"\";return u?w+=`@IF EXIST ${u} (\\r\n  ${u} ${p} ${a} ${E}%*\\r\n) ELSE (\\r\n  @SETLOCAL\\r\n  @SET PATHEXT=%PATHEXT:;.JS;=;%\\r\n  ${A} ${p} ${a} ${E}%*\\r\n)\\r\n`:w+=`@${A} ${p} ${a} ${E}%*\\r\n`,w}function Gwt(t,e,r){let o=cc.relative(cc.dirname(e),t),a=r.prog&&r.prog.split(\"\\\\\").join(\"/\"),n;o=o.split(\"\\\\\").join(\"/\");let u=cc.isAbsolute(o)?`\"${o}\"`:`\"$basedir/${o}\"`,A=r.args||\"\",p=Kj(r.nodePath).posix;a?(n=`\"$basedir/${r.prog}\"`,o=u):(a=u,A=\"\",o=\"\");let h=r.progArgs?`${r.progArgs.join(\" \")} `:\"\",E=`#!/bin/sh\nbasedir=$(dirname \"$(echo \"$0\" | sed -e 's,\\\\\\\\,/,g')\")\n\ncase \\`uname\\` in\n    *CYGWIN*) basedir=\\`cygpath -w \"$basedir\"\\`;;\nesac\n\n`,w=r.nodePath?`export NODE_PATH=\"${p}\"\n`:\"\";return n?E+=`${w}if [ -x ${n} ]; then\n  exec ${n} ${A} ${o} ${h}\"$@\"\nelse\n  exec ${a} ${A} ${o} ${h}\"$@\"\nfi\n`:E+=`${w}${a} ${A} ${o} ${h}\"$@\"\nexit $?\n`,E}function Wwt(t,e,r){let o=cc.relative(cc.dirname(e),t),a=r.prog&&r.prog.split(\"\\\\\").join(\"/\"),n=a&&`\"${a}$exe\"`,u;o=o.split(\"\\\\\").join(\"/\");let A=cc.isAbsolute(o)?`\"${o}\"`:`\"$basedir/${o}\"`,p=r.args||\"\",h=Kj(r.nodePath),E=h.win32,w=h.posix;n?(u=`\"$basedir/${r.prog}$exe\"`,o=A):(n=A,p=\"\",o=\"\");let D=r.progArgs?`${r.progArgs.join(\" \")} `:\"\",b=`#!/usr/bin/env pwsh\n$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent\n\n$exe=\"\"\n${r.nodePath?`$env_node_path=$env:NODE_PATH\n$env:NODE_PATH=\"${E}\"\n`:\"\"}if ($PSVersionTable.PSVersion -lt \"6.0\" -or $IsWindows) {\n  # Fix case when both the Windows and Linux builds of Node\n  # are installed in the same directory\n  $exe=\".exe\"\n}`;return r.nodePath&&(b+=` else {\n  $env:NODE_PATH=\"${w}\"\n}`),u?b+=`\n$ret=0\nif (Test-Path ${u}) {\n  # Support pipeline input\n  if ($MyInvocation.ExpectingInput) {\n    $input | & ${u} ${p} ${o} ${D}$args\n  } else {\n    & ${u} ${p} ${o} ${D}$args\n  }\n  $ret=$LASTEXITCODE\n} else {\n  # Support pipeline input\n  if ($MyInvocation.ExpectingInput) {\n    $input | & ${n} ${p} ${o} ${D}$args\n  } else {\n    & ${n} ${p} ${o} ${D}$args\n  }\n  $ret=$LASTEXITCODE\n}\n${r.nodePath?`$env:NODE_PATH=$env_node_path\n`:\"\"}exit $ret\n`:b+=`\n# Support pipeline input\nif ($MyInvocation.ExpectingInput) {\n  $input | & ${n} ${p} ${o} ${D}$args\n} else {\n  & ${n} ${p} ${o} ${D}$args\n}\n${r.nodePath?`$env:NODE_PATH=$env_node_path\n`:\"\"}exit $LASTEXITCODE\n`,b}function Ywt(t,e){return e.fs_.chmod(t,493)}function Kj(t){if(!t)return{win32:\"\",posix:\"\"};let e=typeof t==\"string\"?t.split(cc.delimiter):Array.from(t),r={};for(let o=0;o<e.length;o++){let a=e[o].split(\"/\").join(\"\\\\\"),n=_1e()?e[o].split(\"\\\\\").join(\"/\").replace(/^([^:\\\\/]*):/,(u,A)=>`/mnt/${A.toLowerCase()}`):e[o];r.win32=r.win32?`${r.win32};${a}`:a,r.posix=r.posix?`${r.posix}:${n}`:n,r[o]={win32:a,posix:n}}return r}q1e.exports=Yj});var a9=_((VZt,c2e)=>{c2e.exports=ve(\"stream\")});var p2e=_((zZt,f2e)=>{\"use strict\";function u2e(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);e&&(o=o.filter(function(a){return Object.getOwnPropertyDescriptor(t,a).enumerable})),r.push.apply(r,o)}return r}function E1t(t){for(var e=1;e<arguments.length;e++){var r=arguments[e]!=null?arguments[e]:{};e%2?u2e(Object(r),!0).forEach(function(o){C1t(t,o,r[o])}):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):u2e(Object(r)).forEach(function(o){Object.defineProperty(t,o,Object.getOwnPropertyDescriptor(r,o))})}return t}function C1t(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function I1t(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function A2e(t,e){for(var r=0;r<e.length;r++){var o=e[r];o.enumerable=o.enumerable||!1,o.configurable=!0,\"value\"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}function w1t(t,e,r){return e&&A2e(t.prototype,e),r&&A2e(t,r),t}var B1t=ve(\"buffer\"),sF=B1t.Buffer,v1t=ve(\"util\"),l9=v1t.inspect,D1t=l9&&l9.custom||\"inspect\";function P1t(t,e,r){sF.prototype.copy.call(t,e,r)}f2e.exports=function(){function t(){I1t(this,t),this.head=null,this.tail=null,this.length=0}return w1t(t,[{key:\"push\",value:function(r){var o={data:r,next:null};this.length>0?this.tail.next=o:this.head=o,this.tail=o,++this.length}},{key:\"unshift\",value:function(r){var o={data:r,next:this.head};this.length===0&&(this.tail=o),this.head=o,++this.length}},{key:\"shift\",value:function(){if(this.length!==0){var r=this.head.data;return this.length===1?this.head=this.tail=null:this.head=this.head.next,--this.length,r}}},{key:\"clear\",value:function(){this.head=this.tail=null,this.length=0}},{key:\"join\",value:function(r){if(this.length===0)return\"\";for(var o=this.head,a=\"\"+o.data;o=o.next;)a+=r+o.data;return a}},{key:\"concat\",value:function(r){if(this.length===0)return sF.alloc(0);for(var o=sF.allocUnsafe(r>>>0),a=this.head,n=0;a;)P1t(a.data,o,n),n+=a.data.length,a=a.next;return o}},{key:\"consume\",value:function(r,o){var a;return r<this.head.data.length?(a=this.head.data.slice(0,r),this.head.data=this.head.data.slice(r)):r===this.head.data.length?a=this.shift():a=o?this._getString(r):this._getBuffer(r),a}},{key:\"first\",value:function(){return this.head.data}},{key:\"_getString\",value:function(r){var o=this.head,a=1,n=o.data;for(r-=n.length;o=o.next;){var u=o.data,A=r>u.length?u.length:r;if(A===u.length?n+=u:n+=u.slice(0,r),r-=A,r===0){A===u.length?(++a,o.next?this.head=o.next:this.head=this.tail=null):(this.head=o,o.data=u.slice(A));break}++a}return this.length-=a,n}},{key:\"_getBuffer\",value:function(r){var o=sF.allocUnsafe(r),a=this.head,n=1;for(a.data.copy(o),r-=a.data.length;a=a.next;){var u=a.data,A=r>u.length?u.length:r;if(u.copy(o,o.length-r,0,A),r-=A,r===0){A===u.length?(++n,a.next?this.head=a.next:this.head=this.tail=null):(this.head=a,a.data=u.slice(A));break}++n}return this.length-=n,o}},{key:D1t,value:function(r,o){return l9(this,E1t({},o,{depth:0,customInspect:!1}))}}]),t}()});var u9=_((JZt,g2e)=>{\"use strict\";function S1t(t,e){var r=this,o=this._readableState&&this._readableState.destroyed,a=this._writableState&&this._writableState.destroyed;return o||a?(e?e(t):t&&(this._writableState?this._writableState.errorEmitted||(this._writableState.errorEmitted=!0,process.nextTick(c9,this,t)):process.nextTick(c9,this,t)),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(t||null,function(n){!e&&n?r._writableState?r._writableState.errorEmitted?process.nextTick(oF,r):(r._writableState.errorEmitted=!0,process.nextTick(h2e,r,n)):process.nextTick(h2e,r,n):e?(process.nextTick(oF,r),e(n)):process.nextTick(oF,r)}),this)}function h2e(t,e){c9(t,e),oF(t)}function oF(t){t._writableState&&!t._writableState.emitClose||t._readableState&&!t._readableState.emitClose||t.emit(\"close\")}function x1t(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finalCalled=!1,this._writableState.prefinished=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}function c9(t,e){t.emit(\"error\",e)}function b1t(t,e){var r=t._readableState,o=t._writableState;r&&r.autoDestroy||o&&o.autoDestroy?t.destroy(e):t.emit(\"error\",e)}g2e.exports={destroy:S1t,undestroy:x1t,errorOrDestroy:b1t}});var zh=_((XZt,y2e)=>{\"use strict\";var m2e={};function Ac(t,e,r){r||(r=Error);function o(n,u,A){return typeof e==\"string\"?e:e(n,u,A)}class a extends r{constructor(u,A,p){super(o(u,A,p))}}a.prototype.name=r.name,a.prototype.code=t,m2e[t]=a}function d2e(t,e){if(Array.isArray(t)){let r=t.length;return t=t.map(o=>String(o)),r>2?`one of ${e} ${t.slice(0,r-1).join(\", \")}, or `+t[r-1]:r===2?`one of ${e} ${t[0]} or ${t[1]}`:`of ${e} ${t[0]}`}else return`of ${e} ${String(t)}`}function k1t(t,e,r){return t.substr(!r||r<0?0:+r,e.length)===e}function Q1t(t,e,r){return(r===void 0||r>t.length)&&(r=t.length),t.substring(r-e.length,r)===e}function F1t(t,e,r){return typeof r!=\"number\"&&(r=0),r+e.length>t.length?!1:t.indexOf(e,r)!==-1}Ac(\"ERR_INVALID_OPT_VALUE\",function(t,e){return'The value \"'+e+'\" is invalid for option \"'+t+'\"'},TypeError);Ac(\"ERR_INVALID_ARG_TYPE\",function(t,e,r){let o;typeof e==\"string\"&&k1t(e,\"not \")?(o=\"must not be\",e=e.replace(/^not /,\"\")):o=\"must be\";let a;if(Q1t(t,\" argument\"))a=`The ${t} ${o} ${d2e(e,\"type\")}`;else{let n=F1t(t,\".\")?\"property\":\"argument\";a=`The \"${t}\" ${n} ${o} ${d2e(e,\"type\")}`}return a+=`. Received type ${typeof r}`,a},TypeError);Ac(\"ERR_STREAM_PUSH_AFTER_EOF\",\"stream.push() after EOF\");Ac(\"ERR_METHOD_NOT_IMPLEMENTED\",function(t){return\"The \"+t+\" method is not implemented\"});Ac(\"ERR_STREAM_PREMATURE_CLOSE\",\"Premature close\");Ac(\"ERR_STREAM_DESTROYED\",function(t){return\"Cannot call \"+t+\" after a stream was destroyed\"});Ac(\"ERR_MULTIPLE_CALLBACK\",\"Callback called multiple times\");Ac(\"ERR_STREAM_CANNOT_PIPE\",\"Cannot pipe, not readable\");Ac(\"ERR_STREAM_WRITE_AFTER_END\",\"write after end\");Ac(\"ERR_STREAM_NULL_VALUES\",\"May not write null values to stream\",TypeError);Ac(\"ERR_UNKNOWN_ENCODING\",function(t){return\"Unknown encoding: \"+t},TypeError);Ac(\"ERR_STREAM_UNSHIFT_AFTER_END_EVENT\",\"stream.unshift() after end event\");y2e.exports.codes=m2e});var A9=_((ZZt,E2e)=>{\"use strict\";var R1t=zh().codes.ERR_INVALID_OPT_VALUE;function T1t(t,e,r){return t.highWaterMark!=null?t.highWaterMark:e?t[r]:null}function L1t(t,e,r,o){var a=T1t(e,o,r);if(a!=null){if(!(isFinite(a)&&Math.floor(a)===a)||a<0){var n=o?r:\"highWaterMark\";throw new R1t(n,a)}return Math.floor(a)}return t.objectMode?16:16*1024}E2e.exports={getHighWaterMark:L1t}});var C2e=_(($Zt,f9)=>{typeof Object.create==\"function\"?f9.exports=function(e,r){r&&(e.super_=r,e.prototype=Object.create(r.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}))}:f9.exports=function(e,r){if(r){e.super_=r;var o=function(){};o.prototype=r.prototype,e.prototype=new o,e.prototype.constructor=e}}});var Jh=_((e$t,h9)=>{try{if(p9=ve(\"util\"),typeof p9.inherits!=\"function\")throw\"\";h9.exports=p9.inherits}catch{h9.exports=C2e()}var p9});var w2e=_((t$t,I2e)=>{I2e.exports=ve(\"util\").deprecate});var m9=_((r$t,x2e)=>{\"use strict\";x2e.exports=Li;function v2e(t){var e=this;this.next=null,this.entry=null,this.finish=function(){l2t(e,t)}}var OC;Li.WritableState=Tv;var N1t={deprecate:w2e()},D2e=a9(),lF=ve(\"buffer\").Buffer,O1t=global.Uint8Array||function(){};function M1t(t){return lF.from(t)}function U1t(t){return lF.isBuffer(t)||t instanceof O1t}var d9=u9(),_1t=A9(),H1t=_1t.getHighWaterMark,Xh=zh().codes,q1t=Xh.ERR_INVALID_ARG_TYPE,j1t=Xh.ERR_METHOD_NOT_IMPLEMENTED,G1t=Xh.ERR_MULTIPLE_CALLBACK,W1t=Xh.ERR_STREAM_CANNOT_PIPE,Y1t=Xh.ERR_STREAM_DESTROYED,K1t=Xh.ERR_STREAM_NULL_VALUES,V1t=Xh.ERR_STREAM_WRITE_AFTER_END,z1t=Xh.ERR_UNKNOWN_ENCODING,MC=d9.errorOrDestroy;Jh()(Li,D2e);function J1t(){}function Tv(t,e,r){OC=OC||dd(),t=t||{},typeof r!=\"boolean\"&&(r=e instanceof OC),this.objectMode=!!t.objectMode,r&&(this.objectMode=this.objectMode||!!t.writableObjectMode),this.highWaterMark=H1t(this,t,\"writableHighWaterMark\",r),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var o=t.decodeStrings===!1;this.decodeStrings=!o,this.defaultEncoding=t.defaultEncoding||\"utf8\",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(a){n2t(e,a)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.emitClose=t.emitClose!==!1,this.autoDestroy=!!t.autoDestroy,this.bufferedRequestCount=0,this.corkedRequestsFree=new v2e(this)}Tv.prototype.getBuffer=function(){for(var e=this.bufferedRequest,r=[];e;)r.push(e),e=e.next;return r};(function(){try{Object.defineProperty(Tv.prototype,\"buffer\",{get:N1t.deprecate(function(){return this.getBuffer()},\"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.\",\"DEP0003\")})}catch{}})();var aF;typeof Symbol==\"function\"&&Symbol.hasInstance&&typeof Function.prototype[Symbol.hasInstance]==\"function\"?(aF=Function.prototype[Symbol.hasInstance],Object.defineProperty(Li,Symbol.hasInstance,{value:function(e){return aF.call(this,e)?!0:this!==Li?!1:e&&e._writableState instanceof Tv}})):aF=function(e){return e instanceof this};function Li(t){OC=OC||dd();var e=this instanceof OC;if(!e&&!aF.call(Li,this))return new Li(t);this._writableState=new Tv(t,this,e),this.writable=!0,t&&(typeof t.write==\"function\"&&(this._write=t.write),typeof t.writev==\"function\"&&(this._writev=t.writev),typeof t.destroy==\"function\"&&(this._destroy=t.destroy),typeof t.final==\"function\"&&(this._final=t.final)),D2e.call(this)}Li.prototype.pipe=function(){MC(this,new W1t)};function X1t(t,e){var r=new V1t;MC(t,r),process.nextTick(e,r)}function Z1t(t,e,r,o){var a;return r===null?a=new K1t:typeof r!=\"string\"&&!e.objectMode&&(a=new q1t(\"chunk\",[\"string\",\"Buffer\"],r)),a?(MC(t,a),process.nextTick(o,a),!1):!0}Li.prototype.write=function(t,e,r){var o=this._writableState,a=!1,n=!o.objectMode&&U1t(t);return n&&!lF.isBuffer(t)&&(t=M1t(t)),typeof e==\"function\"&&(r=e,e=null),n?e=\"buffer\":e||(e=o.defaultEncoding),typeof r!=\"function\"&&(r=J1t),o.ending?X1t(this,r):(n||Z1t(this,o,t,r))&&(o.pendingcb++,a=e2t(this,o,n,t,e,r)),a};Li.prototype.cork=function(){this._writableState.corked++};Li.prototype.uncork=function(){var t=this._writableState;t.corked&&(t.corked--,!t.writing&&!t.corked&&!t.bufferProcessing&&t.bufferedRequest&&P2e(this,t))};Li.prototype.setDefaultEncoding=function(e){if(typeof e==\"string\"&&(e=e.toLowerCase()),!([\"hex\",\"utf8\",\"utf-8\",\"ascii\",\"binary\",\"base64\",\"ucs2\",\"ucs-2\",\"utf16le\",\"utf-16le\",\"raw\"].indexOf((e+\"\").toLowerCase())>-1))throw new z1t(e);return this._writableState.defaultEncoding=e,this};Object.defineProperty(Li.prototype,\"writableBuffer\",{enumerable:!1,get:function(){return this._writableState&&this._writableState.getBuffer()}});function $1t(t,e,r){return!t.objectMode&&t.decodeStrings!==!1&&typeof e==\"string\"&&(e=lF.from(e,r)),e}Object.defineProperty(Li.prototype,\"writableHighWaterMark\",{enumerable:!1,get:function(){return this._writableState.highWaterMark}});function e2t(t,e,r,o,a,n){if(!r){var u=$1t(e,o,a);o!==u&&(r=!0,a=\"buffer\",o=u)}var A=e.objectMode?1:o.length;e.length+=A;var p=e.length<e.highWaterMark;if(p||(e.needDrain=!0),e.writing||e.corked){var h=e.lastBufferedRequest;e.lastBufferedRequest={chunk:o,encoding:a,isBuf:r,callback:n,next:null},h?h.next=e.lastBufferedRequest:e.bufferedRequest=e.lastBufferedRequest,e.bufferedRequestCount+=1}else g9(t,e,!1,A,o,a,n);return p}function g9(t,e,r,o,a,n,u){e.writelen=o,e.writecb=u,e.writing=!0,e.sync=!0,e.destroyed?e.onwrite(new Y1t(\"write\")):r?t._writev(a,e.onwrite):t._write(a,n,e.onwrite),e.sync=!1}function t2t(t,e,r,o,a){--e.pendingcb,r?(process.nextTick(a,o),process.nextTick(Rv,t,e),t._writableState.errorEmitted=!0,MC(t,o)):(a(o),t._writableState.errorEmitted=!0,MC(t,o),Rv(t,e))}function r2t(t){t.writing=!1,t.writecb=null,t.length-=t.writelen,t.writelen=0}function n2t(t,e){var r=t._writableState,o=r.sync,a=r.writecb;if(typeof a!=\"function\")throw new G1t;if(r2t(r),e)t2t(t,r,o,e,a);else{var n=S2e(r)||t.destroyed;!n&&!r.corked&&!r.bufferProcessing&&r.bufferedRequest&&P2e(t,r),o?process.nextTick(B2e,t,r,n,a):B2e(t,r,n,a)}}function B2e(t,e,r,o){r||i2t(t,e),e.pendingcb--,o(),Rv(t,e)}function i2t(t,e){e.length===0&&e.needDrain&&(e.needDrain=!1,t.emit(\"drain\"))}function P2e(t,e){e.bufferProcessing=!0;var r=e.bufferedRequest;if(t._writev&&r&&r.next){var o=e.bufferedRequestCount,a=new Array(o),n=e.corkedRequestsFree;n.entry=r;for(var u=0,A=!0;r;)a[u]=r,r.isBuf||(A=!1),r=r.next,u+=1;a.allBuffers=A,g9(t,e,!0,e.length,a,\"\",n.finish),e.pendingcb++,e.lastBufferedRequest=null,n.next?(e.corkedRequestsFree=n.next,n.next=null):e.corkedRequestsFree=new v2e(e),e.bufferedRequestCount=0}else{for(;r;){var p=r.chunk,h=r.encoding,E=r.callback,w=e.objectMode?1:p.length;if(g9(t,e,!1,w,p,h,E),r=r.next,e.bufferedRequestCount--,e.writing)break}r===null&&(e.lastBufferedRequest=null)}e.bufferedRequest=r,e.bufferProcessing=!1}Li.prototype._write=function(t,e,r){r(new j1t(\"_write()\"))};Li.prototype._writev=null;Li.prototype.end=function(t,e,r){var o=this._writableState;return typeof t==\"function\"?(r=t,t=null,e=null):typeof e==\"function\"&&(r=e,e=null),t!=null&&this.write(t,e),o.corked&&(o.corked=1,this.uncork()),o.ending||a2t(this,o,r),this};Object.defineProperty(Li.prototype,\"writableLength\",{enumerable:!1,get:function(){return this._writableState.length}});function S2e(t){return t.ending&&t.length===0&&t.bufferedRequest===null&&!t.finished&&!t.writing}function s2t(t,e){t._final(function(r){e.pendingcb--,r&&MC(t,r),e.prefinished=!0,t.emit(\"prefinish\"),Rv(t,e)})}function o2t(t,e){!e.prefinished&&!e.finalCalled&&(typeof t._final==\"function\"&&!e.destroyed?(e.pendingcb++,e.finalCalled=!0,process.nextTick(s2t,t,e)):(e.prefinished=!0,t.emit(\"prefinish\")))}function Rv(t,e){var r=S2e(e);if(r&&(o2t(t,e),e.pendingcb===0&&(e.finished=!0,t.emit(\"finish\"),e.autoDestroy))){var o=t._readableState;(!o||o.autoDestroy&&o.endEmitted)&&t.destroy()}return r}function a2t(t,e,r){e.ending=!0,Rv(t,e),r&&(e.finished?process.nextTick(r):t.once(\"finish\",r)),e.ended=!0,t.writable=!1}function l2t(t,e,r){var o=t.entry;for(t.entry=null;o;){var a=o.callback;e.pendingcb--,a(r),o=o.next}e.corkedRequestsFree.next=t}Object.defineProperty(Li.prototype,\"destroyed\",{enumerable:!1,get:function(){return this._writableState===void 0?!1:this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}});Li.prototype.destroy=d9.destroy;Li.prototype._undestroy=d9.undestroy;Li.prototype._destroy=function(t,e){e(t)}});var dd=_((n$t,k2e)=>{\"use strict\";var c2t=Object.keys||function(t){var e=[];for(var r in t)e.push(r);return e};k2e.exports=IA;var b2e=C9(),E9=m9();Jh()(IA,b2e);for(y9=c2t(E9.prototype),cF=0;cF<y9.length;cF++)uF=y9[cF],IA.prototype[uF]||(IA.prototype[uF]=E9.prototype[uF]);var y9,uF,cF;function IA(t){if(!(this instanceof IA))return new IA(t);b2e.call(this,t),E9.call(this,t),this.allowHalfOpen=!0,t&&(t.readable===!1&&(this.readable=!1),t.writable===!1&&(this.writable=!1),t.allowHalfOpen===!1&&(this.allowHalfOpen=!1,this.once(\"end\",u2t)))}Object.defineProperty(IA.prototype,\"writableHighWaterMark\",{enumerable:!1,get:function(){return this._writableState.highWaterMark}});Object.defineProperty(IA.prototype,\"writableBuffer\",{enumerable:!1,get:function(){return this._writableState&&this._writableState.getBuffer()}});Object.defineProperty(IA.prototype,\"writableLength\",{enumerable:!1,get:function(){return this._writableState.length}});function u2t(){this._writableState.ended||process.nextTick(A2t,this)}function A2t(t){t.end()}Object.defineProperty(IA.prototype,\"destroyed\",{enumerable:!1,get:function(){return this._readableState===void 0||this._writableState===void 0?!1:this._readableState.destroyed&&this._writableState.destroyed},set:function(e){this._readableState===void 0||this._writableState===void 0||(this._readableState.destroyed=e,this._writableState.destroyed=e)}})});var R2e=_((I9,F2e)=>{var AF=ve(\"buffer\"),np=AF.Buffer;function Q2e(t,e){for(var r in t)e[r]=t[r]}np.from&&np.alloc&&np.allocUnsafe&&np.allocUnsafeSlow?F2e.exports=AF:(Q2e(AF,I9),I9.Buffer=UC);function UC(t,e,r){return np(t,e,r)}Q2e(np,UC);UC.from=function(t,e,r){if(typeof t==\"number\")throw new TypeError(\"Argument must not be a number\");return np(t,e,r)};UC.alloc=function(t,e,r){if(typeof t!=\"number\")throw new TypeError(\"Argument must be a number\");var o=np(t);return e!==void 0?typeof r==\"string\"?o.fill(e,r):o.fill(e):o.fill(0),o};UC.allocUnsafe=function(t){if(typeof t!=\"number\")throw new TypeError(\"Argument must be a number\");return np(t)};UC.allocUnsafeSlow=function(t){if(typeof t!=\"number\")throw new TypeError(\"Argument must be a number\");return AF.SlowBuffer(t)}});var v9=_(L2e=>{\"use strict\";var B9=R2e().Buffer,T2e=B9.isEncoding||function(t){switch(t=\"\"+t,t&&t.toLowerCase()){case\"hex\":case\"utf8\":case\"utf-8\":case\"ascii\":case\"binary\":case\"base64\":case\"ucs2\":case\"ucs-2\":case\"utf16le\":case\"utf-16le\":case\"raw\":return!0;default:return!1}};function f2t(t){if(!t)return\"utf8\";for(var e;;)switch(t){case\"utf8\":case\"utf-8\":return\"utf8\";case\"ucs2\":case\"ucs-2\":case\"utf16le\":case\"utf-16le\":return\"utf16le\";case\"latin1\":case\"binary\":return\"latin1\";case\"base64\":case\"ascii\":case\"hex\":return t;default:if(e)return;t=(\"\"+t).toLowerCase(),e=!0}}function p2t(t){var e=f2t(t);if(typeof e!=\"string\"&&(B9.isEncoding===T2e||!T2e(t)))throw new Error(\"Unknown encoding: \"+t);return e||t}L2e.StringDecoder=Lv;function Lv(t){this.encoding=p2t(t);var e;switch(this.encoding){case\"utf16le\":this.text=E2t,this.end=C2t,e=4;break;case\"utf8\":this.fillLast=d2t,e=4;break;case\"base64\":this.text=I2t,this.end=w2t,e=3;break;default:this.write=B2t,this.end=v2t;return}this.lastNeed=0,this.lastTotal=0,this.lastChar=B9.allocUnsafe(e)}Lv.prototype.write=function(t){if(t.length===0)return\"\";var e,r;if(this.lastNeed){if(e=this.fillLast(t),e===void 0)return\"\";r=this.lastNeed,this.lastNeed=0}else r=0;return r<t.length?e?e+this.text(t,r):this.text(t,r):e||\"\"};Lv.prototype.end=y2t;Lv.prototype.text=m2t;Lv.prototype.fillLast=function(t){if(this.lastNeed<=t.length)return t.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);t.copy(this.lastChar,this.lastTotal-this.lastNeed,0,t.length),this.lastNeed-=t.length};function w9(t){return t<=127?0:t>>5===6?2:t>>4===14?3:t>>3===30?4:t>>6===2?-1:-2}function h2t(t,e,r){var o=e.length-1;if(o<r)return 0;var a=w9(e[o]);return a>=0?(a>0&&(t.lastNeed=a-1),a):--o<r||a===-2?0:(a=w9(e[o]),a>=0?(a>0&&(t.lastNeed=a-2),a):--o<r||a===-2?0:(a=w9(e[o]),a>=0?(a>0&&(a===2?a=0:t.lastNeed=a-3),a):0))}function g2t(t,e,r){if((e[0]&192)!==128)return t.lastNeed=0,\"\\uFFFD\";if(t.lastNeed>1&&e.length>1){if((e[1]&192)!==128)return t.lastNeed=1,\"\\uFFFD\";if(t.lastNeed>2&&e.length>2&&(e[2]&192)!==128)return t.lastNeed=2,\"\\uFFFD\"}}function d2t(t){var e=this.lastTotal-this.lastNeed,r=g2t(this,t,e);if(r!==void 0)return r;if(this.lastNeed<=t.length)return t.copy(this.lastChar,e,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);t.copy(this.lastChar,e,0,t.length),this.lastNeed-=t.length}function m2t(t,e){var r=h2t(this,t,e);if(!this.lastNeed)return t.toString(\"utf8\",e);this.lastTotal=r;var o=t.length-(r-this.lastNeed);return t.copy(this.lastChar,0,o),t.toString(\"utf8\",e,o)}function y2t(t){var e=t&&t.length?this.write(t):\"\";return this.lastNeed?e+\"\\uFFFD\":e}function E2t(t,e){if((t.length-e)%2===0){var r=t.toString(\"utf16le\",e);if(r){var o=r.charCodeAt(r.length-1);if(o>=55296&&o<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=t[t.length-2],this.lastChar[1]=t[t.length-1],r.slice(0,-1)}return r}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=t[t.length-1],t.toString(\"utf16le\",e,t.length-1)}function C2t(t){var e=t&&t.length?this.write(t):\"\";if(this.lastNeed){var r=this.lastTotal-this.lastNeed;return e+this.lastChar.toString(\"utf16le\",0,r)}return e}function I2t(t,e){var r=(t.length-e)%3;return r===0?t.toString(\"base64\",e):(this.lastNeed=3-r,this.lastTotal=3,r===1?this.lastChar[0]=t[t.length-1]:(this.lastChar[0]=t[t.length-2],this.lastChar[1]=t[t.length-1]),t.toString(\"base64\",e,t.length-r))}function w2t(t){var e=t&&t.length?this.write(t):\"\";return this.lastNeed?e+this.lastChar.toString(\"base64\",0,3-this.lastNeed):e}function B2t(t){return t.toString(this.encoding)}function v2t(t){return t&&t.length?this.write(t):\"\"}});var fF=_((s$t,M2e)=>{\"use strict\";var N2e=zh().codes.ERR_STREAM_PREMATURE_CLOSE;function D2t(t){var e=!1;return function(){if(!e){e=!0;for(var r=arguments.length,o=new Array(r),a=0;a<r;a++)o[a]=arguments[a];t.apply(this,o)}}}function P2t(){}function S2t(t){return t.setHeader&&typeof t.abort==\"function\"}function O2e(t,e,r){if(typeof e==\"function\")return O2e(t,null,e);e||(e={}),r=D2t(r||P2t);var o=e.readable||e.readable!==!1&&t.readable,a=e.writable||e.writable!==!1&&t.writable,n=function(){t.writable||A()},u=t._writableState&&t._writableState.finished,A=function(){a=!1,u=!0,o||r.call(t)},p=t._readableState&&t._readableState.endEmitted,h=function(){o=!1,p=!0,a||r.call(t)},E=function(C){r.call(t,C)},w=function(){var C;if(o&&!p)return(!t._readableState||!t._readableState.ended)&&(C=new N2e),r.call(t,C);if(a&&!u)return(!t._writableState||!t._writableState.ended)&&(C=new N2e),r.call(t,C)},D=function(){t.req.on(\"finish\",A)};return S2t(t)?(t.on(\"complete\",A),t.on(\"abort\",w),t.req?D():t.on(\"request\",D)):a&&!t._writableState&&(t.on(\"end\",n),t.on(\"close\",n)),t.on(\"end\",h),t.on(\"finish\",A),e.error!==!1&&t.on(\"error\",E),t.on(\"close\",w),function(){t.removeListener(\"complete\",A),t.removeListener(\"abort\",w),t.removeListener(\"request\",D),t.req&&t.req.removeListener(\"finish\",A),t.removeListener(\"end\",n),t.removeListener(\"close\",n),t.removeListener(\"finish\",A),t.removeListener(\"end\",h),t.removeListener(\"error\",E),t.removeListener(\"close\",w)}}M2e.exports=O2e});var _2e=_((o$t,U2e)=>{\"use strict\";var pF;function Zh(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}var x2t=fF(),$h=Symbol(\"lastResolve\"),md=Symbol(\"lastReject\"),Nv=Symbol(\"error\"),hF=Symbol(\"ended\"),yd=Symbol(\"lastPromise\"),D9=Symbol(\"handlePromise\"),Ed=Symbol(\"stream\");function e0(t,e){return{value:t,done:e}}function b2t(t){var e=t[$h];if(e!==null){var r=t[Ed].read();r!==null&&(t[yd]=null,t[$h]=null,t[md]=null,e(e0(r,!1)))}}function k2t(t){process.nextTick(b2t,t)}function Q2t(t,e){return function(r,o){t.then(function(){if(e[hF]){r(e0(void 0,!0));return}e[D9](r,o)},o)}}var F2t=Object.getPrototypeOf(function(){}),R2t=Object.setPrototypeOf((pF={get stream(){return this[Ed]},next:function(){var e=this,r=this[Nv];if(r!==null)return Promise.reject(r);if(this[hF])return Promise.resolve(e0(void 0,!0));if(this[Ed].destroyed)return new Promise(function(u,A){process.nextTick(function(){e[Nv]?A(e[Nv]):u(e0(void 0,!0))})});var o=this[yd],a;if(o)a=new Promise(Q2t(o,this));else{var n=this[Ed].read();if(n!==null)return Promise.resolve(e0(n,!1));a=new Promise(this[D9])}return this[yd]=a,a}},Zh(pF,Symbol.asyncIterator,function(){return this}),Zh(pF,\"return\",function(){var e=this;return new Promise(function(r,o){e[Ed].destroy(null,function(a){if(a){o(a);return}r(e0(void 0,!0))})})}),pF),F2t),T2t=function(e){var r,o=Object.create(R2t,(r={},Zh(r,Ed,{value:e,writable:!0}),Zh(r,$h,{value:null,writable:!0}),Zh(r,md,{value:null,writable:!0}),Zh(r,Nv,{value:null,writable:!0}),Zh(r,hF,{value:e._readableState.endEmitted,writable:!0}),Zh(r,D9,{value:function(n,u){var A=o[Ed].read();A?(o[yd]=null,o[$h]=null,o[md]=null,n(e0(A,!1))):(o[$h]=n,o[md]=u)},writable:!0}),r));return o[yd]=null,x2t(e,function(a){if(a&&a.code!==\"ERR_STREAM_PREMATURE_CLOSE\"){var n=o[md];n!==null&&(o[yd]=null,o[$h]=null,o[md]=null,n(a)),o[Nv]=a;return}var u=o[$h];u!==null&&(o[yd]=null,o[$h]=null,o[md]=null,u(e0(void 0,!0))),o[hF]=!0}),e.on(\"readable\",k2t.bind(null,o)),o};U2e.exports=T2t});var G2e=_((a$t,j2e)=>{\"use strict\";function H2e(t,e,r,o,a,n,u){try{var A=t[n](u),p=A.value}catch(h){r(h);return}A.done?e(p):Promise.resolve(p).then(o,a)}function L2t(t){return function(){var e=this,r=arguments;return new Promise(function(o,a){var n=t.apply(e,r);function u(p){H2e(n,o,a,u,A,\"next\",p)}function A(p){H2e(n,o,a,u,A,\"throw\",p)}u(void 0)})}}function q2e(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);e&&(o=o.filter(function(a){return Object.getOwnPropertyDescriptor(t,a).enumerable})),r.push.apply(r,o)}return r}function N2t(t){for(var e=1;e<arguments.length;e++){var r=arguments[e]!=null?arguments[e]:{};e%2?q2e(Object(r),!0).forEach(function(o){O2t(t,o,r[o])}):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):q2e(Object(r)).forEach(function(o){Object.defineProperty(t,o,Object.getOwnPropertyDescriptor(r,o))})}return t}function O2t(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}var M2t=zh().codes.ERR_INVALID_ARG_TYPE;function U2t(t,e,r){var o;if(e&&typeof e.next==\"function\")o=e;else if(e&&e[Symbol.asyncIterator])o=e[Symbol.asyncIterator]();else if(e&&e[Symbol.iterator])o=e[Symbol.iterator]();else throw new M2t(\"iterable\",[\"Iterable\"],e);var a=new t(N2t({objectMode:!0},r)),n=!1;a._read=function(){n||(n=!0,u())};function u(){return A.apply(this,arguments)}function A(){return A=L2t(function*(){try{var p=yield o.next(),h=p.value,E=p.done;E?a.push(null):a.push(yield h)?u():n=!1}catch(w){a.destroy(w)}}),A.apply(this,arguments)}return a}j2e.exports=U2t});var C9=_((c$t,eBe)=>{\"use strict\";eBe.exports=wn;var _C;wn.ReadableState=V2e;var l$t=ve(\"events\").EventEmitter,K2e=function(e,r){return e.listeners(r).length},Mv=a9(),gF=ve(\"buffer\").Buffer,_2t=global.Uint8Array||function(){};function H2t(t){return gF.from(t)}function q2t(t){return gF.isBuffer(t)||t instanceof _2t}var P9=ve(\"util\"),tn;P9&&P9.debuglog?tn=P9.debuglog(\"stream\"):tn=function(){};var j2t=p2e(),R9=u9(),G2t=A9(),W2t=G2t.getHighWaterMark,dF=zh().codes,Y2t=dF.ERR_INVALID_ARG_TYPE,K2t=dF.ERR_STREAM_PUSH_AFTER_EOF,V2t=dF.ERR_METHOD_NOT_IMPLEMENTED,z2t=dF.ERR_STREAM_UNSHIFT_AFTER_END_EVENT,HC,S9,x9;Jh()(wn,Mv);var Ov=R9.errorOrDestroy,b9=[\"error\",\"close\",\"destroy\",\"pause\",\"resume\"];function J2t(t,e,r){if(typeof t.prependListener==\"function\")return t.prependListener(e,r);!t._events||!t._events[e]?t.on(e,r):Array.isArray(t._events[e])?t._events[e].unshift(r):t._events[e]=[r,t._events[e]]}function V2e(t,e,r){_C=_C||dd(),t=t||{},typeof r!=\"boolean\"&&(r=e instanceof _C),this.objectMode=!!t.objectMode,r&&(this.objectMode=this.objectMode||!!t.readableObjectMode),this.highWaterMark=W2t(this,t,\"readableHighWaterMark\",r),this.buffer=new j2t,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.paused=!0,this.emitClose=t.emitClose!==!1,this.autoDestroy=!!t.autoDestroy,this.destroyed=!1,this.defaultEncoding=t.defaultEncoding||\"utf8\",this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,t.encoding&&(HC||(HC=v9().StringDecoder),this.decoder=new HC(t.encoding),this.encoding=t.encoding)}function wn(t){if(_C=_C||dd(),!(this instanceof wn))return new wn(t);var e=this instanceof _C;this._readableState=new V2e(t,this,e),this.readable=!0,t&&(typeof t.read==\"function\"&&(this._read=t.read),typeof t.destroy==\"function\"&&(this._destroy=t.destroy)),Mv.call(this)}Object.defineProperty(wn.prototype,\"destroyed\",{enumerable:!1,get:function(){return this._readableState===void 0?!1:this._readableState.destroyed},set:function(e){this._readableState&&(this._readableState.destroyed=e)}});wn.prototype.destroy=R9.destroy;wn.prototype._undestroy=R9.undestroy;wn.prototype._destroy=function(t,e){e(t)};wn.prototype.push=function(t,e){var r=this._readableState,o;return r.objectMode?o=!0:typeof t==\"string\"&&(e=e||r.defaultEncoding,e!==r.encoding&&(t=gF.from(t,e),e=\"\"),o=!0),z2e(this,t,e,!1,o)};wn.prototype.unshift=function(t){return z2e(this,t,null,!0,!1)};function z2e(t,e,r,o,a){tn(\"readableAddChunk\",e);var n=t._readableState;if(e===null)n.reading=!1,$2t(t,n);else{var u;if(a||(u=X2t(n,e)),u)Ov(t,u);else if(n.objectMode||e&&e.length>0)if(typeof e!=\"string\"&&!n.objectMode&&Object.getPrototypeOf(e)!==gF.prototype&&(e=H2t(e)),o)n.endEmitted?Ov(t,new z2t):k9(t,n,e,!0);else if(n.ended)Ov(t,new K2t);else{if(n.destroyed)return!1;n.reading=!1,n.decoder&&!r?(e=n.decoder.write(e),n.objectMode||e.length!==0?k9(t,n,e,!1):F9(t,n)):k9(t,n,e,!1)}else o||(n.reading=!1,F9(t,n))}return!n.ended&&(n.length<n.highWaterMark||n.length===0)}function k9(t,e,r,o){e.flowing&&e.length===0&&!e.sync?(e.awaitDrain=0,t.emit(\"data\",r)):(e.length+=e.objectMode?1:r.length,o?e.buffer.unshift(r):e.buffer.push(r),e.needReadable&&mF(t)),F9(t,e)}function X2t(t,e){var r;return!q2t(e)&&typeof e!=\"string\"&&e!==void 0&&!t.objectMode&&(r=new Y2t(\"chunk\",[\"string\",\"Buffer\",\"Uint8Array\"],e)),r}wn.prototype.isPaused=function(){return this._readableState.flowing===!1};wn.prototype.setEncoding=function(t){HC||(HC=v9().StringDecoder);var e=new HC(t);this._readableState.decoder=e,this._readableState.encoding=this._readableState.decoder.encoding;for(var r=this._readableState.buffer.head,o=\"\";r!==null;)o+=e.write(r.data),r=r.next;return this._readableState.buffer.clear(),o!==\"\"&&this._readableState.buffer.push(o),this._readableState.length=o.length,this};var W2e=1073741824;function Z2t(t){return t>=W2e?t=W2e:(t--,t|=t>>>1,t|=t>>>2,t|=t>>>4,t|=t>>>8,t|=t>>>16,t++),t}function Y2e(t,e){return t<=0||e.length===0&&e.ended?0:e.objectMode?1:t!==t?e.flowing&&e.length?e.buffer.head.data.length:e.length:(t>e.highWaterMark&&(e.highWaterMark=Z2t(t)),t<=e.length?t:e.ended?e.length:(e.needReadable=!0,0))}wn.prototype.read=function(t){tn(\"read\",t),t=parseInt(t,10);var e=this._readableState,r=t;if(t!==0&&(e.emittedReadable=!1),t===0&&e.needReadable&&((e.highWaterMark!==0?e.length>=e.highWaterMark:e.length>0)||e.ended))return tn(\"read: emitReadable\",e.length,e.ended),e.length===0&&e.ended?Q9(this):mF(this),null;if(t=Y2e(t,e),t===0&&e.ended)return e.length===0&&Q9(this),null;var o=e.needReadable;tn(\"need readable\",o),(e.length===0||e.length-t<e.highWaterMark)&&(o=!0,tn(\"length less than watermark\",o)),e.ended||e.reading?(o=!1,tn(\"reading or ended\",o)):o&&(tn(\"do read\"),e.reading=!0,e.sync=!0,e.length===0&&(e.needReadable=!0),this._read(e.highWaterMark),e.sync=!1,e.reading||(t=Y2e(r,e)));var a;return t>0?a=Z2e(t,e):a=null,a===null?(e.needReadable=e.length<=e.highWaterMark,t=0):(e.length-=t,e.awaitDrain=0),e.length===0&&(e.ended||(e.needReadable=!0),r!==t&&e.ended&&Q9(this)),a!==null&&this.emit(\"data\",a),a};function $2t(t,e){if(tn(\"onEofChunk\"),!e.ended){if(e.decoder){var r=e.decoder.end();r&&r.length&&(e.buffer.push(r),e.length+=e.objectMode?1:r.length)}e.ended=!0,e.sync?mF(t):(e.needReadable=!1,e.emittedReadable||(e.emittedReadable=!0,J2e(t)))}}function mF(t){var e=t._readableState;tn(\"emitReadable\",e.needReadable,e.emittedReadable),e.needReadable=!1,e.emittedReadable||(tn(\"emitReadable\",e.flowing),e.emittedReadable=!0,process.nextTick(J2e,t))}function J2e(t){var e=t._readableState;tn(\"emitReadable_\",e.destroyed,e.length,e.ended),!e.destroyed&&(e.length||e.ended)&&(t.emit(\"readable\"),e.emittedReadable=!1),e.needReadable=!e.flowing&&!e.ended&&e.length<=e.highWaterMark,T9(t)}function F9(t,e){e.readingMore||(e.readingMore=!0,process.nextTick(eBt,t,e))}function eBt(t,e){for(;!e.reading&&!e.ended&&(e.length<e.highWaterMark||e.flowing&&e.length===0);){var r=e.length;if(tn(\"maybeReadMore read 0\"),t.read(0),r===e.length)break}e.readingMore=!1}wn.prototype._read=function(t){Ov(this,new V2t(\"_read()\"))};wn.prototype.pipe=function(t,e){var r=this,o=this._readableState;switch(o.pipesCount){case 0:o.pipes=t;break;case 1:o.pipes=[o.pipes,t];break;default:o.pipes.push(t);break}o.pipesCount+=1,tn(\"pipe count=%d opts=%j\",o.pipesCount,e);var a=(!e||e.end!==!1)&&t!==process.stdout&&t!==process.stderr,n=a?A:T;o.endEmitted?process.nextTick(n):r.once(\"end\",n),t.on(\"unpipe\",u);function u(N,U){tn(\"onunpipe\"),N===r&&U&&U.hasUnpiped===!1&&(U.hasUnpiped=!0,E())}function A(){tn(\"onend\"),t.end()}var p=tBt(r);t.on(\"drain\",p);var h=!1;function E(){tn(\"cleanup\"),t.removeListener(\"close\",b),t.removeListener(\"finish\",C),t.removeListener(\"drain\",p),t.removeListener(\"error\",D),t.removeListener(\"unpipe\",u),r.removeListener(\"end\",A),r.removeListener(\"end\",T),r.removeListener(\"data\",w),h=!0,o.awaitDrain&&(!t._writableState||t._writableState.needDrain)&&p()}r.on(\"data\",w);function w(N){tn(\"ondata\");var U=t.write(N);tn(\"dest.write\",U),U===!1&&((o.pipesCount===1&&o.pipes===t||o.pipesCount>1&&$2e(o.pipes,t)!==-1)&&!h&&(tn(\"false write response, pause\",o.awaitDrain),o.awaitDrain++),r.pause())}function D(N){tn(\"onerror\",N),T(),t.removeListener(\"error\",D),K2e(t,\"error\")===0&&Ov(t,N)}J2t(t,\"error\",D);function b(){t.removeListener(\"finish\",C),T()}t.once(\"close\",b);function C(){tn(\"onfinish\"),t.removeListener(\"close\",b),T()}t.once(\"finish\",C);function T(){tn(\"unpipe\"),r.unpipe(t)}return t.emit(\"pipe\",r),o.flowing||(tn(\"pipe resume\"),r.resume()),t};function tBt(t){return function(){var r=t._readableState;tn(\"pipeOnDrain\",r.awaitDrain),r.awaitDrain&&r.awaitDrain--,r.awaitDrain===0&&K2e(t,\"data\")&&(r.flowing=!0,T9(t))}}wn.prototype.unpipe=function(t){var e=this._readableState,r={hasUnpiped:!1};if(e.pipesCount===0)return this;if(e.pipesCount===1)return t&&t!==e.pipes?this:(t||(t=e.pipes),e.pipes=null,e.pipesCount=0,e.flowing=!1,t&&t.emit(\"unpipe\",this,r),this);if(!t){var o=e.pipes,a=e.pipesCount;e.pipes=null,e.pipesCount=0,e.flowing=!1;for(var n=0;n<a;n++)o[n].emit(\"unpipe\",this,{hasUnpiped:!1});return this}var u=$2e(e.pipes,t);return u===-1?this:(e.pipes.splice(u,1),e.pipesCount-=1,e.pipesCount===1&&(e.pipes=e.pipes[0]),t.emit(\"unpipe\",this,r),this)};wn.prototype.on=function(t,e){var r=Mv.prototype.on.call(this,t,e),o=this._readableState;return t===\"data\"?(o.readableListening=this.listenerCount(\"readable\")>0,o.flowing!==!1&&this.resume()):t===\"readable\"&&!o.endEmitted&&!o.readableListening&&(o.readableListening=o.needReadable=!0,o.flowing=!1,o.emittedReadable=!1,tn(\"on readable\",o.length,o.reading),o.length?mF(this):o.reading||process.nextTick(rBt,this)),r};wn.prototype.addListener=wn.prototype.on;wn.prototype.removeListener=function(t,e){var r=Mv.prototype.removeListener.call(this,t,e);return t===\"readable\"&&process.nextTick(X2e,this),r};wn.prototype.removeAllListeners=function(t){var e=Mv.prototype.removeAllListeners.apply(this,arguments);return(t===\"readable\"||t===void 0)&&process.nextTick(X2e,this),e};function X2e(t){var e=t._readableState;e.readableListening=t.listenerCount(\"readable\")>0,e.resumeScheduled&&!e.paused?e.flowing=!0:t.listenerCount(\"data\")>0&&t.resume()}function rBt(t){tn(\"readable nexttick read 0\"),t.read(0)}wn.prototype.resume=function(){var t=this._readableState;return t.flowing||(tn(\"resume\"),t.flowing=!t.readableListening,nBt(this,t)),t.paused=!1,this};function nBt(t,e){e.resumeScheduled||(e.resumeScheduled=!0,process.nextTick(iBt,t,e))}function iBt(t,e){tn(\"resume\",e.reading),e.reading||t.read(0),e.resumeScheduled=!1,t.emit(\"resume\"),T9(t),e.flowing&&!e.reading&&t.read(0)}wn.prototype.pause=function(){return tn(\"call pause flowing=%j\",this._readableState.flowing),this._readableState.flowing!==!1&&(tn(\"pause\"),this._readableState.flowing=!1,this.emit(\"pause\")),this._readableState.paused=!0,this};function T9(t){var e=t._readableState;for(tn(\"flow\",e.flowing);e.flowing&&t.read()!==null;);}wn.prototype.wrap=function(t){var e=this,r=this._readableState,o=!1;t.on(\"end\",function(){if(tn(\"wrapped end\"),r.decoder&&!r.ended){var u=r.decoder.end();u&&u.length&&e.push(u)}e.push(null)}),t.on(\"data\",function(u){if(tn(\"wrapped data\"),r.decoder&&(u=r.decoder.write(u)),!(r.objectMode&&u==null)&&!(!r.objectMode&&(!u||!u.length))){var A=e.push(u);A||(o=!0,t.pause())}});for(var a in t)this[a]===void 0&&typeof t[a]==\"function\"&&(this[a]=function(A){return function(){return t[A].apply(t,arguments)}}(a));for(var n=0;n<b9.length;n++)t.on(b9[n],this.emit.bind(this,b9[n]));return this._read=function(u){tn(\"wrapped _read\",u),o&&(o=!1,t.resume())},this};typeof Symbol==\"function\"&&(wn.prototype[Symbol.asyncIterator]=function(){return S9===void 0&&(S9=_2e()),S9(this)});Object.defineProperty(wn.prototype,\"readableHighWaterMark\",{enumerable:!1,get:function(){return this._readableState.highWaterMark}});Object.defineProperty(wn.prototype,\"readableBuffer\",{enumerable:!1,get:function(){return this._readableState&&this._readableState.buffer}});Object.defineProperty(wn.prototype,\"readableFlowing\",{enumerable:!1,get:function(){return this._readableState.flowing},set:function(e){this._readableState&&(this._readableState.flowing=e)}});wn._fromList=Z2e;Object.defineProperty(wn.prototype,\"readableLength\",{enumerable:!1,get:function(){return this._readableState.length}});function Z2e(t,e){if(e.length===0)return null;var r;return e.objectMode?r=e.buffer.shift():!t||t>=e.length?(e.decoder?r=e.buffer.join(\"\"):e.buffer.length===1?r=e.buffer.first():r=e.buffer.concat(e.length),e.buffer.clear()):r=e.buffer.consume(t,e.decoder),r}function Q9(t){var e=t._readableState;tn(\"endReadable\",e.endEmitted),e.endEmitted||(e.ended=!0,process.nextTick(sBt,e,t))}function sBt(t,e){if(tn(\"endReadableNT\",t.endEmitted,t.length),!t.endEmitted&&t.length===0&&(t.endEmitted=!0,e.readable=!1,e.emit(\"end\"),t.autoDestroy)){var r=e._writableState;(!r||r.autoDestroy&&r.finished)&&e.destroy()}}typeof Symbol==\"function\"&&(wn.from=function(t,e){return x9===void 0&&(x9=G2e()),x9(wn,t,e)});function $2e(t,e){for(var r=0,o=t.length;r<o;r++)if(t[r]===e)return r;return-1}});var L9=_((u$t,rBe)=>{\"use strict\";rBe.exports=ip;var yF=zh().codes,oBt=yF.ERR_METHOD_NOT_IMPLEMENTED,aBt=yF.ERR_MULTIPLE_CALLBACK,lBt=yF.ERR_TRANSFORM_ALREADY_TRANSFORMING,cBt=yF.ERR_TRANSFORM_WITH_LENGTH_0,EF=dd();Jh()(ip,EF);function uBt(t,e){var r=this._transformState;r.transforming=!1;var o=r.writecb;if(o===null)return this.emit(\"error\",new aBt);r.writechunk=null,r.writecb=null,e!=null&&this.push(e),o(t);var a=this._readableState;a.reading=!1,(a.needReadable||a.length<a.highWaterMark)&&this._read(a.highWaterMark)}function ip(t){if(!(this instanceof ip))return new ip(t);EF.call(this,t),this._transformState={afterTransform:uBt.bind(this),needTransform:!1,transforming:!1,writecb:null,writechunk:null,writeencoding:null},this._readableState.needReadable=!0,this._readableState.sync=!1,t&&(typeof t.transform==\"function\"&&(this._transform=t.transform),typeof t.flush==\"function\"&&(this._flush=t.flush)),this.on(\"prefinish\",ABt)}function ABt(){var t=this;typeof this._flush==\"function\"&&!this._readableState.destroyed?this._flush(function(e,r){tBe(t,e,r)}):tBe(this,null,null)}ip.prototype.push=function(t,e){return this._transformState.needTransform=!1,EF.prototype.push.call(this,t,e)};ip.prototype._transform=function(t,e,r){r(new oBt(\"_transform()\"))};ip.prototype._write=function(t,e,r){var o=this._transformState;if(o.writecb=r,o.writechunk=t,o.writeencoding=e,!o.transforming){var a=this._readableState;(o.needTransform||a.needReadable||a.length<a.highWaterMark)&&this._read(a.highWaterMark)}};ip.prototype._read=function(t){var e=this._transformState;e.writechunk!==null&&!e.transforming?(e.transforming=!0,this._transform(e.writechunk,e.writeencoding,e.afterTransform)):e.needTransform=!0};ip.prototype._destroy=function(t,e){EF.prototype._destroy.call(this,t,function(r){e(r)})};function tBe(t,e,r){if(e)return t.emit(\"error\",e);if(r!=null&&t.push(r),t._writableState.length)throw new cBt;if(t._transformState.transforming)throw new lBt;return t.push(null)}});var sBe=_((A$t,iBe)=>{\"use strict\";iBe.exports=Uv;var nBe=L9();Jh()(Uv,nBe);function Uv(t){if(!(this instanceof Uv))return new Uv(t);nBe.call(this,t)}Uv.prototype._transform=function(t,e,r){r(null,t)}});var uBe=_((f$t,cBe)=>{\"use strict\";var N9;function fBt(t){var e=!1;return function(){e||(e=!0,t.apply(void 0,arguments))}}var lBe=zh().codes,pBt=lBe.ERR_MISSING_ARGS,hBt=lBe.ERR_STREAM_DESTROYED;function oBe(t){if(t)throw t}function gBt(t){return t.setHeader&&typeof t.abort==\"function\"}function dBt(t,e,r,o){o=fBt(o);var a=!1;t.on(\"close\",function(){a=!0}),N9===void 0&&(N9=fF()),N9(t,{readable:e,writable:r},function(u){if(u)return o(u);a=!0,o()});var n=!1;return function(u){if(!a&&!n){if(n=!0,gBt(t))return t.abort();if(typeof t.destroy==\"function\")return t.destroy();o(u||new hBt(\"pipe\"))}}}function aBe(t){t()}function mBt(t,e){return t.pipe(e)}function yBt(t){return!t.length||typeof t[t.length-1]!=\"function\"?oBe:t.pop()}function EBt(){for(var t=arguments.length,e=new Array(t),r=0;r<t;r++)e[r]=arguments[r];var o=yBt(e);if(Array.isArray(e[0])&&(e=e[0]),e.length<2)throw new pBt(\"streams\");var a,n=e.map(function(u,A){var p=A<e.length-1,h=A>0;return dBt(u,p,h,function(E){a||(a=E),E&&n.forEach(aBe),!p&&(n.forEach(aBe),o(a))})});return e.reduce(mBt)}cBe.exports=EBt});var qC=_((fc,Hv)=>{var _v=ve(\"stream\");process.env.READABLE_STREAM===\"disable\"&&_v?(Hv.exports=_v.Readable,Object.assign(Hv.exports,_v),Hv.exports.Stream=_v):(fc=Hv.exports=C9(),fc.Stream=_v||fc,fc.Readable=fc,fc.Writable=m9(),fc.Duplex=dd(),fc.Transform=L9(),fc.PassThrough=sBe(),fc.finished=fF(),fc.pipeline=uBe())});var pBe=_((p$t,fBe)=>{\"use strict\";var{Buffer:hu}=ve(\"buffer\"),ABe=Symbol.for(\"BufferList\");function fi(t){if(!(this instanceof fi))return new fi(t);fi._init.call(this,t)}fi._init=function(e){Object.defineProperty(this,ABe,{value:!0}),this._bufs=[],this.length=0,e&&this.append(e)};fi.prototype._new=function(e){return new fi(e)};fi.prototype._offset=function(e){if(e===0)return[0,0];let r=0;for(let o=0;o<this._bufs.length;o++){let a=r+this._bufs[o].length;if(e<a||o===this._bufs.length-1)return[o,e-r];r=a}};fi.prototype._reverseOffset=function(t){let e=t[0],r=t[1];for(let o=0;o<e;o++)r+=this._bufs[o].length;return r};fi.prototype.get=function(e){if(e>this.length||e<0)return;let r=this._offset(e);return this._bufs[r[0]][r[1]]};fi.prototype.slice=function(e,r){return typeof e==\"number\"&&e<0&&(e+=this.length),typeof r==\"number\"&&r<0&&(r+=this.length),this.copy(null,0,e,r)};fi.prototype.copy=function(e,r,o,a){if((typeof o!=\"number\"||o<0)&&(o=0),(typeof a!=\"number\"||a>this.length)&&(a=this.length),o>=this.length||a<=0)return e||hu.alloc(0);let n=!!e,u=this._offset(o),A=a-o,p=A,h=n&&r||0,E=u[1];if(o===0&&a===this.length){if(!n)return this._bufs.length===1?this._bufs[0]:hu.concat(this._bufs,this.length);for(let w=0;w<this._bufs.length;w++)this._bufs[w].copy(e,h),h+=this._bufs[w].length;return e}if(p<=this._bufs[u[0]].length-E)return n?this._bufs[u[0]].copy(e,r,E,E+p):this._bufs[u[0]].slice(E,E+p);n||(e=hu.allocUnsafe(A));for(let w=u[0];w<this._bufs.length;w++){let D=this._bufs[w].length-E;if(p>D)this._bufs[w].copy(e,h,E),h+=D;else{this._bufs[w].copy(e,h,E,E+p),h+=D;break}p-=D,E&&(E=0)}return e.length>h?e.slice(0,h):e};fi.prototype.shallowSlice=function(e,r){if(e=e||0,r=typeof r!=\"number\"?this.length:r,e<0&&(e+=this.length),r<0&&(r+=this.length),e===r)return this._new();let o=this._offset(e),a=this._offset(r),n=this._bufs.slice(o[0],a[0]+1);return a[1]===0?n.pop():n[n.length-1]=n[n.length-1].slice(0,a[1]),o[1]!==0&&(n[0]=n[0].slice(o[1])),this._new(n)};fi.prototype.toString=function(e,r,o){return this.slice(r,o).toString(e)};fi.prototype.consume=function(e){if(e=Math.trunc(e),Number.isNaN(e)||e<=0)return this;for(;this._bufs.length;)if(e>=this._bufs[0].length)e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift();else{this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}return this};fi.prototype.duplicate=function(){let e=this._new();for(let r=0;r<this._bufs.length;r++)e.append(this._bufs[r]);return e};fi.prototype.append=function(e){if(e==null)return this;if(e.buffer)this._appendBuffer(hu.from(e.buffer,e.byteOffset,e.byteLength));else if(Array.isArray(e))for(let r=0;r<e.length;r++)this.append(e[r]);else if(this._isBufferList(e))for(let r=0;r<e._bufs.length;r++)this.append(e._bufs[r]);else typeof e==\"number\"&&(e=e.toString()),this._appendBuffer(hu.from(e));return this};fi.prototype._appendBuffer=function(e){this._bufs.push(e),this.length+=e.length};fi.prototype.indexOf=function(t,e,r){if(r===void 0&&typeof e==\"string\"&&(r=e,e=void 0),typeof t==\"function\"||Array.isArray(t))throw new TypeError('The \"value\" argument must be one of type string, Buffer, BufferList, or Uint8Array.');if(typeof t==\"number\"?t=hu.from([t]):typeof t==\"string\"?t=hu.from(t,r):this._isBufferList(t)?t=t.slice():Array.isArray(t.buffer)?t=hu.from(t.buffer,t.byteOffset,t.byteLength):hu.isBuffer(t)||(t=hu.from(t)),e=Number(e||0),isNaN(e)&&(e=0),e<0&&(e=this.length+e),e<0&&(e=0),t.length===0)return e>this.length?this.length:e;let o=this._offset(e),a=o[0],n=o[1];for(;a<this._bufs.length;a++){let u=this._bufs[a];for(;n<u.length;)if(u.length-n>=t.length){let p=u.indexOf(t,n);if(p!==-1)return this._reverseOffset([a,p]);n=u.length-t.length+1}else{let p=this._reverseOffset([a,n]);if(this._match(p,t))return p;n++}n=0}return-1};fi.prototype._match=function(t,e){if(this.length-t<e.length)return!1;for(let r=0;r<e.length;r++)if(this.get(t+r)!==e[r])return!1;return!0};(function(){let t={readDoubleBE:8,readDoubleLE:8,readFloatBE:4,readFloatLE:4,readInt32BE:4,readInt32LE:4,readUInt32BE:4,readUInt32LE:4,readInt16BE:2,readInt16LE:2,readUInt16BE:2,readUInt16LE:2,readInt8:1,readUInt8:1,readIntBE:null,readIntLE:null,readUIntBE:null,readUIntLE:null};for(let e in t)(function(r){t[r]===null?fi.prototype[r]=function(o,a){return this.slice(o,o+a)[r](0,a)}:fi.prototype[r]=function(o=0){return this.slice(o,o+t[r])[r](0)}})(e)})();fi.prototype._isBufferList=function(e){return e instanceof fi||fi.isBufferList(e)};fi.isBufferList=function(e){return e!=null&&e[ABe]};fBe.exports=fi});var hBe=_((h$t,CF)=>{\"use strict\";var O9=qC().Duplex,CBt=Jh(),qv=pBe();function Fo(t){if(!(this instanceof Fo))return new Fo(t);if(typeof t==\"function\"){this._callback=t;let e=function(o){this._callback&&(this._callback(o),this._callback=null)}.bind(this);this.on(\"pipe\",function(o){o.on(\"error\",e)}),this.on(\"unpipe\",function(o){o.removeListener(\"error\",e)}),t=null}qv._init.call(this,t),O9.call(this)}CBt(Fo,O9);Object.assign(Fo.prototype,qv.prototype);Fo.prototype._new=function(e){return new Fo(e)};Fo.prototype._write=function(e,r,o){this._appendBuffer(e),typeof o==\"function\"&&o()};Fo.prototype._read=function(e){if(!this.length)return this.push(null);e=Math.min(e,this.length),this.push(this.slice(0,e)),this.consume(e)};Fo.prototype.end=function(e){O9.prototype.end.call(this,e),this._callback&&(this._callback(null,this.slice()),this._callback=null)};Fo.prototype._destroy=function(e,r){this._bufs.length=0,this.length=0,r(e)};Fo.prototype._isBufferList=function(e){return e instanceof Fo||e instanceof qv||Fo.isBufferList(e)};Fo.isBufferList=qv.isBufferList;CF.exports=Fo;CF.exports.BufferListStream=Fo;CF.exports.BufferList=qv});var _9=_(GC=>{var IBt=Buffer.alloc,wBt=\"0000000000000000000\",BBt=\"7777777777777777777\",gBe=48,dBe=Buffer.from(\"ustar\\0\",\"binary\"),vBt=Buffer.from(\"00\",\"binary\"),DBt=Buffer.from(\"ustar \",\"binary\"),PBt=Buffer.from(\" \\0\",\"binary\"),SBt=parseInt(\"7777\",8),jv=257,U9=263,xBt=function(t,e,r){return typeof t!=\"number\"?r:(t=~~t,t>=e?e:t>=0||(t+=e,t>=0)?t:0)},bBt=function(t){switch(t){case 0:return\"file\";case 1:return\"link\";case 2:return\"symlink\";case 3:return\"character-device\";case 4:return\"block-device\";case 5:return\"directory\";case 6:return\"fifo\";case 7:return\"contiguous-file\";case 72:return\"pax-header\";case 55:return\"pax-global-header\";case 27:return\"gnu-long-link-path\";case 28:case 30:return\"gnu-long-path\"}return null},kBt=function(t){switch(t){case\"file\":return 0;case\"link\":return 1;case\"symlink\":return 2;case\"character-device\":return 3;case\"block-device\":return 4;case\"directory\":return 5;case\"fifo\":return 6;case\"contiguous-file\":return 7;case\"pax-header\":return 72}return 0},mBe=function(t,e,r,o){for(;r<o;r++)if(t[r]===e)return r;return o},yBe=function(t){for(var e=256,r=0;r<148;r++)e+=t[r];for(var o=156;o<512;o++)e+=t[o];return e},t0=function(t,e){return t=t.toString(8),t.length>e?BBt.slice(0,e)+\" \":wBt.slice(0,e-t.length)+t+\" \"};function QBt(t){var e;if(t[0]===128)e=!0;else if(t[0]===255)e=!1;else return null;for(var r=[],o=t.length-1;o>0;o--){var a=t[o];e?r.push(a):r.push(255-a)}var n=0,u=r.length;for(o=0;o<u;o++)n+=r[o]*Math.pow(256,o);return e?n:-1*n}var r0=function(t,e,r){if(t=t.slice(e,e+r),e=0,t[e]&128)return QBt(t);for(;e<t.length&&t[e]===32;)e++;for(var o=xBt(mBe(t,32,e,t.length),t.length,t.length);e<o&&t[e]===0;)e++;return o===e?0:parseInt(t.slice(e,o).toString(),8)},jC=function(t,e,r,o){return t.slice(e,mBe(t,0,e,e+r)).toString(o)},M9=function(t){var e=Buffer.byteLength(t),r=Math.floor(Math.log(e)/Math.log(10))+1;return e+r>=Math.pow(10,r)&&r++,e+r+t};GC.decodeLongPath=function(t,e){return jC(t,0,t.length,e)};GC.encodePax=function(t){var e=\"\";t.name&&(e+=M9(\" path=\"+t.name+`\n`)),t.linkname&&(e+=M9(\" linkpath=\"+t.linkname+`\n`));var r=t.pax;if(r)for(var o in r)e+=M9(\" \"+o+\"=\"+r[o]+`\n`);return Buffer.from(e)};GC.decodePax=function(t){for(var e={};t.length;){for(var r=0;r<t.length&&t[r]!==32;)r++;var o=parseInt(t.slice(0,r).toString(),10);if(!o)return e;var a=t.slice(r+1,o-1).toString(),n=a.indexOf(\"=\");if(n===-1)return e;e[a.slice(0,n)]=a.slice(n+1),t=t.slice(o)}return e};GC.encode=function(t){var e=IBt(512),r=t.name,o=\"\";if(t.typeflag===5&&r[r.length-1]!==\"/\"&&(r+=\"/\"),Buffer.byteLength(r)!==r.length)return null;for(;Buffer.byteLength(r)>100;){var a=r.indexOf(\"/\");if(a===-1)return null;o+=o?\"/\"+r.slice(0,a):r.slice(0,a),r=r.slice(a+1)}return Buffer.byteLength(r)>100||Buffer.byteLength(o)>155||t.linkname&&Buffer.byteLength(t.linkname)>100?null:(e.write(r),e.write(t0(t.mode&SBt,6),100),e.write(t0(t.uid,6),108),e.write(t0(t.gid,6),116),e.write(t0(t.size,11),124),e.write(t0(t.mtime.getTime()/1e3|0,11),136),e[156]=gBe+kBt(t.type),t.linkname&&e.write(t.linkname,157),dBe.copy(e,jv),vBt.copy(e,U9),t.uname&&e.write(t.uname,265),t.gname&&e.write(t.gname,297),e.write(t0(t.devmajor||0,6),329),e.write(t0(t.devminor||0,6),337),o&&e.write(o,345),e.write(t0(yBe(e),6),148),e)};GC.decode=function(t,e,r){var o=t[156]===0?0:t[156]-gBe,a=jC(t,0,100,e),n=r0(t,100,8),u=r0(t,108,8),A=r0(t,116,8),p=r0(t,124,12),h=r0(t,136,12),E=bBt(o),w=t[157]===0?null:jC(t,157,100,e),D=jC(t,265,32),b=jC(t,297,32),C=r0(t,329,8),T=r0(t,337,8),N=yBe(t);if(N===8*32)return null;if(N!==r0(t,148,8))throw new Error(\"Invalid tar header. Maybe the tar is corrupted or it needs to be gunzipped?\");if(dBe.compare(t,jv,jv+6)===0)t[345]&&(a=jC(t,345,155,e)+\"/\"+a);else if(!(DBt.compare(t,jv,jv+6)===0&&PBt.compare(t,U9,U9+2)===0)){if(!r)throw new Error(\"Invalid tar header: unknown format.\")}return o===0&&a&&a[a.length-1]===\"/\"&&(o=5),{name:a,mode:n,uid:u,gid:A,size:p,mtime:new Date(1e3*h),type:E,linkname:w,uname:D,gname:b,devmajor:C,devminor:T}}});var DBe=_((d$t,vBe)=>{var CBe=ve(\"util\"),FBt=hBe(),Gv=_9(),IBe=qC().Writable,wBe=qC().PassThrough,BBe=function(){},EBe=function(t){return t&=511,t&&512-t},RBt=function(t,e){var r=new IF(t,e);return r.end(),r},TBt=function(t,e){return e.path&&(t.name=e.path),e.linkpath&&(t.linkname=e.linkpath),e.size&&(t.size=parseInt(e.size,10)),t.pax=e,t},IF=function(t,e){this._parent=t,this.offset=e,wBe.call(this,{autoDestroy:!1})};CBe.inherits(IF,wBe);IF.prototype.destroy=function(t){this._parent.destroy(t)};var sp=function(t){if(!(this instanceof sp))return new sp(t);IBe.call(this,t),t=t||{},this._offset=0,this._buffer=FBt(),this._missing=0,this._partial=!1,this._onparse=BBe,this._header=null,this._stream=null,this._overflow=null,this._cb=null,this._locked=!1,this._destroyed=!1,this._pax=null,this._paxGlobal=null,this._gnuLongPath=null,this._gnuLongLinkPath=null;var e=this,r=e._buffer,o=function(){e._continue()},a=function(D){if(e._locked=!1,D)return e.destroy(D);e._stream||o()},n=function(){e._stream=null;var D=EBe(e._header.size);D?e._parse(D,u):e._parse(512,w),e._locked||o()},u=function(){e._buffer.consume(EBe(e._header.size)),e._parse(512,w),o()},A=function(){var D=e._header.size;e._paxGlobal=Gv.decodePax(r.slice(0,D)),r.consume(D),n()},p=function(){var D=e._header.size;e._pax=Gv.decodePax(r.slice(0,D)),e._paxGlobal&&(e._pax=Object.assign({},e._paxGlobal,e._pax)),r.consume(D),n()},h=function(){var D=e._header.size;this._gnuLongPath=Gv.decodeLongPath(r.slice(0,D),t.filenameEncoding),r.consume(D),n()},E=function(){var D=e._header.size;this._gnuLongLinkPath=Gv.decodeLongPath(r.slice(0,D),t.filenameEncoding),r.consume(D),n()},w=function(){var D=e._offset,b;try{b=e._header=Gv.decode(r.slice(0,512),t.filenameEncoding,t.allowUnknownFormat)}catch(C){e.emit(\"error\",C)}if(r.consume(512),!b){e._parse(512,w),o();return}if(b.type===\"gnu-long-path\"){e._parse(b.size,h),o();return}if(b.type===\"gnu-long-link-path\"){e._parse(b.size,E),o();return}if(b.type===\"pax-global-header\"){e._parse(b.size,A),o();return}if(b.type===\"pax-header\"){e._parse(b.size,p),o();return}if(e._gnuLongPath&&(b.name=e._gnuLongPath,e._gnuLongPath=null),e._gnuLongLinkPath&&(b.linkname=e._gnuLongLinkPath,e._gnuLongLinkPath=null),e._pax&&(e._header=b=TBt(b,e._pax),e._pax=null),e._locked=!0,!b.size||b.type===\"directory\"){e._parse(512,w),e.emit(\"entry\",b,RBt(e,D),a);return}e._stream=new IF(e,D),e.emit(\"entry\",b,e._stream,a),e._parse(b.size,n),o()};this._onheader=w,this._parse(512,w)};CBe.inherits(sp,IBe);sp.prototype.destroy=function(t){this._destroyed||(this._destroyed=!0,t&&this.emit(\"error\",t),this.emit(\"close\"),this._stream&&this._stream.emit(\"close\"))};sp.prototype._parse=function(t,e){this._destroyed||(this._offset+=t,this._missing=t,e===this._onheader&&(this._partial=!1),this._onparse=e)};sp.prototype._continue=function(){if(!this._destroyed){var t=this._cb;this._cb=BBe,this._overflow?this._write(this._overflow,void 0,t):t()}};sp.prototype._write=function(t,e,r){if(!this._destroyed){var o=this._stream,a=this._buffer,n=this._missing;if(t.length&&(this._partial=!0),t.length<n)return this._missing-=t.length,this._overflow=null,o?o.write(t,r):(a.append(t),r());this._cb=r,this._missing=0;var u=null;t.length>n&&(u=t.slice(n),t=t.slice(0,n)),o?o.end(t):a.append(t),this._overflow=u,this._onparse()}};sp.prototype._final=function(t){if(this._partial)return this.destroy(new Error(\"Unexpected end of data\"));t()};vBe.exports=sp});var SBe=_((m$t,PBe)=>{PBe.exports=ve(\"fs\").constants||ve(\"constants\")});var FBe=_((y$t,QBe)=>{var WC=SBe(),xBe=E4(),BF=Jh(),LBt=Buffer.alloc,bBe=qC().Readable,YC=qC().Writable,NBt=ve(\"string_decoder\").StringDecoder,wF=_9(),OBt=parseInt(\"755\",8),MBt=parseInt(\"644\",8),kBe=LBt(1024),q9=function(){},H9=function(t,e){e&=511,e&&t.push(kBe.slice(0,512-e))};function UBt(t){switch(t&WC.S_IFMT){case WC.S_IFBLK:return\"block-device\";case WC.S_IFCHR:return\"character-device\";case WC.S_IFDIR:return\"directory\";case WC.S_IFIFO:return\"fifo\";case WC.S_IFLNK:return\"symlink\"}return\"file\"}var vF=function(t){YC.call(this),this.written=0,this._to=t,this._destroyed=!1};BF(vF,YC);vF.prototype._write=function(t,e,r){if(this.written+=t.length,this._to.push(t))return r();this._to._drain=r};vF.prototype.destroy=function(){this._destroyed||(this._destroyed=!0,this.emit(\"close\"))};var DF=function(){YC.call(this),this.linkname=\"\",this._decoder=new NBt(\"utf-8\"),this._destroyed=!1};BF(DF,YC);DF.prototype._write=function(t,e,r){this.linkname+=this._decoder.write(t),r()};DF.prototype.destroy=function(){this._destroyed||(this._destroyed=!0,this.emit(\"close\"))};var Wv=function(){YC.call(this),this._destroyed=!1};BF(Wv,YC);Wv.prototype._write=function(t,e,r){r(new Error(\"No body allowed for this entry\"))};Wv.prototype.destroy=function(){this._destroyed||(this._destroyed=!0,this.emit(\"close\"))};var wA=function(t){if(!(this instanceof wA))return new wA(t);bBe.call(this,t),this._drain=q9,this._finalized=!1,this._finalizing=!1,this._destroyed=!1,this._stream=null};BF(wA,bBe);wA.prototype.entry=function(t,e,r){if(this._stream)throw new Error(\"already piping an entry\");if(!(this._finalized||this._destroyed)){typeof e==\"function\"&&(r=e,e=null),r||(r=q9);var o=this;if((!t.size||t.type===\"symlink\")&&(t.size=0),t.type||(t.type=UBt(t.mode)),t.mode||(t.mode=t.type===\"directory\"?OBt:MBt),t.uid||(t.uid=0),t.gid||(t.gid=0),t.mtime||(t.mtime=new Date),typeof e==\"string\"&&(e=Buffer.from(e)),Buffer.isBuffer(e)){t.size=e.length,this._encode(t);var a=this.push(e);return H9(o,t.size),a?process.nextTick(r):this._drain=r,new Wv}if(t.type===\"symlink\"&&!t.linkname){var n=new DF;return xBe(n,function(A){if(A)return o.destroy(),r(A);t.linkname=n.linkname,o._encode(t),r()}),n}if(this._encode(t),t.type!==\"file\"&&t.type!==\"contiguous-file\")return process.nextTick(r),new Wv;var u=new vF(this);return this._stream=u,xBe(u,function(A){if(o._stream=null,A)return o.destroy(),r(A);if(u.written!==t.size)return o.destroy(),r(new Error(\"size mismatch\"));H9(o,t.size),o._finalizing&&o.finalize(),r()}),u}};wA.prototype.finalize=function(){if(this._stream){this._finalizing=!0;return}this._finalized||(this._finalized=!0,this.push(kBe),this.push(null))};wA.prototype.destroy=function(t){this._destroyed||(this._destroyed=!0,t&&this.emit(\"error\",t),this.emit(\"close\"),this._stream&&this._stream.destroy&&this._stream.destroy())};wA.prototype._encode=function(t){if(!t.pax){var e=wF.encode(t);if(e){this.push(e);return}}this._encodePax(t)};wA.prototype._encodePax=function(t){var e=wF.encodePax({name:t.name,linkname:t.linkname,pax:t.pax}),r={name:\"PaxHeader\",mode:t.mode,uid:t.uid,gid:t.gid,size:e.length,mtime:t.mtime,type:\"pax-header\",linkname:t.linkname&&\"PaxHeader\",uname:t.uname,gname:t.gname,devmajor:t.devmajor,devminor:t.devminor};this.push(wF.encode(r)),this.push(e),H9(this,e.length),r.size=t.size,r.type=t.type,this.push(wF.encode(r))};wA.prototype._read=function(t){var e=this._drain;this._drain=q9,e()};QBe.exports=wA});var RBe=_(j9=>{j9.extract=DBe();j9.pack=FBe()});var WBe=_((M$t,GBe)=>{\"use strict\";var Yv=class t{constructor(e,r,o){this.__specs=e||{},Object.keys(this.__specs).forEach(a=>{if(typeof this.__specs[a]==\"string\"){let n=this.__specs[a],u=this.__specs[n];if(u){let A=u.aliases||[];A.push(a,n),u.aliases=[...new Set(A)],this.__specs[a]=u}else throw new Error(`Alias refers to invalid key: ${n} -> ${a}`)}}),this.__opts=r||{},this.__providers=qBe(o.filter(a=>a!=null&&typeof a==\"object\")),this.__isFiggyPudding=!0}get(e){return z9(this,e,!0)}get[Symbol.toStringTag](){return\"FiggyPudding\"}forEach(e,r=this){for(let[o,a]of this.entries())e.call(r,a,o,this)}toJSON(){let e={};return this.forEach((r,o)=>{e[o]=r}),e}*entries(e){for(let o of Object.keys(this.__specs))yield[o,this.get(o)];let r=e||this.__opts.other;if(r){let o=new Set;for(let a of this.__providers){let n=a.entries?a.entries(r):evt(a);for(let[u,A]of n)r(u)&&!o.has(u)&&(o.add(u),yield[u,A])}}}*[Symbol.iterator](){for(let[e,r]of this.entries())yield[e,r]}*keys(){for(let[e]of this.entries())yield e}*values(){for(let[,e]of this.entries())yield e}concat(...e){return new Proxy(new t(this.__specs,this.__opts,qBe(this.__providers).concat(e)),jBe)}};try{let t=ve(\"util\");Yv.prototype[t.inspect.custom]=function(e,r){return this[Symbol.toStringTag]+\" \"+t.inspect(this.toJSON(),r)}}catch{}function ZBt(t){throw Object.assign(new Error(`invalid config key requested: ${t}`),{code:\"EBADKEY\"})}function z9(t,e,r){let o=t.__specs[e];if(r&&!o&&(!t.__opts.other||!t.__opts.other(e)))ZBt(e);else{o||(o={});let a;for(let n of t.__providers){if(a=HBe(e,n),a===void 0&&o.aliases&&o.aliases.length){for(let u of o.aliases)if(u!==e&&(a=HBe(u,n),a!==void 0))break}if(a!==void 0)break}return a===void 0&&o.default!==void 0?typeof o.default==\"function\"?o.default(t):o.default:a}}function HBe(t,e){let r;return e.__isFiggyPudding?r=z9(e,t,!1):typeof e.get==\"function\"?r=e.get(t):r=e[t],r}var jBe={has(t,e){return e in t.__specs&&z9(t,e,!1)!==void 0},ownKeys(t){return Object.keys(t.__specs)},get(t,e){return typeof e==\"symbol\"||e.slice(0,2)===\"__\"||e in Yv.prototype?t[e]:t.get(e)},set(t,e,r){if(typeof e==\"symbol\"||e.slice(0,2)===\"__\")return t[e]=r,!0;throw new Error(\"figgyPudding options cannot be modified. Use .concat() instead.\")},deleteProperty(){throw new Error(\"figgyPudding options cannot be deleted. Use .concat() and shadow them instead.\")}};GBe.exports=$Bt;function $Bt(t,e){function r(...o){return new Proxy(new Yv(t,e,o),jBe)}return r}function qBe(t){let e=[];return t.forEach(r=>e.unshift(r)),e}function evt(t){return Object.keys(t).map(e=>[e,t[e]])}});var VBe=_((U$t,DA)=>{\"use strict\";var Vv=ve(\"crypto\"),tvt=WBe(),rvt=ve(\"stream\").Transform,YBe=[\"sha256\",\"sha384\",\"sha512\"],nvt=/^[a-z0-9+/]+(?:=?=?)$/i,ivt=/^([^-]+)-([^?]+)([?\\S*]*)$/,svt=/^([^-]+)-([A-Za-z0-9+/=]{44,88})(\\?[\\x21-\\x7E]*)*$/,ovt=/^[\\x21-\\x7E]+$/,na=tvt({algorithms:{default:[\"sha512\"]},error:{default:!1},integrity:{},options:{default:[]},pickAlgorithm:{default:()=>hvt},Promise:{default:()=>Promise},sep:{default:\" \"},single:{default:!1},size:{},strict:{default:!1}}),n0=class{get isHash(){return!0}constructor(e,r){r=na(r);let o=!!r.strict;this.source=e.trim();let a=this.source.match(o?svt:ivt);if(!a||o&&!YBe.some(u=>u===a[1]))return;this.algorithm=a[1],this.digest=a[2];let n=a[3];this.options=n?n.slice(1).split(\"?\"):[]}hexDigest(){return this.digest&&Buffer.from(this.digest,\"base64\").toString(\"hex\")}toJSON(){return this.toString()}toString(e){if(e=na(e),e.strict&&!(YBe.some(o=>o===this.algorithm)&&this.digest.match(nvt)&&(this.options||[]).every(o=>o.match(ovt))))return\"\";let r=this.options&&this.options.length?`?${this.options.join(\"?\")}`:\"\";return`${this.algorithm}-${this.digest}${r}`}},Cd=class{get isIntegrity(){return!0}toJSON(){return this.toString()}toString(e){e=na(e);let r=e.sep||\" \";return e.strict&&(r=r.replace(/\\S+/g,\" \")),Object.keys(this).map(o=>this[o].map(a=>n0.prototype.toString.call(a,e)).filter(a=>a.length).join(r)).filter(o=>o.length).join(r)}concat(e,r){r=na(r);let o=typeof e==\"string\"?e:Kv(e,r);return vA(`${this.toString(r)} ${o}`,r)}hexDigest(){return vA(this,{single:!0}).hexDigest()}match(e,r){r=na(r);let o=vA(e,r),a=o.pickAlgorithm(r);return this[a]&&o[a]&&this[a].find(n=>o[a].find(u=>n.digest===u.digest))||!1}pickAlgorithm(e){e=na(e);let r=e.pickAlgorithm,o=Object.keys(this);if(!o.length)throw new Error(`No algorithms available for ${JSON.stringify(this.toString())}`);return o.reduce((a,n)=>r(a,n)||a)}};DA.exports.parse=vA;function vA(t,e){if(e=na(e),typeof t==\"string\")return J9(t,e);if(t.algorithm&&t.digest){let r=new Cd;return r[t.algorithm]=[t],J9(Kv(r,e),e)}else return J9(Kv(t,e),e)}function J9(t,e){return e.single?new n0(t,e):t.trim().split(/\\s+/).reduce((r,o)=>{let a=new n0(o,e);if(a.algorithm&&a.digest){let n=a.algorithm;r[n]||(r[n]=[]),r[n].push(a)}return r},new Cd)}DA.exports.stringify=Kv;function Kv(t,e){return e=na(e),t.algorithm&&t.digest?n0.prototype.toString.call(t,e):typeof t==\"string\"?Kv(vA(t,e),e):Cd.prototype.toString.call(t,e)}DA.exports.fromHex=avt;function avt(t,e,r){r=na(r);let o=r.options&&r.options.length?`?${r.options.join(\"?\")}`:\"\";return vA(`${e}-${Buffer.from(t,\"hex\").toString(\"base64\")}${o}`,r)}DA.exports.fromData=lvt;function lvt(t,e){e=na(e);let r=e.algorithms,o=e.options&&e.options.length?`?${e.options.join(\"?\")}`:\"\";return r.reduce((a,n)=>{let u=Vv.createHash(n).update(t).digest(\"base64\"),A=new n0(`${n}-${u}${o}`,e);if(A.algorithm&&A.digest){let p=A.algorithm;a[p]||(a[p]=[]),a[p].push(A)}return a},new Cd)}DA.exports.fromStream=cvt;function cvt(t,e){e=na(e);let r=e.Promise||Promise,o=X9(e);return new r((a,n)=>{t.pipe(o),t.on(\"error\",n),o.on(\"error\",n);let u;o.on(\"integrity\",A=>{u=A}),o.on(\"end\",()=>a(u)),o.on(\"data\",()=>{})})}DA.exports.checkData=uvt;function uvt(t,e,r){if(r=na(r),e=vA(e,r),!Object.keys(e).length){if(r.error)throw Object.assign(new Error(\"No valid integrity hashes to check against\"),{code:\"EINTEGRITY\"});return!1}let o=e.pickAlgorithm(r),a=Vv.createHash(o).update(t).digest(\"base64\"),n=vA({algorithm:o,digest:a}),u=n.match(e,r);if(u||!r.error)return u;if(typeof r.size==\"number\"&&t.length!==r.size){let A=new Error(`data size mismatch when checking ${e}.\n  Wanted: ${r.size}\n  Found: ${t.length}`);throw A.code=\"EBADSIZE\",A.found=t.length,A.expected=r.size,A.sri=e,A}else{let A=new Error(`Integrity checksum failed when using ${o}: Wanted ${e}, but got ${n}. (${t.length} bytes)`);throw A.code=\"EINTEGRITY\",A.found=n,A.expected=e,A.algorithm=o,A.sri=e,A}}DA.exports.checkStream=Avt;function Avt(t,e,r){r=na(r);let o=r.Promise||Promise,a=X9(r.concat({integrity:e}));return new o((n,u)=>{t.pipe(a),t.on(\"error\",u),a.on(\"error\",u);let A;a.on(\"verified\",p=>{A=p}),a.on(\"end\",()=>n(A)),a.on(\"data\",()=>{})})}DA.exports.integrityStream=X9;function X9(t){t=na(t);let e=t.integrity&&vA(t.integrity,t),r=e&&Object.keys(e).length,o=r&&e.pickAlgorithm(t),a=r&&e[o],n=Array.from(new Set(t.algorithms.concat(o?[o]:[]))),u=n.map(Vv.createHash),A=0,p=new rvt({transform(h,E,w){A+=h.length,u.forEach(D=>D.update(h,E)),w(null,h,E)}}).on(\"end\",()=>{let h=t.options&&t.options.length?`?${t.options.join(\"?\")}`:\"\",E=vA(u.map((D,b)=>`${n[b]}-${D.digest(\"base64\")}${h}`).join(\" \"),t),w=r&&E.match(e,t);if(typeof t.size==\"number\"&&A!==t.size){let D=new Error(`stream size mismatch when checking ${e}.\n  Wanted: ${t.size}\n  Found: ${A}`);D.code=\"EBADSIZE\",D.found=A,D.expected=t.size,D.sri=e,p.emit(\"error\",D)}else if(t.integrity&&!w){let D=new Error(`${e} integrity checksum failed when using ${o}: wanted ${a} but got ${E}. (${A} bytes)`);D.code=\"EINTEGRITY\",D.found=E,D.expected=a,D.algorithm=o,D.sri=e,p.emit(\"error\",D)}else p.emit(\"size\",A),p.emit(\"integrity\",E),w&&p.emit(\"verified\",w)});return p}DA.exports.create=fvt;function fvt(t){t=na(t);let e=t.algorithms,r=t.options.length?`?${t.options.join(\"?\")}`:\"\",o=e.map(Vv.createHash);return{update:function(a,n){return o.forEach(u=>u.update(a,n)),this},digest:function(a){return e.reduce((u,A)=>{let p=o.shift().digest(\"base64\"),h=new n0(`${A}-${p}${r}`,t);if(h.algorithm&&h.digest){let E=h.algorithm;u[E]||(u[E]=[]),u[E].push(h)}return u},new Cd)}}}var pvt=new Set(Vv.getHashes()),KBe=[\"md5\",\"whirlpool\",\"sha1\",\"sha224\",\"sha256\",\"sha384\",\"sha512\",\"sha3\",\"sha3-256\",\"sha3-384\",\"sha3-512\",\"sha3_256\",\"sha3_384\",\"sha3_512\"].filter(t=>pvt.has(t));function hvt(t,e){return KBe.indexOf(t.toLowerCase())>=KBe.indexOf(e.toLowerCase())?t:e}});var Bve=_((qnr,wve)=>{var hDt=WN();function gDt(t){return hDt(t)?void 0:t}wve.exports=gDt});var Dve=_((jnr,vve)=>{var dDt=Cb(),mDt=hH(),yDt=yH(),EDt=Wg(),CDt=Eg(),IDt=Bve(),wDt=l8(),BDt=pH(),vDt=1,DDt=2,PDt=4,SDt=wDt(function(t,e){var r={};if(t==null)return r;var o=!1;e=dDt(e,function(n){return n=EDt(n,t),o||(o=n.length>1),n}),CDt(t,BDt(t),r),o&&(r=mDt(r,vDt|DDt|PDt,IDt));for(var a=e.length;a--;)yDt(r,e[a]);return r});vve.exports=SDt});Pt();Ke();Pt();var kve=ve(\"child_process\"),Qve=et(sg());Gt();var oE=new Map([]);var S2={};Kt(S2,{BaseCommand:()=>ut,WorkspaceRequiredError:()=>or,getCli:()=>qhe,getDynamicLibs:()=>Hhe,getPluginConfiguration:()=>lE,openWorkspace:()=>aE,pluginCommands:()=>oE,runExit:()=>Nk});Gt();var ut=class extends st{constructor(){super(...arguments);this.cwd=de.String(\"--cwd\",{hidden:!0})}validateAndExecute(){if(typeof this.cwd<\"u\")throw new ot(\"The --cwd option is ambiguous when used anywhere else than the very first parameter provided in the command line, before even the command path\");return super.validateAndExecute()}};Ke();Pt();Gt();var or=class extends ot{constructor(e,r){let o=K.relative(e,r),a=K.join(e,_t.fileName);super(`This command can only be run from within a workspace of your project (${o} isn't a workspace of ${a}).`)}};Ke();Pt();sA();Ol();J1();Gt();var SAt=et(ni());il();var Hhe=()=>new Map([[\"@yarnpkg/cli\",S2],[\"@yarnpkg/core\",P2],[\"@yarnpkg/fslib\",Aw],[\"@yarnpkg/libzip\",V1],[\"@yarnpkg/parsers\",Ew],[\"@yarnpkg/shell\",e2],[\"clipanion\",Qw],[\"semver\",SAt],[\"typanion\",Yo]]);Ke();async function aE(t,e){let{project:r,workspace:o}=await Qt.find(t,e);if(!o)throw new or(r.cwd,e);return o}Ke();Pt();sA();Ol();J1();Gt();var NDt=et(ni());il();var MH={};Kt(MH,{AddCommand:()=>fE,BinCommand:()=>pE,CacheCleanCommand:()=>hE,ClipanionCommand:()=>CE,ConfigCommand:()=>yE,ConfigGetCommand:()=>gE,ConfigSetCommand:()=>dE,ConfigUnsetCommand:()=>mE,DedupeCommand:()=>EE,EntryCommand:()=>wE,ExecCommand:()=>vE,ExplainCommand:()=>SE,ExplainPeerRequirementsCommand:()=>DE,HelpCommand:()=>IE,InfoCommand:()=>xE,LinkCommand:()=>kE,NodeCommand:()=>QE,PluginCheckCommand:()=>FE,PluginImportCommand:()=>LE,PluginImportSourcesCommand:()=>NE,PluginListCommand:()=>RE,PluginRemoveCommand:()=>OE,PluginRuntimeCommand:()=>ME,RebuildCommand:()=>UE,RemoveCommand:()=>_E,RunCommand:()=>qE,RunIndexCommand:()=>HE,SetResolutionCommand:()=>jE,SetVersionCommand:()=>PE,SetVersionSourcesCommand:()=>TE,UnlinkCommand:()=>GE,UpCommand:()=>WE,VersionCommand:()=>BE,WhyCommand:()=>YE,WorkspaceCommand:()=>XE,WorkspacesListCommand:()=>JE,YarnCommand:()=>bE,dedupeUtils:()=>Yk,default:()=>Igt,suggestUtils:()=>nu});var Eme=et(sg());Ke();Ke();Ke();Gt();var bge=et(Q2());il();var nu={};Kt(nu,{Modifier:()=>lH,Strategy:()=>jk,Target:()=>F2,WorkspaceModifier:()=>vge,applyModifier:()=>Kft,extractDescriptorFromPath:()=>cH,extractRangeModifier:()=>Dge,fetchDescriptorFrom:()=>uH,findProjectDescriptors:()=>xge,getModifier:()=>R2,getSuggestedDescriptors:()=>T2,makeWorkspaceDescriptor:()=>Sge,toWorkspaceModifier:()=>Pge});Ke();Ke();Pt();var aH=et(ni()),Wft=\"workspace:\",F2=(o=>(o.REGULAR=\"dependencies\",o.DEVELOPMENT=\"devDependencies\",o.PEER=\"peerDependencies\",o))(F2||{}),lH=(o=>(o.CARET=\"^\",o.TILDE=\"~\",o.EXACT=\"\",o))(lH||{}),vge=(o=>(o.CARET=\"^\",o.TILDE=\"~\",o.EXACT=\"*\",o))(vge||{}),jk=(n=>(n.KEEP=\"keep\",n.REUSE=\"reuse\",n.PROJECT=\"project\",n.LATEST=\"latest\",n.CACHE=\"cache\",n))(jk||{});function R2(t,e){return t.exact?\"\":t.caret?\"^\":t.tilde?\"~\":e.configuration.get(\"defaultSemverRangePrefix\")}var Yft=/^([\\^~]?)[0-9]+(?:\\.[0-9]+){0,2}(?:-\\S+)?$/;function Dge(t,{project:e}){let r=t.match(Yft);return r?r[1]:e.configuration.get(\"defaultSemverRangePrefix\")}function Kft(t,e){let{protocol:r,source:o,params:a,selector:n}=G.parseRange(t.range);return aH.default.valid(n)&&(n=`${e}${t.range}`),G.makeDescriptor(t,G.makeRange({protocol:r,source:o,params:a,selector:n}))}function Pge(t){switch(t){case\"^\":return\"^\";case\"~\":return\"~\";case\"\":return\"*\";default:throw new Error(`Assertion failed: Unknown modifier: \"${t}\"`)}}function Sge(t,e){return G.makeDescriptor(t.anchoredDescriptor,`${Wft}${Pge(e)}`)}async function xge(t,{project:e,target:r}){let o=new Map,a=n=>{let u=o.get(n.descriptorHash);return u||o.set(n.descriptorHash,u={descriptor:n,locators:[]}),u};for(let n of e.workspaces)if(r===\"peerDependencies\"){let u=n.manifest.peerDependencies.get(t.identHash);u!==void 0&&a(u).locators.push(n.anchoredLocator)}else{let u=n.manifest.dependencies.get(t.identHash),A=n.manifest.devDependencies.get(t.identHash);r===\"devDependencies\"?A!==void 0?a(A).locators.push(n.anchoredLocator):u!==void 0&&a(u).locators.push(n.anchoredLocator):u!==void 0?a(u).locators.push(n.anchoredLocator):A!==void 0&&a(A).locators.push(n.anchoredLocator)}return o}async function cH(t,{cwd:e,workspace:r}){return await Vft(async o=>{K.isAbsolute(t)||(t=K.relative(r.cwd,K.resolve(e,t)),t.match(/^\\.{0,2}\\//)||(t=`./${t}`));let{project:a}=r,n=await uH(G.makeIdent(null,\"archive\"),t,{project:r.project,cache:o,workspace:r});if(!n)throw new Error(\"Assertion failed: The descriptor should have been found\");let u=new Ri,A=a.configuration.makeResolver(),p=a.configuration.makeFetcher(),h={checksums:a.storedChecksums,project:a,cache:o,fetcher:p,report:u,resolver:A},E=A.bindDescriptor(n,r.anchoredLocator,h),w=G.convertDescriptorToLocator(E),D=await p.fetch(w,h),b=await _t.find(D.prefixPath,{baseFs:D.packageFs});if(!b.name)throw new Error(\"Target path doesn't have a name\");return G.makeDescriptor(b.name,t)})}async function T2(t,{project:e,workspace:r,cache:o,target:a,fixed:n,modifier:u,strategies:A,maxResults:p=1/0}){if(!(p>=0))throw new Error(`Invalid maxResults (${p})`);let[h,E]=t.range!==\"unknown\"?n||Ur.validRange(t.range)||!t.range.match(/^[a-z0-9._-]+$/i)?[t.range,\"latest\"]:[\"unknown\",t.range]:[\"unknown\",\"latest\"];if(h!==\"unknown\")return{suggestions:[{descriptor:t,name:`Use ${G.prettyDescriptor(e.configuration,t)}`,reason:\"(unambiguous explicit request)\"}],rejections:[]};let w=typeof r<\"u\"&&r!==null&&r.manifest[a].get(t.identHash)||null,D=[],b=[],C=async T=>{try{await T()}catch(N){b.push(N)}};for(let T of A){if(D.length>=p)break;switch(T){case\"keep\":await C(async()=>{w&&D.push({descriptor:w,name:`Keep ${G.prettyDescriptor(e.configuration,w)}`,reason:\"(no changes)\"})});break;case\"reuse\":await C(async()=>{for(let{descriptor:N,locators:U}of(await xge(t,{project:e,target:a})).values()){if(U.length===1&&U[0].locatorHash===r.anchoredLocator.locatorHash&&A.includes(\"keep\"))continue;let z=`(originally used by ${G.prettyLocator(e.configuration,U[0])}`;z+=U.length>1?` and ${U.length-1} other${U.length>2?\"s\":\"\"})`:\")\",D.push({descriptor:N,name:`Reuse ${G.prettyDescriptor(e.configuration,N)}`,reason:z})}});break;case\"cache\":await C(async()=>{for(let N of e.storedDescriptors.values())N.identHash===t.identHash&&D.push({descriptor:N,name:`Reuse ${G.prettyDescriptor(e.configuration,N)}`,reason:\"(already used somewhere in the lockfile)\"})});break;case\"project\":await C(async()=>{if(r.manifest.name!==null&&t.identHash===r.manifest.name.identHash)return;let N=e.tryWorkspaceByIdent(t);if(N===null)return;let U=Sge(N,u);D.push({descriptor:U,name:`Attach ${G.prettyDescriptor(e.configuration,U)}`,reason:`(local workspace at ${pe.pretty(e.configuration,N.relativeCwd,pe.Type.PATH)})`})});break;case\"latest\":{let N=e.configuration.get(\"enableNetwork\"),U=e.configuration.get(\"enableOfflineMode\");await C(async()=>{if(a===\"peerDependencies\")D.push({descriptor:G.makeDescriptor(t,\"*\"),name:\"Use *\",reason:\"(catch-all peer dependency pattern)\"});else if(!N&&!U)D.push({descriptor:null,name:\"Resolve from latest\",reason:pe.pretty(e.configuration,\"(unavailable because enableNetwork is toggled off)\",\"grey\")});else{let z=await uH(t,E,{project:e,cache:o,workspace:r,modifier:u});z&&D.push({descriptor:z,name:`Use ${G.prettyDescriptor(e.configuration,z)}`,reason:`(resolved from ${U?\"the cache\":\"latest\"})`})}})}break}}return{suggestions:D.slice(0,p),rejections:b.slice(0,p)}}async function uH(t,e,{project:r,cache:o,workspace:a,preserveModifier:n=!0,modifier:u}){let A=r.configuration.normalizeDependency(G.makeDescriptor(t,e)),p=new Ri,h=r.configuration.makeFetcher(),E=r.configuration.makeResolver(),w={project:r,fetcher:h,cache:o,checksums:r.storedChecksums,report:p,cacheOptions:{skipIntegrityCheck:!0}},D={...w,resolver:E,fetchOptions:w},b=E.bindDescriptor(A,a.anchoredLocator,D),C=await E.getCandidates(b,{},D);if(C.length===0)return null;let T=C[0],{protocol:N,source:U,params:z,selector:te}=G.parseRange(G.convertToManifestRange(T.reference));if(N===r.configuration.get(\"defaultProtocol\")&&(N=null),aH.default.valid(te)){let le=te;if(typeof u<\"u\")te=u+te;else if(n!==!1){let Ie=typeof n==\"string\"?n:A.range;te=Dge(Ie,{project:r})+te}let ce=G.makeDescriptor(T,G.makeRange({protocol:N,source:U,params:z,selector:te}));(await E.getCandidates(r.configuration.normalizeDependency(ce),{},D)).length!==1&&(te=le)}return G.makeDescriptor(T,G.makeRange({protocol:N,source:U,params:z,selector:te}))}async function Vft(t){return await ae.mktempPromise(async e=>{let r=Je.create(e);return r.useWithSource(e,{enableMirror:!1,compressionLevel:0},e,{overwrite:!0}),await t(new Wr(e,{configuration:r,check:!1,immutable:!1}))})}var fE=class extends ut{constructor(){super(...arguments);this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.fixed=de.Boolean(\"-F,--fixed\",!1,{description:\"Store dependency tags as-is instead of resolving them\"});this.exact=de.Boolean(\"-E,--exact\",!1,{description:\"Don't use any semver modifier on the resolved range\"});this.tilde=de.Boolean(\"-T,--tilde\",!1,{description:\"Use the `~` semver modifier on the resolved range\"});this.caret=de.Boolean(\"-C,--caret\",!1,{description:\"Use the `^` semver modifier on the resolved range\"});this.dev=de.Boolean(\"-D,--dev\",!1,{description:\"Add a package as a dev dependency\"});this.peer=de.Boolean(\"-P,--peer\",!1,{description:\"Add a package as a peer dependency\"});this.optional=de.Boolean(\"-O,--optional\",!1,{description:\"Add / upgrade a package to an optional regular / peer dependency\"});this.preferDev=de.Boolean(\"--prefer-dev\",!1,{description:\"Add / upgrade a package to a dev dependency\"});this.interactive=de.Boolean(\"-i,--interactive\",{description:\"Reuse the specified package from other workspaces in the project\"});this.cached=de.Boolean(\"--cached\",!1,{description:\"Reuse the highest version already used somewhere within the project\"});this.mode=de.String(\"--mode\",{description:\"Change what artifacts installs generate\",validator:js(yl)});this.silent=de.Boolean(\"--silent\",{hidden:!0});this.packages=de.Rest()}static{this.paths=[[\"add\"]]}static{this.usage=st.Usage({description:\"add dependencies to the project\",details:\"\\n      This command adds a package to the package.json for the nearest workspace.\\n\\n      - If it didn't exist before, the package will by default be added to the regular `dependencies` field, but this behavior can be overriden thanks to the `-D,--dev` flag (which will cause the dependency to be added to the `devDependencies` field instead) and the `-P,--peer` flag (which will do the same but for `peerDependencies`).\\n\\n      - If the package was already listed in your dependencies, it will by default be upgraded whether it's part of your `dependencies` or `devDependencies` (it won't ever update `peerDependencies`, though).\\n\\n      - If set, the `--prefer-dev` flag will operate as a more flexible `-D,--dev` in that it will add the package to your `devDependencies` if it isn't already listed in either `dependencies` or `devDependencies`, but it will also happily upgrade your `dependencies` if that's what you already use (whereas `-D,--dev` would throw an exception).\\n\\n      - If set, the `-O,--optional` flag will add the package to the `optionalDependencies` field and, in combination with the `-P,--peer` flag, it will add the package as an optional peer dependency. If the package was already listed in your `dependencies`, it will be upgraded to `optionalDependencies`. If the package was already listed in your `peerDependencies`, in combination with the `-P,--peer` flag, it will be upgraded to an optional peer dependency: `\\\"peerDependenciesMeta\\\": { \\\"<package>\\\": { \\\"optional\\\": true } }`\\n\\n      - If the added package doesn't specify a range at all its `latest` tag will be resolved and the returned version will be used to generate a new semver range (using the `^` modifier by default unless otherwise configured via the `defaultSemverRangePrefix` configuration, or the `~` modifier if `-T,--tilde` is specified, or no modifier at all if `-E,--exact` is specified). Two exceptions to this rule: the first one is that if the package is a workspace then its local version will be used, and the second one is that if you use `-P,--peer` the default range will be `*` and won't be resolved at all.\\n\\n      - If the added package specifies a range (such as `^1.0.0`, `latest`, or `rc`), Yarn will add this range as-is in the resulting package.json entry (in particular, tags such as `rc` will be encoded as-is rather than being converted into a semver range).\\n\\n      If the `--cached` option is used, Yarn will preferably reuse the highest version already used somewhere within the project, even if through a transitive dependency.\\n\\n      If the `-i,--interactive` option is used (or if the `preferInteractive` settings is toggled on) the command will first try to check whether other workspaces in the project use the specified package and, if so, will offer to reuse them.\\n\\n      If the `--mode=<mode>` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\\n\\n      - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\\n\\n      - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\\n\\n      For a compilation of all the supported protocols, please consult the dedicated page from our website: https://yarnpkg.com/protocols.\\n    \",examples:[[\"Add a regular package to the current workspace\",\"$0 add lodash\"],[\"Add a specific version for a package to the current workspace\",\"$0 add lodash@1.2.3\"],[\"Add a package from a GitHub repository (the master branch) to the current workspace using a URL\",\"$0 add lodash@https://github.com/lodash/lodash\"],[\"Add a package from a GitHub repository (the master branch) to the current workspace using the GitHub protocol\",\"$0 add lodash@github:lodash/lodash\"],[\"Add a package from a GitHub repository (the master branch) to the current workspace using the GitHub protocol (shorthand)\",\"$0 add lodash@lodash/lodash\"],[\"Add a package from a specific branch of a GitHub repository to the current workspace using the GitHub protocol (shorthand)\",\"$0 add lodash-es@lodash/lodash#es\"],[\"Add a local package (gzipped tarball format) to the current workspace\",\"$0 add local-package-name@file:../path/to/local-package-name-v0.1.2.tgz\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Wr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=this.fixed,A=r.isInteractive({interactive:this.interactive,stdout:this.context.stdout}),p=A||r.get(\"preferReuse\"),h=R2(this,o),E=[p?\"reuse\":void 0,\"project\",this.cached?\"cache\":void 0,\"latest\"].filter(U=>typeof U<\"u\"),w=A?1/0:1,D=await Promise.all(this.packages.map(async U=>{let z=U.match(/^\\.{0,2}\\//)?await cH(U,{cwd:this.context.cwd,workspace:a}):G.tryParseDescriptor(U),te=U.match(/^(https?:|git@github)/);if(te)throw new ot(`It seems you are trying to add a package using a ${pe.pretty(r,`${te[0]}...`,pe.Type.RANGE)} url; we now require package names to be explicitly specified.\nTry running the command again with the package name prefixed: ${pe.pretty(r,\"yarn add\",pe.Type.CODE)} ${pe.pretty(r,G.makeDescriptor(G.makeIdent(null,\"my-package\"),`${te[0]}...`),pe.Type.DESCRIPTOR)}`);if(!z)throw new ot(`The ${pe.pretty(r,U,pe.Type.CODE)} string didn't match the required format (package-name@range). Did you perhaps forget to explicitly reference the package name?`);let le=zft(a,z,{dev:this.dev,peer:this.peer,preferDev:this.preferDev,optional:this.optional});return await Promise.all(le.map(async ue=>{let Ie=await T2(z,{project:o,workspace:a,cache:n,fixed:u,target:ue,modifier:h,strategies:E,maxResults:w});return{request:z,suggestedDescriptors:Ie,target:ue}}))})).then(U=>U.flat()),b=await pA.start({configuration:r,stdout:this.context.stdout,suggestInstall:!1},async U=>{for(let{request:z,suggestedDescriptors:{suggestions:te,rejections:le}}of D)if(te.filter(ue=>ue.descriptor!==null).length===0){let[ue]=le;if(typeof ue>\"u\")throw new Error(\"Assertion failed: Expected an error to have been set\");o.configuration.get(\"enableNetwork\")?U.reportError(27,`${G.prettyDescriptor(r,z)} can't be resolved to a satisfying range`):U.reportError(27,`${G.prettyDescriptor(r,z)} can't be resolved to a satisfying range (note: network resolution has been disabled)`),U.reportSeparator(),U.reportExceptionOnce(ue)}});if(b.hasErrors())return b.exitCode();let C=!1,T=[],N=[];for(let{suggestedDescriptors:{suggestions:U},target:z}of D){let te,le=U.filter(he=>he.descriptor!==null),ce=le[0].descriptor,ue=le.every(he=>G.areDescriptorsEqual(he.descriptor,ce));le.length===1||ue?te=ce:(C=!0,{answer:te}=await(0,bge.prompt)({type:\"select\",name:\"answer\",message:\"Which range do you want to use?\",choices:U.map(({descriptor:he,name:De,reason:Ee})=>he?{name:De,hint:Ee,descriptor:he}:{name:De,hint:Ee,disabled:!0}),onCancel:()=>process.exit(130),result(he){return this.find(he,\"descriptor\")},stdin:this.context.stdin,stdout:this.context.stdout}));let Ie=a.manifest[z].get(te.identHash);(typeof Ie>\"u\"||Ie.descriptorHash!==te.descriptorHash)&&(a.manifest[z].set(te.identHash,te),this.optional&&(z===\"dependencies\"?a.manifest.ensureDependencyMeta({...te,range:\"unknown\"}).optional=!0:z===\"peerDependencies\"&&(a.manifest.ensurePeerDependencyMeta({...te,range:\"unknown\"}).optional=!0)),typeof Ie>\"u\"?T.push([a,z,te,E]):N.push([a,z,Ie,te]))}return await r.triggerMultipleHooks(U=>U.afterWorkspaceDependencyAddition,T),await r.triggerMultipleHooks(U=>U.afterWorkspaceDependencyReplacement,N),C&&this.context.stdout.write(`\n`),await o.installWithNewReport({json:this.json,stdout:this.context.stdout,quiet:this.context.quiet},{cache:n,mode:this.mode})}};function zft(t,e,{dev:r,peer:o,preferDev:a,optional:n}){let u=t.manifest.dependencies.has(e.identHash),A=t.manifest.devDependencies.has(e.identHash),p=t.manifest.peerDependencies.has(e.identHash);if((r||o)&&u)throw new ot(`Package \"${G.prettyIdent(t.project.configuration,e)}\" is already listed as a regular dependency - remove the -D,-P flags or remove it from your dependencies first`);if(!r&&!o&&p)throw new ot(`Package \"${G.prettyIdent(t.project.configuration,e)}\" is already listed as a peer dependency - use either of -D or -P, or remove it from your peer dependencies first`);if(n&&A)throw new ot(`Package \"${G.prettyIdent(t.project.configuration,e)}\" is already listed as a dev dependency - remove the -O flag or remove it from your dev dependencies first`);if(n&&!o&&p)throw new ot(`Package \"${G.prettyIdent(t.project.configuration,e)}\" is already listed as a peer dependency - remove the -O flag or add the -P flag or remove it from your peer dependencies first`);if((r||a)&&n)throw new ot(`Package \"${G.prettyIdent(t.project.configuration,e)}\" cannot simultaneously be a dev dependency and an optional dependency`);let h=[];return o&&h.push(\"peerDependencies\"),(r||a)&&h.push(\"devDependencies\"),n&&h.push(\"dependencies\"),h.length>0?h:A?[\"devDependencies\"]:p?[\"peerDependencies\"]:[\"dependencies\"]}Ke();Ke();Gt();var pE=class extends ut{constructor(){super(...arguments);this.verbose=de.Boolean(\"-v,--verbose\",!1,{description:\"Print both the binary name and the locator of the package that provides the binary\"});this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.name=de.String({required:!1})}static{this.paths=[[\"bin\"]]}static{this.usage=st.Usage({description:\"get the path to a binary script\",details:`\n      When used without arguments, this command will print the list of all the binaries available in the current workspace. Adding the \\`-v,--verbose\\` flag will cause the output to contain both the binary name and the locator of the package that provides the binary.\n\n      When an argument is specified, this command will just print the path to the binary on the standard output and exit. Note that the reported path may be stored within a zip archive.\n    `,examples:[[\"List all the available binaries\",\"$0 bin\"],[\"Print the path to a specific binary\",\"$0 bin eslint\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,locator:a}=await Qt.find(r,this.context.cwd);if(await o.restoreInstallState(),this.name){let A=(await hn.getPackageAccessibleBinaries(a,{project:o})).get(this.name);if(!A)throw new ot(`Couldn't find a binary named \"${this.name}\" for package \"${G.prettyLocator(r,a)}\"`);let[,p]=A;return this.context.stdout.write(`${p}\n`),0}return(await Lt.start({configuration:r,json:this.json,stdout:this.context.stdout},async u=>{let A=await hn.getPackageAccessibleBinaries(a,{project:o}),h=Array.from(A.keys()).reduce((E,w)=>Math.max(E,w.length),0);for(let[E,[w,D]]of A)u.reportJson({name:E,source:G.stringifyIdent(w),path:D});if(this.verbose)for(let[E,[w]]of A)u.reportInfo(null,`${E.padEnd(h,\" \")}   ${G.prettyLocator(r,w)}`);else for(let E of A.keys())u.reportInfo(null,E)})).exitCode()}};Ke();Pt();Gt();var hE=class extends ut{constructor(){super(...arguments);this.mirror=de.Boolean(\"--mirror\",!1,{description:\"Remove the global cache files instead of the local cache files\"});this.all=de.Boolean(\"--all\",!1,{description:\"Remove both the global cache files and the local cache files of the current project\"})}static{this.paths=[[\"cache\",\"clean\"],[\"cache\",\"clear\"]]}static{this.usage=st.Usage({description:\"remove the shared cache files\",details:`\n      This command will remove all the files from the cache.\n    `,examples:[[\"Remove all the local archives\",\"$0 cache clean\"],[\"Remove all the archives stored in the ~/.yarn directory\",\"$0 cache clean --mirror\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=await Wr.find(r);return(await Lt.start({configuration:r,stdout:this.context.stdout},async()=>{let n=(this.all||this.mirror)&&o.mirrorCwd!==null,u=!this.mirror;n&&(await ae.removePromise(o.mirrorCwd),await r.triggerHook(A=>A.cleanGlobalArtifacts,r)),u&&await ae.removePromise(o.cwd)})).exitCode()}};Ke();Gt();var Qge=et(L2()),AH=ve(\"util\"),gE=class extends ut{constructor(){super(...arguments);this.why=de.Boolean(\"--why\",!1,{description:\"Print the explanation for why a setting has its value\"});this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.unsafe=de.Boolean(\"--no-redacted\",!1,{description:\"Don't redact secrets (such as tokens) from the output\"});this.name=de.String()}static{this.paths=[[\"config\",\"get\"]]}static{this.usage=st.Usage({description:\"read a configuration settings\",details:`\n      This command will print a configuration setting.\n\n      Secrets (such as tokens) will be redacted from the output by default. If this behavior isn't desired, set the \\`--no-redacted\\` to get the untransformed value.\n    `,examples:[[\"Print a simple configuration setting\",\"yarn config get yarnPath\"],[\"Print a complex configuration setting\",\"yarn config get packageExtensions\"],[\"Print a nested field from the configuration\",`yarn config get 'npmScopes[\"my-company\"].npmRegistryServer'`],[\"Print a token from the configuration\",\"yarn config get npmAuthToken --no-redacted\"],[\"Print a configuration setting as JSON\",\"yarn config get packageExtensions --json\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=this.name.replace(/[.[].*$/,\"\"),a=this.name.replace(/^[^.[]*/,\"\");if(typeof r.settings.get(o)>\"u\")throw new ot(`Couldn't find a configuration settings named \"${o}\"`);let u=r.getSpecial(o,{hideSecrets:!this.unsafe,getNativePaths:!0}),A=qe.convertMapsToIndexableObjects(u),p=a?(0,Qge.default)(A,a):A,h=await Lt.start({configuration:r,includeFooter:!1,json:this.json,stdout:this.context.stdout},async E=>{E.reportJson(p)});if(!this.json){if(typeof p==\"string\")return this.context.stdout.write(`${p}\n`),h.exitCode();AH.inspect.styles.name=\"cyan\",this.context.stdout.write(`${(0,AH.inspect)(p,{depth:1/0,colors:r.get(\"enableColors\"),compact:!1})}\n`)}return h.exitCode()}};Ke();Gt();var Ide=et(gH()),wde=et(L2()),Bde=et(dH()),mH=ve(\"util\"),dE=class extends ut{constructor(){super(...arguments);this.json=de.Boolean(\"--json\",!1,{description:\"Set complex configuration settings to JSON values\"});this.home=de.Boolean(\"-H,--home\",!1,{description:\"Update the home configuration instead of the project configuration\"});this.name=de.String();this.value=de.String()}static{this.paths=[[\"config\",\"set\"]]}static{this.usage=st.Usage({description:\"change a configuration settings\",details:`\n      This command will set a configuration setting.\n\n      When used without the \\`--json\\` flag, it can only set a simple configuration setting (a string, a number, or a boolean).\n\n      When used with the \\`--json\\` flag, it can set both simple and complex configuration settings, including Arrays and Objects.\n    `,examples:[[\"Set a simple configuration setting (a string, a number, or a boolean)\",\"yarn config set initScope myScope\"],[\"Set a simple configuration setting (a string, a number, or a boolean) using the `--json` flag\",'yarn config set initScope --json \\\\\"myScope\\\\\"'],[\"Set a complex configuration setting (an Array) using the `--json` flag\",`yarn config set unsafeHttpWhitelist --json '[\"*.example.com\", \"example.com\"]'`],[\"Set a complex configuration setting (an Object) using the `--json` flag\",`yarn config set packageExtensions --json '{ \"@babel/parser@*\": { \"dependencies\": { \"@babel/types\": \"*\" } } }'`],[\"Set a nested configuration setting\",'yarn config set npmScopes.company.npmRegistryServer \"https://npm.example.com\"'],[\"Set a nested configuration setting using indexed access for non-simple keys\",`yarn config set 'npmRegistries[\"//npm.example.com\"].npmAuthToken' \"ffffffff-ffff-ffff-ffff-ffffffffffff\"`]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=()=>{if(!r.projectCwd)throw new ot(\"This command must be run from within a project folder\");return r.projectCwd},a=this.name.replace(/[.[].*$/,\"\"),n=this.name.replace(/^[^.[]*\\.?/,\"\");if(typeof r.settings.get(a)>\"u\")throw new ot(`Couldn't find a configuration settings named \"${a}\"`);if(a===\"enableStrictSettings\")throw new ot(\"This setting only affects the file it's in, and thus cannot be set from the CLI\");let A=this.json?JSON.parse(this.value):this.value;await(this.home?C=>Je.updateHomeConfiguration(C):C=>Je.updateConfiguration(o(),C))(C=>{if(n){let T=(0,Ide.default)(C);return(0,Bde.default)(T,this.name,A),T}else return{...C,[a]:A}});let E=(await Je.find(this.context.cwd,this.context.plugins)).getSpecial(a,{hideSecrets:!0,getNativePaths:!0}),w=qe.convertMapsToIndexableObjects(E),D=n?(0,wde.default)(w,n):w;return(await Lt.start({configuration:r,includeFooter:!1,stdout:this.context.stdout},async C=>{mH.inspect.styles.name=\"cyan\",C.reportInfo(0,`Successfully set ${this.name} to ${(0,mH.inspect)(D,{depth:1/0,colors:r.get(\"enableColors\"),compact:!1})}`)})).exitCode()}};Ke();Gt();var Tde=et(gH()),Lde=et(Sde()),Nde=et(EH()),mE=class extends ut{constructor(){super(...arguments);this.home=de.Boolean(\"-H,--home\",!1,{description:\"Update the home configuration instead of the project configuration\"});this.name=de.String()}static{this.paths=[[\"config\",\"unset\"]]}static{this.usage=st.Usage({description:\"unset a configuration setting\",details:`\n      This command will unset a configuration setting.\n    `,examples:[[\"Unset a simple configuration setting\",\"yarn config unset initScope\"],[\"Unset a complex configuration setting\",\"yarn config unset packageExtensions\"],[\"Unset a nested configuration setting\",\"yarn config unset npmScopes.company.npmRegistryServer\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=()=>{if(!r.projectCwd)throw new ot(\"This command must be run from within a project folder\");return r.projectCwd},a=this.name.replace(/[.[].*$/,\"\"),n=this.name.replace(/^[^.[]*\\.?/,\"\");if(typeof r.settings.get(a)>\"u\")throw new ot(`Couldn't find a configuration settings named \"${a}\"`);let A=this.home?h=>Je.updateHomeConfiguration(h):h=>Je.updateConfiguration(o(),h);return(await Lt.start({configuration:r,includeFooter:!1,stdout:this.context.stdout},async h=>{let E=!1;await A(w=>{if(!(0,Lde.default)(w,this.name))return h.reportWarning(0,`Configuration doesn't contain setting ${this.name}; there is nothing to unset`),E=!0,w;let D=n?(0,Tde.default)(w):{...w};return(0,Nde.default)(D,this.name),D}),E||h.reportInfo(0,`Successfully unset ${this.name}`)})).exitCode()}};Ke();Pt();Gt();var Wk=ve(\"util\"),yE=class extends ut{constructor(){super(...arguments);this.noDefaults=de.Boolean(\"--no-defaults\",!1,{description:\"Omit the default values from the display\"});this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.verbose=de.Boolean(\"-v,--verbose\",{hidden:!0});this.why=de.Boolean(\"--why\",{hidden:!0});this.names=de.Rest()}static{this.paths=[[\"config\"]]}static{this.usage=st.Usage({description:\"display the current configuration\",details:`\n      This command prints the current active configuration settings.\n    `,examples:[[\"Print the active configuration settings\",\"$0 config\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins,{strict:!1}),o=await Qy({configuration:r,stdout:this.context.stdout,forceError:this.json},[{option:this.verbose,message:\"The --verbose option is deprecated, the settings' descriptions are now always displayed\"},{option:this.why,message:\"The --why option is deprecated, the settings' sources are now always displayed\"}]);if(o!==null)return o;let a=this.names.length>0?[...new Set(this.names)].sort():[...r.settings.keys()].sort(),n,u=await Lt.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async A=>{if(r.invalid.size>0&&!this.json){for(let[p,h]of r.invalid)A.reportError(34,`Invalid configuration key \"${p}\" in ${h}`);A.reportSeparator()}if(this.json)for(let p of a){let h=r.settings.get(p);typeof h>\"u\"&&A.reportError(34,`No configuration key named \"${p}\"`);let E=r.getSpecial(p,{hideSecrets:!0,getNativePaths:!0}),w=r.sources.get(p)??\"<default>\",D=w&&w[0]!==\"<\"?Ae.fromPortablePath(w):w;A.reportJson({key:p,effective:E,source:D,...h})}else{let p={breakLength:1/0,colors:r.get(\"enableColors\"),maxArrayLength:2},h={},E={children:h};for(let w of a){if(this.noDefaults&&!r.sources.has(w))continue;let D=r.settings.get(w),b=r.sources.get(w)??\"<default>\",C=r.getSpecial(w,{hideSecrets:!0,getNativePaths:!0}),T={Description:{label:\"Description\",value:pe.tuple(pe.Type.MARKDOWN,{text:D.description,format:this.cli.format(),paragraphs:!1})},Source:{label:\"Source\",value:pe.tuple(b[0]===\"<\"?pe.Type.CODE:pe.Type.PATH,b)}};h[w]={value:pe.tuple(pe.Type.CODE,w),children:T};let N=(U,z)=>{for(let[te,le]of z)if(le instanceof Map){let ce={};U[te]={children:ce},N(ce,le)}else U[te]={label:te,value:pe.tuple(pe.Type.NO_HINT,(0,Wk.inspect)(le,p))}};C instanceof Map?N(T,C):T.Value={label:\"Value\",value:pe.tuple(pe.Type.NO_HINT,(0,Wk.inspect)(C,p))}}a.length!==1&&(n=void 0),As.emitTree(E,{configuration:r,json:this.json,stdout:this.context.stdout,separators:2})}});if(!this.json&&typeof n<\"u\"){let A=a[0],p=(0,Wk.inspect)(r.getSpecial(A,{hideSecrets:!0,getNativePaths:!0}),{colors:r.get(\"enableColors\")});this.context.stdout.write(`\n`),this.context.stdout.write(`${p}\n`)}return u.exitCode()}};Ke();Gt();il();var Yk={};Kt(Yk,{Strategy:()=>N2,acceptedStrategies:()=>Q0t,dedupe:()=>CH});Ke();Ke();var Ode=et(Xo()),N2=(e=>(e.HIGHEST=\"highest\",e))(N2||{}),Q0t=new Set(Object.values(N2)),F0t={highest:async(t,e,{resolver:r,fetcher:o,resolveOptions:a,fetchOptions:n})=>{let u=new Map;for(let[p,h]of t.storedResolutions){let E=t.storedDescriptors.get(p);if(typeof E>\"u\")throw new Error(`Assertion failed: The descriptor (${p}) should have been registered`);qe.getSetWithDefault(u,E.identHash).add(h)}let A=new Map(qe.mapAndFilter(t.storedDescriptors.values(),p=>G.isVirtualDescriptor(p)?qe.mapAndFilter.skip:[p.descriptorHash,qe.makeDeferred()]));for(let p of t.storedDescriptors.values()){let h=A.get(p.descriptorHash);if(typeof h>\"u\")throw new Error(`Assertion failed: The descriptor (${p.descriptorHash}) should have been registered`);let E=t.storedResolutions.get(p.descriptorHash);if(typeof E>\"u\")throw new Error(`Assertion failed: The resolution (${p.descriptorHash}) should have been registered`);let w=t.originalPackages.get(E);if(typeof w>\"u\")throw new Error(`Assertion failed: The package (${E}) should have been registered`);Promise.resolve().then(async()=>{let D=r.getResolutionDependencies(p,a),b=Object.fromEntries(await qe.allSettledSafe(Object.entries(D).map(async([te,le])=>{let ce=A.get(le.descriptorHash);if(typeof ce>\"u\")throw new Error(`Assertion failed: The descriptor (${le.descriptorHash}) should have been registered`);let ue=await ce.promise;if(!ue)throw new Error(\"Assertion failed: Expected the dependency to have been through the dedupe process itself\");return[te,ue.updatedPackage]})));if(e.length&&!Ode.default.isMatch(G.stringifyIdent(p),e)||!r.shouldPersistResolution(w,a))return w;let C=u.get(p.identHash);if(typeof C>\"u\")throw new Error(`Assertion failed: The resolutions (${p.identHash}) should have been registered`);if(C.size===1)return w;let T=[...C].map(te=>{let le=t.originalPackages.get(te);if(typeof le>\"u\")throw new Error(`Assertion failed: The package (${te}) should have been registered`);return le}),N=await r.getSatisfying(p,b,T,a),U=N.locators?.[0];if(typeof U>\"u\"||!N.sorted)return w;let z=t.originalPackages.get(U.locatorHash);if(typeof z>\"u\")throw new Error(`Assertion failed: The package (${U.locatorHash}) should have been registered`);return z}).then(async D=>{let b=await t.preparePackage(D,{resolver:r,resolveOptions:a});h.resolve({descriptor:p,currentPackage:w,updatedPackage:D,resolvedPackage:b})}).catch(D=>{h.reject(D)})}return[...A.values()].map(p=>p.promise)}};async function CH(t,{strategy:e,patterns:r,cache:o,report:a}){let{configuration:n}=t,u=new Ri,A=n.makeResolver(),p=n.makeFetcher(),h={cache:o,checksums:t.storedChecksums,fetcher:p,project:t,report:u,cacheOptions:{skipIntegrityCheck:!0}},E={project:t,resolver:A,report:u,fetchOptions:h};return await a.startTimerPromise(\"Deduplication step\",async()=>{let w=F0t[e],D=await w(t,r,{resolver:A,resolveOptions:E,fetcher:p,fetchOptions:h}),b=Ws.progressViaCounter(D.length);await a.reportProgress(b);let C=0;await Promise.all(D.map(U=>U.then(z=>{if(z===null||z.currentPackage.locatorHash===z.updatedPackage.locatorHash)return;C++;let{descriptor:te,currentPackage:le,updatedPackage:ce}=z;a.reportInfo(0,`${G.prettyDescriptor(n,te)} can be deduped from ${G.prettyLocator(n,le)} to ${G.prettyLocator(n,ce)}`),a.reportJson({descriptor:G.stringifyDescriptor(te),currentResolution:G.stringifyLocator(le),updatedResolution:G.stringifyLocator(ce)}),t.storedResolutions.set(te.descriptorHash,ce.locatorHash)}).finally(()=>b.tick())));let T;switch(C){case 0:T=\"No packages\";break;case 1:T=\"One package\";break;default:T=`${C} packages`}let N=pe.pretty(n,e,pe.Type.CODE);return a.reportInfo(0,`${T} can be deduped using the ${N} strategy`),C})}var EE=class extends ut{constructor(){super(...arguments);this.strategy=de.String(\"-s,--strategy\",\"highest\",{description:\"The strategy to use when deduping dependencies\",validator:js(N2)});this.check=de.Boolean(\"-c,--check\",!1,{description:\"Exit with exit code 1 when duplicates are found, without persisting the dependency tree\"});this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.mode=de.String(\"--mode\",{description:\"Change what artifacts installs generate\",validator:js(yl)});this.patterns=de.Rest()}static{this.paths=[[\"dedupe\"]]}static{this.usage=st.Usage({description:\"deduplicate dependencies with overlapping ranges\",details:\"\\n      Duplicates are defined as descriptors with overlapping ranges being resolved and locked to different locators. They are a natural consequence of Yarn's deterministic installs, but they can sometimes pile up and unnecessarily increase the size of your project.\\n\\n      This command dedupes dependencies in the current project using different strategies (only one is implemented at the moment):\\n\\n      - `highest`: Reuses (where possible) the locators with the highest versions. This means that dependencies can only be upgraded, never downgraded. It's also guaranteed that it never takes more than a single pass to dedupe the entire dependency tree.\\n\\n      **Note:** Even though it never produces a wrong dependency tree, this command should be used with caution, as it modifies the dependency tree, which can sometimes cause problems when packages don't strictly follow semver recommendations. Because of this, it is recommended to also review the changes manually.\\n\\n      If set, the `-c,--check` flag will only report the found duplicates, without persisting the modified dependency tree. If changes are found, the command will exit with a non-zero exit code, making it suitable for CI purposes.\\n\\n      If the `--mode=<mode>` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\\n\\n      - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\\n\\n      - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\\n\\n      This command accepts glob patterns as arguments (if valid Idents and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them.\\n\\n      ### In-depth explanation:\\n\\n      Yarn doesn't deduplicate dependencies by default, otherwise installs wouldn't be deterministic and the lockfile would be useless. What it actually does is that it tries to not duplicate dependencies in the first place.\\n\\n      **Example:** If `foo@^2.3.4` (a dependency of a dependency) has already been resolved to `foo@2.3.4`, running `yarn add foo@*`will cause Yarn to reuse `foo@2.3.4`, even if the latest `foo` is actually `foo@2.10.14`, thus preventing unnecessary duplication.\\n\\n      Duplication happens when Yarn can't unlock dependencies that have already been locked inside the lockfile.\\n\\n      **Example:** If `foo@^2.3.4` (a dependency of a dependency) has already been resolved to `foo@2.3.4`, running `yarn add foo@2.10.14` will cause Yarn to install `foo@2.10.14` because the existing resolution doesn't satisfy the range `2.10.14`. This behavior can lead to (sometimes) unwanted duplication, since now the lockfile contains 2 separate resolutions for the 2 `foo` descriptors, even though they have overlapping ranges, which means that the lockfile can be simplified so that both descriptors resolve to `foo@2.10.14`.\\n    \",examples:[[\"Dedupe all packages\",\"$0 dedupe\"],[\"Dedupe all packages using a specific strategy\",\"$0 dedupe --strategy highest\"],[\"Dedupe a specific package\",\"$0 dedupe lodash\"],[\"Dedupe all packages with the `@babel/*` scope\",\"$0 dedupe '@babel/*'\"],[\"Check for duplicates (can be used as a CI step)\",\"$0 dedupe --check\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o}=await Qt.find(r,this.context.cwd),a=await Wr.find(r);await o.restoreInstallState({restoreResolutions:!1});let n=0,u=await Lt.start({configuration:r,includeFooter:!1,stdout:this.context.stdout,json:this.json},async A=>{n=await CH(o,{strategy:this.strategy,patterns:this.patterns,cache:a,report:A})});return u.hasErrors()?u.exitCode():this.check?n?1:0:await o.installWithNewReport({json:this.json,stdout:this.context.stdout},{cache:a,mode:this.mode})}};Ke();Gt();var CE=class extends ut{static{this.paths=[[\"--clipanion=definitions\"]]}async execute(){let{plugins:e}=await Je.find(this.context.cwd,this.context.plugins),r=[];for(let u of e){let{commands:A}=u[1];if(A){let h=Vo.from(A).definitions();r.push([u[0],h])}}let o=this.cli.definitions(),a=(u,A)=>u.split(\" \").slice(1).join()===A.split(\" \").slice(1).join(),n=Mde()[\"@yarnpkg/builder\"].bundles.standard;for(let u of r){let A=u[1];for(let p of A)o.find(h=>a(h.path,p.path)).plugin={name:u[0],isDefault:n.includes(u[0])}}this.context.stdout.write(`${JSON.stringify(o,null,2)}\n`)}};var IE=class extends ut{static{this.paths=[[\"help\"],[\"--help\"],[\"-h\"]]}async execute(){this.context.stdout.write(this.cli.usage(null))}};Ke();Pt();Gt();var wE=class extends ut{constructor(){super(...arguments);this.leadingArgument=de.String();this.args=de.Proxy()}async execute(){if(this.leadingArgument.match(/[\\\\/]/)&&!G.tryParseIdent(this.leadingArgument)){let r=K.resolve(this.context.cwd,Ae.toPortablePath(this.leadingArgument));return await this.cli.run(this.args,{cwd:r})}else return await this.cli.run([\"run\",this.leadingArgument,...this.args])}};Ke();var BE=class extends ut{static{this.paths=[[\"-v\"],[\"--version\"]]}async execute(){this.context.stdout.write(`${nn||\"<unknown>\"}\n`)}};Ke();Ke();Gt();var vE=class extends ut{constructor(){super(...arguments);this.commandName=de.String();this.args=de.Proxy()}static{this.paths=[[\"exec\"]]}static{this.usage=st.Usage({description:\"execute a shell script\",details:`\n      This command simply executes a shell script within the context of the root directory of the active workspace using the portable shell.\n\n      It also makes sure to call it in a way that's compatible with the current project (for example, on PnP projects the environment will be setup in such a way that PnP will be correctly injected into the environment).\n    `,examples:[[\"Execute a single shell command\",\"$0 exec echo Hello World\"],[\"Execute a shell script\",'$0 exec \"tsc & babel src --out-dir lib\"']]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,locator:a}=await Qt.find(r,this.context.cwd);return await o.restoreInstallState(),await hn.executePackageShellcode(a,this.commandName,this.args,{cwd:this.context.cwd,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr,project:o})}};Ke();Gt();il();var DE=class extends ut{constructor(){super(...arguments);this.hash=de.String({required:!1,validator:LP(Sm(),[Bw(/^p[0-9a-f]{5}$/)])})}static{this.paths=[[\"explain\",\"peer-requirements\"]]}static{this.usage=st.Usage({description:\"explain a set of peer requirements\",details:`\n      A peer requirement represents all peer requests that a subject must satisfy when providing a requested package to requesters.\n\n      When the hash argument is specified, this command prints a detailed explanation of the peer requirement corresponding to the hash and whether it is satisfied or not.\n\n      When used without arguments, this command lists all peer requirements and the corresponding hash that can be used to get detailed information about a given requirement.\n\n      **Note:** A hash is a six-letter p-prefixed code that can be obtained from peer dependency warnings or from the list of all peer requirements (\\`yarn explain peer-requirements\\`).\n    `,examples:[[\"Explain the corresponding peer requirement for a hash\",\"$0 explain peer-requirements p1a4ed\"],[\"List all peer requirements\",\"$0 explain peer-requirements\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o}=await Qt.find(r,this.context.cwd);return await o.restoreInstallState({restoreResolutions:!1}),await o.applyLightResolution(),typeof this.hash<\"u\"?await T0t(this.hash,o,{stdout:this.context.stdout}):await L0t(o,{stdout:this.context.stdout})}};async function T0t(t,e,r){let o=e.peerRequirementNodes.get(t);if(typeof o>\"u\")throw new Error(`No peerDependency requirements found for hash: \"${t}\"`);let a=new Set,n=p=>a.has(p.requester.locatorHash)?{value:pe.tuple(pe.Type.DEPENDENT,{locator:p.requester,descriptor:p.descriptor}),children:p.children.size>0?[{value:pe.tuple(pe.Type.NO_HINT,\"...\")}]:[]}:(a.add(p.requester.locatorHash),{value:pe.tuple(pe.Type.DEPENDENT,{locator:p.requester,descriptor:p.descriptor}),children:Object.fromEntries(Array.from(p.children.values(),h=>[G.stringifyLocator(h.requester),n(h)]))}),u=e.peerWarnings.find(p=>p.hash===t);return(await Lt.start({configuration:e.configuration,stdout:r.stdout,includeFooter:!1,includePrefix:!1},async p=>{let h=pe.mark(e.configuration),E=u?h.Cross:h.Check;if(p.reportInfo(0,`Package ${pe.pretty(e.configuration,o.subject,pe.Type.LOCATOR)} is requested to provide ${pe.pretty(e.configuration,o.ident,pe.Type.IDENT)} by its descendants`),p.reportSeparator(),p.reportInfo(0,pe.pretty(e.configuration,o.subject,pe.Type.LOCATOR)),As.emitTree({children:Object.fromEntries(Array.from(o.requests.values(),w=>[G.stringifyLocator(w.requester),n(w)]))},{configuration:e.configuration,stdout:r.stdout,json:!1}),p.reportSeparator(),o.provided.range===\"missing:\"){let w=u?\"\":\" , but all peer requests are optional\";p.reportInfo(0,`${E} Package ${pe.pretty(e.configuration,o.subject,pe.Type.LOCATOR)} does not provide ${pe.pretty(e.configuration,o.ident,pe.Type.IDENT)}${w}.`)}else{let w=e.storedResolutions.get(o.provided.descriptorHash);if(!w)throw new Error(\"Assertion failed: Expected the descriptor to be registered\");let D=e.storedPackages.get(w);if(!D)throw new Error(\"Assertion failed: Expected the package to be registered\");p.reportInfo(0,`${E} Package ${pe.pretty(e.configuration,o.subject,pe.Type.LOCATOR)} provides ${pe.pretty(e.configuration,o.ident,pe.Type.IDENT)} with version ${G.prettyReference(e.configuration,D.version??\"0.0.0\")}, ${u?\"which does not satisfy all requests.\":\"which satisfies all requests\"}`),u?.type===3&&(u.range?p.reportInfo(0,`  The combined requested range is ${pe.pretty(e.configuration,u.range,pe.Type.RANGE)}`):p.reportInfo(0,\"  Unfortunately, the requested ranges have no overlap\"))}})).exitCode()}async function L0t(t,e){return(await Lt.start({configuration:t.configuration,stdout:e.stdout,includeFooter:!1,includePrefix:!1},async o=>{let a=pe.mark(t.configuration),n=qe.sortMap(t.peerRequirementNodes,[([,u])=>G.stringifyLocator(u.subject),([,u])=>G.stringifyIdent(u.ident)]);for(let[,u]of n.values()){if(!u.root)continue;let A=t.peerWarnings.find(E=>E.hash===u.hash),p=[...G.allPeerRequests(u)],h;if(p.length>2?h=` and ${p.length-1} other dependencies`:p.length===2?h=\" and 1 other dependency\":h=\"\",u.provided.range!==\"missing:\"){let E=t.storedResolutions.get(u.provided.descriptorHash);if(!E)throw new Error(\"Assertion failed: Expected the resolution to have been registered\");let w=t.storedPackages.get(E);if(!w)throw new Error(\"Assertion failed: Expected the provided package to have been registered\");let D=`${pe.pretty(t.configuration,u.hash,pe.Type.CODE)} \\u2192 ${A?a.Cross:a.Check} ${G.prettyLocator(t.configuration,u.subject)} provides ${G.prettyLocator(t.configuration,w)} to ${G.prettyLocator(t.configuration,p[0].requester)}${h}`;A?o.reportWarning(0,D):o.reportInfo(0,D)}else{let E=`${pe.pretty(t.configuration,u.hash,pe.Type.CODE)} \\u2192 ${A?a.Cross:a.Check} ${G.prettyLocator(t.configuration,u.subject)} doesn't provide ${G.prettyIdent(t.configuration,u.ident)} to ${G.prettyLocator(t.configuration,p[0].requester)}${h}`;A?o.reportWarning(0,E):o.reportInfo(0,E)}}})).exitCode()}Ke();Gt();il();Ke();Ke();Pt();Gt();var Ude=et(ni()),PE=class extends ut{constructor(){super(...arguments);this.useYarnPath=de.Boolean(\"--yarn-path\",{description:\"Set the yarnPath setting even if the version can be accessed by Corepack\"});this.onlyIfNeeded=de.Boolean(\"--only-if-needed\",!1,{description:\"Only lock the Yarn version if it isn't already locked\"});this.version=de.String()}static{this.paths=[[\"set\",\"version\"]]}static{this.usage=st.Usage({description:\"lock the Yarn version used by the project\",details:\"\\n      This command will set a specific release of Yarn to be used by Corepack: https://nodejs.org/api/corepack.html.\\n\\n      By default it only will set the `packageManager` field at the root of your project, but if the referenced release cannot be represented this way, if you already have `yarnPath` configured, or if you set the `--yarn-path` command line flag, then the release will also be downloaded from the Yarn GitHub repository, stored inside your project, and referenced via the `yarnPath` settings from your project `.yarnrc.yml` file.\\n\\n      A very good use case for this command is to enforce the version of Yarn used by any single member of your team inside the same project - by doing this you ensure that you have control over Yarn upgrades and downgrades (including on your deployment servers), and get rid of most of the headaches related to someone using a slightly different version and getting different behavior.\\n\\n      The version specifier can be:\\n\\n      - a tag:\\n        - `latest` / `berry` / `stable` -> the most recent stable berry (`>=2.0.0`) release\\n        - `canary` -> the most recent canary (release candidate) berry (`>=2.0.0`) release\\n        - `classic` -> the most recent classic (`^0.x || ^1.x`) release\\n\\n      - a semver range (e.g. `2.x`) -> the most recent version satisfying the range (limited to berry releases)\\n\\n      - a semver version (e.g. `2.4.1`, `1.22.1`)\\n\\n      - a local file referenced through either a relative or absolute path\\n\\n      - `self` -> the version used to invoke the command\\n    \",examples:[[\"Download the latest release from the Yarn repository\",\"$0 set version latest\"],[\"Download the latest canary release from the Yarn repository\",\"$0 set version canary\"],[\"Download the latest classic release from the Yarn repository\",\"$0 set version classic\"],[\"Download the most recent Yarn 3 build\",\"$0 set version 3.x\"],[\"Download a specific Yarn 2 build\",\"$0 set version 2.0.0-rc.30\"],[\"Switch back to a specific Yarn 1 release\",\"$0 set version 1.22.1\"],[\"Use a release from the local filesystem\",\"$0 set version ./yarn.cjs\"],[\"Use a release from a URL\",\"$0 set version https://repo.yarnpkg.com/3.1.0/packages/yarnpkg-cli/bin/yarn.js\"],[\"Download the version used to invoke the command\",\"$0 set version self\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins);if(this.onlyIfNeeded&&r.get(\"yarnPath\")){let A=r.sources.get(\"yarnPath\");if(!A)throw new Error(\"Assertion failed: Expected 'yarnPath' to have a source\");let p=r.projectCwd??r.startingCwd;if(K.contains(p,A))return 0}let o=()=>{if(typeof nn>\"u\")throw new ot(\"The --install flag can only be used without explicit version specifier from the Yarn CLI\");return`file://${process.argv[1]}`},a,n=(A,p)=>({version:p,url:A.replace(/\\{\\}/g,p)});if(this.version===\"self\")a={url:o(),version:nn??\"self\"};else if(this.version===\"latest\"||this.version===\"berry\"||this.version===\"stable\")a=n(\"https://repo.yarnpkg.com/{}/packages/yarnpkg-cli/bin/yarn.js\",await O2(r,\"stable\"));else if(this.version===\"canary\")a=n(\"https://repo.yarnpkg.com/{}/packages/yarnpkg-cli/bin/yarn.js\",await O2(r,\"canary\"));else if(this.version===\"classic\")a={url:\"https://classic.yarnpkg.com/latest.js\",version:\"classic\"};else if(this.version.match(/^https?:/))a={url:this.version,version:\"remote\"};else if(this.version.match(/^\\.{0,2}[\\\\/]/)||Ae.isAbsolute(this.version))a={url:`file://${K.resolve(Ae.toPortablePath(this.version))}`,version:\"file\"};else if(Ur.satisfiesWithPrereleases(this.version,\">=2.0.0\"))a=n(\"https://repo.yarnpkg.com/{}/packages/yarnpkg-cli/bin/yarn.js\",this.version);else if(Ur.satisfiesWithPrereleases(this.version,\"^0.x || ^1.x\"))a=n(\"https://github.com/yarnpkg/yarn/releases/download/v{}/yarn-{}.js\",this.version);else if(Ur.validRange(this.version))a=n(\"https://repo.yarnpkg.com/{}/packages/yarnpkg-cli/bin/yarn.js\",await N0t(r,this.version));else throw new ot(`Invalid version descriptor \"${this.version}\"`);return(await Lt.start({configuration:r,stdout:this.context.stdout,includeLogs:!this.context.quiet},async A=>{let p=async()=>{let h=\"file://\";return a.url.startsWith(h)?(A.reportInfo(0,`Retrieving ${pe.pretty(r,a.url,pe.Type.PATH)}`),await ae.readFilePromise(a.url.slice(h.length))):(A.reportInfo(0,`Downloading ${pe.pretty(r,a.url,pe.Type.URL)}`),await on.get(a.url,{configuration:r}))};await IH(r,a.version,p,{report:A,useYarnPath:this.useYarnPath})})).exitCode()}};async function N0t(t,e){let o=(await on.get(\"https://repo.yarnpkg.com/tags\",{configuration:t,jsonResponse:!0})).tags.filter(a=>Ur.satisfiesWithPrereleases(a,e));if(o.length===0)throw new ot(`No matching release found for range ${pe.pretty(t,e,pe.Type.RANGE)}.`);return o[0]}async function O2(t,e){let r=await on.get(\"https://repo.yarnpkg.com/tags\",{configuration:t,jsonResponse:!0});if(!r.latest[e])throw new ot(`Tag ${pe.pretty(t,e,pe.Type.RANGE)} not found`);return r.latest[e]}async function IH(t,e,r,{report:o,useYarnPath:a}){let n,u=async()=>(typeof n>\"u\"&&(n=await r()),n);if(e===null){let te=await u();await ae.mktempPromise(async le=>{let ce=K.join(le,\"yarn.cjs\");await ae.writeFilePromise(ce,te);let{stdout:ue}=await Hr.execvp(process.execPath,[Ae.fromPortablePath(ce),\"--version\"],{cwd:le,env:{...t.env,YARN_IGNORE_PATH:\"1\"}});if(e=ue.trim(),!Ude.default.valid(e))throw new Error(`Invalid semver version. ${pe.pretty(t,\"yarn --version\",pe.Type.CODE)} returned:\n${e}`)})}let A=t.projectCwd??t.startingCwd,p=K.resolve(A,\".yarn/releases\"),h=K.resolve(p,`yarn-${e}.cjs`),E=K.relative(t.startingCwd,h),w=qe.isTaggedYarnVersion(e),D=t.get(\"yarnPath\"),b=!w,C=b||!!D||!!a;if(a===!1){if(b)throw new zt(0,\"You explicitly opted out of yarnPath usage in your command line, but the version you specified cannot be represented by Corepack\");C=!1}else!C&&!process.env.COREPACK_ROOT&&(o.reportWarning(0,`You don't seem to have ${pe.applyHyperlink(t,\"Corepack\",\"https://nodejs.org/api/corepack.html\")} enabled; we'll have to rely on ${pe.applyHyperlink(t,\"yarnPath\",\"https://yarnpkg.com/configuration/yarnrc#yarnPath\")} instead`),C=!0);if(C){let te=await u();o.reportInfo(0,`Saving the new release in ${pe.pretty(t,E,\"magenta\")}`),await ae.removePromise(K.dirname(h)),await ae.mkdirPromise(K.dirname(h),{recursive:!0}),await ae.writeFilePromise(h,te,{mode:493}),await Je.updateConfiguration(A,{yarnPath:K.relative(A,h)})}else await ae.removePromise(K.dirname(h)),await Je.updateConfiguration(A,{yarnPath:Je.deleteProperty});let T=await _t.tryFind(A)||new _t;T.packageManager=`yarn@${w?e:await O2(t,\"stable\")}`;let N={};T.exportTo(N);let U=K.join(A,_t.fileName),z=`${JSON.stringify(N,null,T.indent)}\n`;return await ae.changeFilePromise(U,z,{automaticNewlines:!0}),{bundleVersion:e}}function _de(t){return vr[qP(t)]}var O0t=/## (?<code>YN[0-9]{4}) - `(?<name>[A-Z_]+)`\\n\\n(?<details>(?:.(?!##))+)/gs;async function M0t(t){let r=`https://repo.yarnpkg.com/${qe.isTaggedYarnVersion(nn)?nn:await O2(t,\"canary\")}/packages/docusaurus/docs/advanced/01-general-reference/error-codes.mdx`,o=await on.get(r,{configuration:t});return new Map(Array.from(o.toString().matchAll(O0t),({groups:a})=>{if(!a)throw new Error(\"Assertion failed: Expected the match to have been successful\");let n=_de(a.code);if(a.name!==n)throw new Error(`Assertion failed: Invalid error code data: Expected \"${a.name}\" to be named \"${n}\"`);return[a.code,a.details]}))}var SE=class extends ut{constructor(){super(...arguments);this.code=de.String({required:!1,validator:vw(Sm(),[Bw(/^YN[0-9]{4}$/)])});this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"})}static{this.paths=[[\"explain\"]]}static{this.usage=st.Usage({description:\"explain an error code\",details:`\n      When the code argument is specified, this command prints its name and its details.\n\n      When used without arguments, this command lists all error codes and their names.\n    `,examples:[[\"Explain an error code\",\"$0 explain YN0006\"],[\"List all error codes\",\"$0 explain\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins);if(typeof this.code<\"u\"){let o=_de(this.code),a=pe.pretty(r,o,pe.Type.CODE),n=this.cli.format().header(`${this.code} - ${a}`),A=(await M0t(r)).get(this.code),p=typeof A<\"u\"?pe.jsonOrPretty(this.json,r,pe.tuple(pe.Type.MARKDOWN,{text:A,format:this.cli.format(),paragraphs:!0})):`This error code does not have a description.\n\nYou can help us by editing this page on GitHub \\u{1F642}:\n${pe.jsonOrPretty(this.json,r,pe.tuple(pe.Type.URL,\"https://github.com/yarnpkg/berry/blob/master/packages/docusaurus/docs/advanced/01-general-reference/error-codes.mdx\"))}\n`;this.json?this.context.stdout.write(`${JSON.stringify({code:this.code,name:o,details:p})}\n`):this.context.stdout.write(`${n}\n\n${p}\n`)}else{let o={children:qe.mapAndFilter(Object.entries(vr),([a,n])=>Number.isNaN(Number(a))?qe.mapAndFilter.skip:{label:zu(Number(a)),value:pe.tuple(pe.Type.CODE,n)})};As.emitTree(o,{configuration:r,stdout:this.context.stdout,json:this.json})}}};Ke();Pt();Gt();var Hde=et(Xo()),xE=class extends ut{constructor(){super(...arguments);this.all=de.Boolean(\"-A,--all\",!1,{description:\"Print versions of a package from the whole project\"});this.recursive=de.Boolean(\"-R,--recursive\",!1,{description:\"Print information for all packages, including transitive dependencies\"});this.extra=de.Array(\"-X,--extra\",[],{description:\"An array of requests of extra data provided by plugins\"});this.cache=de.Boolean(\"--cache\",!1,{description:\"Print information about the cache entry of a package (path, size, checksum)\"});this.dependents=de.Boolean(\"--dependents\",!1,{description:\"Print all dependents for each matching package\"});this.manifest=de.Boolean(\"--manifest\",!1,{description:\"Print data obtained by looking at the package archive (license, homepage, ...)\"});this.nameOnly=de.Boolean(\"--name-only\",!1,{description:\"Only print the name for the matching packages\"});this.virtuals=de.Boolean(\"--virtuals\",!1,{description:\"Print each instance of the virtual packages\"});this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.patterns=de.Rest()}static{this.paths=[[\"info\"]]}static{this.usage=st.Usage({description:\"see information related to packages\",details:\"\\n      This command prints various information related to the specified packages, accepting glob patterns.\\n\\n      By default, if the locator reference is missing, Yarn will default to print the information about all the matching direct dependencies of the package for the active workspace. To instead print all versions of the package that are direct dependencies of any of your workspaces, use the `-A,--all` flag. Adding the `-R,--recursive` flag will also report transitive dependencies.\\n\\n      Some fields will be hidden by default in order to keep the output readable, but can be selectively displayed by using additional options (`--dependents`, `--manifest`, `--virtuals`, ...) described in the option descriptions.\\n\\n      Note that this command will only print the information directly related to the selected packages - if you wish to know why the package is there in the first place, use `yarn why` which will do just that (it also provides a `-R,--recursive` flag that may be of some help).\\n    \",examples:[[\"Show information about Lodash\",\"$0 info lodash\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Wr.find(r);if(!a&&!this.all)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState();let u=new Set(this.extra);this.cache&&u.add(\"cache\"),this.dependents&&u.add(\"dependents\"),this.manifest&&u.add(\"manifest\");let A=(le,{recursive:ce})=>{let ue=le.anchoredLocator.locatorHash,Ie=new Map,he=[ue];for(;he.length>0;){let De=he.shift();if(Ie.has(De))continue;let Ee=o.storedPackages.get(De);if(typeof Ee>\"u\")throw new Error(\"Assertion failed: Expected the package to be registered\");if(Ie.set(De,Ee),G.isVirtualLocator(Ee)&&he.push(G.devirtualizeLocator(Ee).locatorHash),!(!ce&&De!==ue))for(let g of Ee.dependencies.values()){let me=o.storedResolutions.get(g.descriptorHash);if(typeof me>\"u\")throw new Error(\"Assertion failed: Expected the resolution to be registered\");he.push(me)}}return Ie.values()},p=({recursive:le})=>{let ce=new Map;for(let ue of o.workspaces)for(let Ie of A(ue,{recursive:le}))ce.set(Ie.locatorHash,Ie);return ce.values()},h=({all:le,recursive:ce})=>le&&ce?o.storedPackages.values():le?p({recursive:ce}):A(a,{recursive:ce}),E=({all:le,recursive:ce})=>{let ue=h({all:le,recursive:ce}),Ie=this.patterns.map(Ee=>{let g=G.parseLocator(Ee),me=Hde.default.makeRe(G.stringifyIdent(g)),Ce=G.isVirtualLocator(g),fe=Ce?G.devirtualizeLocator(g):g;return ie=>{let Z=G.stringifyIdent(ie);if(!me.test(Z))return!1;if(g.reference===\"unknown\")return!0;let Pe=G.isVirtualLocator(ie),Re=Pe?G.devirtualizeLocator(ie):ie;return!(Ce&&Pe&&g.reference!==ie.reference||fe.reference!==Re.reference)}}),he=qe.sortMap([...ue],Ee=>G.stringifyLocator(Ee));return{selection:he.filter(Ee=>Ie.length===0||Ie.some(g=>g(Ee))),sortedLookup:he}},{selection:w,sortedLookup:D}=E({all:this.all,recursive:this.recursive});if(w.length===0)throw new ot(\"No package matched your request\");let b=new Map;if(this.dependents)for(let le of D)for(let ce of le.dependencies.values()){let ue=o.storedResolutions.get(ce.descriptorHash);if(typeof ue>\"u\")throw new Error(\"Assertion failed: Expected the resolution to be registered\");qe.getArrayWithDefault(b,ue).push(le)}let C=new Map;for(let le of D){if(!G.isVirtualLocator(le))continue;let ce=G.devirtualizeLocator(le);qe.getArrayWithDefault(C,ce.locatorHash).push(le)}let T={},N={children:T},U=r.makeFetcher(),z={project:o,fetcher:U,cache:n,checksums:o.storedChecksums,report:new Ri,cacheOptions:{skipIntegrityCheck:!0}},te=[async(le,ce,ue)=>{if(!ce.has(\"manifest\"))return;let Ie=await U.fetch(le,z),he;try{he=await _t.find(Ie.prefixPath,{baseFs:Ie.packageFs})}finally{Ie.releaseFs?.()}ue(\"Manifest\",{License:pe.tuple(pe.Type.NO_HINT,he.license),Homepage:pe.tuple(pe.Type.URL,he.raw.homepage??null)})},async(le,ce,ue)=>{if(!ce.has(\"cache\"))return;let Ie=o.storedChecksums.get(le.locatorHash)??null,he=n.getLocatorPath(le,Ie),De;if(he!==null)try{De=await ae.statPromise(he)}catch{}let Ee=typeof De<\"u\"?[De.size,pe.Type.SIZE]:void 0;ue(\"Cache\",{Checksum:pe.tuple(pe.Type.NO_HINT,Ie),Path:pe.tuple(pe.Type.PATH,he),Size:Ee})}];for(let le of w){let ce=G.isVirtualLocator(le);if(!this.virtuals&&ce)continue;let ue={},Ie={value:[le,pe.Type.LOCATOR],children:ue};if(T[G.stringifyLocator(le)]=Ie,this.nameOnly){delete Ie.children;continue}let he=C.get(le.locatorHash);typeof he<\"u\"&&(ue.Instances={label:\"Instances\",value:pe.tuple(pe.Type.NUMBER,he.length)}),ue.Version={label:\"Version\",value:pe.tuple(pe.Type.NO_HINT,le.version)};let De=(g,me)=>{let Ce={};if(ue[g]=Ce,Array.isArray(me))Ce.children=me.map(fe=>({value:fe}));else{let fe={};Ce.children=fe;for(let[ie,Z]of Object.entries(me))typeof Z>\"u\"||(fe[ie]={label:ie,value:Z})}};if(!ce){for(let g of te)await g(le,u,De);await r.triggerHook(g=>g.fetchPackageInfo,le,u,De)}le.bin.size>0&&!ce&&De(\"Exported Binaries\",[...le.bin.keys()].map(g=>pe.tuple(pe.Type.PATH,g)));let Ee=b.get(le.locatorHash);typeof Ee<\"u\"&&Ee.length>0&&De(\"Dependents\",Ee.map(g=>pe.tuple(pe.Type.LOCATOR,g))),le.dependencies.size>0&&!ce&&De(\"Dependencies\",[...le.dependencies.values()].map(g=>{let me=o.storedResolutions.get(g.descriptorHash),Ce=typeof me<\"u\"?o.storedPackages.get(me)??null:null;return pe.tuple(pe.Type.RESOLUTION,{descriptor:g,locator:Ce})})),le.peerDependencies.size>0&&ce&&De(\"Peer dependencies\",[...le.peerDependencies.values()].map(g=>{let me=le.dependencies.get(g.identHash),Ce=typeof me<\"u\"?o.storedResolutions.get(me.descriptorHash)??null:null,fe=Ce!==null?o.storedPackages.get(Ce)??null:null;return pe.tuple(pe.Type.RESOLUTION,{descriptor:g,locator:fe})}))}As.emitTree(N,{configuration:r,json:this.json,stdout:this.context.stdout,separators:this.nameOnly?0:2})}};Ke();Pt();Ol();var Kk=et(sg());Gt();var wH=et(ni());il();var U0t=[{selector:t=>t===-1,name:\"nodeLinker\",value:\"node-modules\"},{selector:t=>t!==-1&&t<8,name:\"enableGlobalCache\",value:!1},{selector:t=>t!==-1&&t<8,name:\"compressionLevel\",value:\"mixed\"}],bE=class extends ut{constructor(){super(...arguments);this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.immutable=de.Boolean(\"--immutable\",{description:\"Abort with an error exit code if the lockfile was to be modified\"});this.immutableCache=de.Boolean(\"--immutable-cache\",{description:\"Abort with an error exit code if the cache folder was to be modified\"});this.refreshLockfile=de.Boolean(\"--refresh-lockfile\",{description:\"Refresh the package metadata stored in the lockfile\"});this.checkCache=de.Boolean(\"--check-cache\",{description:\"Always refetch the packages and ensure that their checksums are consistent\"});this.checkResolutions=de.Boolean(\"--check-resolutions\",{description:\"Validates that the package resolutions are coherent\"});this.inlineBuilds=de.Boolean(\"--inline-builds\",{description:\"Verbosely print the output of the build steps of dependencies\"});this.mode=de.String(\"--mode\",{description:\"Change what artifacts installs generate\",validator:js(yl)});this.cacheFolder=de.String(\"--cache-folder\",{hidden:!0});this.frozenLockfile=de.Boolean(\"--frozen-lockfile\",{hidden:!0});this.ignoreEngines=de.Boolean(\"--ignore-engines\",{hidden:!0});this.nonInteractive=de.Boolean(\"--non-interactive\",{hidden:!0});this.preferOffline=de.Boolean(\"--prefer-offline\",{hidden:!0});this.production=de.Boolean(\"--production\",{hidden:!0});this.registry=de.String(\"--registry\",{hidden:!0});this.silent=de.Boolean(\"--silent\",{hidden:!0});this.networkTimeout=de.String(\"--network-timeout\",{hidden:!0})}static{this.paths=[[\"install\"],st.Default]}static{this.usage=st.Usage({description:\"install the project dependencies\",details:\"\\n      This command sets up your project if needed. The installation is split into four different steps that each have their own characteristics:\\n\\n      - **Resolution:** First the package manager will resolve your dependencies. The exact way a dependency version is privileged over another isn't standardized outside of the regular semver guarantees. If a package doesn't resolve to what you would expect, check that all dependencies are correctly declared (also check our website for more information: ).\\n\\n      - **Fetch:** Then we download all the dependencies if needed, and make sure that they're all stored within our cache (check the value of `cacheFolder` in `yarn config` to see where the cache files are stored).\\n\\n      - **Link:** Then we send the dependency tree information to internal plugins tasked with writing them on the disk in some form (for example by generating the `.pnp.cjs` file you might know).\\n\\n      - **Build:** Once the dependency tree has been written on the disk, the package manager will now be free to run the build scripts for all packages that might need it, in a topological order compatible with the way they depend on one another. See https://yarnpkg.com/advanced/lifecycle-scripts for detail.\\n\\n      Note that running this command is not part of the recommended workflow. Yarn supports zero-installs, which means that as long as you store your cache and your `.pnp.cjs` file inside your repository, everything will work without requiring any install right after cloning your repository or switching branches.\\n\\n      If the `--immutable` option is set (defaults to true on CI), Yarn will abort with an error exit code if the lockfile was to be modified (other paths can be added using the `immutablePatterns` configuration setting). For backward compatibility we offer an alias under the name of `--frozen-lockfile`, but it will be removed in a later release.\\n\\n      If the `--immutable-cache` option is set, Yarn will abort with an error exit code if the cache folder was to be modified (either because files would be added, or because they'd be removed).\\n\\n      If the `--refresh-lockfile` option is set, Yarn will keep the same resolution for the packages currently in the lockfile but will refresh their metadata. If used together with `--immutable`, it can validate that the lockfile information are consistent. This flag is enabled by default when Yarn detects it runs within a pull request context.\\n\\n      If the `--check-cache` option is set, Yarn will always refetch the packages and will ensure that their checksum matches what's 1/ described in the lockfile 2/ inside the existing cache files (if present). This is recommended as part of your CI workflow if you're both following the Zero-Installs model and accepting PRs from third-parties, as they'd otherwise have the ability to alter the checked-in packages before submitting them.\\n\\n      If the `--inline-builds` option is set, Yarn will verbosely print the output of the build steps of your dependencies (instead of writing them into individual files). This is likely useful mostly for debug purposes only when using Docker-like environments.\\n\\n      If the `--mode=<mode>` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\\n\\n      - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\\n\\n      - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\\n    \",examples:[[\"Install the project\",\"$0 install\"],[\"Validate a project when using Zero-Installs\",\"$0 install --immutable --immutable-cache\"],[\"Validate a project when using Zero-Installs (slightly safer if you accept external PRs)\",\"$0 install --immutable --immutable-cache --check-cache\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins);typeof this.inlineBuilds<\"u\"&&r.useWithSource(\"<cli>\",{enableInlineBuilds:this.inlineBuilds},r.startingCwd,{overwrite:!0});let o=!!process.env.FUNCTION_TARGET||!!process.env.GOOGLE_RUNTIME,a=await Qy({configuration:r,stdout:this.context.stdout},[{option:this.ignoreEngines,message:\"The --ignore-engines option is deprecated; engine checking isn't a core feature anymore\",error:!Kk.default.VERCEL},{option:this.registry,message:\"The --registry option is deprecated; prefer setting npmRegistryServer in your .yarnrc.yml file\"},{option:this.preferOffline,message:\"The --prefer-offline flag is deprecated; use the --cached flag with 'yarn add' instead\",error:!Kk.default.VERCEL},{option:this.production,message:\"The --production option is deprecated on 'install'; use 'yarn workspaces focus' instead\",error:!0},{option:this.nonInteractive,message:\"The --non-interactive option is deprecated\",error:!o},{option:this.frozenLockfile,message:\"The --frozen-lockfile option is deprecated; use --immutable and/or --immutable-cache instead\",callback:()=>this.immutable=this.frozenLockfile},{option:this.cacheFolder,message:\"The cache-folder option has been deprecated; use rc settings instead\",error:!Kk.default.NETLIFY}]);if(a!==null)return a;let n=this.mode===\"update-lockfile\";if(n&&(this.immutable||this.immutableCache))throw new ot(`${pe.pretty(r,\"--immutable\",pe.Type.CODE)} and ${pe.pretty(r,\"--immutable-cache\",pe.Type.CODE)} cannot be used with ${pe.pretty(r,\"--mode=update-lockfile\",pe.Type.CODE)}`);let u=(this.immutable??r.get(\"enableImmutableInstalls\"))&&!n,A=this.immutableCache&&!n;if(r.projectCwd!==null){let T=await Lt.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async N=>{let U=!1;await q0t(r,u)&&(N.reportInfo(48,\"Automatically removed core plugins that are now builtins \\u{1F44D}\"),U=!0),await H0t(r,u)&&(N.reportInfo(48,\"Automatically fixed merge conflicts \\u{1F44D}\"),U=!0),U&&N.reportSeparator()});if(T.hasErrors())return T.exitCode()}if(r.projectCwd!==null){let T=await Lt.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async N=>{if(Je.telemetry?.isNew)Je.telemetry.commitTips(),N.reportInfo(65,\"Yarn will periodically gather anonymous telemetry: https://yarnpkg.com/advanced/telemetry\"),N.reportInfo(65,`Run ${pe.pretty(r,\"yarn config set --home enableTelemetry 0\",pe.Type.CODE)} to disable`),N.reportSeparator();else if(Je.telemetry?.shouldShowTips){let U=await on.get(\"https://repo.yarnpkg.com/tags\",{configuration:r,jsonResponse:!0}).catch(()=>null);if(U!==null){let z=null;if(nn!==null){let le=wH.default.prerelease(nn)?\"canary\":\"stable\",ce=U.latest[le];wH.default.gt(ce,nn)&&(z=[le,ce])}if(z)Je.telemetry.commitTips(),N.reportInfo(88,`${pe.applyStyle(r,`A new ${z[0]} version of Yarn is available:`,pe.Style.BOLD)} ${G.prettyReference(r,z[1])}!`),N.reportInfo(88,`Upgrade now by running ${pe.pretty(r,`yarn set version ${z[1]}`,pe.Type.CODE)}`),N.reportSeparator();else{let te=Je.telemetry.selectTip(U.tips);te&&(N.reportInfo(89,pe.pretty(r,te.message,pe.Type.MARKDOWN_INLINE)),te.url&&N.reportInfo(89,`Learn more at ${te.url}`),N.reportSeparator())}}}});if(T.hasErrors())return T.exitCode()}let{project:p,workspace:h}=await Qt.find(r,this.context.cwd),E=p.lockfileLastVersion;if(E!==null){let T=await Lt.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async N=>{let U={};for(let z of U0t)z.selector(E)&&typeof r.sources.get(z.name)>\"u\"&&(r.use(\"<compat>\",{[z.name]:z.value},p.cwd,{overwrite:!0}),U[z.name]=z.value);Object.keys(U).length>0&&(await Je.updateConfiguration(p.cwd,U),N.reportInfo(87,\"Migrated your project to the latest Yarn version \\u{1F680}\"),N.reportSeparator())});if(T.hasErrors())return T.exitCode()}let w=await Wr.find(r,{immutable:A,check:this.checkCache});if(!h)throw new or(p.cwd,this.context.cwd);await p.restoreInstallState({restoreResolutions:!1});let D=r.get(\"enableHardenedMode\");D&&typeof r.sources.get(\"enableHardenedMode\")>\"u\"&&await Lt.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async T=>{T.reportWarning(0,\"Yarn detected that the current workflow is executed from a public pull request. For safety the hardened mode has been enabled.\"),T.reportWarning(0,`It will prevent malicious lockfile manipulations, in exchange for a slower install time. You can opt-out if necessary; check our ${pe.applyHyperlink(r,\"documentation\",\"https://yarnpkg.com/features/security#hardened-mode\")} for more details.`),T.reportSeparator()}),(this.refreshLockfile??D)&&(p.lockfileNeedsRefresh=!0);let b=this.checkResolutions??D;return(await Lt.start({configuration:r,json:this.json,stdout:this.context.stdout,forceSectionAlignment:!0,includeLogs:!0,includeVersion:!0},async T=>{await p.install({cache:w,report:T,immutable:u,checkResolutions:b,mode:this.mode})})).exitCode()}},_0t=\"<<<<<<<\";async function H0t(t,e){if(!t.projectCwd)return!1;let r=K.join(t.projectCwd,mr.lockfile);if(!await ae.existsPromise(r)||!(await ae.readFilePromise(r,\"utf8\")).includes(_0t))return!1;if(e)throw new zt(47,\"Cannot autofix a lockfile when running an immutable install\");let a=await Hr.execvp(\"git\",[\"rev-parse\",\"MERGE_HEAD\",\"HEAD\"],{cwd:t.projectCwd});if(a.code!==0&&(a=await Hr.execvp(\"git\",[\"rev-parse\",\"REBASE_HEAD\",\"HEAD\"],{cwd:t.projectCwd})),a.code!==0&&(a=await Hr.execvp(\"git\",[\"rev-parse\",\"CHERRY_PICK_HEAD\",\"HEAD\"],{cwd:t.projectCwd})),a.code!==0)throw new zt(83,\"Git returned an error when trying to find the commits pertaining to the conflict\");let n=await Promise.all(a.stdout.trim().split(/\\n/).map(async A=>{let p=await Hr.execvp(\"git\",[\"show\",`${A}:./${mr.lockfile}`],{cwd:t.projectCwd});if(p.code!==0)throw new zt(83,`Git returned an error when trying to access the lockfile content in ${A}`);try{return Ki(p.stdout)}catch{throw new zt(46,\"A variant of the conflicting lockfile failed to parse\")}}));n=n.filter(A=>!!A.__metadata);for(let A of n){if(A.__metadata.version<7)for(let p of Object.keys(A)){if(p===\"__metadata\")continue;let h=G.parseDescriptor(p,!0),E=t.normalizeDependency(h),w=G.stringifyDescriptor(E);w!==p&&(A[w]=A[p],delete A[p])}for(let p of Object.keys(A)){if(p===\"__metadata\")continue;let h=A[p].checksum;typeof h==\"string\"&&h.includes(\"/\")||(A[p].checksum=`${A.__metadata.cacheKey}/${h}`)}}let u=Object.assign({},...n);u.__metadata.version=`${Math.min(...n.map(A=>parseInt(A.__metadata.version??0)))}`,u.__metadata.cacheKey=\"merged\";for(let[A,p]of Object.entries(u))typeof p==\"string\"&&delete u[A];return await ae.changeFilePromise(r,Pa(u),{automaticNewlines:!0}),!0}async function q0t(t,e){if(!t.projectCwd)return!1;let r=[],o=K.join(t.projectCwd,\".yarn/plugins/@yarnpkg\");return await Je.updateConfiguration(t.projectCwd,{plugins:n=>{if(!Array.isArray(n))return n;let u=n.filter(A=>{if(!A.path)return!0;let p=K.resolve(t.projectCwd,A.path),h=j1.has(A.spec)&&K.contains(o,p);return h&&r.push(p),!h});return u.length===0?Je.deleteProperty:u.length===n.length?n:u}},{immutable:e})?(await Promise.all(r.map(async n=>{await ae.removePromise(n)})),!0):!1}Ke();Pt();Gt();var kE=class extends ut{constructor(){super(...arguments);this.all=de.Boolean(\"-A,--all\",!1,{description:\"Link all workspaces belonging to the target projects to the current one\"});this.private=de.Boolean(\"-p,--private\",!1,{description:\"Also link private workspaces belonging to the target projects to the current one\"});this.relative=de.Boolean(\"-r,--relative\",!1,{description:\"Link workspaces using relative paths instead of absolute paths\"});this.destinations=de.Rest()}static{this.paths=[[\"link\"]]}static{this.usage=st.Usage({description:\"connect the local project to another one\",details:\"\\n      This command will set a new `resolutions` field in the project-level manifest and point it to the workspace at the specified location (even if part of another project).\\n    \",examples:[[\"Register one or more remote workspaces for use in the current project\",\"$0 link ~/ts-loader ~/jest\"],[\"Register all workspaces from a remote project for use in the current project\",\"$0 link ~/jest --all\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Wr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=o.topLevelWorkspace,A=[];for(let p of this.destinations){let h=K.resolve(this.context.cwd,Ae.toPortablePath(p)),E=await Je.find(h,this.context.plugins,{useRc:!1,strict:!1}),{project:w,workspace:D}=await Qt.find(E,h);if(o.cwd===w.cwd)throw new ot(`Invalid destination '${p}'; Can't link the project to itself`);if(!D)throw new or(w.cwd,h);if(this.all){let b=!1;for(let C of w.workspaces)C.manifest.name&&(!C.manifest.private||this.private)&&(A.push(C),b=!0);if(!b)throw new ot(`No workspace found to be linked in the target project: ${p}`)}else{if(!D.manifest.name)throw new ot(`The target workspace at '${p}' doesn't have a name and thus cannot be linked`);if(D.manifest.private&&!this.private)throw new ot(`The target workspace at '${p}' is marked private - use the --private flag to link it anyway`);A.push(D)}}for(let p of A){let h=G.stringifyIdent(p.anchoredLocator),E=this.relative?K.relative(o.cwd,p.cwd):p.cwd;u.manifest.resolutions.push({pattern:{descriptor:{fullName:h}},reference:`portal:${E}`})}return await o.installWithNewReport({stdout:this.context.stdout},{cache:n})}};Gt();var QE=class extends ut{constructor(){super(...arguments);this.args=de.Proxy()}static{this.paths=[[\"node\"]]}static{this.usage=st.Usage({description:\"run node with the hook already setup\",details:`\n      This command simply runs Node. It also makes sure to call it in a way that's compatible with the current project (for example, on PnP projects the environment will be setup in such a way that PnP will be correctly injected into the environment).\n\n      The Node process will use the exact same version of Node as the one used to run Yarn itself, which might be a good way to ensure that your commands always use a consistent Node version.\n    `,examples:[[\"Run a Node script\",\"$0 node ./my-script.js\"]]})}async execute(){return this.cli.run([\"exec\",\"node\",...this.args])}};Ke();Gt();var FE=class extends ut{constructor(){super(...arguments);this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"})}static{this.paths=[[\"plugin\",\"check\"]]}static{this.usage=st.Usage({category:\"Plugin-related commands\",description:\"find all third-party plugins that differ from their own spec\",details:`\n      Check only the plugins from https.\n\n      If this command detects any plugin differences in the CI environment, it will throw an error.\n    `,examples:[[\"find all third-party plugins that differ from their own spec\",\"$0 plugin check\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=await Je.findRcFiles(this.context.cwd);return(await Lt.start({configuration:r,json:this.json,stdout:this.context.stdout},async n=>{for(let u of o)if(u.data?.plugins)for(let A of u.data.plugins){if(!A.checksum||!A.spec.match(/^https?:/))continue;let p=await on.get(A.spec,{configuration:r}),h=bn.makeHash(p);if(A.checksum===h)continue;let E=pe.pretty(r,A.path,pe.Type.PATH),w=pe.pretty(r,A.spec,pe.Type.URL),D=`${E} is different from the file provided by ${w}`;n.reportJson({...A,newChecksum:h}),n.reportError(0,D)}})).exitCode()}};Ke();Ke();Pt();Gt();var Yde=ve(\"os\");Ke();Pt();Gt();var qde=ve(\"os\");Ke();Ol();Gt();var j0t=\"https://raw.githubusercontent.com/yarnpkg/berry/master/plugins.yml\";async function zg(t,e){let r=await on.get(j0t,{configuration:t}),o=Ki(r.toString());return Object.fromEntries(Object.entries(o).filter(([a,n])=>!e||Ur.satisfiesWithPrereleases(e,n.range??\"<4.0.0-rc.1\")))}var RE=class extends ut{constructor(){super(...arguments);this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"})}static{this.paths=[[\"plugin\",\"list\"]]}static{this.usage=st.Usage({category:\"Plugin-related commands\",description:\"list the available official plugins\",details:\"\\n      This command prints the plugins available directly from the Yarn repository. Only those plugins can be referenced by name in `yarn plugin import`.\\n    \",examples:[[\"List the official plugins\",\"$0 plugin list\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins);return(await Lt.start({configuration:r,json:this.json,stdout:this.context.stdout},async a=>{let n=await zg(r,nn);for(let[u,{experimental:A,...p}]of Object.entries(n)){let h=u;A&&(h+=\" [experimental]\"),a.reportJson({name:u,experimental:A,...p}),a.reportInfo(null,h)}})).exitCode()}};var G0t=/^[0-9]+$/,W0t=process.platform===\"win32\";function jde(t){return G0t.test(t)?`pull/${t}/head`:t}var Y0t=({repository:t,branch:e},r)=>[[\"git\",\"init\",Ae.fromPortablePath(r)],[\"git\",\"remote\",\"add\",\"origin\",t],[\"git\",\"fetch\",\"origin\",\"--depth=1\",jde(e)],[\"git\",\"reset\",\"--hard\",\"FETCH_HEAD\"]],K0t=({branch:t})=>[[\"git\",\"fetch\",\"origin\",\"--depth=1\",jde(t),\"--force\"],[\"git\",\"reset\",\"--hard\",\"FETCH_HEAD\"],[\"git\",\"clean\",\"-dfx\",\"-e\",\"packages/yarnpkg-cli/bundles\"]],V0t=({plugins:t,noMinify:e},r,o)=>[[\"yarn\",\"build:cli\",...new Array().concat(...t.map(a=>[\"--plugin\",K.resolve(o,a)])),...e?[\"--no-minify\"]:[],\"|\"],[W0t?\"move\":\"mv\",\"packages/yarnpkg-cli/bundles/yarn.js\",Ae.fromPortablePath(r),\"|\"]],TE=class extends ut{constructor(){super(...arguments);this.installPath=de.String(\"--path\",{description:\"The path where the repository should be cloned to\"});this.repository=de.String(\"--repository\",\"https://github.com/yarnpkg/berry.git\",{description:\"The repository that should be cloned\"});this.branch=de.String(\"--branch\",\"master\",{description:\"The branch of the repository that should be cloned\"});this.plugins=de.Array(\"--plugin\",[],{description:\"An array of additional plugins that should be included in the bundle\"});this.dryRun=de.Boolean(\"-n,--dry-run\",!1,{description:\"If set, the bundle will be built but not added to the project\"});this.noMinify=de.Boolean(\"--no-minify\",!1,{description:\"Build a bundle for development (debugging) - non-minified and non-mangled\"});this.force=de.Boolean(\"-f,--force\",!1,{description:\"Always clone the repository instead of trying to fetch the latest commits\"});this.skipPlugins=de.Boolean(\"--skip-plugins\",!1,{description:\"Skip updating the contrib plugins\"})}static{this.paths=[[\"set\",\"version\",\"from\",\"sources\"]]}static{this.usage=st.Usage({description:\"build Yarn from master\",details:`\n      This command will clone the Yarn repository into a temporary folder, then build it. The resulting bundle will then be copied into the local project.\n\n      By default, it also updates all contrib plugins to the same commit the bundle is built from. This behavior can be disabled by using the \\`--skip-plugins\\` flag.\n    `,examples:[[\"Build Yarn from master\",\"$0 set version from sources\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o}=await Qt.find(r,this.context.cwd),a=typeof this.installPath<\"u\"?K.resolve(this.context.cwd,Ae.toPortablePath(this.installPath)):K.resolve(Ae.toPortablePath((0,qde.tmpdir)()),\"yarnpkg-sources\",bn.makeHash(this.repository).slice(0,6));return(await Lt.start({configuration:r,stdout:this.context.stdout},async u=>{await BH(this,{configuration:r,report:u,target:a}),u.reportSeparator(),u.reportInfo(0,\"Building a fresh bundle\"),u.reportSeparator();let A=await Hr.execvp(\"git\",[\"rev-parse\",\"--short\",\"HEAD\"],{cwd:a,strict:!0}),p=K.join(a,`packages/yarnpkg-cli/bundles/yarn-${A.stdout.trim()}.js`);ae.existsSync(p)||(await M2(V0t(this,p,a),{configuration:r,context:this.context,target:a}),u.reportSeparator());let h=await ae.readFilePromise(p);if(!this.dryRun){let{bundleVersion:E}=await IH(r,null,async()=>h,{report:u});this.skipPlugins||await z0t(this,E,{project:o,report:u,target:a})}})).exitCode()}};async function M2(t,{configuration:e,context:r,target:o}){for(let[a,...n]of t){let u=n[n.length-1]===\"|\";if(u&&n.pop(),u)await Hr.pipevp(a,n,{cwd:o,stdin:r.stdin,stdout:r.stdout,stderr:r.stderr,strict:!0});else{r.stdout.write(`${pe.pretty(e,`  $ ${[a,...n].join(\" \")}`,\"grey\")}\n`);try{await Hr.execvp(a,n,{cwd:o,strict:!0})}catch(A){throw r.stdout.write(A.stdout||A.stack),A}}}}async function BH(t,{configuration:e,report:r,target:o}){let a=!1;if(!t.force&&ae.existsSync(K.join(o,\".git\"))){r.reportInfo(0,\"Fetching the latest commits\"),r.reportSeparator();try{await M2(K0t(t),{configuration:e,context:t.context,target:o}),a=!0}catch{r.reportSeparator(),r.reportWarning(0,\"Repository update failed; we'll try to regenerate it\")}}a||(r.reportInfo(0,\"Cloning the remote repository\"),r.reportSeparator(),await ae.removePromise(o),await ae.mkdirPromise(o,{recursive:!0}),await M2(Y0t(t,o),{configuration:e,context:t.context,target:o}))}async function z0t(t,e,{project:r,report:o,target:a}){let n=await zg(r.configuration,e),u=new Set(Object.keys(n));for(let A of r.configuration.plugins.keys())u.has(A)&&await vH(A,t,{project:r,report:o,target:a})}Ke();Ke();Pt();Gt();var Gde=et(ni()),Wde=ve(\"vm\");var LE=class extends ut{constructor(){super(...arguments);this.name=de.String();this.checksum=de.Boolean(\"--checksum\",!0,{description:\"Whether to care if this plugin is modified\"})}static{this.paths=[[\"plugin\",\"import\"]]}static{this.usage=st.Usage({category:\"Plugin-related commands\",description:\"download a plugin\",details:`\n      This command downloads the specified plugin from its remote location and updates the configuration to reference it in further CLI invocations.\n\n      Three types of plugin references are accepted:\n\n      - If the plugin is stored within the Yarn repository, it can be referenced by name.\n      - Third-party plugins can be referenced directly through their public urls.\n      - Local plugins can be referenced by their path on the disk.\n\n      If the \\`--no-checksum\\` option is set, Yarn will no longer care if the plugin is modified.\n\n      Plugins cannot be downloaded from the npm registry, and aren't allowed to have dependencies (they need to be bundled into a single file, possibly thanks to the \\`@yarnpkg/builder\\` package).\n    `,examples:[['Download and activate the \"@yarnpkg/plugin-exec\" plugin',\"$0 plugin import @yarnpkg/plugin-exec\"],['Download and activate the \"@yarnpkg/plugin-exec\" plugin (shorthand)',\"$0 plugin import exec\"],[\"Download and activate a community plugin\",\"$0 plugin import https://example.org/path/to/plugin.js\"],[\"Activate a local plugin\",\"$0 plugin import ./path/to/plugin.js\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins);return(await Lt.start({configuration:r,stdout:this.context.stdout},async a=>{let{project:n}=await Qt.find(r,this.context.cwd),u,A;if(this.name.match(/^\\.{0,2}[\\\\/]/)||Ae.isAbsolute(this.name)){let p=K.resolve(this.context.cwd,Ae.toPortablePath(this.name));a.reportInfo(0,`Reading ${pe.pretty(r,p,pe.Type.PATH)}`),u=K.relative(n.cwd,p),A=await ae.readFilePromise(p)}else{let p;if(this.name.match(/^https?:/)){try{new URL(this.name)}catch{throw new zt(52,`Plugin specifier \"${this.name}\" is neither a plugin name nor a valid url`)}u=this.name,p=this.name}else{let h=G.parseLocator(this.name.replace(/^((@yarnpkg\\/)?plugin-)?/,\"@yarnpkg/plugin-\"));if(h.reference!==\"unknown\"&&!Gde.default.valid(h.reference))throw new zt(0,\"Official plugins only accept strict version references. Use an explicit URL if you wish to download them from another location.\");let E=G.stringifyIdent(h),w=await zg(r,nn);if(!Object.hasOwn(w,E)){let D=`Couldn't find a plugin named ${G.prettyIdent(r,h)} on the remote registry.\n`;throw r.plugins.has(E)?D+=`A plugin named ${G.prettyIdent(r,h)} is already installed; possibly attempting to import a built-in plugin.`:D+=`Note that only the plugins referenced on our website (${pe.pretty(r,\"https://github.com/yarnpkg/berry/blob/master/plugins.yml\",pe.Type.URL)}) can be referenced by their name; any other plugin will have to be referenced through its public url (for example ${pe.pretty(r,\"https://github.com/yarnpkg/berry/raw/master/packages/plugin-typescript/bin/%40yarnpkg/plugin-typescript.js\",pe.Type.URL)}).`,new zt(51,D)}u=E,p=w[E].url,h.reference!==\"unknown\"?p=p.replace(/\\/master\\//,`/${E}/${h.reference}/`):nn!==null&&(p=p.replace(/\\/master\\//,`/@yarnpkg/cli/${nn}/`))}a.reportInfo(0,`Downloading ${pe.pretty(r,p,\"green\")}`),A=await on.get(p,{configuration:r})}await DH(u,A,{checksum:this.checksum,project:n,report:a})})).exitCode()}};async function DH(t,e,{checksum:r=!0,project:o,report:a}){let{configuration:n}=o,u={},A={exports:u};(0,Wde.runInNewContext)(e.toString(),{module:A,exports:u});let h=`.yarn/plugins/${A.exports.name}.cjs`,E=K.resolve(o.cwd,h);a.reportInfo(0,`Saving the new plugin in ${pe.pretty(n,h,\"magenta\")}`),await ae.mkdirPromise(K.dirname(E),{recursive:!0}),await ae.writeFilePromise(E,e);let w={path:h,spec:t};r&&(w.checksum=bn.makeHash(e)),await Je.addPlugin(o.cwd,[w])}var J0t=({pluginName:t,noMinify:e},r)=>[[\"yarn\",`build:${t}`,...e?[\"--no-minify\"]:[],\"|\"]],NE=class extends ut{constructor(){super(...arguments);this.installPath=de.String(\"--path\",{description:\"The path where the repository should be cloned to\"});this.repository=de.String(\"--repository\",\"https://github.com/yarnpkg/berry.git\",{description:\"The repository that should be cloned\"});this.branch=de.String(\"--branch\",\"master\",{description:\"The branch of the repository that should be cloned\"});this.noMinify=de.Boolean(\"--no-minify\",!1,{description:\"Build a plugin for development (debugging) - non-minified and non-mangled\"});this.force=de.Boolean(\"-f,--force\",!1,{description:\"Always clone the repository instead of trying to fetch the latest commits\"});this.name=de.String()}static{this.paths=[[\"plugin\",\"import\",\"from\",\"sources\"]]}static{this.usage=st.Usage({category:\"Plugin-related commands\",description:\"build a plugin from sources\",details:`\n      This command clones the Yarn repository into a temporary folder, builds the specified contrib plugin and updates the configuration to reference it in further CLI invocations.\n\n      The plugins can be referenced by their short name if sourced from the official Yarn repository.\n    `,examples:[['Build and activate the \"@yarnpkg/plugin-exec\" plugin',\"$0 plugin import from sources @yarnpkg/plugin-exec\"],['Build and activate the \"@yarnpkg/plugin-exec\" plugin (shorthand)',\"$0 plugin import from sources exec\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=typeof this.installPath<\"u\"?K.resolve(this.context.cwd,Ae.toPortablePath(this.installPath)):K.resolve(Ae.toPortablePath((0,Yde.tmpdir)()),\"yarnpkg-sources\",bn.makeHash(this.repository).slice(0,6));return(await Lt.start({configuration:r,stdout:this.context.stdout},async n=>{let{project:u}=await Qt.find(r,this.context.cwd),A=G.parseIdent(this.name.replace(/^((@yarnpkg\\/)?plugin-)?/,\"@yarnpkg/plugin-\")),p=G.stringifyIdent(A),h=await zg(r,nn);if(!Object.hasOwn(h,p))throw new zt(51,`Couldn't find a plugin named \"${p}\" on the remote registry. Note that only the plugins referenced on our website (https://github.com/yarnpkg/berry/blob/master/plugins.yml) can be built and imported from sources.`);let E=p;await BH(this,{configuration:r,report:n,target:o}),await vH(E,this,{project:u,report:n,target:o})})).exitCode()}};async function vH(t,{context:e,noMinify:r},{project:o,report:a,target:n}){let u=t.replace(/@yarnpkg\\//,\"\"),{configuration:A}=o;a.reportSeparator(),a.reportInfo(0,`Building a fresh ${u}`),a.reportSeparator(),await M2(J0t({pluginName:u,noMinify:r},n),{configuration:A,context:e,target:n}),a.reportSeparator();let p=K.resolve(n,`packages/${u}/bundles/${t}.js`),h=await ae.readFilePromise(p);await DH(t,h,{project:o,report:a})}Ke();Pt();Gt();var OE=class extends ut{constructor(){super(...arguments);this.name=de.String()}static{this.paths=[[\"plugin\",\"remove\"]]}static{this.usage=st.Usage({category:\"Plugin-related commands\",description:\"remove a plugin\",details:`\n      This command deletes the specified plugin from the .yarn/plugins folder and removes it from the configuration.\n\n      **Note:** The plugins have to be referenced by their name property, which can be obtained using the \\`yarn plugin runtime\\` command. Shorthands are not allowed.\n   `,examples:[[\"Remove a plugin imported from the Yarn repository\",\"$0 plugin remove @yarnpkg/plugin-typescript\"],[\"Remove a plugin imported from a local file\",\"$0 plugin remove my-local-plugin\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o}=await Qt.find(r,this.context.cwd);return(await Lt.start({configuration:r,stdout:this.context.stdout},async n=>{let u=this.name,A=G.parseIdent(u);if(!r.plugins.has(u))throw new ot(`${G.prettyIdent(r,A)} isn't referenced by the current configuration`);let p=`.yarn/plugins/${u}.cjs`,h=K.resolve(o.cwd,p);ae.existsSync(h)&&(n.reportInfo(0,`Removing ${pe.pretty(r,p,pe.Type.PATH)}...`),await ae.removePromise(h)),n.reportInfo(0,\"Updating the configuration...\"),await Je.updateConfiguration(o.cwd,{plugins:E=>{if(!Array.isArray(E))return E;let w=E.filter(D=>D.path!==p);return w.length===0?Je.deleteProperty:w.length===E.length?E:w}})})).exitCode()}};Ke();Gt();var ME=class extends ut{constructor(){super(...arguments);this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"})}static{this.paths=[[\"plugin\",\"runtime\"]]}static{this.usage=st.Usage({category:\"Plugin-related commands\",description:\"list the active plugins\",details:`\n      This command prints the currently active plugins. Will be displayed both builtin plugins and external plugins.\n    `,examples:[[\"List the currently active plugins\",\"$0 plugin runtime\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins);return(await Lt.start({configuration:r,json:this.json,stdout:this.context.stdout},async a=>{for(let n of r.plugins.keys()){let u=this.context.plugins.plugins.has(n),A=n;u&&(A+=\" [builtin]\"),a.reportJson({name:n,builtin:u}),a.reportInfo(null,`${A}`)}})).exitCode()}};Ke();Ke();Gt();var UE=class extends ut{constructor(){super(...arguments);this.idents=de.Rest()}static{this.paths=[[\"rebuild\"]]}static{this.usage=st.Usage({description:\"rebuild the project's native packages\",details:`\n      This command will automatically cause Yarn to forget about previous compilations of the given packages and to run them again.\n\n      Note that while Yarn forgets the compilation, the previous artifacts aren't erased from the filesystem and may affect the next builds (in good or bad). To avoid this, you may remove the .yarn/unplugged folder, or any other relevant location where packages might have been stored (Yarn may offer a way to do that automatically in the future).\n\n      By default all packages will be rebuilt, but you can filter the list by specifying the names of the packages you want to clear from memory.\n    `,examples:[[\"Rebuild all packages\",\"$0 rebuild\"],[\"Rebuild fsevents only\",\"$0 rebuild fsevents\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Wr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);let u=new Set;for(let A of this.idents)u.add(G.parseIdent(A).identHash);if(await o.restoreInstallState({restoreResolutions:!1}),await o.resolveEverything({cache:n,report:new Ri}),u.size>0)for(let A of o.storedPackages.values())u.has(A.identHash)&&(o.storedBuildState.delete(A.locatorHash),o.skippedBuilds.delete(A.locatorHash));else o.storedBuildState.clear(),o.skippedBuilds.clear();return await o.installWithNewReport({stdout:this.context.stdout,quiet:this.context.quiet},{cache:n})}};Ke();Ke();Ke();Gt();var PH=et(Xo());il();var _E=class extends ut{constructor(){super(...arguments);this.all=de.Boolean(\"-A,--all\",!1,{description:\"Apply the operation to all workspaces from the current project\"});this.mode=de.String(\"--mode\",{description:\"Change what artifacts installs generate\",validator:js(yl)});this.patterns=de.Rest()}static{this.paths=[[\"remove\"]]}static{this.usage=st.Usage({description:\"remove dependencies from the project\",details:`\n      This command will remove the packages matching the specified patterns from the current workspace.\n\n      If the \\`--mode=<mode>\\` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\n\n      - \\`skip-build\\` will not run the build scripts at all. Note that this is different from setting \\`enableScripts\\` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\n\n      - \\`update-lockfile\\` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\n\n      This command accepts glob patterns as arguments (if valid Idents and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them.\n    `,examples:[[\"Remove a dependency from the current project\",\"$0 remove lodash\"],[\"Remove a dependency from all workspaces at once\",\"$0 remove lodash --all\"],[\"Remove all dependencies starting with `eslint-`\",\"$0 remove 'eslint-*'\"],[\"Remove all dependencies with the `@babel` scope\",\"$0 remove '@babel/*'\"],[\"Remove all dependencies matching `react-dom` or `react-helmet`\",\"$0 remove 'react-{dom,helmet}'\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Wr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=this.all?o.workspaces:[a],A=[\"dependencies\",\"devDependencies\",\"peerDependencies\"],p=[],h=!1,E=[];for(let C of this.patterns){let T=!1,N=G.parseIdent(C);for(let U of u){let z=[...U.manifest.peerDependenciesMeta.keys()];for(let te of(0,PH.default)(z,C))U.manifest.peerDependenciesMeta.delete(te),h=!0,T=!0;for(let te of A){let le=U.manifest.getForScope(te),ce=[...le.values()].map(ue=>G.stringifyIdent(ue));for(let ue of(0,PH.default)(ce,G.stringifyIdent(N))){let{identHash:Ie}=G.parseIdent(ue),he=le.get(Ie);if(typeof he>\"u\")throw new Error(\"Assertion failed: Expected the descriptor to be registered\");U.manifest[te].delete(Ie),E.push([U,te,he]),h=!0,T=!0}}}T||p.push(C)}let w=p.length>1?\"Patterns\":\"Pattern\",D=p.length>1?\"don't\":\"doesn't\",b=this.all?\"any\":\"this\";if(p.length>0)throw new ot(`${w} ${pe.prettyList(r,p,pe.Type.CODE)} ${D} match any packages referenced by ${b} workspace`);return h?(await r.triggerMultipleHooks(C=>C.afterWorkspaceDependencyRemoval,E),await o.installWithNewReport({stdout:this.context.stdout},{cache:n,mode:this.mode})):0}};Ke();Ke();Gt();var Kde=ve(\"util\"),HE=class extends ut{constructor(){super(...arguments);this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"})}static{this.paths=[[\"run\"]]}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);return(await Lt.start({configuration:r,stdout:this.context.stdout,json:this.json},async u=>{let A=a.manifest.scripts,p=qe.sortMap(A.keys(),w=>w),h={breakLength:1/0,colors:r.get(\"enableColors\"),maxArrayLength:2},E=p.reduce((w,D)=>Math.max(w,D.length),0);for(let[w,D]of A.entries())u.reportInfo(null,`${w.padEnd(E,\" \")}   ${(0,Kde.inspect)(D,h)}`),u.reportJson({name:w,script:D})})).exitCode()}};Ke();Ke();Gt();var qE=class extends ut{constructor(){super(...arguments);this.inspect=de.String(\"--inspect\",!1,{tolerateBoolean:!0,description:\"Forwarded to the underlying Node process when executing a binary\"});this.inspectBrk=de.String(\"--inspect-brk\",!1,{tolerateBoolean:!0,description:\"Forwarded to the underlying Node process when executing a binary\"});this.topLevel=de.Boolean(\"-T,--top-level\",!1,{description:\"Check the root workspace for scripts and/or binaries instead of the current one\"});this.binariesOnly=de.Boolean(\"-B,--binaries-only\",!1,{description:\"Ignore any user defined scripts and only check for binaries\"});this.require=de.String(\"--require\",{description:\"Forwarded to the underlying Node process when executing a binary\"});this.silent=de.Boolean(\"--silent\",{hidden:!0});this.scriptName=de.String();this.args=de.Proxy()}static{this.paths=[[\"run\"]]}static{this.usage=st.Usage({description:\"run a script defined in the package.json\",details:`\n      This command will run a tool. The exact tool that will be executed will depend on the current state of your workspace:\n\n      - If the \\`scripts\\` field from your local package.json contains a matching script name, its definition will get executed.\n\n      - Otherwise, if one of the local workspace's dependencies exposes a binary with a matching name, this binary will get executed.\n\n      - Otherwise, if the specified name contains a colon character and if one of the workspaces in the project contains exactly one script with a matching name, then this script will get executed.\n\n      Whatever happens, the cwd of the spawned process will be the workspace that declares the script (which makes it possible to call commands cross-workspaces using the third syntax).\n    `,examples:[[\"Run the tests from the local workspace\",\"$0 run test\"],['Same thing, but without the \"run\" keyword',\"$0 test\"],[\"Inspect Webpack while running\",\"$0 run --inspect-brk webpack\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a,locator:n}=await Qt.find(r,this.context.cwd);await o.restoreInstallState();let u=this.topLevel?o.topLevelWorkspace.anchoredLocator:n;if(!this.binariesOnly&&await hn.hasPackageScript(u,this.scriptName,{project:o}))return await hn.executePackageScript(u,this.scriptName,this.args,{project:o,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});let A=await hn.getPackageAccessibleBinaries(u,{project:o});if(A.get(this.scriptName)){let h=[];return this.inspect&&(typeof this.inspect==\"string\"?h.push(`--inspect=${this.inspect}`):h.push(\"--inspect\")),this.inspectBrk&&(typeof this.inspectBrk==\"string\"?h.push(`--inspect-brk=${this.inspectBrk}`):h.push(\"--inspect-brk\")),this.require&&h.push(`--require=${this.require}`),await hn.executePackageAccessibleBinary(u,this.scriptName,this.args,{cwd:this.context.cwd,project:o,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr,nodeArgs:h,packageAccessibleBinaries:A})}if(!this.topLevel&&!this.binariesOnly&&a&&this.scriptName.includes(\":\")){let E=(await Promise.all(o.workspaces.map(async w=>w.manifest.scripts.has(this.scriptName)?w:null))).filter(w=>w!==null);if(E.length===1)return await hn.executeWorkspaceScript(E[0],this.scriptName,this.args,{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr})}if(this.topLevel)throw this.scriptName===\"node-gyp\"?new ot(`Couldn't find a script name \"${this.scriptName}\" in the top-level (used by ${G.prettyLocator(r,n)}). This typically happens because some package depends on \"node-gyp\" to build itself, but didn't list it in their dependencies. To fix that, please run \"yarn add node-gyp\" into your top-level workspace. You also can open an issue on the repository of the specified package to suggest them to use an optional peer dependency.`):new ot(`Couldn't find a script name \"${this.scriptName}\" in the top-level (used by ${G.prettyLocator(r,n)}).`);{if(this.scriptName===\"global\")throw new ot(\"The 'yarn global' commands have been removed in 2.x - consider using 'yarn dlx' or a third-party plugin instead\");let h=[this.scriptName].concat(this.args);for(let[E,w]of oE)for(let D of w)if(h.length>=D.length&&JSON.stringify(h.slice(0,D.length))===JSON.stringify(D))throw new ot(`Couldn't find a script named \"${this.scriptName}\", but a matching command can be found in the ${E} plugin. You can install it with \"yarn plugin import ${E}\".`);throw new ot(`Couldn't find a script named \"${this.scriptName}\".`)}}};Ke();Ke();Gt();var jE=class extends ut{constructor(){super(...arguments);this.descriptor=de.String();this.resolution=de.String()}static{this.paths=[[\"set\",\"resolution\"]]}static{this.usage=st.Usage({description:\"enforce a package resolution\",details:'\\n      This command updates the resolution table so that `descriptor` is resolved by `resolution`.\\n\\n      Note that by default this command only affect the current resolution table - meaning that this \"manual override\" will disappear if you remove the lockfile, or if the package disappear from the table. If you wish to make the enforced resolution persist whatever happens, edit the `resolutions` field in your top-level manifest.\\n\\n      Note that no attempt is made at validating that `resolution` is a valid resolution entry for `descriptor`.\\n    ',examples:[[\"Force all instances of lodash@npm:^1.2.3 to resolve to 1.5.0\",\"$0 set resolution lodash@npm:^1.2.3 1.5.0\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Wr.find(r);if(await o.restoreInstallState({restoreResolutions:!1}),!a)throw new or(o.cwd,this.context.cwd);let u=G.parseDescriptor(this.descriptor,!0),A=G.makeDescriptor(u,this.resolution);return o.storedDescriptors.set(u.descriptorHash,u),o.storedDescriptors.set(A.descriptorHash,A),o.resolutionAliases.set(u.descriptorHash,A.descriptorHash),await o.installWithNewReport({stdout:this.context.stdout},{cache:n})}};Ke();Pt();Gt();var Vde=et(Xo()),GE=class extends ut{constructor(){super(...arguments);this.all=de.Boolean(\"-A,--all\",!1,{description:\"Unlink all workspaces belonging to the target project from the current one\"});this.leadingArguments=de.Rest()}static{this.paths=[[\"unlink\"]]}static{this.usage=st.Usage({description:\"disconnect the local project from another one\",details:`\n      This command will remove any resolutions in the project-level manifest that would have been added via a yarn link with similar arguments.\n    `,examples:[[\"Unregister a remote workspace in the current project\",\"$0 unlink ~/ts-loader\"],[\"Unregister all workspaces from a remote project in the current project\",\"$0 unlink ~/jest --all\"],[\"Unregister all previously linked workspaces\",\"$0 unlink --all\"],[\"Unregister all workspaces matching a glob\",\"$0 unlink '@babel/*' 'pkg-{a,b}'\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Wr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);let u=o.topLevelWorkspace,A=new Set;if(this.leadingArguments.length===0&&this.all)for(let{pattern:p,reference:h}of u.manifest.resolutions)h.startsWith(\"portal:\")&&A.add(p.descriptor.fullName);if(this.leadingArguments.length>0)for(let p of this.leadingArguments){let h=K.resolve(this.context.cwd,Ae.toPortablePath(p));if(qe.isPathLike(p)){let E=await Je.find(h,this.context.plugins,{useRc:!1,strict:!1}),{project:w,workspace:D}=await Qt.find(E,h);if(!D)throw new or(w.cwd,h);if(this.all){for(let b of w.workspaces)b.manifest.name&&A.add(G.stringifyIdent(b.anchoredLocator));if(A.size===0)throw new ot(\"No workspace found to be unlinked in the target project\")}else{if(!D.manifest.name)throw new ot(\"The target workspace doesn't have a name and thus cannot be unlinked\");A.add(G.stringifyIdent(D.anchoredLocator))}}else{let E=[...u.manifest.resolutions.map(({pattern:w})=>w.descriptor.fullName)];for(let w of(0,Vde.default)(E,p))A.add(w)}}return u.manifest.resolutions=u.manifest.resolutions.filter(({pattern:p})=>!A.has(p.descriptor.fullName)),await o.installWithNewReport({stdout:this.context.stdout,quiet:this.context.quiet},{cache:n})}};Ke();Ke();Ke();Gt();var zde=et(Q2()),SH=et(Xo());il();var WE=class extends ut{constructor(){super(...arguments);this.interactive=de.Boolean(\"-i,--interactive\",{description:\"Offer various choices, depending on the detected upgrade paths\"});this.fixed=de.Boolean(\"-F,--fixed\",!1,{description:\"Store dependency tags as-is instead of resolving them\"});this.exact=de.Boolean(\"-E,--exact\",!1,{description:\"Don't use any semver modifier on the resolved range\"});this.tilde=de.Boolean(\"-T,--tilde\",!1,{description:\"Use the `~` semver modifier on the resolved range\"});this.caret=de.Boolean(\"-C,--caret\",!1,{description:\"Use the `^` semver modifier on the resolved range\"});this.recursive=de.Boolean(\"-R,--recursive\",!1,{description:\"Resolve again ALL resolutions for those packages\"});this.mode=de.String(\"--mode\",{description:\"Change what artifacts installs generate\",validator:js(yl)});this.patterns=de.Rest()}static{this.paths=[[\"up\"]]}static{this.usage=st.Usage({description:\"upgrade dependencies across the project\",details:\"\\n      This command upgrades the packages matching the list of specified patterns to their latest available version across the whole project (regardless of whether they're part of `dependencies` or `devDependencies` - `peerDependencies` won't be affected). This is a project-wide command: all workspaces will be upgraded in the process.\\n\\n      If `-R,--recursive` is set the command will change behavior and no other switch will be allowed. When operating under this mode `yarn up` will force all ranges matching the selected packages to be resolved again (often to the highest available versions) before being stored in the lockfile. It however won't touch your manifests anymore, so depending on your needs you might want to run both `yarn up` and `yarn up -R` to cover all bases.\\n\\n      If `-i,--interactive` is set (or if the `preferInteractive` settings is toggled on) the command will offer various choices, depending on the detected upgrade paths. Some upgrades require this flag in order to resolve ambiguities.\\n\\n      The, `-C,--caret`, `-E,--exact` and  `-T,--tilde` options have the same meaning as in the `add` command (they change the modifier used when the range is missing or a tag, and are ignored when the range is explicitly set).\\n\\n      If the `--mode=<mode>` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\\n\\n      - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\\n\\n      - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\\n\\n      Generally you can see `yarn up` as a counterpart to what was `yarn upgrade --latest` in Yarn 1 (ie it ignores the ranges previously listed in your manifests), but unlike `yarn upgrade` which only upgraded dependencies in the current workspace, `yarn up` will upgrade all workspaces at the same time.\\n\\n      This command accepts glob patterns as arguments (if valid Descriptors and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them.\\n\\n      **Note:** The ranges have to be static, only the package scopes and names can contain glob patterns.\\n    \",examples:[[\"Upgrade all instances of lodash to the latest release\",\"$0 up lodash\"],[\"Upgrade all instances of lodash to the latest release, but ask confirmation for each\",\"$0 up lodash -i\"],[\"Upgrade all instances of lodash to 1.2.3\",\"$0 up lodash@1.2.3\"],[\"Upgrade all instances of packages with the `@babel` scope to the latest release\",\"$0 up '@babel/*'\"],[\"Upgrade all instances of packages containing the word `jest` to the latest release\",\"$0 up '*jest*'\"],[\"Upgrade all instances of packages with the `@babel` scope to 7.0.0\",\"$0 up '@babel/*@7.0.0'\"]]})}static{this.schema=[Pw(\"recursive\",Ku.Forbids,[\"interactive\",\"exact\",\"tilde\",\"caret\"],{ignore:[void 0,!1]})]}async execute(){return this.recursive?await this.executeUpRecursive():await this.executeUpClassic()}async executeUpRecursive(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Wr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=[...o.storedDescriptors.values()],A=u.map(E=>G.stringifyIdent(E)),p=new Set;for(let E of this.patterns){if(G.parseDescriptor(E).range!==\"unknown\")throw new ot(\"Ranges aren't allowed when using --recursive\");for(let w of(0,SH.default)(A,E)){let D=G.parseIdent(w);p.add(D.identHash)}}let h=u.filter(E=>p.has(E.identHash));for(let E of h)o.storedDescriptors.delete(E.descriptorHash),o.storedResolutions.delete(E.descriptorHash);return await o.installWithNewReport({stdout:this.context.stdout},{cache:n,mode:this.mode})}async executeUpClassic(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Wr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=this.fixed,A=r.isInteractive({interactive:this.interactive,stdout:this.context.stdout}),p=R2(this,o),h=A?[\"keep\",\"reuse\",\"project\",\"latest\"]:[\"project\",\"latest\"],E=[],w=[];for(let N of this.patterns){let U=!1,z=G.parseDescriptor(N),te=G.stringifyIdent(z);for(let le of o.workspaces)for(let ce of[\"dependencies\",\"devDependencies\"]){let Ie=[...le.manifest.getForScope(ce).values()].map(De=>G.stringifyIdent(De)),he=te===\"*\"?Ie:(0,SH.default)(Ie,te);for(let De of he){let Ee=G.parseIdent(De),g=le.manifest[ce].get(Ee.identHash);if(typeof g>\"u\")throw new Error(\"Assertion failed: Expected the descriptor to be registered\");let me=G.makeDescriptor(Ee,z.range);E.push(Promise.resolve().then(async()=>[le,ce,g,await T2(me,{project:o,workspace:le,cache:n,target:ce,fixed:u,modifier:p,strategies:h})])),U=!0}}U||w.push(N)}if(w.length>1)throw new ot(`Patterns ${pe.prettyList(r,w,pe.Type.CODE)} don't match any packages referenced by any workspace`);if(w.length>0)throw new ot(`Pattern ${pe.prettyList(r,w,pe.Type.CODE)} doesn't match any packages referenced by any workspace`);let D=await Promise.all(E),b=await pA.start({configuration:r,stdout:this.context.stdout,suggestInstall:!1},async N=>{for(let[,,U,{suggestions:z,rejections:te}]of D){let le=z.filter(ce=>ce.descriptor!==null);if(le.length===0){let[ce]=te;if(typeof ce>\"u\")throw new Error(\"Assertion failed: Expected an error to have been set\");let ue=this.cli.error(ce);o.configuration.get(\"enableNetwork\")?N.reportError(27,`${G.prettyDescriptor(r,U)} can't be resolved to a satisfying range\n\n${ue}`):N.reportError(27,`${G.prettyDescriptor(r,U)} can't be resolved to a satisfying range (note: network resolution has been disabled)\n\n${ue}`)}else le.length>1&&!A&&N.reportError(27,`${G.prettyDescriptor(r,U)} has multiple possible upgrade strategies; use -i to disambiguate manually`)}});if(b.hasErrors())return b.exitCode();let C=!1,T=[];for(let[N,U,,{suggestions:z}]of D){let te,le=z.filter(he=>he.descriptor!==null),ce=le[0].descriptor,ue=le.every(he=>G.areDescriptorsEqual(he.descriptor,ce));le.length===1||ue?te=ce:(C=!0,{answer:te}=await(0,zde.prompt)({type:\"select\",name:\"answer\",message:`Which range do you want to use in ${G.prettyWorkspace(r,N)} \\u276F ${U}?`,choices:z.map(({descriptor:he,name:De,reason:Ee})=>he?{name:De,hint:Ee,descriptor:he}:{name:De,hint:Ee,disabled:!0}),onCancel:()=>process.exit(130),result(he){return this.find(he,\"descriptor\")},stdin:this.context.stdin,stdout:this.context.stdout}));let Ie=N.manifest[U].get(te.identHash);if(typeof Ie>\"u\")throw new Error(\"Assertion failed: This descriptor should have a matching entry\");if(Ie.descriptorHash!==te.descriptorHash)N.manifest[U].set(te.identHash,te),T.push([N,U,Ie,te]);else{let he=r.makeResolver(),De={project:o,resolver:he},Ee=r.normalizeDependency(Ie),g=he.bindDescriptor(Ee,N.anchoredLocator,De);o.forgetResolution(g)}}return await r.triggerMultipleHooks(N=>N.afterWorkspaceDependencyReplacement,T),C&&this.context.stdout.write(`\n`),await o.installWithNewReport({stdout:this.context.stdout},{cache:n,mode:this.mode})}};Ke();Ke();Ke();Gt();var YE=class extends ut{constructor(){super(...arguments);this.recursive=de.Boolean(\"-R,--recursive\",!1,{description:\"List, for each workspace, what are all the paths that lead to the dependency\"});this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.peers=de.Boolean(\"--peers\",!1,{description:\"Also print the peer dependencies that match the specified name\"});this.package=de.String()}static{this.paths=[[\"why\"]]}static{this.usage=st.Usage({description:\"display the reason why a package is needed\",details:`\n      This command prints the exact reasons why a package appears in the dependency tree.\n\n      If \\`-R,--recursive\\` is set, the listing will go in depth and will list, for each workspaces, what are all the paths that lead to the dependency. Note that the display is somewhat optimized in that it will not print the package listing twice for a single package, so if you see a leaf named \"Foo\" when looking for \"Bar\", it means that \"Foo\" already got printed higher in the tree.\n    `,examples:[[\"Explain why lodash is used in your project\",\"$0 why lodash\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState();let n=G.parseIdent(this.package).identHash,u=this.recursive?Z0t(o,n,{configuration:r,peers:this.peers}):X0t(o,n,{configuration:r,peers:this.peers});As.emitTree(u,{configuration:r,stdout:this.context.stdout,json:this.json,separators:1})}};function X0t(t,e,{configuration:r,peers:o}){let a=qe.sortMap(t.storedPackages.values(),A=>G.stringifyLocator(A)),n={},u={children:n};for(let A of a){let p={};for(let E of A.dependencies.values()){if(!o&&A.peerDependencies.has(E.identHash))continue;let w=t.storedResolutions.get(E.descriptorHash);if(!w)throw new Error(\"Assertion failed: The resolution should have been registered\");let D=t.storedPackages.get(w);if(!D)throw new Error(\"Assertion failed: The package should have been registered\");if(D.identHash!==e)continue;{let C=G.stringifyLocator(A);n[C]={value:[A,pe.Type.LOCATOR],children:p}}let b=G.stringifyLocator(D);p[b]={value:[{descriptor:E,locator:D},pe.Type.DEPENDENT]}}}return u}function Z0t(t,e,{configuration:r,peers:o}){let a=qe.sortMap(t.workspaces,D=>G.stringifyLocator(D.anchoredLocator)),n=new Set,u=new Set,A=D=>{if(n.has(D.locatorHash))return u.has(D.locatorHash);if(n.add(D.locatorHash),D.identHash===e)return u.add(D.locatorHash),!0;let b=!1;D.identHash===e&&(b=!0);for(let C of D.dependencies.values()){if(!o&&D.peerDependencies.has(C.identHash))continue;let T=t.storedResolutions.get(C.descriptorHash);if(!T)throw new Error(\"Assertion failed: The resolution should have been registered\");let N=t.storedPackages.get(T);if(!N)throw new Error(\"Assertion failed: The package should have been registered\");A(N)&&(b=!0)}return b&&u.add(D.locatorHash),b};for(let D of a)A(D.anchoredPackage);let p=new Set,h={},E={children:h},w=(D,b,C)=>{if(!u.has(D.locatorHash))return;let T=C!==null?pe.tuple(pe.Type.DEPENDENT,{locator:D,descriptor:C}):pe.tuple(pe.Type.LOCATOR,D),N={},U={value:T,children:N},z=G.stringifyLocator(D);if(b[z]=U,!(C!==null&&t.tryWorkspaceByLocator(D))&&!p.has(D.locatorHash)){p.add(D.locatorHash);for(let te of D.dependencies.values()){if(!o&&D.peerDependencies.has(te.identHash))continue;let le=t.storedResolutions.get(te.descriptorHash);if(!le)throw new Error(\"Assertion failed: The resolution should have been registered\");let ce=t.storedPackages.get(le);if(!ce)throw new Error(\"Assertion failed: The package should have been registered\");w(ce,N,te)}}};for(let D of a)w(D.anchoredPackage,h,null);return E}Ke();var OH={};Kt(OH,{GitFetcher:()=>_2,GitResolver:()=>H2,default:()=>Egt,gitUtils:()=>ra});Ke();Pt();var ra={};Kt(ra,{TreeishProtocols:()=>U2,clone:()=>NH,fetchBase:()=>mme,fetchChangedFiles:()=>yme,fetchChangedWorkspaces:()=>mgt,fetchRoot:()=>dme,isGitUrl:()=>zE,lsRemote:()=>gme,normalizeLocator:()=>dgt,normalizeRepoUrl:()=>KE,resolveUrl:()=>LH,splitRepoUrl:()=>Rh,validateRepoUrl:()=>TH});Ke();Pt();Gt();var fme=et(cme()),pme=et(t3()),VE=et(ve(\"querystring\")),FH=et(ni());function QH(t,e,r){let o=t.indexOf(r);return t.lastIndexOf(e,o>-1?o:1/0)}function ume(t){try{return new URL(t)}catch{return}}function hgt(t){let e=QH(t,\"@\",\"#\"),r=QH(t,\":\",\"#\");return r>e&&(t=`${t.slice(0,r)}/${t.slice(r+1)}`),QH(t,\":\",\"#\")===-1&&t.indexOf(\"//\")===-1&&(t=`ssh://${t}`),t}function Ame(t){return ume(t)||ume(hgt(t))}function KE(t,{git:e=!1}={}){if(t=t.replace(/^git\\+https:/,\"https:\"),t=t.replace(/^(?:github:|https:\\/\\/github\\.com\\/|git:\\/\\/github\\.com\\/)?(?!\\.{1,2}\\/)([a-zA-Z0-9._-]+)\\/(?!\\.{1,2}(?:#|$))([a-zA-Z0-9._-]+?)(?:\\.git)?(#.*)?$/,\"https://github.com/$1/$2.git$3\"),t=t.replace(/^https:\\/\\/github\\.com\\/(?!\\.{1,2}\\/)([a-zA-Z0-9._-]+)\\/(?!\\.{1,2}(?:#|$))([a-zA-Z0-9._-]+?)\\/tarball\\/(.+)?$/,\"https://github.com/$1/$2.git#$3\"),e){let r=Ame(t);r&&(t=r.href),t=t.replace(/^git\\+([^:]+):/,\"$1:\")}return t}function hme(){return{...process.env,GIT_SSH_COMMAND:process.env.GIT_SSH_COMMAND||`${process.env.GIT_SSH||\"ssh\"} -o BatchMode=yes`}}var ggt=[/^ssh:/,/^git(?:\\+[^:]+)?:/,/^(?:git\\+)?https?:[^#]+\\/[^#]+(?:\\.git)(?:#.*)?$/,/^git@[^#]+\\/[^#]+\\.git(?:#.*)?$/,/^(?:github:|https:\\/\\/github\\.com\\/)?(?!\\.{1,2}\\/)([a-zA-Z._0-9-]+)\\/(?!\\.{1,2}(?:#|$))([a-zA-Z._0-9-]+?)(?:\\.git)?(?:#.*)?$/,/^https:\\/\\/github\\.com\\/(?!\\.{1,2}\\/)([a-zA-Z0-9._-]+)\\/(?!\\.{1,2}(?:#|$))([a-zA-Z0-9._-]+?)\\/tarball\\/(.+)?$/],U2=(a=>(a.Commit=\"commit\",a.Head=\"head\",a.Tag=\"tag\",a.Semver=\"semver\",a))(U2||{});function zE(t){return t?ggt.some(e=>!!t.match(e)):!1}function Rh(t){t=KE(t);let e=t.indexOf(\"#\");if(e===-1)return{repo:t,treeish:{protocol:\"head\",request:\"HEAD\"},extra:{}};let r=t.slice(0,e),o=t.slice(e+1);if(o.match(/^[a-z]+=/)){let a=VE.default.parse(o);for(let[p,h]of Object.entries(a))if(typeof h!=\"string\")throw new Error(`Assertion failed: The ${p} parameter must be a literal string`);let n=Object.values(U2).find(p=>Object.hasOwn(a,p)),[u,A]=typeof n<\"u\"?[n,a[n]]:[\"head\",\"HEAD\"];for(let p of Object.values(U2))delete a[p];return{repo:r,treeish:{protocol:u,request:A},extra:a}}else{let a=o.indexOf(\":\"),[n,u]=a===-1?[null,o]:[o.slice(0,a),o.slice(a+1)];return{repo:r,treeish:{protocol:n,request:u},extra:{}}}}function dgt(t){return G.makeLocator(t,KE(t.reference))}function TH(t,{configuration:e}){let r=KE(t,{git:!0});if(!on.getNetworkSettings(`https://${(0,fme.default)(r).resource}`,{configuration:e}).enableNetwork)throw new zt(80,`Request to '${r}' has been blocked because of your configuration settings`);return r}async function gme(t,e){let r=TH(t,{configuration:e}),o=await RH(\"listing refs\",[\"ls-remote\",r],{cwd:e.startingCwd,env:hme()},{configuration:e,normalizedRepoUrl:r}),a=new Map,n=/^([a-f0-9]{40})\\t([^\\n]+)/gm,u;for(;(u=n.exec(o.stdout))!==null;)a.set(u[2],u[1]);return a}async function LH(t,e){let{repo:r,treeish:{protocol:o,request:a},extra:n}=Rh(t),u=await gme(r,e),A=(h,E)=>{switch(h){case\"commit\":{if(!E.match(/^[a-f0-9]{40}$/))throw new Error(\"Invalid commit hash\");return VE.default.stringify({...n,commit:E})}case\"head\":{let w=u.get(E===\"HEAD\"?E:`refs/heads/${E}`);if(typeof w>\"u\")throw new Error(`Unknown head (\"${E}\")`);return VE.default.stringify({...n,commit:w})}case\"tag\":{let w=u.get(`refs/tags/${E}`);if(typeof w>\"u\")throw new Error(`Unknown tag (\"${E}\")`);return VE.default.stringify({...n,commit:w})}case\"semver\":{let w=Ur.validRange(E);if(!w)throw new Error(`Invalid range (\"${E}\")`);let D=new Map([...u.entries()].filter(([C])=>C.startsWith(\"refs/tags/\")).map(([C,T])=>[FH.default.parse(C.slice(10)),T]).filter(C=>C[0]!==null)),b=FH.default.maxSatisfying([...D.keys()],w);if(b===null)throw new Error(`No matching range (\"${E}\")`);return VE.default.stringify({...n,commit:D.get(b)})}case null:{let w;if((w=p(\"commit\",E))!==null||(w=p(\"tag\",E))!==null||(w=p(\"head\",E))!==null)return w;throw E.match(/^[a-f0-9]+$/)?new Error(`Couldn't resolve \"${E}\" as either a commit, a tag, or a head - if a commit, use the 40-characters commit hash`):new Error(`Couldn't resolve \"${E}\" as either a commit, a tag, or a head`)}default:throw new Error(`Invalid Git resolution protocol (\"${h}\")`)}},p=(h,E)=>{try{return A(h,E)}catch{return null}};return KE(`${r}#${A(o,a)}`)}async function NH(t,e){return await e.getLimit(\"cloneConcurrency\")(async()=>{let{repo:r,treeish:{protocol:o,request:a}}=Rh(t);if(o!==\"commit\")throw new Error(\"Invalid treeish protocol when cloning\");let n=TH(r,{configuration:e}),u=await ae.mktempPromise(),A={cwd:u,env:hme()};return await RH(\"cloning the repository\",[\"clone\",\"-c core.autocrlf=false\",n,Ae.fromPortablePath(u)],A,{configuration:e,normalizedRepoUrl:n}),await RH(\"switching branch\",[\"checkout\",`${a}`],A,{configuration:e,normalizedRepoUrl:n}),u})}async function dme(t){let e,r=t;do{if(e=r,await ae.existsPromise(K.join(e,\".git\")))return e;r=K.dirname(e)}while(r!==e);return null}async function mme(t,{baseRefs:e}){if(e.length===0)throw new ot(\"Can't run this command with zero base refs specified.\");let r=[];for(let A of e){let{code:p}=await Hr.execvp(\"git\",[\"merge-base\",A,\"HEAD\"],{cwd:t});p===0&&r.push(A)}if(r.length===0)throw new ot(`No ancestor could be found between any of HEAD and ${e.join(\", \")}`);let{stdout:o}=await Hr.execvp(\"git\",[\"merge-base\",\"HEAD\",...r],{cwd:t,strict:!0}),a=o.trim(),{stdout:n}=await Hr.execvp(\"git\",[\"show\",\"--quiet\",\"--pretty=format:%s\",a],{cwd:t,strict:!0}),u=n.trim();return{hash:a,title:u}}async function yme(t,{base:e,project:r}){let o=qe.buildIgnorePattern(r.configuration.get(\"changesetIgnorePatterns\")),{stdout:a}=await Hr.execvp(\"git\",[\"diff\",\"--name-only\",`${e}`],{cwd:t,strict:!0}),n=a.split(/\\r\\n|\\r|\\n/).filter(h=>h.length>0).map(h=>K.resolve(t,Ae.toPortablePath(h))),{stdout:u}=await Hr.execvp(\"git\",[\"ls-files\",\"--others\",\"--exclude-standard\"],{cwd:t,strict:!0}),A=u.split(/\\r\\n|\\r|\\n/).filter(h=>h.length>0).map(h=>K.resolve(t,Ae.toPortablePath(h))),p=[...new Set([...n,...A].sort())];return o?p.filter(h=>!K.relative(r.cwd,h).match(o)):p}async function mgt({ref:t,project:e}){if(e.configuration.projectCwd===null)throw new ot(\"This command can only be run from within a Yarn project\");let r=[K.resolve(e.cwd,mr.lockfile),K.resolve(e.cwd,e.configuration.get(\"cacheFolder\")),K.resolve(e.cwd,e.configuration.get(\"installStatePath\")),K.resolve(e.cwd,e.configuration.get(\"virtualFolder\"))];await e.configuration.triggerHook(u=>u.populateYarnPaths,e,u=>{u!=null&&r.push(u)});let o=await dme(e.configuration.projectCwd);if(o==null)throw new ot(\"This command can only be run on Git repositories\");let a=await mme(o,{baseRefs:typeof t==\"string\"?[t]:e.configuration.get(\"changesetBaseRefs\")}),n=await yme(o,{base:a.hash,project:e});return new Set(qe.mapAndFilter(n,u=>{let A=e.tryWorkspaceByFilePath(u);return A===null?qe.mapAndFilter.skip:r.some(p=>u.startsWith(p))?qe.mapAndFilter.skip:A}))}async function RH(t,e,r,{configuration:o,normalizedRepoUrl:a}){try{return await Hr.execvp(\"git\",e,{...r,strict:!0})}catch(n){if(!(n instanceof Hr.ExecError))throw n;let u=n.reportExtra,A=n.stderr.toString();throw new zt(1,`Failed ${t}`,p=>{p.reportError(1,`  ${pe.prettyField(o,{label:\"Repository URL\",value:pe.tuple(pe.Type.URL,a)})}`);for(let h of A.matchAll(/^(.+?): (.*)$/gm)){let[,E,w]=h;E=E.toLowerCase();let D=E===\"error\"?\"Error\":`${(0,pme.default)(E)} Error`;p.reportError(1,`  ${pe.prettyField(o,{label:D,value:pe.tuple(pe.Type.NO_HINT,w)})}`)}u?.(p)})}}var _2=class{supports(e,r){return zE(e.reference)}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,a=new Map(r.checksums);a.set(e.locatorHash,o);let n={...r,checksums:a},u=await this.downloadHosted(e,n);if(u!==null)return u;let[A,p,h]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the remote repository`),loader:()=>this.cloneFromRemote(e,n),...r.cacheOptions});return{packageFs:A,releaseFs:p,prefixPath:G.getIdentVendorPath(e),checksum:h}}async downloadHosted(e,r){return r.project.configuration.reduceHook(o=>o.fetchHostedRepository,null,e,r)}async cloneFromRemote(e,r){let o=Rh(e.reference),a=await NH(e.reference,r.project.configuration),n=K.resolve(a,o.extra.cwd??Bt.dot),u=K.join(n,\"package.tgz\");await hn.prepareExternalProject(n,u,{configuration:r.project.configuration,report:r.report,workspace:o.extra.workspace,locator:e});let A=await ae.readFilePromise(u);return await qe.releaseAfterUseAsync(async()=>await $i.convertToZip(A,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1}))}};Ke();Ke();var H2=class{supportsDescriptor(e,r){return zE(e.range)}supportsLocator(e,r){return zE(e.reference)}shouldPersistResolution(e,r){return!0}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){let a=await LH(e.range,o.project.configuration);return[G.makeLocator(e,a)]}async getSatisfying(e,r,o,a){let n=Rh(e.range);return{locators:o.filter(A=>{if(A.identHash!==e.identHash)return!1;let p=Rh(A.reference);return!(n.repo!==p.repo||n.treeish.protocol===\"commit\"&&n.treeish.request!==p.treeish.request)}),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await qe.releaseAfterUseAsync(async()=>await _t.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||\"0.0.0\",languageName:a.languageName||r.project.configuration.get(\"defaultLanguageName\"),linkType:\"HARD\",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var ygt={configuration:{changesetBaseRefs:{description:\"The base git refs that the current HEAD is compared against when detecting changes. Supports git branches, tags, and commits.\",type:\"STRING\",isArray:!0,isNullable:!1,default:[\"master\",\"origin/master\",\"upstream/master\",\"main\",\"origin/main\",\"upstream/main\"]},changesetIgnorePatterns:{description:\"Array of glob patterns; files matching them will be ignored when fetching the changed files\",type:\"STRING\",default:[],isArray:!0},cloneConcurrency:{description:\"Maximal number of concurrent clones\",type:\"NUMBER\",default:2}},fetchers:[_2],resolvers:[H2]};var Egt=ygt;Gt();var JE=class extends ut{constructor(){super(...arguments);this.since=de.String(\"--since\",{description:\"Only include workspaces that have been changed since the specified ref.\",tolerateBoolean:!0});this.recursive=de.Boolean(\"-R,--recursive\",!1,{description:\"Find packages via dependencies/devDependencies instead of using the workspaces field\"});this.noPrivate=de.Boolean(\"--no-private\",{description:\"Exclude workspaces that have the private field set to true\"});this.verbose=de.Boolean(\"-v,--verbose\",!1,{description:\"Also return the cross-dependencies between workspaces\"});this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"})}static{this.paths=[[\"workspaces\",\"list\"]]}static{this.usage=st.Usage({category:\"Workspace-related commands\",description:\"list all available workspaces\",details:\"\\n      This command will print the list of all workspaces in the project.\\n\\n      - If `--since` is set, Yarn will only list workspaces that have been modified since the specified ref. By default Yarn will use the refs specified by the `changesetBaseRefs` configuration option.\\n\\n      - If `-R,--recursive` is set, Yarn will find workspaces to run the command on by recursively evaluating `dependencies` and `devDependencies` fields, instead of looking at the `workspaces` fields.\\n\\n      - If `--no-private` is set, Yarn will not list any workspaces that have the `private` field set to `true`.\\n\\n      - If both the `-v,--verbose` and `--json` options are set, Yarn will also return the cross-dependencies between each workspaces (useful when you wish to automatically generate Buck / Bazel rules).\\n    \"})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o}=await Qt.find(r,this.context.cwd);return(await Lt.start({configuration:r,json:this.json,stdout:this.context.stdout},async n=>{let u=this.since?await ra.fetchChangedWorkspaces({ref:this.since,project:o}):o.workspaces,A=new Set(u);if(this.recursive)for(let p of[...u].map(h=>h.getRecursiveWorkspaceDependents()))for(let h of p)A.add(h);for(let p of A){let{manifest:h}=p;if(h.private&&this.noPrivate)continue;let E;if(this.verbose){let w=new Set,D=new Set;for(let b of _t.hardDependencies)for(let[C,T]of h.getForScope(b)){let N=o.tryWorkspaceByDescriptor(T);N===null?o.workspacesByIdent.has(C)&&D.add(T):w.add(N)}E={workspaceDependencies:Array.from(w).map(b=>b.relativeCwd),mismatchedWorkspaceDependencies:Array.from(D).map(b=>G.stringifyDescriptor(b))}}n.reportInfo(null,`${p.relativeCwd}`),n.reportJson({location:p.relativeCwd,name:h.name?G.stringifyIdent(h.name):null,...E})}})).exitCode()}};Ke();Ke();Gt();var XE=class extends ut{constructor(){super(...arguments);this.workspaceName=de.String();this.commandName=de.String();this.args=de.Proxy()}static{this.paths=[[\"workspace\"]]}static{this.usage=st.Usage({category:\"Workspace-related commands\",description:\"run a command within the specified workspace\",details:`\n      This command will run a given sub-command on a single workspace.\n    `,examples:[[\"Add a package to a single workspace\",\"yarn workspace components add -D react\"],[\"Run build script on a single workspace\",\"yarn workspace components run build\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);let n=o.workspaces,u=new Map(n.map(p=>[G.stringifyIdent(p.anchoredLocator),p])),A=u.get(this.workspaceName);if(A===void 0){let p=Array.from(u.keys()).sort();throw new ot(`Workspace '${this.workspaceName}' not found. Did you mean any of the following:\n  - ${p.join(`\n  - `)}?`)}return this.cli.run([this.commandName,...this.args],{cwd:A.cwd})}};var Cgt={configuration:{enableImmutableInstalls:{description:\"If true (the default on CI), prevents the install command from modifying the lockfile\",type:\"BOOLEAN\",default:Eme.isCI},defaultSemverRangePrefix:{description:\"The default save prefix: '^', '~' or ''\",type:\"STRING\",values:[\"^\",\"~\",\"\"],default:\"^\"},preferReuse:{description:\"If true, `yarn add` will attempt to reuse the most common dependency range in other workspaces.\",type:\"BOOLEAN\",default:!1}},commands:[hE,gE,dE,mE,jE,TE,PE,JE,CE,IE,wE,BE,fE,pE,yE,EE,vE,DE,SE,xE,bE,kE,GE,QE,FE,NE,LE,OE,RE,ME,UE,_E,HE,qE,WE,YE,XE]},Igt=Cgt;var jH={};Kt(jH,{default:()=>Bgt});Ke();var kt={optional:!0},UH=[[\"@tailwindcss/aspect-ratio@<0.2.1\",{peerDependencies:{tailwindcss:\"^2.0.2\"}}],[\"@tailwindcss/line-clamp@<0.2.1\",{peerDependencies:{tailwindcss:\"^2.0.2\"}}],[\"@fullhuman/postcss-purgecss@3.1.3 || 3.1.3-alpha.0\",{peerDependencies:{postcss:\"^8.0.0\"}}],[\"@samverschueren/stream-to-observable@<0.3.1\",{peerDependenciesMeta:{rxjs:kt,zenObservable:kt}}],[\"any-observable@<0.5.1\",{peerDependenciesMeta:{rxjs:kt,zenObservable:kt}}],[\"@pm2/agent@<1.0.4\",{dependencies:{debug:\"*\"}}],[\"debug@<4.2.0\",{peerDependenciesMeta:{\"supports-color\":kt}}],[\"got@<11\",{dependencies:{\"@types/responselike\":\"^1.0.0\",\"@types/keyv\":\"^3.1.1\"}}],[\"cacheable-lookup@<4.1.2\",{dependencies:{\"@types/keyv\":\"^3.1.1\"}}],[\"http-link-dataloader@*\",{peerDependencies:{graphql:\"^0.13.1 || ^14.0.0\"}}],[\"typescript-language-server@*\",{dependencies:{\"vscode-jsonrpc\":\"^5.0.1\",\"vscode-languageserver-protocol\":\"^3.15.0\"}}],[\"postcss-syntax@*\",{peerDependenciesMeta:{\"postcss-html\":kt,\"postcss-jsx\":kt,\"postcss-less\":kt,\"postcss-markdown\":kt,\"postcss-scss\":kt}}],[\"jss-plugin-rule-value-function@<=10.1.1\",{dependencies:{\"tiny-warning\":\"^1.0.2\"}}],[\"ink-select-input@<4.1.0\",{peerDependencies:{react:\"^16.8.2\"}}],[\"license-webpack-plugin@<2.3.18\",{peerDependenciesMeta:{webpack:kt}}],[\"snowpack@>=3.3.0\",{dependencies:{\"node-gyp\":\"^7.1.0\"}}],[\"promise-inflight@*\",{peerDependenciesMeta:{bluebird:kt}}],[\"reactcss@*\",{peerDependencies:{react:\"*\"}}],[\"react-color@<=2.19.0\",{peerDependencies:{react:\"*\"}}],[\"gatsby-plugin-i18n@*\",{dependencies:{ramda:\"^0.24.1\"}}],[\"useragent@^2.0.0\",{dependencies:{request:\"^2.88.0\",yamlparser:\"0.0.x\",semver:\"5.5.x\"}}],[\"@apollographql/apollo-tools@<=0.5.2\",{peerDependencies:{graphql:\"^14.2.1 || ^15.0.0\"}}],[\"material-table@^2.0.0\",{dependencies:{\"@babel/runtime\":\"^7.11.2\"}}],[\"@babel/parser@*\",{dependencies:{\"@babel/types\":\"^7.8.3\"}}],[\"fork-ts-checker-webpack-plugin@<=6.3.4\",{peerDependencies:{eslint:\">= 6\",typescript:\">= 2.7\",webpack:\">= 4\",\"vue-template-compiler\":\"*\"},peerDependenciesMeta:{eslint:kt,\"vue-template-compiler\":kt}}],[\"rc-animate@<=3.1.1\",{peerDependencies:{react:\">=16.9.0\",\"react-dom\":\">=16.9.0\"}}],[\"react-bootstrap-table2-paginator@*\",{dependencies:{classnames:\"^2.2.6\"}}],[\"react-draggable@<=4.4.3\",{peerDependencies:{react:\">= 16.3.0\",\"react-dom\":\">= 16.3.0\"}}],[\"apollo-upload-client@<14\",{peerDependencies:{graphql:\"14 - 15\"}}],[\"react-instantsearch-core@<=6.7.0\",{peerDependencies:{algoliasearch:\">= 3.1 < 5\"}}],[\"react-instantsearch-dom@<=6.7.0\",{dependencies:{\"react-fast-compare\":\"^3.0.0\"}}],[\"ws@<7.2.1\",{peerDependencies:{bufferutil:\"^4.0.1\",\"utf-8-validate\":\"^5.0.2\"},peerDependenciesMeta:{bufferutil:kt,\"utf-8-validate\":kt}}],[\"react-portal@<4.2.2\",{peerDependencies:{\"react-dom\":\"^15.0.0-0 || ^16.0.0-0 || ^17.0.0-0\"}}],[\"react-scripts@<=4.0.1\",{peerDependencies:{react:\"*\"}}],[\"testcafe@<=1.10.1\",{dependencies:{\"@babel/plugin-transform-for-of\":\"^7.12.1\",\"@babel/runtime\":\"^7.12.5\"}}],[\"testcafe-legacy-api@<=4.2.0\",{dependencies:{\"testcafe-hammerhead\":\"^17.0.1\",\"read-file-relative\":\"^1.2.0\"}}],[\"@google-cloud/firestore@<=4.9.3\",{dependencies:{protobufjs:\"^6.8.6\"}}],[\"gatsby-source-apiserver@*\",{dependencies:{\"babel-polyfill\":\"^6.26.0\"}}],[\"@webpack-cli/package-utils@<=1.0.1-alpha.4\",{dependencies:{\"cross-spawn\":\"^7.0.3\"}}],[\"gatsby-remark-prismjs@<3.3.28\",{dependencies:{lodash:\"^4\"}}],[\"gatsby-plugin-favicon@*\",{peerDependencies:{webpack:\"*\"}}],[\"gatsby-plugin-sharp@<=4.6.0-next.3\",{dependencies:{debug:\"^4.3.1\"}}],[\"gatsby-react-router-scroll@<=5.6.0-next.0\",{dependencies:{\"prop-types\":\"^15.7.2\"}}],[\"@rebass/forms@*\",{dependencies:{\"@styled-system/should-forward-prop\":\"^5.0.0\"},peerDependencies:{react:\"^16.8.6\"}}],[\"rebass@*\",{peerDependencies:{react:\"^16.8.6\"}}],[\"@ant-design/react-slick@<=0.28.3\",{peerDependencies:{react:\">=16.0.0\"}}],[\"mqtt@<4.2.7\",{dependencies:{duplexify:\"^4.1.1\"}}],[\"vue-cli-plugin-vuetify@<=2.0.3\",{dependencies:{semver:\"^6.3.0\"},peerDependenciesMeta:{\"sass-loader\":kt,\"vuetify-loader\":kt}}],[\"vue-cli-plugin-vuetify@<=2.0.4\",{dependencies:{\"null-loader\":\"^3.0.0\"}}],[\"vue-cli-plugin-vuetify@>=2.4.3\",{peerDependencies:{vue:\"*\"}}],[\"@vuetify/cli-plugin-utils@<=0.0.4\",{dependencies:{semver:\"^6.3.0\"},peerDependenciesMeta:{\"sass-loader\":kt}}],[\"@vue/cli-plugin-typescript@<=5.0.0-alpha.0\",{dependencies:{\"babel-loader\":\"^8.1.0\"}}],[\"@vue/cli-plugin-typescript@<=5.0.0-beta.0\",{dependencies:{\"@babel/core\":\"^7.12.16\"},peerDependencies:{\"vue-template-compiler\":\"^2.0.0\"},peerDependenciesMeta:{\"vue-template-compiler\":kt}}],[\"cordova-ios@<=6.3.0\",{dependencies:{underscore:\"^1.9.2\"}}],[\"cordova-lib@<=10.0.1\",{dependencies:{underscore:\"^1.9.2\"}}],[\"git-node-fs@*\",{peerDependencies:{\"js-git\":\"^0.7.8\"},peerDependenciesMeta:{\"js-git\":kt}}],[\"consolidate@<0.16.0\",{peerDependencies:{mustache:\"^3.0.0\"},peerDependenciesMeta:{mustache:kt}}],[\"consolidate@<=0.16.0\",{peerDependencies:{velocityjs:\"^2.0.1\",tinyliquid:\"^0.2.34\",\"liquid-node\":\"^3.0.1\",jade:\"^1.11.0\",\"then-jade\":\"*\",dust:\"^0.3.0\",\"dustjs-helpers\":\"^1.7.4\",\"dustjs-linkedin\":\"^2.7.5\",swig:\"^1.4.2\",\"swig-templates\":\"^2.0.3\",\"razor-tmpl\":\"^1.3.1\",atpl:\">=0.7.6\",liquor:\"^0.0.5\",twig:\"^1.15.2\",ejs:\"^3.1.5\",eco:\"^1.1.0-rc-3\",jazz:\"^0.0.18\",jqtpl:\"~1.1.0\",hamljs:\"^0.6.2\",hamlet:\"^0.3.3\",whiskers:\"^0.4.0\",\"haml-coffee\":\"^1.14.1\",\"hogan.js\":\"^3.0.2\",templayed:\">=0.2.3\",handlebars:\"^4.7.6\",underscore:\"^1.11.0\",lodash:\"^4.17.20\",pug:\"^3.0.0\",\"then-pug\":\"*\",qejs:\"^3.0.5\",walrus:\"^0.10.1\",mustache:\"^4.0.1\",just:\"^0.1.8\",ect:\"^0.5.9\",mote:\"^0.2.0\",toffee:\"^0.3.6\",dot:\"^1.1.3\",\"bracket-template\":\"^1.1.5\",ractive:\"^1.3.12\",nunjucks:\"^3.2.2\",htmling:\"^0.0.8\",\"babel-core\":\"^6.26.3\",plates:\"~0.4.11\",\"react-dom\":\"^16.13.1\",react:\"^16.13.1\",\"arc-templates\":\"^0.5.3\",vash:\"^0.13.0\",slm:\"^2.0.0\",marko:\"^3.14.4\",teacup:\"^2.0.0\",\"coffee-script\":\"^1.12.7\",squirrelly:\"^5.1.0\",twing:\"^5.0.2\"},peerDependenciesMeta:{velocityjs:kt,tinyliquid:kt,\"liquid-node\":kt,jade:kt,\"then-jade\":kt,dust:kt,\"dustjs-helpers\":kt,\"dustjs-linkedin\":kt,swig:kt,\"swig-templates\":kt,\"razor-tmpl\":kt,atpl:kt,liquor:kt,twig:kt,ejs:kt,eco:kt,jazz:kt,jqtpl:kt,hamljs:kt,hamlet:kt,whiskers:kt,\"haml-coffee\":kt,\"hogan.js\":kt,templayed:kt,handlebars:kt,underscore:kt,lodash:kt,pug:kt,\"then-pug\":kt,qejs:kt,walrus:kt,mustache:kt,just:kt,ect:kt,mote:kt,toffee:kt,dot:kt,\"bracket-template\":kt,ractive:kt,nunjucks:kt,htmling:kt,\"babel-core\":kt,plates:kt,\"react-dom\":kt,react:kt,\"arc-templates\":kt,vash:kt,slm:kt,marko:kt,teacup:kt,\"coffee-script\":kt,squirrelly:kt,twing:kt}}],[\"vue-loader@<=16.3.3\",{peerDependencies:{\"@vue/compiler-sfc\":\"^3.0.8\",webpack:\"^4.1.0 || ^5.0.0-0\"},peerDependenciesMeta:{\"@vue/compiler-sfc\":kt}}],[\"vue-loader@^16.7.0\",{peerDependencies:{\"@vue/compiler-sfc\":\"^3.0.8\",vue:\"^3.2.13\"},peerDependenciesMeta:{\"@vue/compiler-sfc\":kt,vue:kt}}],[\"scss-parser@<=1.0.5\",{dependencies:{lodash:\"^4.17.21\"}}],[\"query-ast@<1.0.5\",{dependencies:{lodash:\"^4.17.21\"}}],[\"redux-thunk@<=2.3.0\",{peerDependencies:{redux:\"^4.0.0\"}}],[\"skypack@<=0.3.2\",{dependencies:{tar:\"^6.1.0\"}}],[\"@npmcli/metavuln-calculator@<2.0.0\",{dependencies:{\"json-parse-even-better-errors\":\"^2.3.1\"}}],[\"bin-links@<2.3.0\",{dependencies:{\"mkdirp-infer-owner\":\"^1.0.2\"}}],[\"rollup-plugin-polyfill-node@<=0.8.0\",{peerDependencies:{rollup:\"^1.20.0 || ^2.0.0\"}}],[\"snowpack@<3.8.6\",{dependencies:{\"magic-string\":\"^0.25.7\"}}],[\"elm-webpack-loader@*\",{dependencies:{temp:\"^0.9.4\"}}],[\"winston-transport@<=4.4.0\",{dependencies:{logform:\"^2.2.0\"}}],[\"jest-vue-preprocessor@*\",{dependencies:{\"@babel/core\":\"7.8.7\",\"@babel/template\":\"7.8.6\"},peerDependencies:{pug:\"^2.0.4\"},peerDependenciesMeta:{pug:kt}}],[\"redux-persist@*\",{peerDependencies:{react:\">=16\"},peerDependenciesMeta:{react:kt}}],[\"sodium@>=3\",{dependencies:{\"node-gyp\":\"^3.8.0\"}}],[\"babel-plugin-graphql-tag@<=3.1.0\",{peerDependencies:{graphql:\"^14.0.0 || ^15.0.0\"}}],[\"@playwright/test@<=1.14.1\",{dependencies:{\"jest-matcher-utils\":\"^26.4.2\"}}],...[\"babel-plugin-remove-graphql-queries@<3.14.0-next.1\",\"babel-preset-gatsby-package@<1.14.0-next.1\",\"create-gatsby@<1.14.0-next.1\",\"gatsby-admin@<0.24.0-next.1\",\"gatsby-cli@<3.14.0-next.1\",\"gatsby-core-utils@<2.14.0-next.1\",\"gatsby-design-tokens@<3.14.0-next.1\",\"gatsby-legacy-polyfills@<1.14.0-next.1\",\"gatsby-plugin-benchmark-reporting@<1.14.0-next.1\",\"gatsby-plugin-graphql-config@<0.23.0-next.1\",\"gatsby-plugin-image@<1.14.0-next.1\",\"gatsby-plugin-mdx@<2.14.0-next.1\",\"gatsby-plugin-netlify-cms@<5.14.0-next.1\",\"gatsby-plugin-no-sourcemaps@<3.14.0-next.1\",\"gatsby-plugin-page-creator@<3.14.0-next.1\",\"gatsby-plugin-preact@<5.14.0-next.1\",\"gatsby-plugin-preload-fonts@<2.14.0-next.1\",\"gatsby-plugin-schema-snapshot@<2.14.0-next.1\",\"gatsby-plugin-styletron@<6.14.0-next.1\",\"gatsby-plugin-subfont@<3.14.0-next.1\",\"gatsby-plugin-utils@<1.14.0-next.1\",\"gatsby-recipes@<0.25.0-next.1\",\"gatsby-source-shopify@<5.6.0-next.1\",\"gatsby-source-wikipedia@<3.14.0-next.1\",\"gatsby-transformer-screenshot@<3.14.0-next.1\",\"gatsby-worker@<0.5.0-next.1\"].map(t=>[t,{dependencies:{\"@babel/runtime\":\"^7.14.8\"}}]),[\"gatsby-core-utils@<2.14.0-next.1\",{dependencies:{got:\"8.3.2\"}}],[\"gatsby-plugin-gatsby-cloud@<=3.1.0-next.0\",{dependencies:{\"gatsby-core-utils\":\"^2.13.0-next.0\"}}],[\"gatsby-plugin-gatsby-cloud@<=3.2.0-next.1\",{peerDependencies:{webpack:\"*\"}}],[\"babel-plugin-remove-graphql-queries@<=3.14.0-next.1\",{dependencies:{\"gatsby-core-utils\":\"^2.8.0-next.1\"}}],[\"gatsby-plugin-netlify@3.13.0-next.1\",{dependencies:{\"gatsby-core-utils\":\"^2.13.0-next.0\"}}],[\"clipanion-v3-codemod@<=0.2.0\",{peerDependencies:{jscodeshift:\"^0.11.0\"}}],[\"react-live@*\",{peerDependencies:{\"react-dom\":\"*\",react:\"*\"}}],[\"webpack@<4.44.1\",{peerDependenciesMeta:{\"webpack-cli\":kt,\"webpack-command\":kt}}],[\"webpack@<5.0.0-beta.23\",{peerDependenciesMeta:{\"webpack-cli\":kt}}],[\"webpack-dev-server@<3.10.2\",{peerDependenciesMeta:{\"webpack-cli\":kt}}],[\"@docusaurus/responsive-loader@<1.5.0\",{peerDependenciesMeta:{sharp:kt,jimp:kt}}],[\"eslint-module-utils@*\",{peerDependenciesMeta:{\"eslint-import-resolver-node\":kt,\"eslint-import-resolver-typescript\":kt,\"eslint-import-resolver-webpack\":kt,\"@typescript-eslint/parser\":kt}}],[\"eslint-plugin-import@*\",{peerDependenciesMeta:{\"@typescript-eslint/parser\":kt}}],[\"critters-webpack-plugin@<3.0.2\",{peerDependenciesMeta:{\"html-webpack-plugin\":kt}}],[\"terser@<=5.10.0\",{dependencies:{acorn:\"^8.5.0\"}}],[\"babel-preset-react-app@10.0.x <10.0.2\",{dependencies:{\"@babel/plugin-proposal-private-property-in-object\":\"^7.16.7\"}}],[\"eslint-config-react-app@*\",{peerDependenciesMeta:{typescript:kt}}],[\"@vue/eslint-config-typescript@<11.0.0\",{peerDependenciesMeta:{typescript:kt}}],[\"unplugin-vue2-script-setup@<0.9.1\",{peerDependencies:{\"@vue/composition-api\":\"^1.4.3\",\"@vue/runtime-dom\":\"^3.2.26\"}}],[\"@cypress/snapshot@*\",{dependencies:{debug:\"^3.2.7\"}}],[\"auto-relay@<=0.14.0\",{peerDependencies:{\"reflect-metadata\":\"^0.1.13\"}}],[\"vue-template-babel-compiler@<1.2.0\",{peerDependencies:{\"vue-template-compiler\":\"^2.6.0\"}}],[\"@parcel/transformer-image@<2.5.0\",{peerDependencies:{\"@parcel/core\":\"*\"}}],[\"@parcel/transformer-js@<2.5.0\",{peerDependencies:{\"@parcel/core\":\"*\"}}],[\"parcel@*\",{peerDependenciesMeta:{\"@parcel/core\":kt}}],[\"react-scripts@*\",{peerDependencies:{eslint:\"*\"}}],[\"focus-trap-react@^8.0.0\",{dependencies:{tabbable:\"^5.3.2\"}}],[\"react-rnd@<10.3.7\",{peerDependencies:{react:\">=16.3.0\",\"react-dom\":\">=16.3.0\"}}],[\"connect-mongo@<5.0.0\",{peerDependencies:{\"express-session\":\"^1.17.1\"}}],[\"vue-i18n@<9\",{peerDependencies:{vue:\"^2\"}}],[\"vue-router@<4\",{peerDependencies:{vue:\"^2\"}}],[\"unified@<10\",{dependencies:{\"@types/unist\":\"^2.0.0\"}}],[\"react-github-btn@<=1.3.0\",{peerDependencies:{react:\">=16.3.0\"}}],[\"react-dev-utils@*\",{peerDependencies:{typescript:\">=2.7\",webpack:\">=4\"},peerDependenciesMeta:{typescript:kt}}],[\"@asyncapi/react-component@<=1.0.0-next.39\",{peerDependencies:{react:\">=16.8.0\",\"react-dom\":\">=16.8.0\"}}],[\"xo@*\",{peerDependencies:{webpack:\">=1.11.0\"},peerDependenciesMeta:{webpack:kt}}],[\"babel-plugin-remove-graphql-queries@<=4.20.0-next.0\",{dependencies:{\"@babel/types\":\"^7.15.4\"}}],[\"gatsby-plugin-page-creator@<=4.20.0-next.1\",{dependencies:{\"fs-extra\":\"^10.1.0\"}}],[\"gatsby-plugin-utils@<=3.14.0-next.1\",{dependencies:{fastq:\"^1.13.0\"},peerDependencies:{graphql:\"^15.0.0\"}}],[\"gatsby-plugin-mdx@<3.1.0-next.1\",{dependencies:{mkdirp:\"^1.0.4\"}}],[\"gatsby-plugin-mdx@^2\",{peerDependencies:{gatsby:\"^3.0.0-next\"}}],[\"fdir@<=5.2.0\",{peerDependencies:{picomatch:\"2.x\"},peerDependenciesMeta:{picomatch:kt}}],[\"babel-plugin-transform-typescript-metadata@<=0.3.2\",{peerDependencies:{\"@babel/core\":\"^7\",\"@babel/traverse\":\"^7\"},peerDependenciesMeta:{\"@babel/traverse\":kt}}],[\"graphql-compose@>=9.0.10\",{peerDependencies:{graphql:\"^14.2.0 || ^15.0.0 || ^16.0.0\"}}],[\"vite-plugin-vuetify@<=1.0.2\",{peerDependencies:{vue:\"^3.0.0\"}}],[\"webpack-plugin-vuetify@<=2.0.1\",{peerDependencies:{vue:\"^3.2.6\"}}],[\"eslint-import-resolver-vite@<2.0.1\",{dependencies:{debug:\"^4.3.4\",resolve:\"^1.22.8\"}}],[\"notistack@^3.0.0\",{dependencies:{csstype:\"^3.0.10\"}}]];var _H;function Cme(){return typeof _H>\"u\"&&(_H=ve(\"zlib\").brotliDecompressSync(Buffer.from(\"G7weAByFTVk3Vs7UfHhq4yykgEM7pbW7TI43SG2S5tvGrwHBAzdz+s/npQ6tgEvobvxisrPIadkXeUAJotBn5bDZ5kAhcRqsIHe3F75Walet5hNalwgFDtxb0BiDUjiUQkjG0yW2hto9HPgiCkm316d6bC0kST72YN7D7rfkhCE9x4J0XwB0yavalxpUu2t9xszHrmtwalOxT7VslsxWcB1qpqZwERUra4psWhTV8BgwWeizurec82Caf1ABL11YMfbf8FJ9JBceZOkgmvrQPbC9DUldX/yMbmX06UQluCEjSwUoyO+EZPIjofr+/oAZUck2enraRD+oWLlnlYnj8xB+gwSo9lmmks4fXv574qSqcWA6z21uYkzMu3EWj+K23RxeQlLqiE35/rC8GcS4CGkKHKKq+zAIQwD9iRDNfiAqueLLpicFFrNsAI4zeTD/eO9MHcnRa5m8UT+M2+V+AkFST4BlKneiAQRSdST8KEAIyFlULt6wa9EBd0Ds28VmpaxquJdVt+nwdEs5xUskI13OVtFyY0UrQIRAlCuvvWivvlSKQfTO+2Q8OyUR1W5RvetaPz4jD27hdtwHFFA1Ptx6Ee/t2cY2rg2G46M1pNDRf2pWhvpy8pqMnuI3++4OF3+7OFIWXGjh+o7Nr2jNvbiYcQdQS1h903/jVFgOpA0yJ78z+x759bFA0rq+6aY5qPB4FzS3oYoLupDUhD9nDz6F6H7hpnlMf18KNKDu4IKjTWwrAnY6MFQw1W6ymOALHlFyCZmQhldg1MQHaMVVQTVgDC60TfaBqG++Y8PEoFhN/PBTZT175KNP/BlHDYGOOBmnBdzqJKplZ/ljiVG0ZBzfqeBRrrUkn6rA54462SgiliKoYVnbeptMdXNfAuaupIEi0bApF10TlgHfmEJAPUVidRVFyDupSem5po5vErPqWKhKbUIp0LozpYsIKK57dM/HKr+nguF+7924IIWMICkQ8JUigs9D+W+c4LnNoRtPPKNRUiCYmP+Jfo2lfKCKw8qpraEeWU3uiNRO6zcyKQoXPR5htmzzLznke7b4YbXW3I1lIRzmgG02Udb58U+7TpwyN7XymCgH+wuPDthZVQvRZuEP+SnLtMicz9m5zASWOBiAcLmkuFlTKuHspSIhCBD0yUPKcxu81A+4YD78rA2vtwsUEday9WNyrShyrl60rWmA+SmbYZkQOwFJWArxRYYc5jGhA5ikxYw1rx3ei4NmeX/lKiwpZ9Ln1tV2Ae7sArvxuVLbJjqJRjW1vFXAyHpvLG+8MJ6T2Ubx5M2KDa2SN6vuIGxJ9WQM9Mk3Q7aCNiZONXllhqq24DmoLbQfW2rYWsOgHWjtOmIQMyMKdiHZDjoyIq5+U700nZ6odJAoYXPQBvFNiQ78d5jaXliBqLTJEqUCwi+LiH2mx92EmNKDsJL74Z613+3lf20pxkV1+erOrjj8pW00vsPaahKUM+05ssd5uwM7K482KWEf3TCwlg/o3e5ngto7qSMz7YteIgCsF1UOcsLk7F7MxWbvrPMY473ew0G+noVL8EPbkmEMftMSeL6HFub/zy+2JQ==\",\"base64\")).toString()),_H}var HH;function Ime(){return typeof HH>\"u\"&&(HH=ve(\"zlib\").brotliDecompressSync(Buffer.from(\"G8MSIIzURnVBnObTcvb3XE6v2S9Qgc2K801Oa5otNKEtK8BINZNcaQHy+9/vf/WXBimwutXC33P2DPc64pps5rz7NGGWaOKNSPL4Y2KRE8twut2lFOIN+OXPtRmPMRhMTILib2bEQx43az2I5d3YS8Roa5UZpF/ujHb3Djd3GDvYUfvFYSUQ39vb2cmifp/rgB4J/65JK3wRBTvMBoNBmn3mbXC63/gbBkW/2IRPri0O8bcsRBsmarF328pAln04nyJFkwUAvNu934supAqLtyerZZpJ8I8suJHhf/ocMV+scKwa8NOiDKIPXw6Ex/EEZD6TEGaW8N5zvNHYF10l6Lfooj7D5W2k3dgvQSbp2Wv8TGOayS978gxlOLVjTGXs66ozewbrjwElLtyrYNnWTfzzdEutgROUFPVMhnMoy8EjJLLlWwIEoySxliim9kYW30JUHiPVyjt0iAw/ZpPmCbUCltYPnq6ZNblIKhTNhqS/oqC9iya5sGKZTOVsTEg34n92uZTf2iPpcZih8rPW8CzA+adIGmyCPcKdLMsBLShd+zuEbTrqpwuh+DLmracZcjPC5Sdf5odDAhKpFuOsQS67RT+1VgWWygSv3YwxDnylc04/PYuaMeIzhBkLrvs7e/OUzRTF56MmfY6rI63QtEjEQzq637zQqJ39nNhu3NmoRRhW/086bHGBUtx0PE0j3aEGvkdh9WJC8y8j8mqqke9/dQ5la+Q3ba4RlhvTbnfQhPDDab3tUifkjKuOsp13mXEmO00Mu88F/M67R7LXfoFDFLNtgCSWjWX+3Jn1371pJTK9xPBiMJafvDjtFyAzu8rxeQ0TKMQXNPs5xxiBOd+BRJP8KP88XPtJIbZKh/cdW8KvBUkpqKpGoiIaA32c3/JnQr4efXt85mXvidOvn/eU3Pase1typLYBalJ14mCso9h79nuMOuCa/kZAOkJHmTjP5RM2WNoPasZUAnT1TAE/NH25hUxcQv6hQWR/m1PKk4ooXMcM4SR1iYU3fUohvqk4RY2hbmTVVIXv6TvqO+0doOjgeVFAcom+RlwJQmOVH7pr1Q9LoJT6n1DeQEB+NHygsATbIwTcOKZlJsY8G4+suX1uQLjUWwLjjs0mvSvZcLTpIGAekeR7GCgl8eo3ndAqEe2XCav4huliHjdbIPBsGJuPX7lrO9HX1UbXRH5opOe1x6JsOSgHZR+EaxuXVhpLLxm6jk1LJtZfHSc6BKPun3CpYYVMJGwEUyk8MTGG0XL5MfEwaXpnc9TKnBmlGn6nHiGREc3ysn47XIBDzA+YvFdjZzVIEDcKGpS6PbUJehFRjEne8D0lVU1XuRtlgszq6pTNlQ/3MzNOEgCWPyTct22V2mEi2krizn5VDo9B19/X2DB3hCGRMM7ONbtnAcIx/OWB1u5uPbW1gsH8irXxT/IzG0PoXWYjhbMsH3KTuoOl5o17PulcgvsfTSnKFM354GWI8luqZnrswWjiXy3G+Vbyo1KMopFmmvBwNELgaS8z8dNZchx/Cl/xjddxhMcyqtzFyONb2Zdu90NkI8pAeufe7YlXrp53v8Dj/l8vWeVspRKBGXScBBPI/HinSTGmLDOGGOCIyH0JFdOZx0gWsacNlQLJMIrBhqRxXxHF/5pseWwejlAAvZ3klZSDSYY8mkToaWejXhgNomeGtx1DTLEUFMRkgF5yFB22WYdJnaWN14r1YJj81hGi45+jrADS5nYRhCiSlCJJ1nL8pYX+HDSMhdTEWyRcgHVp/IsUIZYMfT+YYncUQPgcxNGCHfZ88vDdrcUuaGIl6zhAsiaq7R5dfqrqXH/JcBhfjT8D0azayIyEz75Nxp6YkcyDxlJq3EXnJUpqDohJJOysL1t1uNiHESlvsxPb5cpbW0+ICZqJmUZus1BMW0F5IVBODLIo2zHHjA0=\",\"base64\")).toString()),HH}var qH;function wme(){return typeof qH>\"u\"&&(qH=ve(\"zlib\").brotliDecompressSync(Buffer.from(\"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\",\"base64\")).toString()),qH}var Bme=new Map([[G.makeIdent(null,\"fsevents\").identHash,Cme],[G.makeIdent(null,\"resolve\").identHash,Ime],[G.makeIdent(null,\"typescript\").identHash,wme]]),wgt={hooks:{registerPackageExtensions:async(t,e)=>{for(let[r,o]of UH)e(G.parseDescriptor(r,!0),o)},getBuiltinPatch:async(t,e)=>{let r=\"compat/\";if(!e.startsWith(r))return;let o=G.parseIdent(e.slice(r.length)),a=Bme.get(o.identHash)?.();return typeof a<\"u\"?a:null},reduceDependency:async(t,e,r,o)=>typeof Bme.get(t.identHash)>\"u\"?t:G.makeDescriptor(t,G.makeRange({protocol:\"patch:\",source:G.stringifyDescriptor(t),selector:`optional!builtin<compat/${G.stringifyIdent(t)}>`,params:null}))}},Bgt=wgt;var a6={};Kt(a6,{ConstraintsCheckCommand:()=>sC,ConstraintsQueryCommand:()=>nC,ConstraintsSourceCommand:()=>iC,default:()=>Jgt});Ke();Ke();j2();var $E=class{constructor(e){this.project=e}createEnvironment(){let e=new ZE([\"cwd\",\"ident\"]),r=new ZE([\"workspace\",\"type\",\"ident\"]),o=new ZE([\"ident\"]),a={manifestUpdates:new Map,reportedErrors:new Map},n=new Map,u=new Map;for(let A of this.project.storedPackages.values()){let p=Array.from(A.peerDependencies.values(),h=>[G.stringifyIdent(h),h.range]);n.set(A.locatorHash,{workspace:null,ident:G.stringifyIdent(A),version:A.version,dependencies:new Map,peerDependencies:new Map(p.filter(([h])=>A.peerDependenciesMeta.get(h)?.optional!==!0)),optionalPeerDependencies:new Map(p.filter(([h])=>A.peerDependenciesMeta.get(h)?.optional===!0))})}for(let A of this.project.storedPackages.values()){let p=n.get(A.locatorHash);p.dependencies=new Map(Array.from(A.dependencies.values(),h=>{let E=this.project.storedResolutions.get(h.descriptorHash);if(typeof E>\"u\")throw new Error(\"Assertion failed: The resolution should have been registered\");let w=n.get(E);if(typeof w>\"u\")throw new Error(\"Assertion failed: The package should have been registered\");return[G.stringifyIdent(h),w]})),p.dependencies.delete(p.ident)}for(let A of this.project.workspaces){let p=G.stringifyIdent(A.anchoredLocator),h=A.manifest.exportTo({}),E=n.get(A.anchoredLocator.locatorHash);if(typeof E>\"u\")throw new Error(\"Assertion failed: The package should have been registered\");let w=(T,N,{caller:U=Xi.getCaller()}={})=>{let z=q2(T),te=qe.getMapWithDefault(a.manifestUpdates,A.cwd),le=qe.getMapWithDefault(te,z),ce=qe.getSetWithDefault(le,N);U!==null&&ce.add(U)},D=T=>w(T,void 0,{caller:Xi.getCaller()}),b=T=>{qe.getArrayWithDefault(a.reportedErrors,A.cwd).push(T)},C=e.insert({cwd:A.relativeCwd,ident:p,manifest:h,pkg:E,set:w,unset:D,error:b});u.set(A,C);for(let T of _t.allDependencies)for(let N of A.manifest[T].values()){let U=G.stringifyIdent(N),z=()=>{w([T,U],void 0,{caller:Xi.getCaller()})},te=ce=>{w([T,U],ce,{caller:Xi.getCaller()})},le=null;if(T!==\"peerDependencies\"&&(T!==\"dependencies\"||!A.manifest.devDependencies.has(N.identHash))){let ce=A.anchoredPackage.dependencies.get(N.identHash);if(ce){if(typeof ce>\"u\")throw new Error(\"Assertion failed: The dependency should have been registered\");let ue=this.project.storedResolutions.get(ce.descriptorHash);if(typeof ue>\"u\")throw new Error(\"Assertion failed: The resolution should have been registered\");let Ie=n.get(ue);if(typeof Ie>\"u\")throw new Error(\"Assertion failed: The package should have been registered\");le=Ie}}r.insert({workspace:C,ident:U,range:N.range,type:T,resolution:le,update:te,delete:z,error:b})}}for(let A of this.project.storedPackages.values()){let p=this.project.tryWorkspaceByLocator(A);if(!p)continue;let h=u.get(p);if(typeof h>\"u\")throw new Error(\"Assertion failed: The workspace should have been registered\");let E=n.get(A.locatorHash);if(typeof E>\"u\")throw new Error(\"Assertion failed: The package should have been registered\");E.workspace=h}return{workspaces:e,dependencies:r,packages:o,result:a}}async process(){let e=this.createEnvironment(),r={Yarn:{workspace:a=>e.workspaces.find(a)[0]??null,workspaces:a=>e.workspaces.find(a),dependency:a=>e.dependencies.find(a)[0]??null,dependencies:a=>e.dependencies.find(a),package:a=>e.packages.find(a)[0]??null,packages:a=>e.packages.find(a)}},o=await this.project.loadUserConfig();return o?.constraints?(await o.constraints(r),e.result):null}};Ke();Ke();Gt();var nC=class extends ut{constructor(){super(...arguments);this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.query=de.String()}static{this.paths=[[\"constraints\",\"query\"]]}static{this.usage=st.Usage({category:\"Constraints-related commands\",description:\"query the constraints fact database\",details:`\n      This command will output all matches to the given prolog query.\n    `,examples:[[\"List all dependencies throughout the workspace\",\"yarn constraints query 'workspace_has_dependency(_, DependencyName, _, _).'\"]]})}async execute(){let{Constraints:r}=await Promise.resolve().then(()=>(K2(),Y2)),o=await Je.find(this.context.cwd,this.context.plugins),{project:a}=await Qt.find(o,this.context.cwd),n=await r.find(a),u=this.query;return u.endsWith(\".\")||(u=`${u}.`),(await Lt.start({configuration:o,json:this.json,stdout:this.context.stdout},async p=>{for await(let h of n.query(u)){let E=Array.from(Object.entries(h)),w=E.length,D=E.reduce((b,[C])=>Math.max(b,C.length),0);for(let b=0;b<w;b++){let[C,T]=E[b];p.reportInfo(null,`${Vgt(b,w)}${C.padEnd(D,\" \")} = ${Kgt(T)}`)}p.reportJson(h)}})).exitCode()}};function Kgt(t){return typeof t!=\"string\"?`${t}`:t.match(/^[a-zA-Z][a-zA-Z0-9_]+$/)?t:`'${t}'`}function Vgt(t,e){let r=t===0,o=t===e-1;return r&&o?\"\":r?\"\\u250C \":o?\"\\u2514 \":\"\\u2502 \"}Ke();Gt();var iC=class extends ut{constructor(){super(...arguments);this.verbose=de.Boolean(\"-v,--verbose\",!1,{description:\"Also print the fact database automatically compiled from the workspace manifests\"})}static{this.paths=[[\"constraints\",\"source\"]]}static{this.usage=st.Usage({category:\"Constraints-related commands\",description:\"print the source code for the constraints\",details:\"\\n      This command will print the Prolog source code used by the constraints engine. Adding the `-v,--verbose` flag will print the *full* source code, including the fact database automatically compiled from the workspace manifests.\\n    \",examples:[[\"Prints the source code\",\"yarn constraints source\"],[\"Print the source code and the fact database\",\"yarn constraints source -v\"]]})}async execute(){let{Constraints:r}=await Promise.resolve().then(()=>(K2(),Y2)),o=await Je.find(this.context.cwd,this.context.plugins),{project:a}=await Qt.find(o,this.context.cwd),n=await r.find(a);this.context.stdout.write(this.verbose?n.fullSource:n.source)}};Ke();Ke();Gt();j2();var sC=class extends ut{constructor(){super(...arguments);this.fix=de.Boolean(\"--fix\",!1,{description:\"Attempt to automatically fix unambiguous issues, following a multi-pass process\"});this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"})}static{this.paths=[[\"constraints\"]]}static{this.usage=st.Usage({category:\"Constraints-related commands\",description:\"check that the project constraints are met\",details:`\n      This command will run constraints on your project and emit errors for each one that is found but isn't met. If any error is emitted the process will exit with a non-zero exit code.\n\n      If the \\`--fix\\` flag is used, Yarn will attempt to automatically fix the issues the best it can, following a multi-pass process (with a maximum of 10 iterations). Some ambiguous patterns cannot be autofixed, in which case you'll have to manually specify the right resolution.\n\n      For more information as to how to write constraints, please consult our dedicated page on our website: https://yarnpkg.com/features/constraints.\n    `,examples:[[\"Check that all constraints are satisfied\",\"yarn constraints\"],[\"Autofix all unmet constraints\",\"yarn constraints --fix\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o}=await Qt.find(r,this.context.cwd);await o.restoreInstallState();let a=await o.loadUserConfig(),n;if(a?.constraints)n=new $E(o);else{let{Constraints:h}=await Promise.resolve().then(()=>(K2(),Y2));n=await h.find(o)}let u,A=!1,p=!1;for(let h=this.fix?10:1;h>0;--h){let E=await n.process();if(!E)break;let{changedWorkspaces:w,remainingErrors:D}=Vk(o,E,{fix:this.fix}),b=[];for(let[C,T]of w){let N=C.manifest.indent;C.manifest=new _t,C.manifest.indent=N,C.manifest.load(T),b.push(C.persistManifest())}if(await Promise.all(b),!(w.size>0&&h>1)){u=kme(D,{configuration:r}),A=!1,p=!0;for(let[,C]of D)for(let T of C)T.fixable?A=!0:p=!1}}if(u.children.length===0)return 0;if(A){let h=p?`Those errors can all be fixed by running ${pe.pretty(r,\"yarn constraints --fix\",pe.Type.CODE)}`:`Errors prefixed by '\\u2699' can be fixed by running ${pe.pretty(r,\"yarn constraints --fix\",pe.Type.CODE)}`;await Lt.start({configuration:r,stdout:this.context.stdout,includeNames:!1,includeFooter:!1},async E=>{E.reportInfo(0,h),E.reportSeparator()})}return u.children=qe.sortMap(u.children,h=>h.value[1]),As.emitTree(u,{configuration:r,stdout:this.context.stdout,json:this.json,separators:1}),1}};j2();var zgt={configuration:{enableConstraintsChecks:{description:\"If true, constraints will run during installs\",type:\"BOOLEAN\",default:!1},constraintsPath:{description:\"The path of the constraints file.\",type:\"ABSOLUTE_PATH\",default:\"./constraints.pro\"}},commands:[nC,iC,sC],hooks:{async validateProjectAfterInstall(t,{reportError:e}){if(!t.configuration.get(\"enableConstraintsChecks\"))return;let r=await t.loadUserConfig(),o;if(r?.constraints)o=new $E(t);else{let{Constraints:u}=await Promise.resolve().then(()=>(K2(),Y2));o=await u.find(t)}let a=await o.process();if(!a)return;let{remainingErrors:n}=Vk(t,a);if(n.size!==0)if(t.configuration.isCI)for(let[u,A]of n)for(let p of A)e(84,`${pe.pretty(t.configuration,u.anchoredLocator,pe.Type.IDENT)}: ${p.text}`);else e(84,`Constraint check failed; run ${pe.pretty(t.configuration,\"yarn constraints\",pe.Type.CODE)} for more details`)}}},Jgt=zgt;var l6={};Kt(l6,{CreateCommand:()=>oC,DlxCommand:()=>aC,default:()=>Zgt});Ke();Gt();var oC=class extends ut{constructor(){super(...arguments);this.pkg=de.String(\"-p,--package\",{description:\"The package to run the provided command from\"});this.quiet=de.Boolean(\"-q,--quiet\",!1,{description:\"Only report critical errors instead of printing the full install logs\"});this.command=de.String();this.args=de.Proxy()}static{this.paths=[[\"create\"]]}async execute(){let r=[];this.pkg&&r.push(\"--package\",this.pkg),this.quiet&&r.push(\"--quiet\");let o=this.command.replace(/^(@[^@/]+)(@|$)/,\"$1/create$2\"),a=G.parseDescriptor(o),n=a.name.match(/^create(-|$)/)?a:a.scope?G.makeIdent(a.scope,`create-${a.name}`):G.makeIdent(null,`create-${a.name}`),u=G.stringifyIdent(n);return a.range!==\"unknown\"&&(u+=`@${a.range}`),this.cli.run([\"dlx\",...r,u,...this.args])}};Ke();Ke();Pt();Gt();var aC=class extends ut{constructor(){super(...arguments);this.packages=de.Array(\"-p,--package\",{description:\"The package(s) to install before running the command\"});this.quiet=de.Boolean(\"-q,--quiet\",!1,{description:\"Only report critical errors instead of printing the full install logs\"});this.command=de.String();this.args=de.Proxy()}static{this.paths=[[\"dlx\"]]}static{this.usage=st.Usage({description:\"run a package in a temporary environment\",details:\"\\n      This command will install a package within a temporary environment, and run its binary script if it contains any. The binary will run within the current cwd.\\n\\n      By default Yarn will download the package named `command`, but this can be changed through the use of the `-p,--package` flag which will instruct Yarn to still run the same command but from a different package.\\n\\n      Using `yarn dlx` as a replacement of `yarn add` isn't recommended, as it makes your project non-deterministic (Yarn doesn't keep track of the packages installed through `dlx` - neither their name, nor their version).\\n    \",examples:[[\"Use create-react-app to create a new React app\",\"yarn dlx create-react-app ./my-app\"],[\"Install multiple packages for a single command\",`yarn dlx -p typescript -p ts-node ts-node --transpile-only -e \"console.log('hello!')\"`]]})}async execute(){return Je.telemetry=null,await ae.mktempPromise(async r=>{let o=K.join(r,`dlx-${process.pid}`);await ae.mkdirPromise(o),await ae.writeFilePromise(K.join(o,\"package.json\"),`{}\n`),await ae.writeFilePromise(K.join(o,\"yarn.lock\"),\"\");let a=K.join(o,\".yarnrc.yml\"),n=await Je.findProjectCwd(this.context.cwd),A={enableGlobalCache:!(await Je.find(this.context.cwd,null,{strict:!1})).get(\"enableGlobalCache\"),enableTelemetry:!1,logFilters:[{code:zu(68),level:pe.LogLevel.Discard}]},p=n!==null?K.join(n,\".yarnrc.yml\"):null;p!==null&&ae.existsSync(p)?(await ae.copyFilePromise(p,a),await Je.updateConfiguration(o,N=>{let U=qe.toMerged(N,A);return Array.isArray(N.plugins)&&(U.plugins=N.plugins.map(z=>{let te=typeof z==\"string\"?z:z.path,le=Ae.isAbsolute(te)?te:Ae.resolve(Ae.fromPortablePath(n),te);return typeof z==\"string\"?le:{path:le,spec:z.spec}})),U})):await ae.writeJsonPromise(a,A);let h=this.packages??[this.command],E=G.parseDescriptor(this.command).name,w=await this.cli.run([\"add\",\"--fixed\",\"--\",...h],{cwd:o,quiet:this.quiet});if(w!==0)return w;this.quiet||this.context.stdout.write(`\n`);let D=await Je.find(o,this.context.plugins),{project:b,workspace:C}=await Qt.find(D,o);if(C===null)throw new or(b.cwd,o);await b.restoreInstallState();let T=await hn.getWorkspaceAccessibleBinaries(C);return T.has(E)===!1&&T.size===1&&typeof this.packages>\"u\"&&(E=Array.from(T)[0][0]),await hn.executeWorkspaceAccessibleBinary(C,E,this.args,{packageAccessibleBinaries:T,cwd:this.context.cwd,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr})})}};var Xgt={commands:[oC,aC]},Zgt=Xgt;var A6={};Kt(A6,{ExecFetcher:()=>z2,ExecResolver:()=>J2,default:()=>tdt,execUtils:()=>Zk});Ke();Ke();Pt();var hA=\"exec:\";var Zk={};Kt(Zk,{loadGeneratorFile:()=>V2,makeLocator:()=>u6,makeSpec:()=>rye,parseSpec:()=>c6});Ke();Pt();function c6(t){let{params:e,selector:r}=G.parseRange(t),o=Ae.toPortablePath(r);return{parentLocator:e&&typeof e.locator==\"string\"?G.parseLocator(e.locator):null,path:o}}function rye({parentLocator:t,path:e,generatorHash:r,protocol:o}){let a=t!==null?{locator:G.stringifyLocator(t)}:{},n=typeof r<\"u\"?{hash:r}:{};return G.makeRange({protocol:o,source:e,selector:e,params:{...n,...a}})}function u6(t,{parentLocator:e,path:r,generatorHash:o,protocol:a}){return G.makeLocator(t,rye({parentLocator:e,path:r,generatorHash:o,protocol:a}))}async function V2(t,e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(t,{protocol:e}),n=K.isAbsolute(a)?{packageFs:new En(Bt.root),prefixPath:Bt.dot,localPath:Bt.root}:await r.fetcher.fetch(o,r),u=n.localPath?{packageFs:new En(Bt.root),prefixPath:K.relative(Bt.root,n.localPath)}:n;n!==u&&n.releaseFs&&n.releaseFs();let A=u.packageFs,p=K.join(u.prefixPath,a);return await A.readFilePromise(p,\"utf8\")}var z2=class{supports(e,r){return!!e.reference.startsWith(hA)}getLocalPath(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:hA});if(K.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(o,r);return n===null?null:K.resolve(n,a)}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e),loader:()=>this.fetchFromDisk(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),localPath:this.getLocalPath(e,r),checksum:u}}async fetchFromDisk(e,r){let o=await V2(e.reference,hA,r);return ae.mktempPromise(async a=>{let n=K.join(a,\"generator.js\");return await ae.writeFilePromise(n,o),ae.mktempPromise(async u=>{if(await this.generatePackage(u,e,n,r),!ae.existsSync(K.join(u,\"build\")))throw new Error(\"The script should have generated a build directory\");return await $i.makeArchiveFromDirectory(K.join(u,\"build\"),{prefixPath:G.getIdentVendorPath(e),compressionLevel:r.project.configuration.get(\"compressionLevel\")})})})}async generatePackage(e,r,o,a){return await ae.mktempPromise(async n=>{let u=await hn.makeScriptEnv({project:a.project,binFolder:n}),A=K.join(e,\"runtime.js\");return await ae.mktempPromise(async p=>{let h=K.join(p,\"buildfile.log\"),E=K.join(e,\"generator\"),w=K.join(e,\"build\");await ae.mkdirPromise(E),await ae.mkdirPromise(w);let D={tempDir:Ae.fromPortablePath(E),buildDir:Ae.fromPortablePath(w),locator:G.stringifyLocator(r)};await ae.writeFilePromise(A,`\n          // Expose 'Module' as a global variable\n          Object.defineProperty(global, 'Module', {\n            get: () => require('module'),\n            configurable: true,\n            enumerable: false,\n          });\n\n          // Expose non-hidden built-in modules as global variables\n          for (const name of Module.builtinModules.filter((name) => name !== 'module' && !name.startsWith('_'))) {\n            Object.defineProperty(global, name, {\n              get: () => require(name),\n              configurable: true,\n              enumerable: false,\n            });\n          }\n\n          // Expose the 'execEnv' global variable\n          Object.defineProperty(global, 'execEnv', {\n            value: {\n              ...${JSON.stringify(D)},\n            },\n            enumerable: true,\n          });\n        `);let b=u.NODE_OPTIONS||\"\",C=/\\s*--require\\s+\\S*\\.pnp\\.c?js\\s*/g;b=b.replace(C,\" \").trim(),u.NODE_OPTIONS=b;let{stdout:T,stderr:N}=a.project.configuration.getSubprocessStreams(h,{header:`# This file contains the result of Yarn generating a package (${G.stringifyLocator(r)})\n`,prefix:G.prettyLocator(a.project.configuration,r),report:a.report}),{code:U}=await Hr.pipevp(process.execPath,[\"--require\",Ae.fromPortablePath(A),Ae.fromPortablePath(o),G.stringifyIdent(r)],{cwd:e,env:u,stdin:null,stdout:T,stderr:N});if(U!==0)throw ae.detachTemp(p),new Error(`Package generation failed (exit code ${U}, logs can be found here: ${pe.pretty(a.project.configuration,h,pe.Type.PATH)})`)})})}};Ke();Ke();var $gt=2,J2=class{supportsDescriptor(e,r){return!!e.range.startsWith(hA)}supportsLocator(e,r){return!!e.reference.startsWith(hA)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){if(!o.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let{path:a,parentLocator:n}=c6(e.range);if(n===null)throw new Error(\"Assertion failed: The descriptor should have been bound\");let u=await V2(G.makeRange({protocol:hA,source:a,selector:a,params:{locator:G.stringifyLocator(n)}}),hA,o.fetchOptions),A=bn.makeHash(`${$gt}`,u).slice(0,6);return[u6(e,{parentLocator:n,path:a,generatorHash:A,protocol:hA})]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await qe.releaseAfterUseAsync(async()=>await _t.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||\"0.0.0\",languageName:a.languageName||r.project.configuration.get(\"defaultLanguageName\"),linkType:\"HARD\",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var edt={fetchers:[z2],resolvers:[J2]},tdt=edt;var p6={};Kt(p6,{FileFetcher:()=>eB,FileResolver:()=>tB,TarballFileFetcher:()=>rB,TarballFileResolver:()=>nB,default:()=>idt,fileUtils:()=>$g});Ke();Pt();var lC=/^(?:[a-zA-Z]:[\\\\/]|\\.{0,2}\\/)/,X2=/^[^?]*\\.(?:tar\\.gz|tgz)(?:::.*)?$/,_i=\"file:\";var $g={};Kt($g,{fetchArchiveFromLocator:()=>$2,makeArchiveFromLocator:()=>$k,makeBufferFromLocator:()=>f6,makeLocator:()=>cC,makeSpec:()=>nye,parseSpec:()=>Z2});Ke();Pt();function Z2(t){let{params:e,selector:r}=G.parseRange(t),o=Ae.toPortablePath(r);return{parentLocator:e&&typeof e.locator==\"string\"?G.parseLocator(e.locator):null,path:o}}function nye({parentLocator:t,path:e,hash:r,protocol:o}){let a=t!==null?{locator:G.stringifyLocator(t)}:{},n=typeof r<\"u\"?{hash:r}:{};return G.makeRange({protocol:o,source:e,selector:e,params:{...n,...a}})}function cC(t,{parentLocator:e,path:r,hash:o,protocol:a}){return G.makeLocator(t,nye({parentLocator:e,path:r,hash:o,protocol:a}))}async function $2(t,e){let{parentLocator:r,path:o}=G.parseFileStyleRange(t.reference,{protocol:_i}),a=K.isAbsolute(o)?{packageFs:new En(Bt.root),prefixPath:Bt.dot,localPath:Bt.root}:await e.fetcher.fetch(r,e),n=a.localPath?{packageFs:new En(Bt.root),prefixPath:K.relative(Bt.root,a.localPath)}:a;a!==n&&a.releaseFs&&a.releaseFs();let u=n.packageFs,A=K.join(n.prefixPath,o);return await qe.releaseAfterUseAsync(async()=>await u.readFilePromise(A),n.releaseFs)}async function $k(t,{protocol:e,fetchOptions:r,inMemory:o=!1}){let{parentLocator:a,path:n}=G.parseFileStyleRange(t.reference,{protocol:e}),u=K.isAbsolute(n)?{packageFs:new En(Bt.root),prefixPath:Bt.dot,localPath:Bt.root}:await r.fetcher.fetch(a,r),A=u.localPath?{packageFs:new En(Bt.root),prefixPath:K.relative(Bt.root,u.localPath)}:u;u!==A&&u.releaseFs&&u.releaseFs();let p=A.packageFs,h=K.join(A.prefixPath,n);return await qe.releaseAfterUseAsync(async()=>await $i.makeArchiveFromDirectory(h,{baseFs:p,prefixPath:G.getIdentVendorPath(t),compressionLevel:r.project.configuration.get(\"compressionLevel\"),inMemory:o}),A.releaseFs)}async function f6(t,{protocol:e,fetchOptions:r}){return(await $k(t,{protocol:e,fetchOptions:r,inMemory:!0})).getBufferAndClose()}var eB=class{supports(e,r){return!!e.reference.startsWith(_i)}getLocalPath(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:_i});if(K.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(o,r);return n===null?null:K.resolve(n,a)}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the disk`),loader:()=>this.fetchFromDisk(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),localPath:this.getLocalPath(e,r),checksum:u}}async fetchFromDisk(e,r){return $k(e,{protocol:_i,fetchOptions:r})}};Ke();Ke();var rdt=2,tB=class{supportsDescriptor(e,r){return e.range.match(lC)?!0:!!e.range.startsWith(_i)}supportsLocator(e,r){return!!e.reference.startsWith(_i)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return lC.test(e.range)&&(e=G.makeDescriptor(e,`${_i}${e.range}`)),G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){if(!o.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let{path:a,parentLocator:n}=Z2(e.range);if(n===null)throw new Error(\"Assertion failed: The descriptor should have been bound\");let u=await f6(G.makeLocator(e,G.makeRange({protocol:_i,source:a,selector:a,params:{locator:G.stringifyLocator(n)}})),{protocol:_i,fetchOptions:o.fetchOptions}),A=bn.makeHash(`${rdt}`,u).slice(0,6);return[cC(e,{parentLocator:n,path:a,hash:A,protocol:_i})]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await qe.releaseAfterUseAsync(async()=>await _t.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||\"0.0.0\",languageName:a.languageName||r.project.configuration.get(\"defaultLanguageName\"),linkType:\"HARD\",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};Ke();var rB=class{supports(e,r){return X2.test(e.reference)?!!e.reference.startsWith(_i):!1}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the disk`),loader:()=>this.fetchFromDisk(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),checksum:u}}async fetchFromDisk(e,r){let o=await $2(e,r);return await $i.convertToZip(o,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1})}};Ke();Ke();Ke();var nB=class{supportsDescriptor(e,r){return X2.test(e.range)?!!(e.range.startsWith(_i)||lC.test(e.range)):!1}supportsLocator(e,r){return X2.test(e.reference)?!!e.reference.startsWith(_i):!1}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return lC.test(e.range)&&(e=G.makeDescriptor(e,`${_i}${e.range}`)),G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){if(!o.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let{path:a,parentLocator:n}=Z2(e.range);if(n===null)throw new Error(\"Assertion failed: The descriptor should have been bound\");let u=cC(e,{parentLocator:n,path:a,hash:\"\",protocol:_i}),A=await $2(u,o.fetchOptions),p=bn.makeHash(A).slice(0,6);return[cC(e,{parentLocator:n,path:a,hash:p,protocol:_i})]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await qe.releaseAfterUseAsync(async()=>await _t.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||\"0.0.0\",languageName:a.languageName||r.project.configuration.get(\"defaultLanguageName\"),linkType:\"HARD\",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var ndt={fetchers:[rB,eB],resolvers:[nB,tB]},idt=ndt;var d6={};Kt(d6,{GithubFetcher:()=>iB,default:()=>odt,githubUtils:()=>eQ});Ke();Pt();var eQ={};Kt(eQ,{invalidGithubUrlMessage:()=>oye,isGithubUrl:()=>h6,parseGithubUrl:()=>g6});var iye=et(ve(\"querystring\")),sye=[/^https?:\\/\\/(?:([^/]+?)@)?github.com\\/([^/#]+)\\/([^/#]+)\\/tarball\\/([^/#]+)(?:#(.*))?$/,/^https?:\\/\\/(?:([^/]+?)@)?github.com\\/([^/#]+)\\/([^/#]+?)(?:\\.git)?(?:#(.*))?$/];function h6(t){return t?sye.some(e=>!!t.match(e)):!1}function g6(t){let e;for(let A of sye)if(e=t.match(A),e)break;if(!e)throw new Error(oye(t));let[,r,o,a,n=\"master\"]=e,{commit:u}=iye.default.parse(n);return n=u||n.replace(/[^:]*:/,\"\"),{auth:r,username:o,reponame:a,treeish:n}}function oye(t){return`Input cannot be parsed as a valid GitHub URL ('${t}').`}var iB=class{supports(e,r){return!!h6(e.reference)}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from GitHub`),loader:()=>this.fetchFromNetwork(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),checksum:u}}async fetchFromNetwork(e,r){let o=await on.get(this.getLocatorUrl(e,r),{configuration:r.project.configuration});return await ae.mktempPromise(async a=>{let n=new En(a);await $i.extractArchiveTo(o,n,{stripComponents:1});let u=ra.splitRepoUrl(e.reference),A=K.join(a,\"package.tgz\");await hn.prepareExternalProject(a,A,{configuration:r.project.configuration,report:r.report,workspace:u.extra.workspace,locator:e});let p=await ae.readFilePromise(A);return await $i.convertToZip(p,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1})})}getLocatorUrl(e,r){let{auth:o,username:a,reponame:n,treeish:u}=g6(e.reference);return`https://${o?`${o}@`:\"\"}github.com/${a}/${n}/archive/${u}.tar.gz`}};var sdt={hooks:{async fetchHostedRepository(t,e,r){if(t!==null)return t;let o=new iB;if(!o.supports(e,r))return null;try{return await o.fetch(e,r)}catch{return null}}}},odt=sdt;var m6={};Kt(m6,{TarballHttpFetcher:()=>oB,TarballHttpResolver:()=>aB,default:()=>ldt});Ke();function sB(t){let e;try{e=new URL(t)}catch{return!1}return!(e.protocol!==\"http:\"&&e.protocol!==\"https:\"||!e.pathname.match(/(\\.tar\\.gz|\\.tgz|\\/[^.]+)$/))}var oB=class{supports(e,r){return sB(e.reference)}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the remote server`),loader:()=>this.fetchFromNetwork(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),checksum:u}}async fetchFromNetwork(e,r){let o=await on.get(e.reference,{configuration:r.project.configuration});return await $i.convertToZip(o,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1})}};Ke();Ke();var aB=class{supportsDescriptor(e,r){return sB(e.range)}supportsLocator(e,r){return sB(e.reference)}shouldPersistResolution(e,r){return!0}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){return[G.convertDescriptorToLocator(e)]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await qe.releaseAfterUseAsync(async()=>await _t.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||\"0.0.0\",languageName:a.languageName||r.project.configuration.get(\"defaultLanguageName\"),linkType:\"HARD\",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var adt={fetchers:[oB],resolvers:[aB]},ldt=adt;var y6={};Kt(y6,{InitCommand:()=>uC,default:()=>udt});Ke();Ke();Pt();Gt();var uC=class extends ut{constructor(){super(...arguments);this.private=de.Boolean(\"-p,--private\",!1,{description:\"Initialize a private package\"});this.workspace=de.Boolean(\"-w,--workspace\",!1,{description:\"Initialize a workspace root with a `packages/` directory\"});this.install=de.String(\"-i,--install\",!1,{tolerateBoolean:!0,description:\"Initialize a package with a specific bundle that will be locked in the project\"});this.name=de.String(\"-n,--name\",{description:\"Initialize a package with the given name\"});this.usev2=de.Boolean(\"-2\",!1,{hidden:!0});this.yes=de.Boolean(\"-y,--yes\",{hidden:!0})}static{this.paths=[[\"init\"]]}static{this.usage=st.Usage({description:\"create a new package\",details:\"\\n      This command will setup a new package in your local directory.\\n\\n      If the `-p,--private` or `-w,--workspace` options are set, the package will be private by default.\\n\\n      If the `-w,--workspace` option is set, the package will be configured to accept a set of workspaces in the `packages/` directory.\\n\\n      If the `-i,--install` option is given a value, Yarn will first download it using `yarn set version` and only then forward the init call to the newly downloaded bundle. Without arguments, the downloaded bundle will be `latest`.\\n\\n      The initial settings of the manifest can be changed by using the `initScope` and `initFields` configuration values. Additionally, Yarn will generate an EditorConfig file whose rules can be altered via `initEditorConfig`, and will initialize a Git repository in the current directory.\\n    \",examples:[[\"Create a new package in the local directory\",\"yarn init\"],[\"Create a new private package in the local directory\",\"yarn init -p\"],[\"Create a new package and store the Yarn release inside\",\"yarn init -i=latest\"],[\"Create a new private package and defines it as a workspace root\",\"yarn init -w\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=typeof this.install==\"string\"?this.install:this.usev2||this.install===!0?\"latest\":null;return o!==null?await this.executeProxy(r,o):await this.executeRegular(r)}async executeProxy(r,o){if(r.projectCwd!==null&&r.projectCwd!==this.context.cwd)throw new ot(\"Cannot use the --install flag from within a project subdirectory\");ae.existsSync(this.context.cwd)||await ae.mkdirPromise(this.context.cwd,{recursive:!0});let a=K.join(this.context.cwd,mr.lockfile);ae.existsSync(a)||await ae.writeFilePromise(a,\"\");let n=await this.cli.run([\"set\",\"version\",o],{quiet:!0});if(n!==0)return n;let u=[];return this.private&&u.push(\"-p\"),this.workspace&&u.push(\"-w\"),this.name&&u.push(`-n=${this.name}`),this.yes&&u.push(\"-y\"),await ae.mktempPromise(async A=>{let{code:p}=await Hr.pipevp(\"yarn\",[\"init\",...u],{cwd:this.context.cwd,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr,env:await hn.makeScriptEnv({binFolder:A})});return p})}async executeRegular(r){let o=null;try{o=(await Qt.find(r,this.context.cwd)).project}catch{o=null}ae.existsSync(this.context.cwd)||await ae.mkdirPromise(this.context.cwd,{recursive:!0});let a=await _t.tryFind(this.context.cwd),n=a??new _t,u=Object.fromEntries(r.get(\"initFields\").entries());n.load(u),n.name=n.name??G.makeIdent(r.get(\"initScope\"),this.name??K.basename(this.context.cwd)),n.packageManager=nn&&qe.isTaggedYarnVersion(nn)?`yarn@${nn}`:null,(!a&&this.workspace||this.private)&&(n.private=!0),this.workspace&&n.workspaceDefinitions.length===0&&(await ae.mkdirPromise(K.join(this.context.cwd,\"packages\"),{recursive:!0}),n.workspaceDefinitions=[{pattern:\"packages/*\"}]);let A={};n.exportTo(A);let p=K.join(this.context.cwd,_t.fileName);await ae.changeFilePromise(p,`${JSON.stringify(A,null,2)}\n`,{automaticNewlines:!0});let h=[p],E=K.join(this.context.cwd,\"README.md\");if(ae.existsSync(E)||(await ae.writeFilePromise(E,`# ${G.stringifyIdent(n.name)}\n`),h.push(E)),!o||o.cwd===this.context.cwd){let w=K.join(this.context.cwd,mr.lockfile);ae.existsSync(w)||(await ae.writeFilePromise(w,\"\"),h.push(w));let b=[\".yarn/*\",\"!.yarn/patches\",\"!.yarn/plugins\",\"!.yarn/releases\",\"!.yarn/sdks\",\"!.yarn/versions\",\"\",\"# Swap the comments on the following lines if you wish to use zero-installs\",\"# In that case, don't forget to run `yarn config set enableGlobalCache false`!\",\"# Documentation here: https://yarnpkg.com/features/caching#zero-installs\",\"\",\"#!.yarn/cache\",\".pnp.*\"].map(ce=>`${ce}\n`).join(\"\"),C=K.join(this.context.cwd,\".gitignore\");ae.existsSync(C)||(await ae.writeFilePromise(C,b),h.push(C));let N=[\"/.yarn/**            linguist-vendored\",\"/.yarn/releases/*    binary\",\"/.yarn/plugins/**/*  binary\",\"/.pnp.*              binary linguist-generated\"].map(ce=>`${ce}\n`).join(\"\"),U=K.join(this.context.cwd,\".gitattributes\");ae.existsSync(U)||(await ae.writeFilePromise(U,N),h.push(U));let z={\"*\":{endOfLine:\"lf\",insertFinalNewline:!0},\"*.{js,json,yml}\":{charset:\"utf-8\",indentStyle:\"space\",indentSize:2}};qe.mergeIntoTarget(z,r.get(\"initEditorConfig\"));let te=`root = true\n`;for(let[ce,ue]of Object.entries(z)){te+=`\n[${ce}]\n`;for(let[Ie,he]of Object.entries(ue)){let De=Ie.replace(/[A-Z]/g,Ee=>`_${Ee.toLowerCase()}`);te+=`${De} = ${he}\n`}}let le=K.join(this.context.cwd,\".editorconfig\");ae.existsSync(le)||(await ae.writeFilePromise(le,te),h.push(le)),await this.cli.run([\"install\"],{quiet:!0}),ae.existsSync(K.join(this.context.cwd,\".git\"))||(await Hr.execvp(\"git\",[\"init\"],{cwd:this.context.cwd}),await Hr.execvp(\"git\",[\"add\",\"--\",...h],{cwd:this.context.cwd}),await Hr.execvp(\"git\",[\"commit\",\"--allow-empty\",\"-m\",\"First commit\"],{cwd:this.context.cwd}))}}};var cdt={configuration:{initScope:{description:\"Scope used when creating packages via the init command\",type:\"STRING\",default:null},initFields:{description:\"Additional fields to set when creating packages via the init command\",type:\"MAP\",valueDefinition:{description:\"\",type:\"ANY\"}},initEditorConfig:{description:\"Extra rules to define in the generator editorconfig\",type:\"MAP\",valueDefinition:{description:\"\",type:\"ANY\"}}},commands:[uC]},udt=cdt;var mj={};Kt(mj,{SearchCommand:()=>xC,UpgradeInteractiveCommand:()=>bC,default:()=>UIt});Ke();var lye=et(ve(\"os\"));function AC({stdout:t}){if(lye.default.endianness()===\"BE\")throw new Error(\"Interactive commands cannot be used on big-endian systems because ink depends on yoga-layout-prebuilt which only supports little-endian architectures\");if(!t.isTTY)throw new Error(\"Interactive commands can only be used inside a TTY environment\")}Gt();var CEe=et(N6()),O6={appId:\"OFCNCOG2CU\",apiKey:\"6fe4476ee5a1832882e326b506d14126\",indexName:\"npm-search\"},ayt=(0,CEe.default)(O6.appId,O6.apiKey).initIndex(O6.indexName),M6=async(t,e=0)=>await ayt.search(t,{analyticsTags:[\"yarn-plugin-interactive-tools\"],attributesToRetrieve:[\"name\",\"version\",\"owner\",\"repository\",\"humanDownloadsLast30Days\"],page:e,hitsPerPage:10});var sv=[\"regular\",\"dev\",\"peer\"],xC=class extends ut{static{this.paths=[[\"search\"]]}static{this.usage=st.Usage({category:\"Interactive commands\",description:\"open the search interface\",details:`\n    This command opens a fullscreen terminal interface where you can search for and install packages from the npm registry.\n    `,examples:[[\"Open the search window\",\"yarn search\"]]})}async execute(){AC(this.context);let{Gem:e}=await Promise.resolve().then(()=>(UQ(),oj)),{ScrollableItems:r}=await Promise.resolve().then(()=>(jQ(),qQ)),{useKeypress:o}=await Promise.resolve().then(()=>(rv(),bwe)),{useMinistore:a}=await Promise.resolve().then(()=>(fj(),Aj)),{renderForm:n}=await Promise.resolve().then(()=>(KQ(),YQ)),{default:u}=await Promise.resolve().then(()=>et(Uwe())),{Box:A,Text:p}=await Promise.resolve().then(()=>et(ac())),{default:h,useEffect:E,useState:w}=await Promise.resolve().then(()=>et(ln())),D=await Je.find(this.context.cwd,this.context.plugins),b=()=>h.createElement(A,{flexDirection:\"row\"},h.createElement(A,{flexDirection:\"column\",width:48},h.createElement(A,null,h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<up>\"),\"/\",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<down>\"),\" to move between packages.\")),h.createElement(A,null,h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<space>\"),\" to select a package.\")),h.createElement(A,null,h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<space>\"),\" again to change the target.\"))),h.createElement(A,{flexDirection:\"column\"},h.createElement(A,{marginLeft:1},h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<enter>\"),\" to install the selected packages.\")),h.createElement(A,{marginLeft:1},h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<ctrl+c>\"),\" to abort.\")))),C=()=>h.createElement(h.Fragment,null,h.createElement(A,{width:15},h.createElement(p,{bold:!0,underline:!0,color:\"gray\"},\"Owner\")),h.createElement(A,{width:11},h.createElement(p,{bold:!0,underline:!0,color:\"gray\"},\"Version\")),h.createElement(A,{width:10},h.createElement(p,{bold:!0,underline:!0,color:\"gray\"},\"Downloads\"))),T=()=>h.createElement(A,{width:17},h.createElement(p,{bold:!0,underline:!0,color:\"gray\"},\"Target\")),N=({hit:he,active:De})=>{let[Ee,g]=a(he.name,null);o({active:De},(fe,ie)=>{if(ie.name!==\"space\")return;if(!Ee){g(sv[0]);return}let Z=sv.indexOf(Ee)+1;Z===sv.length?g(null):g(sv[Z])},[Ee,g]);let me=G.parseIdent(he.name),Ce=G.prettyIdent(D,me);return h.createElement(A,null,h.createElement(A,{width:45},h.createElement(p,{bold:!0,wrap:\"wrap\"},Ce)),h.createElement(A,{width:14,marginLeft:1},h.createElement(p,{bold:!0,wrap:\"truncate\"},he.owner.name)),h.createElement(A,{width:10,marginLeft:1},h.createElement(p,{italic:!0,wrap:\"truncate\"},he.version)),h.createElement(A,{width:16,marginLeft:1},h.createElement(p,null,he.humanDownloadsLast30Days)))},U=({name:he,active:De})=>{let[Ee]=a(he,null),g=G.parseIdent(he);return h.createElement(A,null,h.createElement(A,{width:47},h.createElement(p,{bold:!0},\" - \",G.prettyIdent(D,g))),sv.map(me=>h.createElement(A,{key:me,width:14,marginLeft:1},h.createElement(p,null,\" \",h.createElement(e,{active:Ee===me}),\" \",h.createElement(p,{bold:!0},me)))))},z=()=>h.createElement(A,{marginTop:1},h.createElement(p,null,\"Powered by Algolia.\")),le=await n(({useSubmit:he})=>{let De=a();he(De);let Ee=Array.from(De.keys()).filter(q=>De.get(q)!==null),[g,me]=w(\"\"),[Ce,fe]=w(0),[ie,Z]=w([]),Pe=q=>{q.match(/\\t| /)||me(q)},Re=async()=>{fe(0);let q=await M6(g);q.query===g&&Z(q.hits)},ht=async()=>{let q=await M6(g,Ce+1);q.query===g&&q.page-1===Ce&&(fe(q.page),Z([...ie,...q.hits]))};return E(()=>{g?Re():Z([])},[g]),h.createElement(A,{flexDirection:\"column\"},h.createElement(b,null),h.createElement(A,{flexDirection:\"row\",marginTop:1},h.createElement(p,{bold:!0},\"Search: \"),h.createElement(A,{width:41},h.createElement(u,{value:g,onChange:Pe,placeholder:\"i.e. babel, webpack, react...\",showCursor:!1})),h.createElement(C,null)),ie.length?h.createElement(r,{radius:2,loop:!1,children:ie.map(q=>h.createElement(N,{key:q.name,hit:q,active:!1})),willReachEnd:ht}):h.createElement(p,{color:\"gray\"},\"Start typing...\"),h.createElement(A,{flexDirection:\"row\",marginTop:1},h.createElement(A,{width:49},h.createElement(p,{bold:!0},\"Selected:\")),h.createElement(T,null)),Ee.length?Ee.map(q=>h.createElement(U,{key:q,name:q,active:!1})):h.createElement(p,{color:\"gray\"},\"No selected packages...\"),h.createElement(z,null))},{},{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});if(typeof le>\"u\")return 1;let ce=Array.from(le.keys()).filter(he=>le.get(he)===\"regular\"),ue=Array.from(le.keys()).filter(he=>le.get(he)===\"dev\"),Ie=Array.from(le.keys()).filter(he=>le.get(he)===\"peer\");return ce.length&&await this.cli.run([\"add\",...ce]),ue.length&&await this.cli.run([\"add\",\"--dev\",...ue]),Ie&&await this.cli.run([\"add\",\"--peer\",...Ie]),0}};Ke();Gt();n8();var Ywe=et(ni()),Wwe=/^((?:[\\^~]|>=?)?)([0-9]+)(\\.[0-9]+)(\\.[0-9]+)((?:-\\S+)?)$/,Kwe=(t,e)=>t.length>0?[t.slice(0,e)].concat(Kwe(t.slice(e),e)):[],bC=class extends ut{static{this.paths=[[\"upgrade-interactive\"]]}static{this.usage=st.Usage({category:\"Interactive commands\",description:\"open the upgrade interface\",details:`\n      This command opens a fullscreen terminal interface where you can see any out of date packages used by your application, their status compared to the latest versions available on the remote registry, and select packages to upgrade.\n    `,examples:[[\"Open the upgrade window\",\"yarn upgrade-interactive\"]]})}async execute(){AC(this.context);let{ItemOptions:e}=await Promise.resolve().then(()=>(Gwe(),jwe)),{Pad:r}=await Promise.resolve().then(()=>(dj(),qwe)),{ScrollableItems:o}=await Promise.resolve().then(()=>(jQ(),qQ)),{useMinistore:a}=await Promise.resolve().then(()=>(fj(),Aj)),{renderForm:n}=await Promise.resolve().then(()=>(KQ(),YQ)),{Box:u,Text:A}=await Promise.resolve().then(()=>et(ac())),{default:p,useEffect:h,useRef:E,useState:w}=await Promise.resolve().then(()=>et(ln())),D=await Je.find(this.context.cwd,this.context.plugins),{project:b,workspace:C}=await Qt.find(D,this.context.cwd),T=await Wr.find(D);if(!C)throw new or(b.cwd,this.context.cwd);await b.restoreInstallState({restoreResolutions:!1});let N=this.context.stdout.rows-7,U=(me,Ce)=>{let fe=$pe(me,Ce),ie=\"\";for(let Z of fe)Z.added?ie+=pe.pretty(D,Z.value,\"green\"):Z.removed||(ie+=Z.value);return ie},z=(me,Ce)=>{if(me===Ce)return Ce;let fe=G.parseRange(me),ie=G.parseRange(Ce),Z=fe.selector.match(Wwe),Pe=ie.selector.match(Wwe);if(!Z||!Pe)return U(me,Ce);let Re=[\"gray\",\"red\",\"yellow\",\"green\",\"magenta\"],ht=null,q=\"\";for(let nt=1;nt<Re.length;++nt)ht!==null||Z[nt]!==Pe[nt]?(ht===null&&(ht=Re[nt-1]),q+=pe.pretty(D,Pe[nt],ht)):q+=Pe[nt];return q},te=async(me,Ce,fe)=>{let ie=await nu.fetchDescriptorFrom(me,fe,{project:b,cache:T,preserveModifier:Ce,workspace:C});return ie!==null?ie.range:me.range},le=async me=>{let Ce=Ywe.default.valid(me.range)?`^${me.range}`:me.range,[fe,ie]=await Promise.all([te(me,me.range,Ce).catch(()=>null),te(me,me.range,\"latest\").catch(()=>null)]),Z=[{value:null,label:me.range}];return fe&&fe!==me.range?Z.push({value:fe,label:z(me.range,fe)}):Z.push({value:null,label:\"\"}),ie&&ie!==fe&&ie!==me.range?Z.push({value:ie,label:z(me.range,ie)}):Z.push({value:null,label:\"\"}),Z},ce=()=>p.createElement(u,{flexDirection:\"row\"},p.createElement(u,{flexDirection:\"column\",width:49},p.createElement(u,{marginLeft:1},p.createElement(A,null,\"Press \",p.createElement(A,{bold:!0,color:\"cyanBright\"},\"<up>\"),\"/\",p.createElement(A,{bold:!0,color:\"cyanBright\"},\"<down>\"),\" to select packages.\")),p.createElement(u,{marginLeft:1},p.createElement(A,null,\"Press \",p.createElement(A,{bold:!0,color:\"cyanBright\"},\"<left>\"),\"/\",p.createElement(A,{bold:!0,color:\"cyanBright\"},\"<right>\"),\" to select versions.\"))),p.createElement(u,{flexDirection:\"column\"},p.createElement(u,{marginLeft:1},p.createElement(A,null,\"Press \",p.createElement(A,{bold:!0,color:\"cyanBright\"},\"<enter>\"),\" to install.\")),p.createElement(u,{marginLeft:1},p.createElement(A,null,\"Press \",p.createElement(A,{bold:!0,color:\"cyanBright\"},\"<ctrl+c>\"),\" to abort.\")))),ue=()=>p.createElement(u,{flexDirection:\"row\",paddingTop:1,paddingBottom:1},p.createElement(u,{width:50},p.createElement(A,{bold:!0},p.createElement(A,{color:\"greenBright\"},\"?\"),\" Pick the packages you want to upgrade.\")),p.createElement(u,{width:17},p.createElement(A,{bold:!0,underline:!0,color:\"gray\"},\"Current\")),p.createElement(u,{width:17},p.createElement(A,{bold:!0,underline:!0,color:\"gray\"},\"Range\")),p.createElement(u,{width:17},p.createElement(A,{bold:!0,underline:!0,color:\"gray\"},\"Latest\"))),Ie=({active:me,descriptor:Ce,suggestions:fe})=>{let[ie,Z]=a(Ce.descriptorHash,null),Pe=G.stringifyIdent(Ce),Re=Math.max(0,45-Pe.length);return p.createElement(p.Fragment,null,p.createElement(u,null,p.createElement(u,{width:45},p.createElement(A,{bold:!0},G.prettyIdent(D,Ce)),p.createElement(r,{active:me,length:Re})),p.createElement(e,{active:me,options:fe,value:ie,skewer:!0,onChange:Z,sizes:[17,17,17]})))},he=({dependencies:me})=>{let[Ce,fe]=w(me.map(()=>null)),ie=E(!0),Z=async Pe=>{let Re=await le(Pe);return Re.filter(ht=>ht.label!==\"\").length<=1?null:{descriptor:Pe,suggestions:Re}};return h(()=>()=>{ie.current=!1},[]),h(()=>{let Pe=Math.trunc(N*1.75),Re=me.slice(0,Pe),ht=me.slice(Pe),q=Kwe(ht,N),nt=Re.map(Z).reduce(async(Le,Te)=>{await Le;let ke=await Te;ke!==null&&ie.current&&fe(Ve=>{let xe=Ve.findIndex(He=>He===null),tt=[...Ve];return tt[xe]=ke,tt})},Promise.resolve());q.reduce((Le,Te)=>Promise.all(Te.map(ke=>Promise.resolve().then(()=>Z(ke)))).then(async ke=>{ke=ke.filter(Ve=>Ve!==null),await Le,ie.current&&fe(Ve=>{let xe=Ve.findIndex(tt=>tt===null);return Ve.slice(0,xe).concat(ke).concat(Ve.slice(xe+ke.length))})}),nt).then(()=>{ie.current&&fe(Le=>Le.filter(Te=>Te!==null))})},[]),Ce.length?p.createElement(o,{radius:N>>1,children:Ce.map((Pe,Re)=>Pe!==null?p.createElement(Ie,{key:Re,active:!1,descriptor:Pe.descriptor,suggestions:Pe.suggestions}):p.createElement(A,{key:Re},\"Loading...\"))}):p.createElement(A,null,\"No upgrades found\")},Ee=await n(({useSubmit:me})=>{me(a());let Ce=new Map;for(let ie of b.workspaces)for(let Z of[\"dependencies\",\"devDependencies\"])for(let Pe of ie.manifest[Z].values())b.tryWorkspaceByDescriptor(Pe)===null&&(Pe.range.startsWith(\"link:\")||Ce.set(Pe.descriptorHash,Pe));let fe=qe.sortMap(Ce.values(),ie=>G.stringifyDescriptor(ie));return p.createElement(u,{flexDirection:\"column\"},p.createElement(ce,null),p.createElement(ue,null),p.createElement(he,{dependencies:fe}))},{},{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});if(typeof Ee>\"u\")return 1;let g=!1;for(let me of b.workspaces)for(let Ce of[\"dependencies\",\"devDependencies\"]){let fe=me.manifest[Ce];for(let ie of fe.values()){let Z=Ee.get(ie.descriptorHash);typeof Z<\"u\"&&Z!==null&&(fe.set(ie.identHash,G.makeDescriptor(ie,Z)),g=!0)}}return g?await b.installWithNewReport({quiet:this.context.quiet,stdout:this.context.stdout},{cache:T}):0}};var MIt={commands:[xC,bC]},UIt=MIt;var yj={};Kt(yj,{LinkFetcher:()=>av,LinkResolver:()=>lv,PortalFetcher:()=>cv,PortalResolver:()=>uv,default:()=>HIt});Ke();Pt();var Zf=\"portal:\",$f=\"link:\";var av=class{supports(e,r){return!!e.reference.startsWith($f)}getLocalPath(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:$f});if(K.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(o,r);return n===null?null:K.resolve(n,a)}async fetch(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:$f}),n=K.isAbsolute(a)?{packageFs:new En(Bt.root),prefixPath:Bt.dot,localPath:Bt.root}:await r.fetcher.fetch(o,r),u=n.localPath?{packageFs:new En(Bt.root),prefixPath:K.relative(Bt.root,n.localPath),localPath:Bt.root}:n;n!==u&&n.releaseFs&&n.releaseFs();let A=u.packageFs,p=K.resolve(u.localPath??u.packageFs.getRealPath(),u.prefixPath,a);return n.localPath?{packageFs:new En(p,{baseFs:A}),releaseFs:u.releaseFs,prefixPath:Bt.dot,discardFromLookup:!0,localPath:p}:{packageFs:new Gu(p,{baseFs:A}),releaseFs:u.releaseFs,prefixPath:Bt.dot,discardFromLookup:!0}}};Ke();Pt();var lv=class{supportsDescriptor(e,r){return!!e.range.startsWith($f)}supportsLocator(e,r){return!!e.reference.startsWith($f)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){let a=e.range.slice($f.length);return[G.makeLocator(e,`${$f}${Ae.toPortablePath(a)}`)]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){return{...e,version:\"0.0.0\",languageName:r.project.configuration.get(\"defaultLanguageName\"),linkType:\"SOFT\",conditions:null,dependencies:new Map,peerDependencies:new Map,dependenciesMeta:new Map,peerDependenciesMeta:new Map,bin:new Map}}};Ke();Pt();var cv=class{supports(e,r){return!!e.reference.startsWith(Zf)}getLocalPath(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:Zf});if(K.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(o,r);return n===null?null:K.resolve(n,a)}async fetch(e,r){let{parentLocator:o,path:a}=G.parseFileStyleRange(e.reference,{protocol:Zf}),n=K.isAbsolute(a)?{packageFs:new En(Bt.root),prefixPath:Bt.dot,localPath:Bt.root}:await r.fetcher.fetch(o,r),u=n.localPath?{packageFs:new En(Bt.root),prefixPath:K.relative(Bt.root,n.localPath),localPath:Bt.root}:n;n!==u&&n.releaseFs&&n.releaseFs();let A=u.packageFs,p=K.resolve(u.localPath??u.packageFs.getRealPath(),u.prefixPath,a);return n.localPath?{packageFs:new En(p,{baseFs:A}),releaseFs:u.releaseFs,prefixPath:Bt.dot,localPath:p}:{packageFs:new Gu(p,{baseFs:A}),releaseFs:u.releaseFs,prefixPath:Bt.dot}}};Ke();Ke();Pt();var uv=class{supportsDescriptor(e,r){return!!e.range.startsWith(Zf)}supportsLocator(e,r){return!!e.reference.startsWith(Zf)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){return G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){let a=e.range.slice(Zf.length);return[G.makeLocator(e,`${Zf}${Ae.toPortablePath(a)}`)]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let o=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await qe.releaseAfterUseAsync(async()=>await _t.find(o.prefixPath,{baseFs:o.packageFs}),o.releaseFs);return{...e,version:a.version||\"0.0.0\",languageName:a.languageName||r.project.configuration.get(\"defaultLanguageName\"),linkType:\"SOFT\",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var _It={fetchers:[av,cv],resolvers:[lv,uv]},HIt=_It;var t9={};Kt(t9,{NodeModulesLinker:()=>Dv,NodeModulesMode:()=>Xj,PnpLooseLinker:()=>Pv,default:()=>n1t});Pt();Ke();Pt();Pt();var Cj=(t,e)=>`${t}@${e}`,Vwe=(t,e)=>{let r=e.indexOf(\"#\"),o=r>=0?e.substring(r+1):e;return Cj(t,o)};var Jwe=(t,e={})=>{let r=e.debugLevel||Number(process.env.NM_DEBUG_LEVEL||-1),o=e.check||r>=9,a=e.hoistingLimits||new Map,n={check:o,debugLevel:r,hoistingLimits:a,fastLookupPossible:!0},u;n.debugLevel>=0&&(u=Date.now());let A=VIt(t,n),p=!1,h=0;do{let E=Ij(A,[A],new Set([A.locator]),new Map,n);p=E.anotherRoundNeeded||E.isGraphChanged,n.fastLookupPossible=!1,h++}while(p);if(n.debugLevel>=0&&console.log(`hoist time: ${Date.now()-u}ms, rounds: ${h}`),n.debugLevel>=1){let E=Av(A);if(Ij(A,[A],new Set([A.locator]),new Map,n).isGraphChanged)throw new Error(`The hoisting result is not terminal, prev tree:\n${E}, next tree:\n${Av(A)}`);let D=Xwe(A);if(D)throw new Error(`${D}, after hoisting finished:\n${Av(A)}`)}return n.debugLevel>=2&&console.log(Av(A)),zIt(A)},qIt=t=>{let e=t[t.length-1],r=new Map,o=new Set,a=n=>{if(!o.has(n)){o.add(n);for(let u of n.hoistedDependencies.values())r.set(u.name,u);for(let u of n.dependencies.values())n.peerNames.has(u.name)||a(u)}};return a(e),r},jIt=t=>{let e=t[t.length-1],r=new Map,o=new Set,a=new Set,n=(u,A)=>{if(o.has(u))return;o.add(u);for(let h of u.hoistedDependencies.values())if(!A.has(h.name)){let E;for(let w of t)E=w.dependencies.get(h.name),E&&r.set(E.name,E)}let p=new Set;for(let h of u.dependencies.values())p.add(h.name);for(let h of u.dependencies.values())u.peerNames.has(h.name)||n(h,p)};return n(e,a),r},zwe=(t,e)=>{if(e.decoupled)return e;let{name:r,references:o,ident:a,locator:n,dependencies:u,originalDependencies:A,hoistedDependencies:p,peerNames:h,reasons:E,isHoistBorder:w,hoistPriority:D,dependencyKind:b,hoistedFrom:C,hoistedTo:T}=e,N={name:r,references:new Set(o),ident:a,locator:n,dependencies:new Map(u),originalDependencies:new Map(A),hoistedDependencies:new Map(p),peerNames:new Set(h),reasons:new Map(E),decoupled:!0,isHoistBorder:w,hoistPriority:D,dependencyKind:b,hoistedFrom:new Map(C),hoistedTo:new Map(T)},U=N.dependencies.get(r);return U&&U.ident==N.ident&&N.dependencies.set(r,N),t.dependencies.set(N.name,N),N},GIt=(t,e)=>{let r=new Map([[t.name,[t.ident]]]);for(let a of t.dependencies.values())t.peerNames.has(a.name)||r.set(a.name,[a.ident]);let o=Array.from(e.keys());o.sort((a,n)=>{let u=e.get(a),A=e.get(n);if(A.hoistPriority!==u.hoistPriority)return A.hoistPriority-u.hoistPriority;{let p=u.dependents.size+u.peerDependents.size;return A.dependents.size+A.peerDependents.size-p}});for(let a of o){let n=a.substring(0,a.indexOf(\"@\",1)),u=a.substring(n.length+1);if(!t.peerNames.has(n)){let A=r.get(n);A||(A=[],r.set(n,A)),A.indexOf(u)<0&&A.push(u)}}return r},Ej=t=>{let e=new Set,r=(o,a=new Set)=>{if(!a.has(o)){a.add(o);for(let n of o.peerNames)if(!t.peerNames.has(n)){let u=t.dependencies.get(n);u&&!e.has(u)&&r(u,a)}e.add(o)}};for(let o of t.dependencies.values())t.peerNames.has(o.name)||r(o);return e},Ij=(t,e,r,o,a,n=new Set)=>{let u=e[e.length-1];if(n.has(u))return{anotherRoundNeeded:!1,isGraphChanged:!1};n.add(u);let A=JIt(u),p=GIt(u,A),h=t==u?new Map:a.fastLookupPossible?qIt(e):jIt(e),E,w=!1,D=!1,b=new Map(Array.from(p.entries()).map(([T,N])=>[T,N[0]])),C=new Map;do{let T=KIt(t,e,r,h,b,p,o,C,a);T.isGraphChanged&&(D=!0),T.anotherRoundNeeded&&(w=!0),E=!1;for(let[N,U]of p)U.length>1&&!u.dependencies.has(N)&&(b.delete(N),U.shift(),b.set(N,U[0]),E=!0)}while(E);for(let T of u.dependencies.values())if(!u.peerNames.has(T.name)&&!r.has(T.locator)){r.add(T.locator);let N=Ij(t,[...e,T],r,C,a);N.isGraphChanged&&(D=!0),N.anotherRoundNeeded&&(w=!0),r.delete(T.locator)}return{anotherRoundNeeded:w,isGraphChanged:D}},WIt=t=>{for(let[e,r]of t.dependencies)if(!t.peerNames.has(e)&&r.ident!==t.ident)return!0;return!1},YIt=(t,e,r,o,a,n,u,A,{outputReason:p,fastLookupPossible:h})=>{let E,w=null,D=new Set;p&&(E=`${Array.from(e).map(N=>Js(N)).join(\"\\u2192\")}`);let b=r[r.length-1],T=!(o.ident===b.ident);if(p&&!T&&(w=\"- self-reference\"),T&&(T=o.dependencyKind!==1,p&&!T&&(w=\"- workspace\")),T&&o.dependencyKind===2&&(T=!WIt(o),p&&!T&&(w=\"- external soft link with unhoisted dependencies\")),T&&(T=!t.peerNames.has(o.name),p&&!T&&(w=`- cannot shadow peer: ${Js(t.originalDependencies.get(o.name).locator)} at ${E}`)),T){let N=!1,U=a.get(o.name);if(N=!U||U.ident===o.ident,p&&!N&&(w=`- filled by: ${Js(U.locator)} at ${E}`),N)for(let z=r.length-1;z>=1;z--){let le=r[z].dependencies.get(o.name);if(le&&le.ident!==o.ident){N=!1;let ce=A.get(b);ce||(ce=new Set,A.set(b,ce)),ce.add(o.name),p&&(w=`- filled by ${Js(le.locator)} at ${r.slice(0,z).map(ue=>Js(ue.locator)).join(\"\\u2192\")}`);break}}T=N}if(T&&(T=n.get(o.name)===o.ident,p&&!T&&(w=`- filled by: ${Js(u.get(o.name)[0])} at ${E}`)),T){let N=!0,U=new Set(o.peerNames);for(let z=r.length-1;z>=1;z--){let te=r[z];for(let le of U){if(te.peerNames.has(le)&&te.originalDependencies.has(le))continue;let ce=te.dependencies.get(le);ce&&t.dependencies.get(le)!==ce&&(z===r.length-1?D.add(ce):(D=null,N=!1,p&&(w=`- peer dependency ${Js(ce.locator)} from parent ${Js(te.locator)} was not hoisted to ${E}`))),U.delete(le)}if(!N)break}T=N}if(T&&!h)for(let N of o.hoistedDependencies.values()){let U=a.get(N.name)||t.dependencies.get(N.name);if(!U||N.ident!==U.ident){T=!1,p&&(w=`- previously hoisted dependency mismatch, needed: ${Js(N.locator)}, available: ${Js(U?.locator)}`);break}}return D!==null&&D.size>0?{isHoistable:2,dependsOn:D,reason:w}:{isHoistable:T?0:1,reason:w}},VQ=t=>`${t.name}@${t.locator}`,KIt=(t,e,r,o,a,n,u,A,p)=>{let h=e[e.length-1],E=new Set,w=!1,D=!1,b=(U,z,te,le,ce)=>{if(E.has(le))return;let ue=[...z,VQ(le)],Ie=[...te,VQ(le)],he=new Map,De=new Map;for(let fe of Ej(le)){let ie=YIt(h,r,[h,...U,le],fe,o,a,n,A,{outputReason:p.debugLevel>=2,fastLookupPossible:p.fastLookupPossible});if(De.set(fe,ie),ie.isHoistable===2)for(let Z of ie.dependsOn){let Pe=he.get(Z.name)||new Set;Pe.add(fe.name),he.set(Z.name,Pe)}}let Ee=new Set,g=(fe,ie,Z)=>{if(!Ee.has(fe)){Ee.add(fe),De.set(fe,{isHoistable:1,reason:Z});for(let Pe of he.get(fe.name)||[])g(le.dependencies.get(Pe),ie,p.debugLevel>=2?`- peer dependency ${Js(fe.locator)} from parent ${Js(le.locator)} was not hoisted`:\"\")}};for(let[fe,ie]of De)ie.isHoistable===1&&g(fe,ie,ie.reason);let me=!1;for(let fe of De.keys())if(!Ee.has(fe)){D=!0;let ie=u.get(le);ie&&ie.has(fe.name)&&(w=!0),me=!0,le.dependencies.delete(fe.name),le.hoistedDependencies.set(fe.name,fe),le.reasons.delete(fe.name);let Z=h.dependencies.get(fe.name);if(p.debugLevel>=2){let Pe=Array.from(z).concat([le.locator]).map(ht=>Js(ht)).join(\"\\u2192\"),Re=h.hoistedFrom.get(fe.name);Re||(Re=[],h.hoistedFrom.set(fe.name,Re)),Re.push(Pe),le.hoistedTo.set(fe.name,Array.from(e).map(ht=>Js(ht.locator)).join(\"\\u2192\"))}if(!Z)h.ident!==fe.ident&&(h.dependencies.set(fe.name,fe),ce.add(fe));else for(let Pe of fe.references)Z.references.add(Pe)}if(le.dependencyKind===2&&me&&(w=!0),p.check){let fe=Xwe(t);if(fe)throw new Error(`${fe}, after hoisting dependencies of ${[h,...U,le].map(ie=>Js(ie.locator)).join(\"\\u2192\")}:\n${Av(t)}`)}let Ce=Ej(le);for(let fe of Ce)if(Ee.has(fe)){let ie=De.get(fe);if((a.get(fe.name)===fe.ident||!le.reasons.has(fe.name))&&ie.isHoistable!==0&&le.reasons.set(fe.name,ie.reason),!fe.isHoistBorder&&Ie.indexOf(VQ(fe))<0){E.add(le);let Pe=zwe(le,fe);b([...U,le],ue,Ie,Pe,T),E.delete(le)}}},C,T=new Set(Ej(h)),N=Array.from(e).map(U=>VQ(U));do{C=T,T=new Set;for(let U of C){if(U.locator===h.locator||U.isHoistBorder)continue;let z=zwe(h,U);b([],Array.from(r),N,z,T)}}while(T.size>0);return{anotherRoundNeeded:w,isGraphChanged:D}},Xwe=t=>{let e=[],r=new Set,o=new Set,a=(n,u,A)=>{if(r.has(n)||(r.add(n),o.has(n)))return;let p=new Map(u);for(let h of n.dependencies.values())n.peerNames.has(h.name)||p.set(h.name,h);for(let h of n.originalDependencies.values()){let E=p.get(h.name),w=()=>`${Array.from(o).concat([n]).map(D=>Js(D.locator)).join(\"\\u2192\")}`;if(n.peerNames.has(h.name)){let D=u.get(h.name);(D!==E||!D||D.ident!==h.ident)&&e.push(`${w()} - broken peer promise: expected ${h.ident} but found ${D&&D.ident}`)}else{let D=A.hoistedFrom.get(n.name),b=n.hoistedTo.get(h.name),C=`${D?` hoisted from ${D.join(\", \")}`:\"\"}`,T=`${b?` hoisted to ${b}`:\"\"}`,N=`${w()}${C}`;E?E.ident!==h.ident&&e.push(`${N} - broken require promise for ${h.name}${T}: expected ${h.ident}, but found: ${E.ident}`):e.push(`${N} - broken require promise: no required dependency ${h.name}${T} found`)}}o.add(n);for(let h of n.dependencies.values())n.peerNames.has(h.name)||a(h,p,n);o.delete(n)};return a(t,t.dependencies,t),e.join(`\n`)},VIt=(t,e)=>{let{identName:r,name:o,reference:a,peerNames:n}=t,u={name:o,references:new Set([a]),locator:Cj(r,a),ident:Vwe(r,a),dependencies:new Map,originalDependencies:new Map,hoistedDependencies:new Map,peerNames:new Set(n),reasons:new Map,decoupled:!0,isHoistBorder:!0,hoistPriority:0,dependencyKind:1,hoistedFrom:new Map,hoistedTo:new Map},A=new Map([[t,u]]),p=(h,E)=>{let w=A.get(h),D=!!w;if(!w){let{name:b,identName:C,reference:T,peerNames:N,hoistPriority:U,dependencyKind:z}=h,te=e.hoistingLimits.get(E.locator);w={name:b,references:new Set([T]),locator:Cj(C,T),ident:Vwe(C,T),dependencies:new Map,originalDependencies:new Map,hoistedDependencies:new Map,peerNames:new Set(N),reasons:new Map,decoupled:!0,isHoistBorder:te?te.has(b):!1,hoistPriority:U||0,dependencyKind:z||0,hoistedFrom:new Map,hoistedTo:new Map},A.set(h,w)}if(E.dependencies.set(h.name,w),E.originalDependencies.set(h.name,w),D){let b=new Set,C=T=>{if(!b.has(T)){b.add(T),T.decoupled=!1;for(let N of T.dependencies.values())T.peerNames.has(N.name)||C(N)}};C(w)}else for(let b of h.dependencies)p(b,w)};for(let h of t.dependencies)p(h,u);return u},wj=t=>t.substring(0,t.indexOf(\"@\",1)),zIt=t=>{let e={name:t.name,identName:wj(t.locator),references:new Set(t.references),dependencies:new Set},r=new Set([t]),o=(a,n,u)=>{let A=r.has(a),p;if(n===a)p=u;else{let{name:h,references:E,locator:w}=a;p={name:h,identName:wj(w),references:E,dependencies:new Set}}if(u.dependencies.add(p),!A){r.add(a);for(let h of a.dependencies.values())a.peerNames.has(h.name)||o(h,a,p);r.delete(a)}};for(let a of t.dependencies.values())o(a,t,e);return e},JIt=t=>{let e=new Map,r=new Set([t]),o=u=>`${u.name}@${u.ident}`,a=u=>{let A=o(u),p=e.get(A);return p||(p={dependents:new Set,peerDependents:new Set,hoistPriority:0},e.set(A,p)),p},n=(u,A)=>{let p=!!r.has(A);if(a(A).dependents.add(u.ident),!p){r.add(A);for(let E of A.dependencies.values()){let w=a(E);w.hoistPriority=Math.max(w.hoistPriority,E.hoistPriority),A.peerNames.has(E.name)?w.peerDependents.add(A.ident):n(A,E)}}};for(let u of t.dependencies.values())t.peerNames.has(u.name)||n(t,u);return e},Js=t=>{if(!t)return\"none\";let e=t.indexOf(\"@\",1),r=t.substring(0,e);r.endsWith(\"$wsroot$\")&&(r=`wh:${r.replace(\"$wsroot$\",\"\")}`);let o=t.substring(e+1);if(o===\"workspace:.\")return\".\";if(o){let a=(o.indexOf(\"#\")>0?o.split(\"#\")[1]:o).replace(\"npm:\",\"\");return o.startsWith(\"virtual\")&&(r=`v:${r}`),a.startsWith(\"workspace\")&&(r=`w:${r}`,a=\"\"),`${r}${a?`@${a}`:\"\"}`}else return`${r}`};var Av=t=>{let e=0,r=(a,n,u=\"\")=>{if(e>5e4||n.has(a))return\"\";e++;let A=Array.from(a.dependencies.values()).sort((h,E)=>h.name===E.name?0:h.name>E.name?1:-1),p=\"\";n.add(a);for(let h=0;h<A.length;h++){let E=A[h];if(!a.peerNames.has(E.name)&&E!==a){let w=a.reasons.get(E.name),D=wj(E.locator);p+=`${u}${h<A.length-1?\"\\u251C\\u2500\":\"\\u2514\\u2500\"}${(n.has(E)?\">\":\"\")+(D!==E.name?`a:${E.name}:`:\"\")+Js(E.locator)+(w?` ${w}`:\"\")}\n`,p+=r(E,n,`${u}${h<A.length-1?\"\\u2502 \":\"  \"}`)}}return n.delete(a),p};return r(t,new Set)+(e>5e4?`\nTree is too large, part of the tree has been dunped\n`:\"\")};var fv=(o=>(o.WORKSPACES=\"workspaces\",o.DEPENDENCIES=\"dependencies\",o.NONE=\"none\",o))(fv||{}),Zwe=\"node_modules\",jh=\"$wsroot$\";var pv=(t,e)=>{let{packageTree:r,hoistingLimits:o,errors:a,preserveSymlinksRequired:n}=ZIt(t,e),u=null;if(a.length===0){let A=Jwe(r,{hoistingLimits:o});u=ewt(t,A,e)}return{tree:u,errors:a,preserveSymlinksRequired:n}},yA=t=>`${t.name}@${t.reference}`,vj=t=>{let e=new Map;for(let[r,o]of t.entries())if(!o.dirList){let a=e.get(o.locator);a||(a={target:o.target,linkType:o.linkType,locations:[],aliases:o.aliases},e.set(o.locator,a)),a.locations.push(r)}for(let r of e.values())r.locations=r.locations.sort((o,a)=>{let n=o.split(K.delimiter).length,u=a.split(K.delimiter).length;return a===o?0:n!==u?u-n:a>o?1:-1});return e},$we=(t,e)=>{let r=G.isVirtualLocator(t)?G.devirtualizeLocator(t):t,o=G.isVirtualLocator(e)?G.devirtualizeLocator(e):e;return G.areLocatorsEqual(r,o)},Bj=(t,e,r,o)=>{if(t.linkType!==\"SOFT\")return!1;let a=Ae.toPortablePath(r.resolveVirtual&&e.reference&&e.reference.startsWith(\"virtual:\")?r.resolveVirtual(t.packageLocation):t.packageLocation);return K.contains(o,a)===null},XIt=t=>{let e=t.getPackageInformation(t.topLevel);if(e===null)throw new Error(\"Assertion failed: Expected the top-level package to have been registered\");if(t.findPackageLocator(e.packageLocation)===null)throw new Error(\"Assertion failed: Expected the top-level package to have a physical locator\");let o=Ae.toPortablePath(e.packageLocation.slice(0,-1)),a=new Map,n={children:new Map},u=t.getDependencyTreeRoots(),A=new Map,p=new Set,h=(D,b)=>{let C=yA(D);if(p.has(C))return;p.add(C);let T=t.getPackageInformation(D);if(T){let N=b?yA(b):\"\";if(yA(D)!==N&&T.linkType===\"SOFT\"&&!D.reference.startsWith(\"link:\")&&!Bj(T,D,t,o)){let U=e1e(T,D,t);(!A.get(U)||D.reference.startsWith(\"workspace:\"))&&A.set(U,D)}for(let[U,z]of T.packageDependencies)z!==null&&(T.packagePeers.has(U)||h(t.getLocator(U,z),D))}};for(let D of u)h(D,null);let E=o.split(K.sep);for(let D of A.values()){let b=t.getPackageInformation(D),T=Ae.toPortablePath(b.packageLocation.slice(0,-1)).split(K.sep).slice(E.length),N=n;for(let U of T){let z=N.children.get(U);z||(z={children:new Map},N.children.set(U,z)),N=z}N.workspaceLocator=D}let w=(D,b)=>{if(D.workspaceLocator){let C=yA(b),T=a.get(C);T||(T=new Set,a.set(C,T)),T.add(D.workspaceLocator)}for(let C of D.children.values())w(C,D.workspaceLocator||b)};for(let D of n.children.values())w(D,n.workspaceLocator);return a},ZIt=(t,e)=>{let r=[],o=!1,a=new Map,n=XIt(t),u=t.getPackageInformation(t.topLevel);if(u===null)throw new Error(\"Assertion failed: Expected the top-level package to have been registered\");let A=t.findPackageLocator(u.packageLocation);if(A===null)throw new Error(\"Assertion failed: Expected the top-level package to have a physical locator\");let p=Ae.toPortablePath(u.packageLocation.slice(0,-1)),h={name:A.name,identName:A.name,reference:A.reference,peerNames:u.packagePeers,dependencies:new Set,dependencyKind:1},E=new Map,w=(b,C)=>`${yA(C)}:${b}`,D=(b,C,T,N,U,z,te,le)=>{let ce=w(b,T),ue=E.get(ce),Ie=!!ue;!Ie&&T.name===A.name&&T.reference===A.reference&&(ue=h,E.set(ce,h));let he=Bj(C,T,t,p);if(!ue){let fe=0;he?fe=2:C.linkType===\"SOFT\"&&T.name.endsWith(jh)&&(fe=1),ue={name:b,identName:T.name,reference:T.reference,dependencies:new Set,peerNames:fe===1?new Set:C.packagePeers,dependencyKind:fe},E.set(ce,ue)}let De;if(he?De=2:U.linkType===\"SOFT\"?De=1:De=0,ue.hoistPriority=Math.max(ue.hoistPriority||0,De),le&&!he){let fe=yA({name:N.identName,reference:N.reference}),ie=a.get(fe)||new Set;a.set(fe,ie),ie.add(ue.name)}let Ee=new Map(C.packageDependencies);if(e.project){let fe=e.project.workspacesByCwd.get(Ae.toPortablePath(C.packageLocation.slice(0,-1)));if(fe){let ie=new Set([...Array.from(fe.manifest.peerDependencies.values(),Z=>G.stringifyIdent(Z)),...Array.from(fe.manifest.peerDependenciesMeta.keys())]);for(let Z of ie)Ee.has(Z)||(Ee.set(Z,z.get(Z)||null),ue.peerNames.add(Z))}}let g=yA({name:T.name.replace(jh,\"\"),reference:T.reference}),me=n.get(g);if(me)for(let fe of me)Ee.set(`${fe.name}${jh}`,fe.reference);(C!==U||C.linkType!==\"SOFT\"||!he&&(!e.selfReferencesByCwd||e.selfReferencesByCwd.get(te)))&&N.dependencies.add(ue);let Ce=T!==A&&C.linkType===\"SOFT\"&&!T.name.endsWith(jh)&&!he;if(!Ie&&!Ce){let fe=new Map;for(let[ie,Z]of Ee)if(Z!==null){let Pe=t.getLocator(ie,Z),Re=t.getLocator(ie.replace(jh,\"\"),Z),ht=t.getPackageInformation(Re);if(ht===null)throw new Error(\"Assertion failed: Expected the package to have been registered\");let q=Bj(ht,Pe,t,p);if(e.validateExternalSoftLinks&&e.project&&q){ht.packageDependencies.size>0&&(o=!0);for(let[Ve,xe]of ht.packageDependencies)if(xe!==null){let tt=G.parseLocator(Array.isArray(xe)?`${xe[0]}@${xe[1]}`:`${Ve}@${xe}`);if(yA(tt)!==yA(Pe)){let He=Ee.get(Ve);if(He){let x=G.parseLocator(Array.isArray(He)?`${He[0]}@${He[1]}`:`${Ve}@${He}`);$we(x,tt)||r.push({messageName:71,text:`Cannot link ${G.prettyIdent(e.project.configuration,G.parseIdent(Pe.name))} into ${G.prettyLocator(e.project.configuration,G.parseLocator(`${T.name}@${T.reference}`))} dependency ${G.prettyLocator(e.project.configuration,tt)} conflicts with parent dependency ${G.prettyLocator(e.project.configuration,x)}`})}else{let x=fe.get(Ve);if(x){let I=x.target,S=G.parseLocator(Array.isArray(I)?`${I[0]}@${I[1]}`:`${Ve}@${I}`);$we(S,tt)||r.push({messageName:71,text:`Cannot link ${G.prettyIdent(e.project.configuration,G.parseIdent(Pe.name))} into ${G.prettyLocator(e.project.configuration,G.parseLocator(`${T.name}@${T.reference}`))} dependency ${G.prettyLocator(e.project.configuration,tt)} conflicts with dependency ${G.prettyLocator(e.project.configuration,S)} from sibling portal ${G.prettyIdent(e.project.configuration,G.parseIdent(x.portal.name))}`})}else fe.set(Ve,{target:tt.reference,portal:Pe})}}}}let nt=e.hoistingLimitsByCwd?.get(te),Le=q?te:K.relative(p,Ae.toPortablePath(ht.packageLocation))||Bt.dot,Te=e.hoistingLimitsByCwd?.get(Le);D(ie,ht,Pe,ue,C,Ee,Le,nt===\"dependencies\"||Te===\"dependencies\"||Te===\"workspaces\")}}};return D(A.name,u,A,h,u,u.packageDependencies,Bt.dot,!1),{packageTree:h,hoistingLimits:a,errors:r,preserveSymlinksRequired:o}};function e1e(t,e,r){let o=r.resolveVirtual&&e.reference&&e.reference.startsWith(\"virtual:\")?r.resolveVirtual(t.packageLocation):t.packageLocation;return Ae.toPortablePath(o||t.packageLocation)}function $It(t,e,r){let o=e.getLocator(t.name.replace(jh,\"\"),t.reference),a=e.getPackageInformation(o);if(a===null)throw new Error(\"Assertion failed: Expected the package to be registered\");return r.pnpifyFs?{linkType:\"SOFT\",target:Ae.toPortablePath(a.packageLocation)}:{linkType:a.linkType,target:e1e(a,t,e)}}var ewt=(t,e,r)=>{let o=new Map,a=(E,w,D)=>{let{linkType:b,target:C}=$It(E,t,r);return{locator:yA(E),nodePath:w,target:C,linkType:b,aliases:D}},n=E=>{let[w,D]=E.split(\"/\");return D?{scope:w,name:D}:{scope:null,name:w}},u=new Set,A=(E,w,D)=>{if(u.has(E))return;u.add(E);let b=Array.from(E.references).sort().join(\"#\");for(let C of E.dependencies){let T=Array.from(C.references).sort().join(\"#\");if(C.identName===E.identName.replace(jh,\"\")&&T===b)continue;let N=Array.from(C.references).sort(),U={name:C.identName,reference:N[0]},{name:z,scope:te}=n(C.name),le=te?[te,z]:[z],ce=K.join(w,Zwe),ue=K.join(ce,...le),Ie=`${D}/${U.name}`,he=a(U,D,N.slice(1)),De=!1;if(he.linkType===\"SOFT\"&&r.project){let Ee=r.project.workspacesByCwd.get(he.target.slice(0,-1));De=!!(Ee&&!Ee.manifest.name)}if(!C.name.endsWith(jh)&&!De){let Ee=o.get(ue);if(Ee){if(Ee.dirList)throw new Error(`Assertion failed: ${ue} cannot merge dir node with leaf node`);{let Ce=G.parseLocator(Ee.locator),fe=G.parseLocator(he.locator);if(Ee.linkType!==he.linkType)throw new Error(`Assertion failed: ${ue} cannot merge nodes with different link types ${Ee.nodePath}/${G.stringifyLocator(Ce)} and ${D}/${G.stringifyLocator(fe)}`);if(Ce.identHash!==fe.identHash)throw new Error(`Assertion failed: ${ue} cannot merge nodes with different idents ${Ee.nodePath}/${G.stringifyLocator(Ce)} and ${D}/s${G.stringifyLocator(fe)}`);he.aliases=[...he.aliases,...Ee.aliases,G.parseLocator(Ee.locator).reference]}}o.set(ue,he);let g=ue.split(\"/\"),me=g.indexOf(Zwe);for(let Ce=g.length-1;me>=0&&Ce>me;Ce--){let fe=Ae.toPortablePath(g.slice(0,Ce).join(K.sep)),ie=g[Ce],Z=o.get(fe);if(!Z)o.set(fe,{dirList:new Set([ie])});else if(Z.dirList){if(Z.dirList.has(ie))break;Z.dirList.add(ie)}}}A(C,he.linkType===\"SOFT\"?he.target:ue,Ie)}},p=a({name:e.name,reference:Array.from(e.references)[0]},\"\",[]),h=p.target;return o.set(h,p),A(e,h,\"\"),o};Ke();Ke();Pt();Pt();sA();Ol();var jj={};Kt(jj,{PnpInstaller:()=>pd,PnpLinker:()=>Yh,UnplugCommand:()=>QC,default:()=>kwt,getPnpPath:()=>Kh,jsInstallUtils:()=>CA,pnpUtils:()=>vv,quotePathIfNeeded:()=>M1e});Pt();var O1e=ve(\"url\");Ke();Ke();Pt();Pt();var t1e={DEFAULT:{collapsed:!1,next:{\"*\":\"DEFAULT\"}},TOP_LEVEL:{collapsed:!1,next:{fallbackExclusionList:\"FALLBACK_EXCLUSION_LIST\",packageRegistryData:\"PACKAGE_REGISTRY_DATA\",\"*\":\"DEFAULT\"}},FALLBACK_EXCLUSION_LIST:{collapsed:!1,next:{\"*\":\"FALLBACK_EXCLUSION_ENTRIES\"}},FALLBACK_EXCLUSION_ENTRIES:{collapsed:!0,next:{\"*\":\"FALLBACK_EXCLUSION_DATA\"}},FALLBACK_EXCLUSION_DATA:{collapsed:!0,next:{\"*\":\"DEFAULT\"}},PACKAGE_REGISTRY_DATA:{collapsed:!1,next:{\"*\":\"PACKAGE_REGISTRY_ENTRIES\"}},PACKAGE_REGISTRY_ENTRIES:{collapsed:!0,next:{\"*\":\"PACKAGE_STORE_DATA\"}},PACKAGE_STORE_DATA:{collapsed:!1,next:{\"*\":\"PACKAGE_STORE_ENTRIES\"}},PACKAGE_STORE_ENTRIES:{collapsed:!0,next:{\"*\":\"PACKAGE_INFORMATION_DATA\"}},PACKAGE_INFORMATION_DATA:{collapsed:!1,next:{packageDependencies:\"PACKAGE_DEPENDENCIES\",\"*\":\"DEFAULT\"}},PACKAGE_DEPENDENCIES:{collapsed:!1,next:{\"*\":\"PACKAGE_DEPENDENCY\"}},PACKAGE_DEPENDENCY:{collapsed:!0,next:{\"*\":\"DEFAULT\"}}};function twt(t,e,r){let o=\"\";o+=\"[\";for(let a=0,n=t.length;a<n;++a)o+=zQ(String(a),t[a],e,r).replace(/^ +/g,\"\"),a+1<n&&(o+=\", \");return o+=\"]\",o}function rwt(t,e,r){let o=`${r}  `,a=\"\";a+=r,a+=`[\n`;for(let n=0,u=t.length;n<u;++n)a+=o+zQ(String(n),t[n],e,o).replace(/^ +/,\"\"),n+1<u&&(a+=\",\"),a+=`\n`;return a+=r,a+=\"]\",a}function nwt(t,e,r){let o=Object.keys(t),a=\"\";a+=\"{\";for(let n=0,u=o.length,A=0;n<u;++n){let p=o[n],h=t[p];typeof h>\"u\"||(A!==0&&(a+=\", \"),a+=JSON.stringify(p),a+=\": \",a+=zQ(p,h,e,r).replace(/^ +/g,\"\"),A+=1)}return a+=\"}\",a}function iwt(t,e,r){let o=Object.keys(t),a=`${r}  `,n=\"\";n+=r,n+=`{\n`;let u=0;for(let A=0,p=o.length;A<p;++A){let h=o[A],E=t[h];typeof E>\"u\"||(u!==0&&(n+=\",\",n+=`\n`),n+=a,n+=JSON.stringify(h),n+=\": \",n+=zQ(h,E,e,a).replace(/^ +/g,\"\"),u+=1)}return u!==0&&(n+=`\n`),n+=r,n+=\"}\",n}function zQ(t,e,r,o){let{next:a}=t1e[r],n=a[t]||a[\"*\"];return r1e(e,n,o)}function r1e(t,e,r){let{collapsed:o}=t1e[e];return Array.isArray(t)?o?twt(t,e,r):rwt(t,e,r):typeof t==\"object\"&&t!==null?o?nwt(t,e,r):iwt(t,e,r):JSON.stringify(t)}function n1e(t){return r1e(t,\"TOP_LEVEL\",\"\")}function hv(t,e){let r=Array.from(t);Array.isArray(e)||(e=[e]);let o=[];for(let n of e)o.push(r.map(u=>n(u)));let a=r.map((n,u)=>u);return a.sort((n,u)=>{for(let A of o){let p=A[n]<A[u]?-1:A[n]>A[u]?1:0;if(p!==0)return p}return 0}),a.map(n=>r[n])}function swt(t){let e=new Map,r=hv(t.fallbackExclusionList||[],[({name:o,reference:a})=>o,({name:o,reference:a})=>a]);for(let{name:o,reference:a}of r){let n=e.get(o);typeof n>\"u\"&&e.set(o,n=new Set),n.add(a)}return Array.from(e).map(([o,a])=>[o,Array.from(a)])}function owt(t){return hv(t.fallbackPool||[],([e])=>e)}function awt(t){let e=[];for(let[r,o]of hv(t.packageRegistry,([a])=>a===null?\"0\":`1${a}`)){let a=[];e.push([r,a]);for(let[n,{packageLocation:u,packageDependencies:A,packagePeers:p,linkType:h,discardFromLookup:E}]of hv(o,([w])=>w===null?\"0\":`1${w}`)){let w=[];r!==null&&n!==null&&!A.has(r)&&w.push([r,n]);for(let[C,T]of hv(A.entries(),([N])=>N))w.push([C,T]);let D=p&&p.size>0?Array.from(p):void 0,b=E||void 0;a.push([n,{packageLocation:u,packageDependencies:w,packagePeers:D,linkType:h,discardFromLookup:b}])}}return e}function gv(t){return{__info:[\"This file is automatically generated. Do not touch it, or risk\",\"your modifications being lost.\"],dependencyTreeRoots:t.dependencyTreeRoots,enableTopLevelFallback:t.enableTopLevelFallback||!1,ignorePatternData:t.ignorePattern||null,fallbackExclusionList:swt(t),fallbackPool:owt(t),packageRegistryData:awt(t)}}var o1e=et(s1e());function a1e(t,e){return[t?`${t}\n`:\"\",`/* eslint-disable */\n`,`// @ts-nocheck\n`,`\"use strict\";\n`,`\n`,e,`\n`,(0,o1e.default)()].join(\"\")}function lwt(t){return JSON.stringify(t,null,2)}function cwt(t){return`'${t.replace(/\\\\/g,\"\\\\\\\\\").replace(/'/g,\"\\\\'\").replace(/\\n/g,`\\\\\n`)}'`}function uwt(t){return[`const RAW_RUNTIME_STATE =\n`,`${cwt(n1e(t))};\n\n`,`function $$SETUP_STATE(hydrateRuntimeState, basePath) {\n`,`  return hydrateRuntimeState(JSON.parse(RAW_RUNTIME_STATE), {basePath: basePath || __dirname});\n`,`}\n`].join(\"\")}function Awt(){return[`function $$SETUP_STATE(hydrateRuntimeState, basePath) {\n`,`  const fs = require('fs');\n`,`  const path = require('path');\n`,`  const pnpDataFilepath = path.resolve(__dirname, ${JSON.stringify(mr.pnpData)});\n`,`  return hydrateRuntimeState(JSON.parse(fs.readFileSync(pnpDataFilepath, 'utf8')), {basePath: basePath || __dirname});\n`,`}\n`].join(\"\")}function l1e(t){let e=gv(t),r=uwt(e);return a1e(t.shebang,r)}function c1e(t){let e=gv(t),r=Awt(),o=a1e(t.shebang,r);return{dataFile:lwt(e),loaderFile:o}}Pt();function Pj(t,{basePath:e}){let r=Ae.toPortablePath(e),o=K.resolve(r),a=t.ignorePatternData!==null?new RegExp(t.ignorePatternData):null,n=new Map,u=new Map(t.packageRegistryData.map(([w,D])=>[w,new Map(D.map(([b,C])=>{if(w===null!=(b===null))throw new Error(\"Assertion failed: The name and reference should be null, or neither should\");let T=C.discardFromLookup??!1,N={name:w,reference:b},U=n.get(C.packageLocation);U?(U.discardFromLookup=U.discardFromLookup&&T,T||(U.locator=N)):n.set(C.packageLocation,{locator:N,discardFromLookup:T});let z=null;return[b,{packageDependencies:new Map(C.packageDependencies),packagePeers:new Set(C.packagePeers),linkType:C.linkType,discardFromLookup:T,get packageLocation(){return z||(z=K.join(o,C.packageLocation))}}]}))])),A=new Map(t.fallbackExclusionList.map(([w,D])=>[w,new Set(D)])),p=new Map(t.fallbackPool),h=t.dependencyTreeRoots,E=t.enableTopLevelFallback;return{basePath:r,dependencyTreeRoots:h,enableTopLevelFallback:E,fallbackExclusionList:A,fallbackPool:p,ignorePattern:a,packageLocatorsByLocations:n,packageRegistry:u}}Pt();Pt();var tp=ve(\"module\"),fd=ve(\"url\"),Nj=ve(\"util\");var Qo=ve(\"url\");var p1e=et(ve(\"assert\"));var Sj=Array.isArray,dv=JSON.stringify,mv=Object.getOwnPropertyNames,Ad=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),xj=(t,e)=>RegExp.prototype.exec.call(t,e),bj=(t,...e)=>RegExp.prototype[Symbol.replace].apply(t,e),Gh=(t,...e)=>String.prototype.endsWith.apply(t,e),kj=(t,...e)=>String.prototype.includes.apply(t,e),Qj=(t,...e)=>String.prototype.lastIndexOf.apply(t,e),yv=(t,...e)=>String.prototype.indexOf.apply(t,e),u1e=(t,...e)=>String.prototype.replace.apply(t,e),Wh=(t,...e)=>String.prototype.slice.apply(t,e),EA=(t,...e)=>String.prototype.startsWith.apply(t,e),A1e=Map,f1e=JSON.parse;function Ev(t,e,r){return class extends r{constructor(...o){super(e(...o)),this.code=t,this.name=`${r.name} [${t}]`}}}var h1e=Ev(\"ERR_PACKAGE_IMPORT_NOT_DEFINED\",(t,e,r)=>`Package import specifier \"${t}\" is not defined${e?` in package ${e}package.json`:\"\"} imported from ${r}`,TypeError),Fj=Ev(\"ERR_INVALID_MODULE_SPECIFIER\",(t,e,r=void 0)=>`Invalid module \"${t}\" ${e}${r?` imported from ${r}`:\"\"}`,TypeError),g1e=Ev(\"ERR_INVALID_PACKAGE_TARGET\",(t,e,r,o=!1,a=void 0)=>{let n=typeof r==\"string\"&&!o&&r.length&&!EA(r,\"./\");return e===\".\"?((0,p1e.default)(o===!1),`Invalid \"exports\" main target ${dv(r)} defined in the package config ${t}package.json${a?` imported from ${a}`:\"\"}${n?'; targets must start with \"./\"':\"\"}`):`Invalid \"${o?\"imports\":\"exports\"}\" target ${dv(r)} defined for '${e}' in the package config ${t}package.json${a?` imported from ${a}`:\"\"}${n?'; targets must start with \"./\"':\"\"}`},Error),Cv=Ev(\"ERR_INVALID_PACKAGE_CONFIG\",(t,e,r)=>`Invalid package config ${t}${e?` while importing ${e}`:\"\"}${r?`. ${r}`:\"\"}`,Error),d1e=Ev(\"ERR_PACKAGE_PATH_NOT_EXPORTED\",(t,e,r=void 0)=>e===\".\"?`No \"exports\" main defined in ${t}package.json${r?` imported from ${r}`:\"\"}`:`Package subpath '${e}' is not defined by \"exports\" in ${t}package.json${r?` imported from ${r}`:\"\"}`,Error);var XQ=ve(\"url\");function m1e(t,e){let r=Object.create(null);for(let o=0;o<e.length;o++){let a=e[o];Ad(t,a)&&(r[a]=t[a])}return r}var JQ=new A1e;function fwt(t,e,r,o){let a=JQ.get(t);if(a!==void 0)return a;let n=o(t);if(n===void 0){let b={pjsonPath:t,exists:!1,main:void 0,name:void 0,type:\"none\",exports:void 0,imports:void 0};return JQ.set(t,b),b}let u;try{u=f1e(n)}catch(b){throw new Cv(t,(r?`\"${e}\" from `:\"\")+(0,XQ.fileURLToPath)(r||e),b.message)}let{imports:A,main:p,name:h,type:E}=m1e(u,[\"imports\",\"main\",\"name\",\"type\"]),w=Ad(u,\"exports\")?u.exports:void 0;(typeof A!=\"object\"||A===null)&&(A=void 0),typeof p!=\"string\"&&(p=void 0),typeof h!=\"string\"&&(h=void 0),E!==\"module\"&&E!==\"commonjs\"&&(E=\"none\");let D={pjsonPath:t,exists:!0,main:p,name:h,type:E,exports:w,imports:A};return JQ.set(t,D),D}function y1e(t,e){let r=new URL(\"./package.json\",t);for(;;){let n=r.pathname;if(Gh(n,\"node_modules/package.json\"))break;let u=fwt((0,XQ.fileURLToPath)(r),t,void 0,e);if(u.exists)return u;let A=r;if(r=new URL(\"../package.json\",r),r.pathname===A.pathname)break}let o=(0,XQ.fileURLToPath)(r),a={pjsonPath:o,exists:!1,main:void 0,name:void 0,type:\"none\",exports:void 0,imports:void 0};return JQ.set(o,a),a}function pwt(t,e,r){throw new h1e(t,e&&(0,Qo.fileURLToPath)(new URL(\".\",e)),(0,Qo.fileURLToPath)(r))}function hwt(t,e,r,o){let a=`request is not a valid subpath for the \"${r?\"imports\":\"exports\"}\" resolution of ${(0,Qo.fileURLToPath)(e)}`;throw new Fj(t,a,o&&(0,Qo.fileURLToPath)(o))}function Iv(t,e,r,o,a){throw typeof e==\"object\"&&e!==null?e=dv(e,null,\"\"):e=`${e}`,new g1e((0,Qo.fileURLToPath)(new URL(\".\",r)),t,e,o,a&&(0,Qo.fileURLToPath)(a))}var E1e=/(^|\\\\|\\/)((\\.|%2e)(\\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))(\\\\|\\/|$)/i,C1e=/\\*/g;function gwt(t,e,r,o,a,n,u,A){if(e!==\"\"&&!n&&t[t.length-1]!==\"/\"&&Iv(r,t,o,u,a),!EA(t,\"./\")){if(u&&!EA(t,\"../\")&&!EA(t,\"/\")){let w=!1;try{new URL(t),w=!0}catch{}if(!w)return n?bj(C1e,t,()=>e):t+e}Iv(r,t,o,u,a)}xj(E1e,Wh(t,2))!==null&&Iv(r,t,o,u,a);let p=new URL(t,o),h=p.pathname,E=new URL(\".\",o).pathname;if(EA(h,E)||Iv(r,t,o,u,a),e===\"\")return p;if(xj(E1e,e)!==null){let w=n?u1e(r,\"*\",()=>e):r+e;hwt(w,o,u,a)}return n?new URL(bj(C1e,p.href,()=>e)):new URL(e,p)}function dwt(t){let e=+t;return`${e}`!==t?!1:e>=0&&e<4294967295}function kC(t,e,r,o,a,n,u,A){if(typeof e==\"string\")return gwt(e,r,o,t,a,n,u,A);if(Sj(e)){if(e.length===0)return null;let p;for(let h=0;h<e.length;h++){let E=e[h],w;try{w=kC(t,E,r,o,a,n,u,A)}catch(D){if(p=D,D.code===\"ERR_INVALID_PACKAGE_TARGET\")continue;throw D}if(w!==void 0){if(w===null){p=null;continue}return w}}if(p==null)return p;throw p}else if(typeof e==\"object\"&&e!==null){let p=mv(e);for(let h=0;h<p.length;h++){let E=p[h];if(dwt(E))throw new Cv((0,Qo.fileURLToPath)(t),a,'\"exports\" cannot contain numeric property keys.')}for(let h=0;h<p.length;h++){let E=p[h];if(E===\"default\"||A.has(E)){let w=e[E],D=kC(t,w,r,o,a,n,u,A);if(D===void 0)continue;return D}}return}else if(e===null)return null;Iv(o,e,t,u,a)}function w1e(t,e){let r=yv(t,\"*\"),o=yv(e,\"*\"),a=r===-1?t.length:r+1,n=o===-1?e.length:o+1;return a>n?-1:n>a||r===-1?1:o===-1||t.length>e.length?-1:e.length>t.length?1:0}function mwt(t,e,r){if(typeof t==\"string\"||Sj(t))return!0;if(typeof t!=\"object\"||t===null)return!1;let o=mv(t),a=!1,n=0;for(let u=0;u<o.length;u++){let A=o[u],p=A===\"\"||A[0]!==\".\";if(n++===0)a=p;else if(a!==p)throw new Cv((0,Qo.fileURLToPath)(e),r,`\"exports\" cannot contain some keys starting with '.' and some not. The exports object must either be an object of package subpath keys or an object of main entry condition name keys only.`)}return a}function Rj(t,e,r){throw new d1e((0,Qo.fileURLToPath)(new URL(\".\",e)),t,r&&(0,Qo.fileURLToPath)(r))}var I1e=new Set;function ywt(t,e,r){let o=(0,Qo.fileURLToPath)(e);I1e.has(o+\"|\"+t)||(I1e.add(o+\"|\"+t),process.emitWarning(`Use of deprecated trailing slash pattern mapping \"${t}\" in the \"exports\" field module resolution of the package at ${o}${r?` imported from ${(0,Qo.fileURLToPath)(r)}`:\"\"}. Mapping specifiers ending in \"/\" is no longer supported.`,\"DeprecationWarning\",\"DEP0155\"))}function B1e({packageJSONUrl:t,packageSubpath:e,exports:r,base:o,conditions:a}){if(mwt(r,t,o)&&(r={\".\":r}),Ad(r,e)&&!kj(e,\"*\")&&!Gh(e,\"/\")){let p=r[e],h=kC(t,p,\"\",e,o,!1,!1,a);return h==null&&Rj(e,t,o),h}let n=\"\",u,A=mv(r);for(let p=0;p<A.length;p++){let h=A[p],E=yv(h,\"*\");if(E!==-1&&EA(e,Wh(h,0,E))){Gh(e,\"/\")&&ywt(e,t,o);let w=Wh(h,E+1);e.length>=h.length&&Gh(e,w)&&w1e(n,h)===1&&Qj(h,\"*\")===E&&(n=h,u=Wh(e,E,e.length-w.length))}}if(n){let p=r[n],h=kC(t,p,u,n,o,!0,!1,a);return h==null&&Rj(e,t,o),h}Rj(e,t,o)}function v1e({name:t,base:e,conditions:r,readFileSyncFn:o}){if(t===\"#\"||EA(t,\"#/\")||Gh(t,\"/\")){let u=\"is not a valid internal imports specifier name\";throw new Fj(t,u,(0,Qo.fileURLToPath)(e))}let a,n=y1e(e,o);if(n.exists){a=(0,Qo.pathToFileURL)(n.pjsonPath);let u=n.imports;if(u)if(Ad(u,t)&&!kj(t,\"*\")){let A=kC(a,u[t],\"\",t,e,!1,!0,r);if(A!=null)return A}else{let A=\"\",p,h=mv(u);for(let E=0;E<h.length;E++){let w=h[E],D=yv(w,\"*\");if(D!==-1&&EA(t,Wh(w,0,D))){let b=Wh(w,D+1);t.length>=w.length&&Gh(t,b)&&w1e(A,w)===1&&Qj(w,\"*\")===D&&(A=w,p=Wh(t,D,t.length-b.length))}}if(A){let E=u[A],w=kC(a,E,p,A,e,!0,!0,r);if(w!=null)return w}}}pwt(t,a,e)}Pt();var Ewt=new Set([\"BUILTIN_NODE_RESOLUTION_FAILED\",\"MISSING_DEPENDENCY\",\"MISSING_PEER_DEPENDENCY\",\"QUALIFIED_PATH_RESOLUTION_FAILED\",\"UNDECLARED_DEPENDENCY\"]);function ts(t,e,r={},o){o??=Ewt.has(t)?\"MODULE_NOT_FOUND\":t;let a={configurable:!0,writable:!0,enumerable:!1};return Object.defineProperties(new Error(e),{code:{...a,value:o},pnpCode:{...a,value:t},data:{...a,value:r}})}function pu(t){return Ae.normalize(Ae.fromPortablePath(t))}var x1e=et(P1e());function b1e(t){return Cwt(),Lj[t]}var Lj;function Cwt(){Lj||(Lj={\"--conditions\":[],...S1e(Iwt()),...S1e(process.execArgv)})}function S1e(t){return(0,x1e.default)({\"--conditions\":[String],\"-C\":\"--conditions\"},{argv:t,permissive:!0})}function Iwt(){let t=[],e=wwt(process.env.NODE_OPTIONS||\"\",t);return t.length,e}function wwt(t,e){let r=[],o=!1,a=!0;for(let n=0;n<t.length;++n){let u=t[n];if(u===\"\\\\\"&&o){if(n+1===t.length)return e.push(`invalid value for NODE_OPTIONS (invalid escape)\n`),r;u=t[++n]}else if(u===\" \"&&!o){a=!0;continue}else if(u==='\"'){o=!o;continue}a?(r.push(u),a=!1):r[r.length-1]+=u}return o&&e.push(`invalid value for NODE_OPTIONS (unterminated string)\n`),r}Pt();var[Ha,ep]=process.versions.node.split(\".\").map(t=>parseInt(t,10)),k1e=Ha>19||Ha===19&&ep>=2||Ha===18&&ep>=13,tJt=Ha===20&&ep<6||Ha===19&&ep>=3,rJt=Ha>19||Ha===19&&ep>=6,nJt=Ha>=21||Ha===20&&ep>=10||Ha===18&&ep>=19,iJt=Ha>=21||Ha===20&&ep>=10||Ha===18&&ep>=20,sJt=Ha>=22;function Q1e(t){if(process.env.WATCH_REPORT_DEPENDENCIES&&process.send)if(t=t.map(e=>Ae.fromPortablePath(qs.resolveVirtual(Ae.toPortablePath(e)))),k1e)process.send({\"watch:require\":t});else for(let e of t)process.send({\"watch:require\":e})}function Oj(t,e){let r=Number(process.env.PNP_ALWAYS_WARN_ON_FALLBACK)>0,o=Number(process.env.PNP_DEBUG_LEVEL),a=/^(?![a-zA-Z]:[\\\\/]|\\\\\\\\|\\.{0,2}(?:\\/|$))((?:node:)?(?:@[^/]+\\/)?[^/]+)\\/*(.*|)$/,n=/^(\\/|\\.{1,2}(\\/|$))/,u=/\\/$/,A=/^\\.{0,2}\\//,p={name:null,reference:null},h=[],E=new Set;if(t.enableTopLevelFallback===!0&&h.push(p),e.compatibilityMode!==!1)for(let Le of[\"react-scripts\",\"gatsby\"]){let Te=t.packageRegistry.get(Le);if(Te)for(let ke of Te.keys()){if(ke===null)throw new Error(\"Assertion failed: This reference shouldn't be null\");h.push({name:Le,reference:ke})}}let{ignorePattern:w,packageRegistry:D,packageLocatorsByLocations:b}=t;function C(Le,Te){return{fn:Le,args:Te,error:null,result:null}}function T(Le){let Te=process.stderr?.hasColors?.()??process.stdout.isTTY,ke=(tt,He)=>`\\x1B[${tt}m${He}\\x1B[0m`,Ve=Le.error;console.error(Ve?ke(\"31;1\",`\\u2716 ${Le.error?.message.replace(/\\n.*/s,\"\")}`):ke(\"33;1\",\"\\u203C Resolution\")),Le.args.length>0&&console.error();for(let tt of Le.args)console.error(`  ${ke(\"37;1\",\"In \\u2190\")} ${(0,Nj.inspect)(tt,{colors:Te,compact:!0})}`);Le.result&&(console.error(),console.error(`  ${ke(\"37;1\",\"Out \\u2192\")} ${(0,Nj.inspect)(Le.result,{colors:Te,compact:!0})}`));let xe=new Error().stack.match(/(?<=^ +)at.*/gm)?.slice(2)??[];if(xe.length>0){console.error();for(let tt of xe)console.error(`  ${ke(\"38;5;244\",tt)}`)}console.error()}function N(Le,Te){if(e.allowDebug===!1)return Te;if(Number.isFinite(o)){if(o>=2)return(...ke)=>{let Ve=C(Le,ke);try{return Ve.result=Te(...ke)}catch(xe){throw Ve.error=xe}finally{T(Ve)}};if(o>=1)return(...ke)=>{try{return Te(...ke)}catch(Ve){let xe=C(Le,ke);throw xe.error=Ve,T(xe),Ve}}}return Te}function U(Le){let Te=g(Le);if(!Te)throw ts(\"INTERNAL\",\"Couldn't find a matching entry in the dependency tree for the specified parent (this is probably an internal error)\");return Te}function z(Le){if(Le.name===null)return!0;for(let Te of t.dependencyTreeRoots)if(Te.name===Le.name&&Te.reference===Le.reference)return!0;return!1}let te=new Set([\"node\",\"require\",...b1e(\"--conditions\")]);function le(Le,Te=te,ke){let Ve=fe(K.join(Le,\"internal.js\"),{resolveIgnored:!0,includeDiscardFromLookup:!0});if(Ve===null)throw ts(\"INTERNAL\",`The locator that owns the \"${Le}\" path can't be found inside the dependency tree (this is probably an internal error)`);let{packageLocation:xe}=U(Ve),tt=K.join(xe,mr.manifest);if(!e.fakeFs.existsSync(tt))return null;let He=JSON.parse(e.fakeFs.readFileSync(tt,\"utf8\"));if(He.exports==null)return null;let x=K.contains(xe,Le);if(x===null)throw ts(\"INTERNAL\",\"unqualifiedPath doesn't contain the packageLocation (this is probably an internal error)\");x!==\".\"&&!A.test(x)&&(x=`./${x}`);try{let I=B1e({packageJSONUrl:(0,fd.pathToFileURL)(Ae.fromPortablePath(tt)),packageSubpath:x,exports:He.exports,base:ke?(0,fd.pathToFileURL)(Ae.fromPortablePath(ke)):null,conditions:Te});return Ae.toPortablePath((0,fd.fileURLToPath)(I))}catch(I){throw ts(\"EXPORTS_RESOLUTION_FAILED\",I.message,{unqualifiedPath:pu(Le),locator:Ve,pkgJson:He,subpath:pu(x),conditions:Te},I.code)}}function ce(Le,Te,{extensions:ke}){let Ve;try{Te.push(Le),Ve=e.fakeFs.statSync(Le)}catch{}if(Ve&&!Ve.isDirectory())return e.fakeFs.realpathSync(Le);if(Ve&&Ve.isDirectory()){let xe;try{xe=JSON.parse(e.fakeFs.readFileSync(K.join(Le,mr.manifest),\"utf8\"))}catch{}let tt;if(xe&&xe.main&&(tt=K.resolve(Le,xe.main)),tt&&tt!==Le){let He=ce(tt,Te,{extensions:ke});if(He!==null)return He}}for(let xe=0,tt=ke.length;xe<tt;xe++){let He=`${Le}${ke[xe]}`;if(Te.push(He),e.fakeFs.existsSync(He))return He}if(Ve&&Ve.isDirectory())for(let xe=0,tt=ke.length;xe<tt;xe++){let He=K.format({dir:Le,name:\"index\",ext:ke[xe]});if(Te.push(He),e.fakeFs.existsSync(He))return He}return null}function ue(Le){let Te=new tp.Module(Le,null);return Te.filename=Le,Te.paths=tp.Module._nodeModulePaths(Le),Te}function Ie(Le,Te){return Te.endsWith(\"/\")&&(Te=K.join(Te,\"internal.js\")),tp.Module._resolveFilename(Ae.fromPortablePath(Le),ue(Ae.fromPortablePath(Te)),!1,{plugnplay:!1})}function he(Le){if(w===null)return!1;let Te=K.contains(t.basePath,Le);return Te===null?!1:!!w.test(Te.replace(/\\/$/,\"\"))}let De={std:3,resolveVirtual:1,getAllLocators:1},Ee=p;function g({name:Le,reference:Te}){let ke=D.get(Le);if(!ke)return null;let Ve=ke.get(Te);return Ve||null}function me({name:Le,reference:Te}){let ke=[];for(let[Ve,xe]of D)if(Ve!==null)for(let[tt,He]of xe)tt===null||He.packageDependencies.get(Le)!==Te||Ve===Le&&tt===Te||ke.push({name:Ve,reference:tt});return ke}function Ce(Le,Te){let ke=new Map,Ve=new Set,xe=He=>{let x=JSON.stringify(He.name);if(Ve.has(x))return;Ve.add(x);let I=me(He);for(let S of I)if(U(S).packagePeers.has(Le))xe(S);else{let R=ke.get(S.name);typeof R>\"u\"&&ke.set(S.name,R=new Set),R.add(S.reference)}};xe(Te);let tt=[];for(let He of[...ke.keys()].sort())for(let x of[...ke.get(He)].sort())tt.push({name:He,reference:x});return tt}function fe(Le,{resolveIgnored:Te=!1,includeDiscardFromLookup:ke=!1}={}){if(he(Le)&&!Te)return null;let Ve=K.relative(t.basePath,Le);Ve.match(n)||(Ve=`./${Ve}`),Ve.endsWith(\"/\")||(Ve=`${Ve}/`);do{let xe=b.get(Ve);if(typeof xe>\"u\"||xe.discardFromLookup&&!ke){Ve=Ve.substring(0,Ve.lastIndexOf(\"/\",Ve.length-2)+1);continue}return xe.locator}while(Ve!==\"\");return null}function ie(Le){try{return e.fakeFs.readFileSync(Ae.toPortablePath(Le),\"utf8\")}catch(Te){if(Te.code===\"ENOENT\")return;throw Te}}function Z(Le,Te,{considerBuiltins:ke=!0}={}){if(Le.startsWith(\"#\"))throw new Error(\"resolveToUnqualified can not handle private import mappings\");if(Le===\"pnpapi\")return Ae.toPortablePath(e.pnpapiResolution);if(ke&&(0,tp.isBuiltin)(Le))return null;let Ve=pu(Le),xe=Te&&pu(Te);if(Te&&he(Te)&&(!K.isAbsolute(Le)||fe(Le)===null)){let x=Ie(Le,Te);if(x===!1)throw ts(\"BUILTIN_NODE_RESOLUTION_FAILED\",`The builtin node resolution algorithm was unable to resolve the requested module (it didn't go through the pnp resolver because the issuer was explicitely ignored by the regexp)\n\nRequire request: \"${Ve}\"\nRequired by: ${xe}\n`,{request:Ve,issuer:xe});return Ae.toPortablePath(x)}let tt,He=Le.match(a);if(He){if(!Te)throw ts(\"API_ERROR\",\"The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute\",{request:Ve,issuer:xe});let[,x,I]=He,S=fe(Te);if(!S){let Fe=Ie(Le,Te);if(Fe===!1)throw ts(\"BUILTIN_NODE_RESOLUTION_FAILED\",`The builtin node resolution algorithm was unable to resolve the requested module (it didn't go through the pnp resolver because the issuer doesn't seem to be part of the Yarn-managed dependency tree).\n\nRequire path: \"${Ve}\"\nRequired by: ${xe}\n`,{request:Ve,issuer:xe});return Ae.toPortablePath(Fe)}let R=U(S).packageDependencies.get(x),J=null;if(R==null&&S.name!==null){let Fe=t.fallbackExclusionList.get(S.name);if(!Fe||!Fe.has(S.reference)){for(let Et=0,qt=h.length;Et<qt;++Et){let St=U(h[Et]).packageDependencies.get(x);if(St!=null){r?J=St:R=St;break}}if(t.enableTopLevelFallback&&R==null&&J===null){let Et=t.fallbackPool.get(x);Et!=null&&(J=Et)}}}let X=null;if(R===null)if(z(S))X=ts(\"MISSING_PEER_DEPENDENCY\",`Your application tried to access ${x} (a peer dependency); this isn't allowed as there is no ancestor to satisfy the requirement. Use a devDependency if needed.\n\nRequired package: ${x}${x!==Ve?` (via \"${Ve}\")`:\"\"}\nRequired by: ${xe}\n`,{request:Ve,issuer:xe,dependencyName:x});else{let Fe=Ce(x,S);Fe.every(lt=>z(lt))?X=ts(\"MISSING_PEER_DEPENDENCY\",`${S.name} tried to access ${x} (a peer dependency) but it isn't provided by your application; this makes the require call ambiguous and unsound.\n\nRequired package: ${x}${x!==Ve?` (via \"${Ve}\")`:\"\"}\nRequired by: ${S.name}@${S.reference} (via ${xe})\n${Fe.map(lt=>`Ancestor breaking the chain: ${lt.name}@${lt.reference}\n`).join(\"\")}\n`,{request:Ve,issuer:xe,issuerLocator:Object.assign({},S),dependencyName:x,brokenAncestors:Fe}):X=ts(\"MISSING_PEER_DEPENDENCY\",`${S.name} tried to access ${x} (a peer dependency) but it isn't provided by its ancestors; this makes the require call ambiguous and unsound.\n\nRequired package: ${x}${x!==Ve?` (via \"${Ve}\")`:\"\"}\nRequired by: ${S.name}@${S.reference} (via ${xe})\n\n${Fe.map(lt=>`Ancestor breaking the chain: ${lt.name}@${lt.reference}\n`).join(\"\")}\n`,{request:Ve,issuer:xe,issuerLocator:Object.assign({},S),dependencyName:x,brokenAncestors:Fe})}else R===void 0&&(!ke&&(0,tp.isBuiltin)(Le)?z(S)?X=ts(\"UNDECLARED_DEPENDENCY\",`Your application tried to access ${x}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${x} isn't otherwise declared in your dependencies, this makes the require call ambiguous and unsound.\n\nRequired package: ${x}${x!==Ve?` (via \"${Ve}\")`:\"\"}\nRequired by: ${xe}\n`,{request:Ve,issuer:xe,dependencyName:x}):X=ts(\"UNDECLARED_DEPENDENCY\",`${S.name} tried to access ${x}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${x} isn't otherwise declared in ${S.name}'s dependencies, this makes the require call ambiguous and unsound.\n\nRequired package: ${x}${x!==Ve?` (via \"${Ve}\")`:\"\"}\nRequired by: ${xe}\n`,{request:Ve,issuer:xe,issuerLocator:Object.assign({},S),dependencyName:x}):z(S)?X=ts(\"UNDECLARED_DEPENDENCY\",`Your application tried to access ${x}, but it isn't declared in your dependencies; this makes the require call ambiguous and unsound.\n\nRequired package: ${x}${x!==Ve?` (via \"${Ve}\")`:\"\"}\nRequired by: ${xe}\n`,{request:Ve,issuer:xe,dependencyName:x}):X=ts(\"UNDECLARED_DEPENDENCY\",`${S.name} tried to access ${x}, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound.\n\nRequired package: ${x}${x!==Ve?` (via \"${Ve}\")`:\"\"}\nRequired by: ${S.name}@${S.reference} (via ${xe})\n`,{request:Ve,issuer:xe,issuerLocator:Object.assign({},S),dependencyName:x}));if(R==null){if(J===null||X===null)throw X||new Error(\"Assertion failed: Expected an error to have been set\");R=J;let Fe=X.message.replace(/\\n.*/g,\"\");X.message=Fe,!E.has(Fe)&&o!==0&&(E.add(Fe),process.emitWarning(X))}let $=Array.isArray(R)?{name:R[0],reference:R[1]}:{name:x,reference:R},se=U($);if(!se.packageLocation)throw ts(\"MISSING_DEPENDENCY\",`A dependency seems valid but didn't get installed for some reason. This might be caused by a partial install, such as dev vs prod.\n\nRequired package: ${$.name}@${$.reference}${$.name!==Ve?` (via \"${Ve}\")`:\"\"}\nRequired by: ${S.name}@${S.reference} (via ${xe})\n`,{request:Ve,issuer:xe,dependencyLocator:Object.assign({},$)});let be=se.packageLocation;I?tt=K.join(be,I):tt=be}else if(K.isAbsolute(Le))tt=K.normalize(Le);else{if(!Te)throw ts(\"API_ERROR\",\"The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute\",{request:Ve,issuer:xe});let x=K.resolve(Te);Te.match(u)?tt=K.normalize(K.join(x,Le)):tt=K.normalize(K.join(K.dirname(x),Le))}return K.normalize(tt)}function Pe(Le,Te,ke=te,Ve){if(n.test(Le))return Te;let xe=le(Te,ke,Ve);return xe?K.normalize(xe):Te}function Re(Le,{extensions:Te=Object.keys(tp.Module._extensions)}={}){let ke=[],Ve=ce(Le,ke,{extensions:Te});if(Ve)return K.normalize(Ve);{Q1e(ke.map(He=>Ae.fromPortablePath(He)));let xe=pu(Le),tt=fe(Le);if(tt){let{packageLocation:He}=U(tt),x=!0;try{e.fakeFs.accessSync(He)}catch(I){if(I?.code===\"ENOENT\")x=!1;else{let S=(I?.message??I??\"empty exception thrown\").replace(/^[A-Z]/,y=>y.toLowerCase());throw ts(\"QUALIFIED_PATH_RESOLUTION_FAILED\",`Required package exists but could not be accessed (${S}).\n\nMissing package: ${tt.name}@${tt.reference}\nExpected package location: ${pu(He)}\n`,{unqualifiedPath:xe,extensions:Te})}}if(!x){let I=He.includes(\"/unplugged/\")?\"Required unplugged package missing from disk. This may happen when switching branches without running installs (unplugged packages must be fully materialized on disk to work).\":\"Required package missing from disk. If you keep your packages inside your repository then restarting the Node process may be enough. Otherwise, try to run an install first.\";throw ts(\"QUALIFIED_PATH_RESOLUTION_FAILED\",`${I}\n\nMissing package: ${tt.name}@${tt.reference}\nExpected package location: ${pu(He)}\n`,{unqualifiedPath:xe,extensions:Te})}}throw ts(\"QUALIFIED_PATH_RESOLUTION_FAILED\",`Qualified path resolution failed: we looked for the following paths, but none could be accessed.\n\nSource path: ${xe}\n${ke.map(He=>`Not found: ${pu(He)}\n`).join(\"\")}`,{unqualifiedPath:xe,extensions:Te})}}function ht(Le,Te,ke){if(!Te)throw new Error(\"Assertion failed: An issuer is required to resolve private import mappings\");let Ve=v1e({name:Le,base:(0,fd.pathToFileURL)(Ae.fromPortablePath(Te)),conditions:ke.conditions??te,readFileSyncFn:ie});if(Ve instanceof URL)return Re(Ae.toPortablePath((0,fd.fileURLToPath)(Ve)),{extensions:ke.extensions});if(Ve.startsWith(\"#\"))throw new Error(\"Mapping from one private import to another isn't allowed\");return q(Ve,Te,ke)}function q(Le,Te,ke={}){try{if(Le.startsWith(\"#\"))return ht(Le,Te,ke);let{considerBuiltins:Ve,extensions:xe,conditions:tt}=ke,He=Z(Le,Te,{considerBuiltins:Ve});if(Le===\"pnpapi\")return He;if(He===null)return null;let x=()=>Te!==null?he(Te):!1,I=(!Ve||!(0,tp.isBuiltin)(Le))&&!x()?Pe(Le,He,tt,Te):He;return Re(I,{extensions:xe})}catch(Ve){throw Object.hasOwn(Ve,\"pnpCode\")&&Object.assign(Ve.data,{request:pu(Le),issuer:Te&&pu(Te)}),Ve}}function nt(Le){let Te=K.normalize(Le),ke=qs.resolveVirtual(Te);return ke!==Te?ke:null}return{VERSIONS:De,topLevel:Ee,getLocator:(Le,Te)=>Array.isArray(Te)?{name:Te[0],reference:Te[1]}:{name:Le,reference:Te},getDependencyTreeRoots:()=>[...t.dependencyTreeRoots],getAllLocators(){let Le=[];for(let[Te,ke]of D)for(let Ve of ke.keys())Te!==null&&Ve!==null&&Le.push({name:Te,reference:Ve});return Le},getPackageInformation:Le=>{let Te=g(Le);if(Te===null)return null;let ke=Ae.fromPortablePath(Te.packageLocation);return{...Te,packageLocation:ke}},findPackageLocator:Le=>fe(Ae.toPortablePath(Le)),resolveToUnqualified:N(\"resolveToUnqualified\",(Le,Te,ke)=>{let Ve=Te!==null?Ae.toPortablePath(Te):null,xe=Z(Ae.toPortablePath(Le),Ve,ke);return xe===null?null:Ae.fromPortablePath(xe)}),resolveUnqualified:N(\"resolveUnqualified\",(Le,Te)=>Ae.fromPortablePath(Re(Ae.toPortablePath(Le),Te))),resolveRequest:N(\"resolveRequest\",(Le,Te,ke)=>{let Ve=Te!==null?Ae.toPortablePath(Te):null,xe=q(Ae.toPortablePath(Le),Ve,ke);return xe===null?null:Ae.fromPortablePath(xe)}),resolveVirtual:N(\"resolveVirtual\",Le=>{let Te=nt(Ae.toPortablePath(Le));return Te!==null?Ae.fromPortablePath(Te):null})}}Pt();var F1e=(t,e,r)=>{let o=gv(t),a=Pj(o,{basePath:e}),n=Ae.join(e,mr.pnpCjs);return Oj(a,{fakeFs:r,pnpapiResolution:n})};var Uj=et(T1e());Gt();var CA={};Kt(CA,{checkManifestCompatibility:()=>L1e,extractBuildRequest:()=>ZQ,getExtractHint:()=>_j,hasBindingGyp:()=>Hj});Ke();Pt();function L1e(t){return G.isPackageCompatible(t,Xi.getArchitectureSet())}function ZQ(t,e,r,{configuration:o}){let a=[];for(let n of[\"preinstall\",\"install\",\"postinstall\"])e.manifest.scripts.has(n)&&a.push({type:0,script:n});return!e.manifest.scripts.has(\"install\")&&e.misc.hasBindingGyp&&a.push({type:1,script:\"node-gyp rebuild\"}),a.length===0?null:t.linkType!==\"HARD\"?{skipped:!0,explain:n=>n.reportWarningOnce(6,`${G.prettyLocator(o,t)} lists build scripts, but is referenced through a soft link. Soft links don't support build scripts, so they'll be ignored.`)}:r&&r.built===!1?{skipped:!0,explain:n=>n.reportInfoOnce(5,`${G.prettyLocator(o,t)} lists build scripts, but its build has been explicitly disabled through configuration.`)}:!o.get(\"enableScripts\")&&!r.built?{skipped:!0,explain:n=>n.reportWarningOnce(4,`${G.prettyLocator(o,t)} lists build scripts, but all build scripts have been disabled.`)}:L1e(t)?{skipped:!1,directives:a}:{skipped:!0,explain:n=>n.reportWarningOnce(76,`${G.prettyLocator(o,t)} The ${Xi.getArchitectureName()} architecture is incompatible with this package, build skipped.`)}}var vwt=new Set([\".exe\",\".bin\",\".h\",\".hh\",\".hpp\",\".c\",\".cc\",\".cpp\",\".java\",\".jar\",\".node\"]);function _j(t){return t.packageFs.getExtractHint({relevantExtensions:vwt})}function Hj(t){let e=K.join(t.prefixPath,\"binding.gyp\");return t.packageFs.existsSync(e)}var vv={};Kt(vv,{getUnpluggedPath:()=>Bv});Ke();Pt();function Bv(t,{configuration:e}){return K.resolve(e.get(\"pnpUnpluggedFolder\"),G.slugifyLocator(t))}var Dwt=new Set([G.makeIdent(null,\"open\").identHash,G.makeIdent(null,\"opn\").identHash]),Yh=class{constructor(){this.mode=\"strict\";this.pnpCache=new Map}getCustomDataKey(){return JSON.stringify({name:\"PnpLinker\",version:2})}supportsPackage(e,r){return this.isEnabled(r)}async findPackageLocation(e,r){if(!this.isEnabled(r))throw new Error(\"Assertion failed: Expected the PnP linker to be enabled\");let o=Kh(r.project).cjs;if(!ae.existsSync(o))throw new ot(`The project in ${pe.pretty(r.project.configuration,`${r.project.cwd}/package.json`,pe.Type.PATH)} doesn't seem to have been installed - running an install there might help`);let a=qe.getFactoryWithDefault(this.pnpCache,o,()=>qe.dynamicRequire(o,{cachingStrategy:qe.CachingStrategy.FsTime})),n={name:G.stringifyIdent(e),reference:e.reference},u=a.getPackageInformation(n);if(!u)throw new ot(`Couldn't find ${G.prettyLocator(r.project.configuration,e)} in the currently installed PnP map - running an install might help`);return Ae.toPortablePath(u.packageLocation)}async findPackageLocator(e,r){if(!this.isEnabled(r))return null;let o=Kh(r.project).cjs;if(!ae.existsSync(o))return null;let n=qe.getFactoryWithDefault(this.pnpCache,o,()=>qe.dynamicRequire(o,{cachingStrategy:qe.CachingStrategy.FsTime})).findPackageLocator(Ae.fromPortablePath(e));return n?G.makeLocator(G.parseIdent(n.name),n.reference):null}makeInstaller(e){return new pd(e)}isEnabled(e){return!(e.project.configuration.get(\"nodeLinker\")!==\"pnp\"||e.project.configuration.get(\"pnpMode\")!==this.mode)}},pd=class{constructor(e){this.opts=e;this.mode=\"strict\";this.asyncActions=new qe.AsyncActions(10);this.packageRegistry=new Map;this.virtualTemplates=new Map;this.isESMLoaderRequired=!1;this.customData={store:new Map};this.unpluggedPaths=new Set;this.opts=e}attachCustomData(e){this.customData=e}async installPackage(e,r,o){let a=G.stringifyIdent(e),n=e.reference,u=!!this.opts.project.tryWorkspaceByLocator(e),A=G.isVirtualLocator(e),p=e.peerDependencies.size>0&&!A,h=!p&&!u,E=!p&&e.linkType!==\"SOFT\",w,D;if(h||E){let te=A?G.devirtualizeLocator(e):e;w=this.customData.store.get(te.locatorHash),typeof w>\"u\"&&(w=await Pwt(r),e.linkType===\"HARD\"&&this.customData.store.set(te.locatorHash,w)),w.manifest.type===\"module\"&&(this.isESMLoaderRequired=!0),D=this.opts.project.getDependencyMeta(te,e.version)}let b=h?ZQ(e,w,D,{configuration:this.opts.project.configuration}):null,C=E?await this.unplugPackageIfNeeded(e,w,r,D,o):r.packageFs;if(K.isAbsolute(r.prefixPath))throw new Error(`Assertion failed: Expected the prefix path (${r.prefixPath}) to be relative to the parent`);let T=K.resolve(C.getRealPath(),r.prefixPath),N=qj(this.opts.project.cwd,T),U=new Map,z=new Set;if(A){for(let te of e.peerDependencies.values())U.set(G.stringifyIdent(te),null),z.add(G.stringifyIdent(te));if(!u){let te=G.devirtualizeLocator(e);this.virtualTemplates.set(te.locatorHash,{location:qj(this.opts.project.cwd,qs.resolveVirtual(T)),locator:te})}}return qe.getMapWithDefault(this.packageRegistry,a).set(n,{packageLocation:N,packageDependencies:U,packagePeers:z,linkType:e.linkType,discardFromLookup:r.discardFromLookup||!1}),{packageLocation:T,buildRequest:b}}async attachInternalDependencies(e,r){let o=this.getPackageInformation(e);for(let[a,n]of r){let u=G.areIdentsEqual(a,n)?n.reference:[G.stringifyIdent(n),n.reference];o.packageDependencies.set(G.stringifyIdent(a),u)}}async attachExternalDependents(e,r){for(let o of r)this.getDiskInformation(o).packageDependencies.set(G.stringifyIdent(e),e.reference)}async finalizeInstall(){if(this.opts.project.configuration.get(\"pnpMode\")!==this.mode)return;let e=Kh(this.opts.project);if(this.isEsmEnabled()||await ae.removePromise(e.esmLoader),this.opts.project.configuration.get(\"nodeLinker\")!==\"pnp\"){await ae.removePromise(e.cjs),await ae.removePromise(e.data),await ae.removePromise(e.esmLoader),await ae.removePromise(this.opts.project.configuration.get(\"pnpUnpluggedFolder\"));return}for(let{locator:E,location:w}of this.virtualTemplates.values())qe.getMapWithDefault(this.packageRegistry,G.stringifyIdent(E)).set(E.reference,{packageLocation:w,packageDependencies:new Map,packagePeers:new Set,linkType:\"SOFT\",discardFromLookup:!1});this.packageRegistry.set(null,new Map([[null,this.getPackageInformation(this.opts.project.topLevelWorkspace.anchoredLocator)]]));let r=this.opts.project.configuration.get(\"pnpFallbackMode\"),o=this.opts.project.workspaces.map(({anchoredLocator:E})=>({name:G.stringifyIdent(E),reference:E.reference})),a=r!==\"none\",n=[],u=new Map,A=qe.buildIgnorePattern([\".yarn/sdks/**\",...this.opts.project.configuration.get(\"pnpIgnorePatterns\")]),p=this.packageRegistry,h=this.opts.project.configuration.get(\"pnpShebang\");if(r===\"dependencies-only\")for(let E of this.opts.project.storedPackages.values())this.opts.project.tryWorkspaceByLocator(E)&&n.push({name:G.stringifyIdent(E),reference:E.reference});return await this.asyncActions.wait(),await this.finalizeInstallWithPnp({dependencyTreeRoots:o,enableTopLevelFallback:a,fallbackExclusionList:n,fallbackPool:u,ignorePattern:A,packageRegistry:p,shebang:h}),{customData:this.customData}}async transformPnpSettings(e){}isEsmEnabled(){if(this.opts.project.configuration.sources.has(\"pnpEnableEsmLoader\"))return this.opts.project.configuration.get(\"pnpEnableEsmLoader\");if(this.isESMLoaderRequired)return!0;for(let e of this.opts.project.workspaces)if(e.manifest.type===\"module\")return!0;return!1}async finalizeInstallWithPnp(e){let r=Kh(this.opts.project),o=await this.locateNodeModules(e.ignorePattern);if(o.length>0){this.opts.report.reportWarning(31,\"One or more node_modules have been detected and will be removed. This operation may take some time.\");for(let n of o)await ae.removePromise(n)}if(await this.transformPnpSettings(e),this.opts.project.configuration.get(\"pnpEnableInlining\")){let n=l1e(e);await ae.changeFilePromise(r.cjs,n,{automaticNewlines:!0,mode:493}),await ae.removePromise(r.data)}else{let{dataFile:n,loaderFile:u}=c1e(e);await ae.changeFilePromise(r.cjs,u,{automaticNewlines:!0,mode:493}),await ae.changeFilePromise(r.data,n,{automaticNewlines:!0,mode:420})}this.isEsmEnabled()&&(this.opts.report.reportWarning(0,\"ESM support for PnP uses the experimental loader API and is therefore experimental\"),await ae.changeFilePromise(r.esmLoader,(0,Uj.default)(),{automaticNewlines:!0,mode:420}));let a=this.opts.project.configuration.get(\"pnpUnpluggedFolder\");if(this.unpluggedPaths.size===0)await ae.removePromise(a);else for(let n of await ae.readdirPromise(a)){let u=K.resolve(a,n);this.unpluggedPaths.has(u)||await ae.removePromise(u)}}async locateNodeModules(e){let r=[],o=e?new RegExp(e):null;for(let a of this.opts.project.workspaces){let n=K.join(a.cwd,\"node_modules\");if(o&&o.test(K.relative(this.opts.project.cwd,a.cwd))||!ae.existsSync(n))continue;let u=await ae.readdirPromise(n,{withFileTypes:!0}),A=u.filter(p=>!p.isDirectory()||p.name===\".bin\"||!p.name.startsWith(\".\"));if(A.length===u.length)r.push(n);else for(let p of A)r.push(K.join(n,p.name))}return r}async unplugPackageIfNeeded(e,r,o,a,n){return this.shouldBeUnplugged(e,r,a)?this.unplugPackage(e,o,n):o.packageFs}shouldBeUnplugged(e,r,o){return typeof o.unplugged<\"u\"?o.unplugged:Dwt.has(e.identHash)||e.conditions!=null?!0:r.manifest.preferUnplugged!==null?r.manifest.preferUnplugged:!!(ZQ(e,r,o,{configuration:this.opts.project.configuration})?.skipped===!1||r.misc.extractHint)}async unplugPackage(e,r,o){let a=Bv(e,{configuration:this.opts.project.configuration});return this.opts.project.disabledLocators.has(e.locatorHash)?new ju(a,{baseFs:r.packageFs,pathUtils:K}):(this.unpluggedPaths.add(a),o.holdFetchResult(this.asyncActions.set(e.locatorHash,async()=>{let n=K.join(a,r.prefixPath,\".ready\");await ae.existsPromise(n)||(this.opts.project.storedBuildState.delete(e.locatorHash),await ae.mkdirPromise(a,{recursive:!0}),await ae.copyPromise(a,Bt.dot,{baseFs:r.packageFs,overwrite:!1}),await ae.writeFilePromise(n,\"\"))})),new En(a))}getPackageInformation(e){let r=G.stringifyIdent(e),o=e.reference,a=this.packageRegistry.get(r);if(!a)throw new Error(`Assertion failed: The package information store should have been available (for ${G.prettyIdent(this.opts.project.configuration,e)})`);let n=a.get(o);if(!n)throw new Error(`Assertion failed: The package information should have been available (for ${G.prettyLocator(this.opts.project.configuration,e)})`);return n}getDiskInformation(e){let r=qe.getMapWithDefault(this.packageRegistry,\"@@disk\"),o=qj(this.opts.project.cwd,e);return qe.getFactoryWithDefault(r,o,()=>({packageLocation:o,packageDependencies:new Map,packagePeers:new Set,linkType:\"SOFT\",discardFromLookup:!1}))}};function qj(t,e){let r=K.relative(t,e);return r.match(/^\\.{0,2}\\//)||(r=`./${r}`),r.replace(/\\/?$/,\"/\")}async function Pwt(t){let e=await _t.tryFind(t.prefixPath,{baseFs:t.packageFs})??new _t,r=new Set([\"preinstall\",\"install\",\"postinstall\"]);for(let o of e.scripts.keys())r.has(o)||e.scripts.delete(o);return{manifest:{scripts:e.scripts,preferUnplugged:e.preferUnplugged,type:e.type},misc:{extractHint:_j(t),hasBindingGyp:Hj(t)}}}Ke();Ke();Gt();var N1e=et(Xo());var QC=class extends ut{constructor(){super(...arguments);this.all=de.Boolean(\"-A,--all\",!1,{description:\"Unplug direct dependencies from the entire project\"});this.recursive=de.Boolean(\"-R,--recursive\",!1,{description:\"Unplug both direct and transitive dependencies\"});this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.patterns=de.Rest()}static{this.paths=[[\"unplug\"]]}static{this.usage=st.Usage({description:\"force the unpacking of a list of packages\",details:\"\\n      This command will add the selectors matching the specified patterns to the list of packages that must be unplugged when installed.\\n\\n      A package being unplugged means that instead of being referenced directly through its archive, it will be unpacked at install time in the directory configured via `pnpUnpluggedFolder`. Note that unpacking packages this way is generally not recommended because it'll make it harder to store your packages within the repository. However, it's a good approach to quickly and safely debug some packages, and can even sometimes be required depending on the context (for example when the package contains shellscripts).\\n\\n      Running the command will set a persistent flag inside your top-level `package.json`, in the `dependenciesMeta` field. As such, to undo its effects, you'll need to revert the changes made to the manifest and run `yarn install` to apply the modification.\\n\\n      By default, only direct dependencies from the current workspace are affected. If `-A,--all` is set, direct dependencies from the entire project are affected. Using the `-R,--recursive` flag will affect transitive dependencies as well as direct ones.\\n\\n      This command accepts glob patterns inside the scope and name components (not the range). Make sure to escape the patterns to prevent your own shell from trying to expand them.\\n    \",examples:[[\"Unplug the lodash dependency from the active workspace\",\"yarn unplug lodash\"],[\"Unplug all instances of lodash referenced by any workspace\",\"yarn unplug lodash -A\"],[\"Unplug all instances of lodash referenced by the active workspace and its dependencies\",\"yarn unplug lodash -R\"],[\"Unplug all instances of lodash, anywhere\",\"yarn unplug lodash -AR\"],[\"Unplug one specific version of lodash\",\"yarn unplug lodash@1.2.3\"],[\"Unplug all packages with the `@babel` scope\",\"yarn unplug '@babel/*'\"],[\"Unplug all packages (only for testing, not recommended)\",\"yarn unplug -R '*'\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Wr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);if(r.get(\"nodeLinker\")!==\"pnp\")throw new ot(\"This command can only be used if the `nodeLinker` option is set to `pnp`\");await o.restoreInstallState();let u=new Set(this.patterns),A=this.patterns.map(b=>{let C=G.parseDescriptor(b),T=C.range!==\"unknown\"?C:G.makeDescriptor(C,\"*\");if(!Ur.validRange(T.range))throw new ot(`The range of the descriptor patterns must be a valid semver range (${G.prettyDescriptor(r,T)})`);return N=>{let U=G.stringifyIdent(N);return!N1e.default.isMatch(U,G.stringifyIdent(T))||N.version&&!Ur.satisfiesWithPrereleases(N.version,T.range)?!1:(u.delete(b),!0)}}),p=()=>{let b=[];for(let C of o.storedPackages.values())!o.tryWorkspaceByLocator(C)&&!G.isVirtualLocator(C)&&A.some(T=>T(C))&&b.push(C);return b},h=b=>{let C=new Set,T=[],N=(U,z)=>{if(C.has(U.locatorHash))return;let te=!!o.tryWorkspaceByLocator(U);if(!(z>0&&!this.recursive&&te)&&(C.add(U.locatorHash),!o.tryWorkspaceByLocator(U)&&A.some(le=>le(U))&&T.push(U),!(z>0&&!this.recursive)))for(let le of U.dependencies.values()){let ce=o.storedResolutions.get(le.descriptorHash);if(!ce)throw new Error(\"Assertion failed: The resolution should have been registered\");let ue=o.storedPackages.get(ce);if(!ue)throw new Error(\"Assertion failed: The package should have been registered\");N(ue,z+1)}};for(let U of b)N(U.anchoredPackage,0);return T},E,w;if(this.all&&this.recursive?(E=p(),w=\"the project\"):this.all?(E=h(o.workspaces),w=\"any workspace\"):(E=h([a]),w=\"this workspace\"),u.size>1)throw new ot(`Patterns ${pe.prettyList(r,u,pe.Type.CODE)} don't match any packages referenced by ${w}`);if(u.size>0)throw new ot(`Pattern ${pe.prettyList(r,u,pe.Type.CODE)} doesn't match any packages referenced by ${w}`);E=qe.sortMap(E,b=>G.stringifyLocator(b));let D=await Lt.start({configuration:r,stdout:this.context.stdout,json:this.json},async b=>{for(let C of E){let T=C.version??\"unknown\",N=o.topLevelWorkspace.manifest.ensureDependencyMeta(G.makeDescriptor(C,T));N.unplugged=!0,b.reportInfo(0,`Will unpack ${G.prettyLocator(r,C)} to ${pe.pretty(r,Bv(C,{configuration:r}),pe.Type.PATH)}`),b.reportJson({locator:G.stringifyLocator(C),version:T})}await o.topLevelWorkspace.persistManifest(),this.json||b.reportSeparator()});return D.hasErrors()?D.exitCode():await o.installWithNewReport({json:this.json,stdout:this.context.stdout},{cache:n})}};var Kh=t=>({cjs:K.join(t.cwd,mr.pnpCjs),data:K.join(t.cwd,mr.pnpData),esmLoader:K.join(t.cwd,mr.pnpEsmLoader)}),M1e=t=>/\\s/.test(t)?JSON.stringify(t):t;async function Swt(t,e,r){let o=/\\s*--require\\s+\\S*\\.pnp\\.c?js\\s*/g,a=/\\s*--experimental-loader\\s+\\S*\\.pnp\\.loader\\.mjs\\s*/,n=(e.NODE_OPTIONS??\"\").replace(o,\" \").replace(a,\" \").trim();if(t.configuration.get(\"nodeLinker\")!==\"pnp\"){e.NODE_OPTIONS=n||void 0;return}let u=Kh(t),A=`--require ${M1e(Ae.fromPortablePath(u.cjs))}`;ae.existsSync(u.esmLoader)&&(A=`${A} --experimental-loader ${(0,O1e.pathToFileURL)(Ae.fromPortablePath(u.esmLoader)).href}`),ae.existsSync(u.cjs)&&(e.NODE_OPTIONS=n?`${A} ${n}`:A)}async function xwt(t,e){let r=Kh(t);e(r.cjs),e(r.data),e(r.esmLoader),e(t.configuration.get(\"pnpUnpluggedFolder\"))}var bwt={hooks:{populateYarnPaths:xwt,setupScriptEnvironment:Swt},configuration:{nodeLinker:{description:'The linker used for installing Node packages, one of: \"pnp\", \"pnpm\", or \"node-modules\"',type:\"STRING\",default:\"pnp\"},winLinkType:{description:\"Whether Yarn should use Windows Junctions or symlinks when creating links on Windows.\",type:\"STRING\",values:[\"junctions\",\"symlinks\"],default:\"junctions\"},pnpMode:{description:\"If 'strict', generates standard PnP maps. If 'loose', merges them with the n_m resolution.\",type:\"STRING\",default:\"strict\"},pnpShebang:{description:\"String to prepend to the generated PnP script\",type:\"STRING\",default:\"#!/usr/bin/env node\"},pnpIgnorePatterns:{description:\"Array of glob patterns; files matching them will use the classic resolution\",type:\"STRING\",default:[],isArray:!0},pnpEnableEsmLoader:{description:\"If true, Yarn will generate an ESM loader (`.pnp.loader.mjs`). If this is not explicitly set Yarn tries to automatically detect whether ESM support is required.\",type:\"BOOLEAN\",default:!1},pnpEnableInlining:{description:\"If true, the PnP data will be inlined along with the generated loader\",type:\"BOOLEAN\",default:!0},pnpFallbackMode:{description:\"If true, the generated PnP loader will follow the top-level fallback rule\",type:\"STRING\",default:\"dependencies-only\"},pnpUnpluggedFolder:{description:\"Folder where the unplugged packages must be stored\",type:\"ABSOLUTE_PATH\",default:\"./.yarn/unplugged\"}},linkers:[Yh],commands:[QC]},kwt=bwt;var Y1e=et(j1e());Gt();var Jj=et(ve(\"crypto\")),K1e=et(ve(\"fs\")),V1e=1,xi=\"node_modules\",$Q=\".bin\",z1e=\".yarn-state.yml\",Kwt=1e3,Xj=(o=>(o.CLASSIC=\"classic\",o.HARDLINKS_LOCAL=\"hardlinks-local\",o.HARDLINKS_GLOBAL=\"hardlinks-global\",o))(Xj||{}),Dv=class{constructor(){this.installStateCache=new Map}getCustomDataKey(){return JSON.stringify({name:\"NodeModulesLinker\",version:3})}supportsPackage(e,r){return this.isEnabled(r)}async findPackageLocation(e,r){if(!this.isEnabled(r))throw new Error(\"Assertion failed: Expected the node-modules linker to be enabled\");let o=r.project.tryWorkspaceByLocator(e);if(o)return o.cwd;let a=await qe.getFactoryWithDefault(this.installStateCache,r.project.cwd,async()=>await zj(r.project,{unrollAliases:!0}));if(a===null)throw new ot(\"Couldn't find the node_modules state file - running an install might help (findPackageLocation)\");let n=a.locatorMap.get(G.stringifyLocator(e));if(!n){let p=new ot(`Couldn't find ${G.prettyLocator(r.project.configuration,e)} in the currently installed node_modules map - running an install might help`);throw p.code=\"LOCATOR_NOT_INSTALLED\",p}let u=n.locations.sort((p,h)=>p.split(K.sep).length-h.split(K.sep).length),A=K.join(r.project.configuration.startingCwd,xi);return u.find(p=>K.contains(A,p))||n.locations[0]}async findPackageLocator(e,r){if(!this.isEnabled(r))return null;let o=await qe.getFactoryWithDefault(this.installStateCache,r.project.cwd,async()=>await zj(r.project,{unrollAliases:!0}));if(o===null)return null;let{locationRoot:a,segments:n}=eF(K.resolve(e),{skipPrefix:r.project.cwd}),u=o.locationTree.get(a);if(!u)return null;let A=u.locator;for(let p of n){if(u=u.children.get(p),!u)break;A=u.locator||A}return G.parseLocator(A)}makeInstaller(e){return new Vj(e)}isEnabled(e){return e.project.configuration.get(\"nodeLinker\")===\"node-modules\"}},Vj=class{constructor(e){this.opts=e;this.localStore=new Map;this.realLocatorChecksums=new Map;this.customData={store:new Map}}attachCustomData(e){this.customData=e}async installPackage(e,r){let o=K.resolve(r.packageFs.getRealPath(),r.prefixPath),a=this.customData.store.get(e.locatorHash);if(typeof a>\"u\"&&(a=await Vwt(e,r),e.linkType===\"HARD\"&&this.customData.store.set(e.locatorHash,a)),!G.isPackageCompatible(e,this.opts.project.configuration.getSupportedArchitectures()))return{packageLocation:null,buildRequest:null};let n=new Map,u=new Set;n.has(G.stringifyIdent(e))||n.set(G.stringifyIdent(e),e.reference);let A=e;if(G.isVirtualLocator(e)){A=G.devirtualizeLocator(e);for(let E of e.peerDependencies.values())n.set(G.stringifyIdent(E),null),u.add(G.stringifyIdent(E))}let p={packageLocation:`${Ae.fromPortablePath(o)}/`,packageDependencies:n,packagePeers:u,linkType:e.linkType,discardFromLookup:r.discardFromLookup??!1};this.localStore.set(e.locatorHash,{pkg:e,customPackageData:a,dependencyMeta:this.opts.project.getDependencyMeta(e,e.version),pnpNode:p});let h=r.checksum?r.checksum.substring(r.checksum.indexOf(\"/\")+1):null;return this.realLocatorChecksums.set(A.locatorHash,h),{packageLocation:o,buildRequest:null}}async attachInternalDependencies(e,r){let o=this.localStore.get(e.locatorHash);if(typeof o>\"u\")throw new Error(\"Assertion failed: Expected information object to have been registered\");for(let[a,n]of r){let u=G.areIdentsEqual(a,n)?n.reference:[G.stringifyIdent(n),n.reference];o.pnpNode.packageDependencies.set(G.stringifyIdent(a),u)}}async attachExternalDependents(e,r){throw new Error(\"External dependencies haven't been implemented for the node-modules linker\")}async finalizeInstall(){if(this.opts.project.configuration.get(\"nodeLinker\")!==\"node-modules\")return;let e=new qs({baseFs:new iA({maxOpenFiles:80,readOnlyArchives:!0})}),r=await zj(this.opts.project),o=this.opts.project.configuration.get(\"nmMode\");(r===null||o!==r.nmMode)&&(this.opts.project.storedBuildState.clear(),r={locatorMap:new Map,binSymlinks:new Map,locationTree:new Map,nmMode:o,mtimeMs:0});let a=new Map(this.opts.project.workspaces.map(D=>{let b=this.opts.project.configuration.get(\"nmHoistingLimits\");try{b=qe.validateEnum(fv,D.manifest.installConfig?.hoistingLimits??b)}catch{let T=G.prettyWorkspace(this.opts.project.configuration,D);this.opts.report.reportWarning(57,`${T}: Invalid 'installConfig.hoistingLimits' value. Expected one of ${Object.values(fv).join(\", \")}, using default: \"${b}\"`)}return[D.relativeCwd,b]})),n=new Map(this.opts.project.workspaces.map(D=>{let b=this.opts.project.configuration.get(\"nmSelfReferences\");return b=D.manifest.installConfig?.selfReferences??b,[D.relativeCwd,b]})),u={VERSIONS:{std:1},topLevel:{name:null,reference:null},getLocator:(D,b)=>Array.isArray(b)?{name:b[0],reference:b[1]}:{name:D,reference:b},getDependencyTreeRoots:()=>this.opts.project.workspaces.map(D=>{let b=D.anchoredLocator;return{name:G.stringifyIdent(b),reference:b.reference}}),getPackageInformation:D=>{let b=D.reference===null?this.opts.project.topLevelWorkspace.anchoredLocator:G.makeLocator(G.parseIdent(D.name),D.reference),C=this.localStore.get(b.locatorHash);if(typeof C>\"u\")throw new Error(\"Assertion failed: Expected the package reference to have been registered\");return C.pnpNode},findPackageLocator:D=>{let b=this.opts.project.tryWorkspaceByCwd(Ae.toPortablePath(D));if(b!==null){let C=b.anchoredLocator;return{name:G.stringifyIdent(C),reference:C.reference}}throw new Error(\"Assertion failed: Unimplemented\")},resolveToUnqualified:()=>{throw new Error(\"Assertion failed: Unimplemented\")},resolveUnqualified:()=>{throw new Error(\"Assertion failed: Unimplemented\")},resolveRequest:()=>{throw new Error(\"Assertion failed: Unimplemented\")},resolveVirtual:D=>Ae.fromPortablePath(qs.resolveVirtual(Ae.toPortablePath(D)))},{tree:A,errors:p,preserveSymlinksRequired:h}=pv(u,{pnpifyFs:!1,validateExternalSoftLinks:!0,hoistingLimitsByCwd:a,project:this.opts.project,selfReferencesByCwd:n});if(!A){for(let{messageName:D,text:b}of p)this.opts.report.reportError(D,b);return}let E=vj(A);await e1t(r,E,{baseFs:e,project:this.opts.project,report:this.opts.report,realLocatorChecksums:this.realLocatorChecksums,loadManifest:async D=>{let b=G.parseLocator(D),C=this.localStore.get(b.locatorHash);if(typeof C>\"u\")throw new Error(\"Assertion failed: Expected the slot to exist\");return C.customPackageData.manifest}});let w=[];for(let[D,b]of E.entries()){if(Z1e(D))continue;let C=G.parseLocator(D),T=this.localStore.get(C.locatorHash);if(typeof T>\"u\")throw new Error(\"Assertion failed: Expected the slot to exist\");if(this.opts.project.tryWorkspaceByLocator(T.pkg))continue;let N=CA.extractBuildRequest(T.pkg,T.customPackageData,T.dependencyMeta,{configuration:this.opts.project.configuration});N&&w.push({buildLocations:b.locations,locator:C,buildRequest:N})}return h&&this.opts.report.reportWarning(72,`The application uses portals and that's why ${pe.pretty(this.opts.project.configuration,\"--preserve-symlinks\",pe.Type.CODE)} Node option is required for launching it`),{customData:this.customData,records:w}}};async function Vwt(t,e){let r=await _t.tryFind(e.prefixPath,{baseFs:e.packageFs})??new _t,o=new Set([\"preinstall\",\"install\",\"postinstall\"]);for(let a of r.scripts.keys())o.has(a)||r.scripts.delete(a);return{manifest:{bin:r.bin,scripts:r.scripts},misc:{hasBindingGyp:CA.hasBindingGyp(e)}}}async function zwt(t,e,r,o,{installChangedByUser:a}){let n=\"\";n+=`# Warning: This file is automatically generated. Removing it is fine, but will\n`,n+=`# cause your node_modules installation to become invalidated.\n`,n+=`\n`,n+=`__metadata:\n`,n+=`  version: ${V1e}\n`,n+=`  nmMode: ${o.value}\n`;let u=Array.from(e.keys()).sort(),A=G.stringifyLocator(t.topLevelWorkspace.anchoredLocator);for(let E of u){let w=e.get(E);n+=`\n`,n+=`${JSON.stringify(E)}:\n`,n+=`  locations:\n`;for(let D of w.locations){let b=K.contains(t.cwd,D);if(b===null)throw new Error(`Assertion failed: Expected the path to be within the project (${D})`);n+=`    - ${JSON.stringify(b)}\n`}if(w.aliases.length>0){n+=`  aliases:\n`;for(let D of w.aliases)n+=`    - ${JSON.stringify(D)}\n`}if(E===A&&r.size>0){n+=`  bin:\n`;for(let[D,b]of r){let C=K.contains(t.cwd,D);if(C===null)throw new Error(`Assertion failed: Expected the path to be within the project (${D})`);n+=`    ${JSON.stringify(C)}:\n`;for(let[T,N]of b){let U=K.relative(K.join(D,xi),N);n+=`      ${JSON.stringify(T)}: ${JSON.stringify(U)}\n`}}}}let p=t.cwd,h=K.join(p,xi,z1e);a&&await ae.removePromise(h),await ae.changeFilePromise(h,n,{automaticNewlines:!0})}async function zj(t,{unrollAliases:e=!1}={}){let r=t.cwd,o=K.join(r,xi,z1e),a;try{a=await ae.statPromise(o)}catch{}if(!a)return null;let n=Ki(await ae.readFilePromise(o,\"utf8\"));if(n.__metadata.version>V1e)return null;let u=n.__metadata.nmMode||\"classic\",A=new Map,p=new Map;delete n.__metadata;for(let[h,E]of Object.entries(n)){let w=E.locations.map(b=>K.join(r,b)),D=E.bin;if(D)for(let[b,C]of Object.entries(D)){let T=K.join(r,Ae.toPortablePath(b)),N=qe.getMapWithDefault(p,T);for(let[U,z]of Object.entries(C))N.set(U,Ae.toPortablePath([T,xi,z].join(K.sep)))}if(A.set(h,{target:Bt.dot,linkType:\"HARD\",locations:w,aliases:E.aliases||[]}),e&&E.aliases)for(let b of E.aliases){let{scope:C,name:T}=G.parseLocator(h),N=G.makeLocator(G.makeIdent(C,T),b),U=G.stringifyLocator(N);A.set(U,{target:Bt.dot,linkType:\"HARD\",locations:w,aliases:[]})}}return{locatorMap:A,binSymlinks:p,locationTree:J1e(A,{skipPrefix:t.cwd}),nmMode:u,mtimeMs:a.mtimeMs}}var RC=async(t,e)=>{if(t.split(K.sep).indexOf(xi)<0)throw new Error(`Assertion failed: trying to remove dir that doesn't contain node_modules: ${t}`);try{let r;if(!e.innerLoop&&(r=await ae.lstatPromise(t),!r.isDirectory()&&!r.isSymbolicLink()||r.isSymbolicLink()&&!e.isWorkspaceDir)){await ae.unlinkPromise(t);return}let o=await ae.readdirPromise(t,{withFileTypes:!0});for(let n of o){let u=K.join(t,n.name);n.isDirectory()?(n.name!==xi||e&&e.innerLoop)&&await RC(u,{innerLoop:!0,contentsOnly:!1}):await ae.unlinkPromise(u)}let a=!e.innerLoop&&e.isWorkspaceDir&&r?.isSymbolicLink();!e.contentsOnly&&!a&&await ae.rmdirPromise(t)}catch(r){if(r.code!==\"ENOENT\"&&r.code!==\"ENOTEMPTY\")throw r}},G1e=4,eF=(t,{skipPrefix:e})=>{let r=K.contains(e,t);if(r===null)throw new Error(`Assertion failed: Writing attempt prevented to ${t} which is outside project root: ${e}`);let o=r.split(K.sep).filter(p=>p!==\"\"),a=o.indexOf(xi),n=o.slice(0,a).join(K.sep),u=K.join(e,n),A=o.slice(a);return{locationRoot:u,segments:A}},J1e=(t,{skipPrefix:e})=>{let r=new Map;if(t===null)return r;let o=()=>({children:new Map,linkType:\"HARD\"});for(let[a,n]of t.entries()){if(n.linkType===\"SOFT\"&&K.contains(e,n.target)!==null){let A=qe.getFactoryWithDefault(r,n.target,o);A.locator=a,A.linkType=n.linkType}for(let u of n.locations){let{locationRoot:A,segments:p}=eF(u,{skipPrefix:e}),h=qe.getFactoryWithDefault(r,A,o);for(let E=0;E<p.length;++E){let w=p[E];if(w!==\".\"){let D=qe.getFactoryWithDefault(h.children,w,o);h.children.set(w,D),h=D}E===p.length-1&&(h.locator=a,h.linkType=n.linkType)}}}return r},Zj=async(t,e,r)=>{if(process.platform===\"win32\"&&r===\"junctions\"){let o;try{o=await ae.lstatPromise(t)}catch{}if(!o||o.isDirectory()){await ae.symlinkPromise(t,e,\"junction\");return}}await ae.symlinkPromise(K.relative(K.dirname(e),t),e)};async function X1e(t,e,r){let o=K.join(t,`${Jj.default.randomBytes(16).toString(\"hex\")}.tmp`);try{await ae.writeFilePromise(o,r);try{await ae.linkPromise(o,e)}catch{}}finally{await ae.unlinkPromise(o)}}async function Jwt({srcPath:t,dstPath:e,entry:r,globalHardlinksStore:o,baseFs:a,nmMode:n}){if(r.kind===\"file\"){if(n.value===\"hardlinks-global\"&&o&&r.digest){let A=K.join(o,r.digest.substring(0,2),`${r.digest.substring(2)}.dat`),p;try{let h=await ae.statPromise(A);if(h&&(!r.mtimeMs||h.mtimeMs>r.mtimeMs||h.mtimeMs<r.mtimeMs-Kwt))if(await bn.checksumFile(A,{baseFs:ae,algorithm:\"sha1\"})!==r.digest){let w=K.join(o,`${Jj.default.randomBytes(16).toString(\"hex\")}.tmp`);await ae.renamePromise(A,w);let D=await a.readFilePromise(t);await ae.writeFilePromise(w,D);try{await ae.linkPromise(w,A),r.mtimeMs=new Date().getTime(),await ae.unlinkPromise(w)}catch{}}else r.mtimeMs||(r.mtimeMs=Math.ceil(h.mtimeMs));await ae.linkPromise(A,e),p=!0}catch{p=!1}if(!p){let h=await a.readFilePromise(t);await X1e(o,A,h),r.mtimeMs=new Date().getTime();try{await ae.linkPromise(A,e)}catch(E){E&&E.code&&E.code==\"EXDEV\"&&(n.value=\"hardlinks-local\",await a.copyFilePromise(t,e))}}}else await a.copyFilePromise(t,e);let u=r.mode&511;u!==420&&await ae.chmodPromise(e,u)}}var Xwt=async(t,e,{baseFs:r,globalHardlinksStore:o,nmMode:a,windowsLinkType:n,packageChecksum:u})=>{await ae.mkdirPromise(t,{recursive:!0});let A=async(E=Bt.dot)=>{let w=K.join(e,E),D=await r.readdirPromise(w,{withFileTypes:!0}),b=new Map;for(let C of D){let T=K.join(E,C.name),N,U=K.join(w,C.name);if(C.isFile()){if(N={kind:\"file\",mode:(await r.lstatPromise(U)).mode},a.value===\"hardlinks-global\"){let z=await bn.checksumFile(U,{baseFs:r,algorithm:\"sha1\"});N.digest=z}}else if(C.isDirectory())N={kind:\"directory\"};else if(C.isSymbolicLink())N={kind:\"symlink\",symlinkTo:await r.readlinkPromise(U)};else throw new Error(`Unsupported file type (file: ${U}, mode: 0o${await r.statSync(U).mode.toString(8).padStart(6,\"0\")})`);if(b.set(T,N),C.isDirectory()&&T!==xi){let z=await A(T);for(let[te,le]of z)b.set(te,le)}}return b},p;if(a.value===\"hardlinks-global\"&&o&&u){let E=K.join(o,u.substring(0,2),`${u.substring(2)}.json`);try{p=new Map(Object.entries(JSON.parse(await ae.readFilePromise(E,\"utf8\"))))}catch{p=await A()}}else p=await A();let h=!1;for(let[E,w]of p){let D=K.join(e,E),b=K.join(t,E);if(w.kind===\"directory\")await ae.mkdirPromise(b,{recursive:!0});else if(w.kind===\"file\"){let C=w.mtimeMs;await Jwt({srcPath:D,dstPath:b,entry:w,nmMode:a,baseFs:r,globalHardlinksStore:o}),w.mtimeMs!==C&&(h=!0)}else w.kind===\"symlink\"&&await Zj(K.resolve(K.dirname(b),w.symlinkTo),b,n)}if(a.value===\"hardlinks-global\"&&o&&h&&u){let E=K.join(o,u.substring(0,2),`${u.substring(2)}.json`);await ae.removePromise(E),await X1e(o,E,Buffer.from(JSON.stringify(Object.fromEntries(p))))}};function Zwt(t,e,r,o){let a=new Map,n=new Map,u=new Map,A=!1,p=(h,E,w,D,b)=>{let C=!0,T=K.join(h,E),N=new Set;if(E===xi||E.startsWith(\"@\")){let z;try{z=ae.statSync(T)}catch{}C=!!z,z?z.mtimeMs>r?(A=!0,N=new Set(ae.readdirSync(T))):N=new Set(w.children.get(E).children.keys()):A=!0;let te=e.get(h);if(te){let le=K.join(h,xi,$Q),ce;try{ce=ae.statSync(le)}catch{}if(!ce)A=!0;else if(ce.mtimeMs>r){A=!0;let ue=new Set(ae.readdirSync(le)),Ie=new Map;n.set(h,Ie);for(let[he,De]of te)ue.has(he)&&Ie.set(he,De)}else n.set(h,te)}}else C=b.has(E);let U=w.children.get(E);if(C){let{linkType:z,locator:te}=U,le={children:new Map,linkType:z,locator:te};if(D.children.set(E,le),te){let ce=qe.getSetWithDefault(u,te);ce.add(T),u.set(te,ce)}for(let ce of U.children.keys())p(T,ce,U,le,N)}else U.locator&&o.storedBuildState.delete(G.parseLocator(U.locator).locatorHash)};for(let[h,E]of t){let{linkType:w,locator:D}=E,b={children:new Map,linkType:w,locator:D};if(a.set(h,b),D){let C=qe.getSetWithDefault(u,E.locator);C.add(h),u.set(E.locator,C)}E.children.has(xi)&&p(h,xi,E,b,new Set)}return{locationTree:a,binSymlinks:n,locatorLocations:u,installChangedByUser:A}}function Z1e(t){let e=G.parseDescriptor(t);return G.isVirtualDescriptor(e)&&(e=G.devirtualizeDescriptor(e)),e.range.startsWith(\"link:\")}async function $wt(t,e,r,{loadManifest:o}){let a=new Map;for(let[A,{locations:p}]of t){let h=Z1e(A)?null:await o(A,p[0]),E=new Map;if(h)for(let[w,D]of h.bin){let b=K.join(p[0],D);D!==\"\"&&ae.existsSync(b)&&E.set(w,D)}a.set(A,E)}let n=new Map,u=(A,p,h)=>{let E=new Map,w=K.contains(r,A);if(h.locator&&w!==null){let D=a.get(h.locator);for(let[b,C]of D){let T=K.join(A,Ae.toPortablePath(C));E.set(b,T)}for(let[b,C]of h.children){let T=K.join(A,b),N=u(T,T,C);N.size>0&&n.set(A,new Map([...n.get(A)||new Map,...N]))}}else for(let[D,b]of h.children){let C=u(K.join(A,D),p,b);for(let[T,N]of C)E.set(T,N)}return E};for(let[A,p]of e){let h=u(A,A,p);h.size>0&&n.set(A,new Map([...n.get(A)||new Map,...h]))}return n}var W1e=(t,e)=>{if(!t||!e)return t===e;let r=G.parseLocator(t);G.isVirtualLocator(r)&&(r=G.devirtualizeLocator(r));let o=G.parseLocator(e);return G.isVirtualLocator(o)&&(o=G.devirtualizeLocator(o)),G.areLocatorsEqual(r,o)};function $j(t){return K.join(t.get(\"globalFolder\"),\"store\")}async function e1t(t,e,{baseFs:r,project:o,report:a,loadManifest:n,realLocatorChecksums:u}){let A=K.join(o.cwd,xi),{locationTree:p,binSymlinks:h,locatorLocations:E,installChangedByUser:w}=Zwt(t.locationTree,t.binSymlinks,t.mtimeMs,o),D=J1e(e,{skipPrefix:o.cwd}),b=[],C=async({srcDir:De,dstDir:Ee,linkType:g,globalHardlinksStore:me,nmMode:Ce,windowsLinkType:fe,packageChecksum:ie})=>{let Z=(async()=>{try{g===\"SOFT\"?(await ae.mkdirPromise(K.dirname(Ee),{recursive:!0}),await Zj(K.resolve(De),Ee,fe)):await Xwt(Ee,De,{baseFs:r,globalHardlinksStore:me,nmMode:Ce,windowsLinkType:fe,packageChecksum:ie})}catch(Pe){throw Pe.message=`While persisting ${De} -> ${Ee} ${Pe.message}`,Pe}finally{le.tick()}})().then(()=>b.splice(b.indexOf(Z),1));b.push(Z),b.length>G1e&&await Promise.race(b)},T=async(De,Ee,g)=>{let me=(async()=>{let Ce=async(fe,ie,Z)=>{try{Z.innerLoop||await ae.mkdirPromise(ie,{recursive:!0});let Pe=await ae.readdirPromise(fe,{withFileTypes:!0});for(let Re of Pe){if(!Z.innerLoop&&Re.name===$Q)continue;let ht=K.join(fe,Re.name),q=K.join(ie,Re.name);Re.isDirectory()?(Re.name!==xi||Z&&Z.innerLoop)&&(await ae.mkdirPromise(q,{recursive:!0}),await Ce(ht,q,{...Z,innerLoop:!0})):Ie.value===\"hardlinks-local\"||Ie.value===\"hardlinks-global\"?await ae.linkPromise(ht,q):await ae.copyFilePromise(ht,q,K1e.default.constants.COPYFILE_FICLONE)}}catch(Pe){throw Z.innerLoop||(Pe.message=`While cloning ${fe} -> ${ie} ${Pe.message}`),Pe}finally{Z.innerLoop||le.tick()}};await Ce(De,Ee,g)})().then(()=>b.splice(b.indexOf(me),1));b.push(me),b.length>G1e&&await Promise.race(b)},N=async(De,Ee,g)=>{if(g)for(let[me,Ce]of Ee.children){let fe=g.children.get(me);await N(K.join(De,me),Ce,fe)}else{Ee.children.has(xi)&&await RC(K.join(De,xi),{contentsOnly:!1});let me=K.basename(De)===xi&&p.has(K.join(K.dirname(De)));await RC(De,{contentsOnly:De===A,isWorkspaceDir:me})}};for(let[De,Ee]of p){let g=D.get(De);for(let[me,Ce]of Ee.children){if(me===\".\")continue;let fe=g&&g.children.get(me),ie=K.join(De,me);await N(ie,Ce,fe)}}let U=async(De,Ee,g)=>{if(g){W1e(Ee.locator,g.locator)||await RC(De,{contentsOnly:Ee.linkType===\"HARD\"});for(let[me,Ce]of Ee.children){let fe=g.children.get(me);await U(K.join(De,me),Ce,fe)}}else{Ee.children.has(xi)&&await RC(K.join(De,xi),{contentsOnly:!0});let me=K.basename(De)===xi&&D.has(K.join(K.dirname(De)));await RC(De,{contentsOnly:Ee.linkType===\"HARD\",isWorkspaceDir:me})}};for(let[De,Ee]of D){let g=p.get(De);for(let[me,Ce]of Ee.children){if(me===\".\")continue;let fe=g&&g.children.get(me);await U(K.join(De,me),Ce,fe)}}let z=new Map,te=[];for(let[De,Ee]of E)for(let g of Ee){let{locationRoot:me,segments:Ce}=eF(g,{skipPrefix:o.cwd}),fe=D.get(me),ie=me;if(fe){for(let Z of Ce)if(ie=K.join(ie,Z),fe=fe.children.get(Z),!fe)break;if(fe){let Z=W1e(fe.locator,De),Pe=e.get(fe.locator),Re=Pe.target,ht=ie,q=Pe.linkType;if(Z)z.has(Re)||z.set(Re,ht);else if(Re!==ht){let nt=G.parseLocator(fe.locator);G.isVirtualLocator(nt)&&(nt=G.devirtualizeLocator(nt)),te.push({srcDir:Re,dstDir:ht,linkType:q,realLocatorHash:nt.locatorHash})}}}}for(let[De,{locations:Ee}]of e.entries())for(let g of Ee){let{locationRoot:me,segments:Ce}=eF(g,{skipPrefix:o.cwd}),fe=p.get(me),ie=D.get(me),Z=me,Pe=e.get(De),Re=G.parseLocator(De);G.isVirtualLocator(Re)&&(Re=G.devirtualizeLocator(Re));let ht=Re.locatorHash,q=Pe.target,nt=g;if(q===nt)continue;let Le=Pe.linkType;for(let Te of Ce)ie=ie.children.get(Te);if(!fe)te.push({srcDir:q,dstDir:nt,linkType:Le,realLocatorHash:ht});else for(let Te of Ce)if(Z=K.join(Z,Te),fe=fe.children.get(Te),!fe){te.push({srcDir:q,dstDir:nt,linkType:Le,realLocatorHash:ht});break}}let le=Ws.progressViaCounter(te.length),ce=a.reportProgress(le),ue=o.configuration.get(\"nmMode\"),Ie={value:ue},he=o.configuration.get(\"winLinkType\");try{let De=Ie.value===\"hardlinks-global\"?`${$j(o.configuration)}/v1`:null;if(De&&!await ae.existsPromise(De)){await ae.mkdirpPromise(De);for(let g=0;g<256;g++)await ae.mkdirPromise(K.join(De,g.toString(16).padStart(2,\"0\")))}for(let g of te)(g.linkType===\"SOFT\"||!z.has(g.srcDir))&&(z.set(g.srcDir,g.dstDir),await C({...g,globalHardlinksStore:De,nmMode:Ie,windowsLinkType:he,packageChecksum:u.get(g.realLocatorHash)||null}));await Promise.all(b),b.length=0;for(let g of te){let me=z.get(g.srcDir);g.linkType!==\"SOFT\"&&g.dstDir!==me&&await T(me,g.dstDir,{nmMode:Ie})}await Promise.all(b),await ae.mkdirPromise(A,{recursive:!0});let Ee=await $wt(e,D,o.cwd,{loadManifest:n});await t1t(h,Ee,o.cwd,he),await zwt(o,e,Ee,Ie,{installChangedByUser:w}),ue==\"hardlinks-global\"&&Ie.value==\"hardlinks-local\"&&a.reportWarningOnce(74,\"'nmMode' has been downgraded to 'hardlinks-local' due to global cache and install folder being on different devices\")}finally{ce.stop()}}async function t1t(t,e,r,o){for(let a of t.keys()){if(K.contains(r,a)===null)throw new Error(`Assertion failed. Excepted bin symlink location to be inside project dir, instead it was at ${a}`);if(!e.has(a)){let n=K.join(a,xi,$Q);await ae.removePromise(n)}}for(let[a,n]of e){if(K.contains(r,a)===null)throw new Error(`Assertion failed. Excepted bin symlink location to be inside project dir, instead it was at ${a}`);let u=K.join(a,xi,$Q),A=t.get(a)||new Map;await ae.mkdirPromise(u,{recursive:!0});for(let p of A.keys())n.has(p)||(await ae.removePromise(K.join(u,p)),process.platform===\"win32\"&&await ae.removePromise(K.join(u,`${p}.cmd`)));for(let[p,h]of n){let E=A.get(p),w=K.join(u,p);E!==h&&(process.platform===\"win32\"?await(0,Y1e.default)(Ae.fromPortablePath(h),Ae.fromPortablePath(w),{createPwshFile:!1}):(await ae.removePromise(w),await Zj(h,w,o),K.contains(r,await ae.realpathPromise(h))!==null&&await ae.chmodPromise(h,493)))}}}Ke();Pt();sA();var Pv=class extends Yh{constructor(){super(...arguments);this.mode=\"loose\"}makeInstaller(r){return new e9(r)}},e9=class extends pd{constructor(){super(...arguments);this.mode=\"loose\"}async transformPnpSettings(r){let o=new qs({baseFs:new iA({maxOpenFiles:80,readOnlyArchives:!0})}),a=F1e(r,this.opts.project.cwd,o),{tree:n,errors:u}=pv(a,{pnpifyFs:!1,project:this.opts.project});if(!n){for(let{messageName:w,text:D}of u)this.opts.report.reportError(w,D);return}let A=new Map;r.fallbackPool=A;let p=(w,D)=>{let b=G.parseLocator(D.locator),C=G.stringifyIdent(b);C===w?A.set(w,b.reference):A.set(w,[C,b.reference])},h=K.join(this.opts.project.cwd,mr.nodeModules),E=n.get(h);if(!(typeof E>\"u\")){if(\"target\"in E)throw new Error(\"Assertion failed: Expected the root junction point to be a directory\");for(let w of E.dirList){let D=K.join(h,w),b=n.get(D);if(typeof b>\"u\")throw new Error(\"Assertion failed: Expected the child to have been registered\");if(\"target\"in b)p(w,b);else for(let C of b.dirList){let T=K.join(D,C),N=n.get(T);if(typeof N>\"u\")throw new Error(\"Assertion failed: Expected the subchild to have been registered\");if(\"target\"in N)p(`${w}/${C}`,N);else throw new Error(\"Assertion failed: Expected the leaf junction to be a package\")}}}}};var r1t={hooks:{cleanGlobalArtifacts:async t=>{let e=$j(t);await ae.removePromise(e)}},configuration:{nmHoistingLimits:{description:\"Prevents packages to be hoisted past specific levels\",type:\"STRING\",values:[\"workspaces\",\"dependencies\",\"none\"],default:\"none\"},nmMode:{description:\"Defines in which measure Yarn must use hardlinks and symlinks when generated `node_modules` directories.\",type:\"STRING\",values:[\"classic\",\"hardlinks-local\",\"hardlinks-global\"],default:\"classic\"},nmSelfReferences:{description:\"Defines whether the linker should generate self-referencing symlinks for workspaces.\",type:\"BOOLEAN\",default:!0}},linkers:[Dv,Pv]},n1t=r1t;var $9={};Kt($9,{NpmHttpFetcher:()=>bv,NpmRemapResolver:()=>kv,NpmSemverFetcher:()=>rp,NpmSemverResolver:()=>Qv,NpmTagResolver:()=>Fv,default:()=>yvt,npmConfigUtils:()=>si,npmHttpUtils:()=>en,npmPublishUtils:()=>VC});Ke();var o2e=et(ni());var Zn=\"npm:\";var en={};Kt(en,{AuthType:()=>n2e,customPackageError:()=>hd,del:()=>g1t,get:()=>gd,getIdentUrl:()=>tF,getPackageMetadata:()=>NC,handleInvalidAuthenticationError:()=>Vh,post:()=>p1t,put:()=>h1t});Ke();Ke();Pt();var i9=et(Q2()),t2e=et(c8()),r2e=et(ni());var si={};Kt(si,{RegistryType:()=>$1e,getAuditRegistry:()=>i1t,getAuthConfiguration:()=>n9,getDefaultRegistry:()=>Sv,getPublishRegistry:()=>s1t,getRegistryConfiguration:()=>e2e,getScopeConfiguration:()=>r9,getScopeRegistry:()=>TC,normalizeRegistry:()=>uc});var $1e=(o=>(o.AUDIT_REGISTRY=\"npmAuditRegistry\",o.FETCH_REGISTRY=\"npmRegistryServer\",o.PUBLISH_REGISTRY=\"npmPublishRegistry\",o))($1e||{});function uc(t){return t.replace(/\\/$/,\"\")}function i1t({configuration:t}){return Sv({configuration:t,type:\"npmAuditRegistry\"})}function s1t(t,{configuration:e}){return t.publishConfig?.registry?uc(t.publishConfig.registry):t.name?TC(t.name.scope,{configuration:e,type:\"npmPublishRegistry\"}):Sv({configuration:e,type:\"npmPublishRegistry\"})}function TC(t,{configuration:e,type:r=\"npmRegistryServer\"}){let o=r9(t,{configuration:e});if(o===null)return Sv({configuration:e,type:r});let a=o.get(r);return a===null?Sv({configuration:e,type:r}):uc(a)}function Sv({configuration:t,type:e=\"npmRegistryServer\"}){let r=t.get(e);return uc(r!==null?r:t.get(\"npmRegistryServer\"))}function e2e(t,{configuration:e}){let r=e.get(\"npmRegistries\"),o=uc(t),a=r.get(o);if(typeof a<\"u\")return a;let n=r.get(o.replace(/^[a-z]+:/,\"\"));return typeof n<\"u\"?n:null}function r9(t,{configuration:e}){if(t===null)return null;let o=e.get(\"npmScopes\").get(t);return o||null}function n9(t,{configuration:e,ident:r}){let o=r&&r9(r.scope,{configuration:e});return o?.get(\"npmAuthIdent\")||o?.get(\"npmAuthToken\")?o:e2e(t,{configuration:e})||e}var n2e=(a=>(a[a.NO_AUTH=0]=\"NO_AUTH\",a[a.BEST_EFFORT=1]=\"BEST_EFFORT\",a[a.CONFIGURATION=2]=\"CONFIGURATION\",a[a.ALWAYS_AUTH=3]=\"ALWAYS_AUTH\",a))(n2e||{});async function Vh(t,{attemptedAs:e,registry:r,headers:o,configuration:a}){if(nF(t))throw new zt(41,\"Invalid OTP token\");if(t.originalError?.name===\"HTTPError\"&&t.originalError?.response.statusCode===401)throw new zt(41,`Invalid authentication (${typeof e!=\"string\"?`as ${await m1t(r,o,{configuration:a})}`:`attempted as ${e}`})`)}function hd(t,e){let r=t.response?.statusCode;return r?r===404?\"Package not found\":r>=500&&r<600?`The registry appears to be down (using a ${pe.applyHyperlink(e,\"local cache\",\"https://yarnpkg.com/advanced/lexicon#local-cache\")} might have protected you against such outages)`:null:null}function tF(t){return t.scope?`/@${t.scope}%2f${t.name}`:`/${t.name}`}var i2e=new Map,o1t=new Map;async function a1t(t){return await qe.getFactoryWithDefault(i2e,t,async()=>{let e=null;try{e=await ae.readJsonPromise(t)}catch{}return e})}async function l1t(t,e,{configuration:r,cached:o,registry:a,headers:n,version:u,...A}){return await qe.getFactoryWithDefault(o1t,t,async()=>await gd(tF(e),{...A,customErrorMessage:hd,configuration:r,registry:a,ident:e,headers:{...n,\"If-None-Match\":o?.etag,\"If-Modified-Since\":o?.lastModified},wrapNetworkRequest:async p=>async()=>{let h=await p();if(h.statusCode===304){if(o===null)throw new Error(\"Assertion failed: cachedMetadata should not be null\");return{...h,body:o.metadata}}let E=c1t(JSON.parse(h.body.toString())),w={metadata:E,etag:h.headers.etag,lastModified:h.headers[\"last-modified\"]};return i2e.set(t,Promise.resolve(w)),Promise.resolve().then(async()=>{let D=`${t}-${process.pid}.tmp`;await ae.mkdirPromise(K.dirname(D),{recursive:!0}),await ae.writeJsonPromise(D,w,{compact:!0}),await ae.renamePromise(D,t)}).catch(()=>{}),{...h,body:E}}}))}async function NC(t,{cache:e,project:r,registry:o,headers:a,version:n,...u}){let{configuration:A}=r;o=xv(A,{ident:t,registry:o});let p=A1t(A,o),h=K.join(p,`${G.slugifyIdent(t)}.json`),E=null;if(!r.lockfileNeedsRefresh&&(E=await a1t(h),E)){if(typeof n<\"u\"&&typeof E.metadata.versions[n]<\"u\")return E.metadata;if(A.get(\"enableOfflineMode\")){let w=structuredClone(E.metadata),D=new Set;if(e){for(let C of Object.keys(w.versions)){let T=G.makeLocator(t,`npm:${C}`),N=e.getLocatorMirrorPath(T);(!N||!ae.existsSync(N))&&(delete w.versions[C],D.add(C))}let b=w[\"dist-tags\"].latest;if(D.has(b)){let C=Object.keys(E.metadata.versions).sort(r2e.default.compare),T=C.indexOf(b);for(;D.has(C[T])&&T>=0;)T-=1;T>=0?w[\"dist-tags\"].latest=C[T]:delete w[\"dist-tags\"].latest}}return w}}return await l1t(h,t,{...u,configuration:A,cached:E,registry:o,headers:a,version:n})}var s2e=[\"name\",\"dist.tarball\",\"bin\",\"scripts\",\"os\",\"cpu\",\"libc\",\"dependencies\",\"dependenciesMeta\",\"optionalDependencies\",\"peerDependencies\",\"peerDependenciesMeta\",\"deprecated\"];function c1t(t){return{\"dist-tags\":t[\"dist-tags\"],versions:Object.fromEntries(Object.entries(t.versions).map(([e,r])=>[e,(0,t2e.default)(r,s2e)]))}}var u1t=bn.makeHash(...s2e).slice(0,6);function A1t(t,e){let r=f1t(t),o=new URL(e);return K.join(r,u1t,o.hostname)}function f1t(t){return K.join(t.get(\"globalFolder\"),\"metadata/npm\")}async function gd(t,{configuration:e,headers:r,ident:o,authType:a,registry:n,...u}){n=xv(e,{ident:o,registry:n}),o&&o.scope&&typeof a>\"u\"&&(a=1);let A=await rF(n,{authType:a,configuration:e,ident:o});A&&(r={...r,authorization:A});try{return await on.get(t.charAt(0)===\"/\"?`${n}${t}`:t,{configuration:e,headers:r,...u})}catch(p){throw await Vh(p,{registry:n,configuration:e,headers:r}),p}}async function p1t(t,e,{attemptedAs:r,configuration:o,headers:a,ident:n,authType:u=3,registry:A,otp:p,...h}){A=xv(o,{ident:n,registry:A});let E=await rF(A,{authType:u,configuration:o,ident:n});E&&(a={...a,authorization:E}),p&&(a={...a,...LC(p)});try{return await on.post(A+t,e,{configuration:o,headers:a,...h})}catch(w){if(!nF(w)||p)throw await Vh(w,{attemptedAs:r,registry:A,configuration:o,headers:a}),w;p=await s9(w,{configuration:o});let D={...a,...LC(p)};try{return await on.post(`${A}${t}`,e,{configuration:o,headers:D,...h})}catch(b){throw await Vh(b,{attemptedAs:r,registry:A,configuration:o,headers:a}),b}}}async function h1t(t,e,{attemptedAs:r,configuration:o,headers:a,ident:n,authType:u=3,registry:A,otp:p,...h}){A=xv(o,{ident:n,registry:A});let E=await rF(A,{authType:u,configuration:o,ident:n});E&&(a={...a,authorization:E}),p&&(a={...a,...LC(p)});try{return await on.put(A+t,e,{configuration:o,headers:a,...h})}catch(w){if(!nF(w))throw await Vh(w,{attemptedAs:r,registry:A,configuration:o,headers:a}),w;p=await s9(w,{configuration:o});let D={...a,...LC(p)};try{return await on.put(`${A}${t}`,e,{configuration:o,headers:D,...h})}catch(b){throw await Vh(b,{attemptedAs:r,registry:A,configuration:o,headers:a}),b}}}async function g1t(t,{attemptedAs:e,configuration:r,headers:o,ident:a,authType:n=3,registry:u,otp:A,...p}){u=xv(r,{ident:a,registry:u});let h=await rF(u,{authType:n,configuration:r,ident:a});h&&(o={...o,authorization:h}),A&&(o={...o,...LC(A)});try{return await on.del(u+t,{configuration:r,headers:o,...p})}catch(E){if(!nF(E)||A)throw await Vh(E,{attemptedAs:e,registry:u,configuration:r,headers:o}),E;A=await s9(E,{configuration:r});let w={...o,...LC(A)};try{return await on.del(`${u}${t}`,{configuration:r,headers:w,...p})}catch(D){throw await Vh(D,{attemptedAs:e,registry:u,configuration:r,headers:o}),D}}}function xv(t,{ident:e,registry:r}){if(typeof r>\"u\"&&e)return TC(e.scope,{configuration:t});if(typeof r!=\"string\")throw new Error(\"Assertion failed: The registry should be a string\");return uc(r)}async function rF(t,{authType:e=2,configuration:r,ident:o}){let a=n9(t,{configuration:r,ident:o}),n=d1t(a,e);if(!n)return null;let u=await r.reduceHook(A=>A.getNpmAuthenticationHeader,void 0,t,{configuration:r,ident:o});if(u)return u;if(a.get(\"npmAuthToken\"))return`Bearer ${a.get(\"npmAuthToken\")}`;if(a.get(\"npmAuthIdent\")){let A=a.get(\"npmAuthIdent\");return A.includes(\":\")?`Basic ${Buffer.from(A).toString(\"base64\")}`:`Basic ${A}`}if(n&&e!==1)throw new zt(33,\"No authentication configured for request\");return null}function d1t(t,e){switch(e){case 2:return t.get(\"npmAlwaysAuth\");case 1:case 3:return!0;case 0:return!1;default:throw new Error(\"Unreachable\")}}async function m1t(t,e,{configuration:r}){if(typeof e>\"u\"||typeof e.authorization>\"u\")return\"an anonymous user\";try{return(await on.get(new URL(`${t}/-/whoami`).href,{configuration:r,headers:e,jsonResponse:!0})).username??\"an unknown user\"}catch{return\"an unknown user\"}}async function s9(t,{configuration:e}){let r=t.originalError?.response.headers[\"npm-notice\"];if(r&&(await Lt.start({configuration:e,stdout:process.stdout,includeFooter:!1},async a=>{if(a.reportInfo(0,r.replace(/(https?:\\/\\/\\S+)/g,pe.pretty(e,\"$1\",pe.Type.URL))),!process.env.YARN_IS_TEST_ENV){let n=r.match(/open (https?:\\/\\/\\S+)/i);if(n&&Xi.openUrl){let{openNow:u}=await(0,i9.prompt)({type:\"confirm\",name:\"openNow\",message:\"Do you want to try to open this url now?\",required:!0,initial:!0,onCancel:()=>process.exit(130)});u&&(await Xi.openUrl(n[1])||(a.reportSeparator(),a.reportWarning(0,\"We failed to automatically open the url; you'll have to open it yourself in your browser of choice.\")))}}}),process.stdout.write(`\n`)),process.env.YARN_IS_TEST_ENV)return process.env.YARN_INJECT_NPM_2FA_TOKEN||\"\";let{otp:o}=await(0,i9.prompt)({type:\"password\",name:\"otp\",message:\"One-time password:\",required:!0,onCancel:()=>process.exit(130)});return process.stdout.write(`\n`),o}function nF(t){if(t.originalError?.name!==\"HTTPError\")return!1;try{return(t.originalError?.response.headers[\"www-authenticate\"].split(/,\\s*/).map(r=>r.toLowerCase())).includes(\"otp\")}catch{return!1}}function LC(t){return{\"npm-otp\":t}}var bv=class{supports(e,r){if(!e.reference.startsWith(Zn))return!1;let{selector:o,params:a}=G.parseRange(e.reference);return!(!o2e.default.valid(o)||a===null||typeof a.__archiveUrl!=\"string\")}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the remote server`),loader:()=>this.fetchFromNetwork(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),checksum:u}}async fetchFromNetwork(e,r){let{params:o}=G.parseRange(e.reference);if(o===null||typeof o.__archiveUrl!=\"string\")throw new Error(\"Assertion failed: The archiveUrl querystring parameter should have been available\");let a=await gd(o.__archiveUrl,{customErrorMessage:hd,configuration:r.project.configuration,ident:e});return await $i.convertToZip(a,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1})}};Ke();var kv=class{supportsDescriptor(e,r){return!(!e.range.startsWith(Zn)||!G.tryParseDescriptor(e.range.slice(Zn.length),!0))}supportsLocator(e,r){return!1}shouldPersistResolution(e,r){throw new Error(\"Unreachable\")}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){let o=r.project.configuration.normalizeDependency(G.parseDescriptor(e.range.slice(Zn.length),!0));return r.resolver.getResolutionDependencies(o,r)}async getCandidates(e,r,o){let a=o.project.configuration.normalizeDependency(G.parseDescriptor(e.range.slice(Zn.length),!0));return await o.resolver.getCandidates(a,r,o)}async getSatisfying(e,r,o,a){let n=a.project.configuration.normalizeDependency(G.parseDescriptor(e.range.slice(Zn.length),!0));return a.resolver.getSatisfying(n,r,o,a)}resolve(e,r){throw new Error(\"Unreachable\")}};Ke();Ke();var a2e=et(ni());var rp=class t{supports(e,r){if(!e.reference.startsWith(Zn))return!1;let o=new URL(e.reference);return!(!a2e.default.valid(o.pathname)||o.searchParams.has(\"__archiveUrl\"))}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the remote registry`),loader:()=>this.fetchFromNetwork(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),checksum:u}}async fetchFromNetwork(e,r){let o;try{o=await gd(t.getLocatorUrl(e),{customErrorMessage:hd,configuration:r.project.configuration,ident:e})}catch{o=await gd(t.getLocatorUrl(e).replace(/%2f/g,\"/\"),{customErrorMessage:hd,configuration:r.project.configuration,ident:e})}return await $i.convertToZip(o,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1})}static isConventionalTarballUrl(e,r,{configuration:o}){let a=TC(e.scope,{configuration:o}),n=t.getLocatorUrl(e);return r=r.replace(/^https?:(\\/\\/(?:[^/]+\\.)?npmjs.org(?:$|\\/))/,\"https:$1\"),a=a.replace(/^https:\\/\\/registry\\.npmjs\\.org($|\\/)/,\"https://registry.yarnpkg.com$1\"),r=r.replace(/^https:\\/\\/registry\\.npmjs\\.org($|\\/)/,\"https://registry.yarnpkg.com$1\"),r===a+n||r===a+n.replace(/%2f/g,\"/\")}static getLocatorUrl(e){let r=Ur.clean(e.reference.slice(Zn.length));if(r===null)throw new zt(10,\"The npm semver resolver got selected, but the version isn't semver\");return`${tF(e)}/-/${e.name}-${r}.tgz`}};Ke();Ke();Ke();var o9=et(ni());var iF=G.makeIdent(null,\"node-gyp\"),y1t=/\\b(node-gyp|prebuild-install)\\b/,Qv=class{supportsDescriptor(e,r){return e.range.startsWith(Zn)?!!Ur.validRange(e.range.slice(Zn.length)):!1}supportsLocator(e,r){if(!e.reference.startsWith(Zn))return!1;let{selector:o}=G.parseRange(e.reference);return!!o9.default.valid(o)}shouldPersistResolution(e,r){return!0}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){let a=Ur.validRange(e.range.slice(Zn.length));if(a===null)throw new Error(`Expected a valid range, got ${e.range.slice(Zn.length)}`);let n=await NC(e,{cache:o.fetchOptions?.cache,project:o.project,version:o9.default.valid(a.raw)?a.raw:void 0}),u=qe.mapAndFilter(Object.keys(n.versions),h=>{try{let E=new Ur.SemVer(h);if(a.test(E))return E}catch{}return qe.mapAndFilter.skip}),A=u.filter(h=>!n.versions[h.raw].deprecated),p=A.length>0?A:u;return p.sort((h,E)=>-h.compare(E)),p.map(h=>{let E=G.makeLocator(e,`${Zn}${h.raw}`),w=n.versions[h.raw].dist.tarball;return rp.isConventionalTarballUrl(E,w,{configuration:o.project.configuration})?E:G.bindLocator(E,{__archiveUrl:w})})}async getSatisfying(e,r,o,a){let n=Ur.validRange(e.range.slice(Zn.length));if(n===null)throw new Error(`Expected a valid range, got ${e.range.slice(Zn.length)}`);return{locators:qe.mapAndFilter(o,p=>{if(p.identHash!==e.identHash)return qe.mapAndFilter.skip;let h=G.tryParseRange(p.reference,{requireProtocol:Zn});if(!h)return qe.mapAndFilter.skip;let E=new Ur.SemVer(h.selector);return n.test(E)?{locator:p,version:E}:qe.mapAndFilter.skip}).sort((p,h)=>-p.version.compare(h.version)).map(({locator:p})=>p),sorted:!0}}async resolve(e,r){let{selector:o}=G.parseRange(e.reference),a=Ur.clean(o);if(a===null)throw new zt(10,\"The npm semver resolver got selected, but the version isn't semver\");let n=await NC(e,{cache:r.fetchOptions?.cache,project:r.project,version:a});if(!Object.hasOwn(n,\"versions\"))throw new zt(15,'Registry returned invalid data for - missing \"versions\" field');if(!Object.hasOwn(n.versions,a))throw new zt(16,`Registry failed to return reference \"${a}\"`);let u=new _t;if(u.load(n.versions[a]),!u.dependencies.has(iF.identHash)&&!u.peerDependencies.has(iF.identHash)){for(let A of u.scripts.values())if(A.match(y1t)){u.dependencies.set(iF.identHash,G.makeDescriptor(iF,\"latest\"));break}}return{...e,version:a,languageName:\"node\",linkType:\"HARD\",conditions:u.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(u.dependencies),peerDependencies:u.peerDependencies,dependenciesMeta:u.dependenciesMeta,peerDependenciesMeta:u.peerDependenciesMeta,bin:u.bin}}};Ke();Ke();var l2e=et(ni());var Fv=class{supportsDescriptor(e,r){return!(!e.range.startsWith(Zn)||!by.test(e.range.slice(Zn.length)))}supportsLocator(e,r){return!1}shouldPersistResolution(e,r){throw new Error(\"Unreachable\")}bindDescriptor(e,r,o){return e}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,o){let a=e.range.slice(Zn.length),n=await NC(e,{cache:o.fetchOptions?.cache,project:o.project});if(!Object.hasOwn(n,\"dist-tags\"))throw new zt(15,'Registry returned invalid data - missing \"dist-tags\" field');let u=n[\"dist-tags\"];if(!Object.hasOwn(u,a))throw new zt(16,`Registry failed to return tag \"${a}\"`);let A=u[a],p=G.makeLocator(e,`${Zn}${A}`),h=n.versions[A].dist.tarball;return rp.isConventionalTarballUrl(p,h,{configuration:o.project.configuration})?[p]:[G.bindLocator(p,{__archiveUrl:h})]}async getSatisfying(e,r,o,a){let n=[];for(let u of o){if(u.identHash!==e.identHash)continue;let A=G.tryParseRange(u.reference,{requireProtocol:Zn});if(!(!A||!l2e.default.valid(A.selector))){if(A.params?.__archiveUrl){let p=G.makeRange({protocol:Zn,selector:A.selector,source:null,params:null}),[h]=await a.resolver.getCandidates(G.makeDescriptor(e,p),r,a);if(u.reference!==h.reference)continue}n.push(u)}}return{locators:n,sorted:!1}}async resolve(e,r){throw new Error(\"Unreachable\")}};var VC={};Kt(VC,{getGitHead:()=>dvt,getPublishAccess:()=>XBe,getReadmeContent:()=>ZBe,makePublishBody:()=>gvt});Ke();Ke();Pt();var V9={};Kt(V9,{PackCommand:()=>KC,default:()=>XBt,packUtils:()=>BA});Ke();Ke();Ke();Pt();Gt();var BA={};Kt(BA,{genPackList:()=>SF,genPackStream:()=>K9,genPackageManifest:()=>UBe,hasPackScripts:()=>W9,prepareForPack:()=>Y9});Ke();Pt();var G9=et(Xo()),OBe=et(RBe()),MBe=ve(\"zlib\"),_Bt=[\"/package.json\",\"/readme\",\"/readme.*\",\"/license\",\"/license.*\",\"/licence\",\"/licence.*\",\"/changelog\",\"/changelog.*\"],HBt=[\"/package.tgz\",\".github\",\".git\",\".hg\",\"node_modules\",\".npmignore\",\".gitignore\",\".#*\",\".DS_Store\"];async function W9(t){return!!(hn.hasWorkspaceScript(t,\"prepack\")||hn.hasWorkspaceScript(t,\"postpack\"))}async function Y9(t,{report:e},r){await hn.maybeExecuteWorkspaceLifecycleScript(t,\"prepack\",{report:e});try{let o=K.join(t.cwd,_t.fileName);await ae.existsPromise(o)&&await t.manifest.loadFile(o,{baseFs:ae}),await r()}finally{await hn.maybeExecuteWorkspaceLifecycleScript(t,\"postpack\",{report:e})}}async function K9(t,e){typeof e>\"u\"&&(e=await SF(t));let r=new Set;for(let n of t.manifest.publishConfig?.executableFiles??new Set)r.add(K.normalize(n));for(let n of t.manifest.bin.values())r.add(K.normalize(n));let o=OBe.default.pack();process.nextTick(async()=>{for(let n of e){let u=K.normalize(n),A=K.resolve(t.cwd,u),p=K.join(\"package\",u),h=await ae.lstatPromise(A),E={name:p,mtime:new Date(Pi.SAFE_TIME*1e3)},w=r.has(u)?493:420,D,b,C=new Promise((N,U)=>{D=N,b=U}),T=N=>{N?b(N):D()};if(h.isFile()){let N;u===\"package.json\"?N=Buffer.from(JSON.stringify(await UBe(t),null,2)):N=await ae.readFilePromise(A),o.entry({...E,mode:w,type:\"file\"},N,T)}else h.isSymbolicLink()?o.entry({...E,mode:w,type:\"symlink\",linkname:await ae.readlinkPromise(A)},T):T(new Error(`Unsupported file type ${h.mode} for ${Ae.fromPortablePath(u)}`));await C}o.finalize()});let a=(0,MBe.createGzip)();return o.pipe(a),a}async function UBe(t){let e=JSON.parse(JSON.stringify(t.manifest.raw));return await t.project.configuration.triggerHook(r=>r.beforeWorkspacePacking,t,e),e}async function SF(t){let e=t.project,r=e.configuration,o={accept:[],reject:[]};for(let w of HBt)o.reject.push(w);for(let w of _Bt)o.accept.push(w);o.reject.push(r.get(\"rcFilename\"));let a=w=>{if(w===null||!w.startsWith(`${t.cwd}/`))return;let D=K.relative(t.cwd,w),b=K.resolve(Bt.root,D);o.reject.push(b)};a(K.resolve(e.cwd,mr.lockfile)),a(r.get(\"cacheFolder\")),a(r.get(\"globalFolder\")),a(r.get(\"installStatePath\")),a(r.get(\"virtualFolder\")),a(r.get(\"yarnPath\")),await r.triggerHook(w=>w.populateYarnPaths,e,w=>{a(w)});for(let w of e.workspaces){let D=K.relative(t.cwd,w.cwd);D!==\"\"&&!D.match(/^(\\.\\.)?\\//)&&o.reject.push(`/${D}`)}let n={accept:[],reject:[]},u=t.manifest.publishConfig?.main??t.manifest.main,A=t.manifest.publishConfig?.module??t.manifest.module,p=t.manifest.publishConfig?.browser??t.manifest.browser,h=t.manifest.publishConfig?.bin??t.manifest.bin;u!=null&&n.accept.push(K.resolve(Bt.root,u)),A!=null&&n.accept.push(K.resolve(Bt.root,A)),typeof p==\"string\"&&n.accept.push(K.resolve(Bt.root,p));for(let w of h.values())n.accept.push(K.resolve(Bt.root,w));if(p instanceof Map)for(let[w,D]of p.entries())n.accept.push(K.resolve(Bt.root,w)),typeof D==\"string\"&&n.accept.push(K.resolve(Bt.root,D));let E=t.manifest.files!==null;if(E){n.reject.push(\"/*\");for(let w of t.manifest.files)_Be(n.accept,w,{cwd:Bt.root})}return await qBt(t.cwd,{hasExplicitFileList:E,globalList:o,ignoreList:n})}async function qBt(t,{hasExplicitFileList:e,globalList:r,ignoreList:o}){let a=[],n=new Gu(t),u=[[Bt.root,[o]]];for(;u.length>0;){let[A,p]=u.pop(),h=await n.lstatPromise(A);if(!LBe(A,{globalList:r,ignoreLists:h.isDirectory()?null:p}))if(h.isDirectory()){let E=await n.readdirPromise(A),w=!1,D=!1;if(!e||A!==Bt.root)for(let T of E)w=w||T===\".gitignore\",D=D||T===\".npmignore\";let b=D?await TBe(n,A,\".npmignore\"):w?await TBe(n,A,\".gitignore\"):null,C=b!==null?[b].concat(p):p;LBe(A,{globalList:r,ignoreLists:p})&&(C=[...p,{accept:[],reject:[\"**/*\"]}]);for(let T of E)u.push([K.resolve(A,T),C])}else(h.isFile()||h.isSymbolicLink())&&a.push(K.relative(Bt.root,A))}return a.sort()}async function TBe(t,e,r){let o={accept:[],reject:[]},a=await t.readFilePromise(K.join(e,r),\"utf8\");for(let n of a.split(/\\n/g))_Be(o.reject,n,{cwd:e});return o}function jBt(t,{cwd:e}){let r=t[0]===\"!\";return r&&(t=t.slice(1)),t.match(/\\.{0,1}\\//)&&(t=K.resolve(e,t)),r&&(t=`!${t}`),t}function _Be(t,e,{cwd:r}){let o=e.trim();o===\"\"||o[0]===\"#\"||t.push(jBt(o,{cwd:r}))}function LBe(t,{globalList:e,ignoreLists:r}){let o=PF(t,e.accept);if(o!==0)return o===2;let a=PF(t,e.reject);if(a!==0)return a===1;if(r!==null)for(let n of r){let u=PF(t,n.accept);if(u!==0)return u===2;let A=PF(t,n.reject);if(A!==0)return A===1}return!1}function PF(t,e){let r=e,o=[];for(let a=0;a<e.length;++a)e[a][0]!==\"!\"?r!==e&&r.push(e[a]):(r===e&&(r=e.slice(0,a)),o.push(e[a].slice(1)));return NBe(t,o)?2:NBe(t,r)?1:0}function NBe(t,e){let r=e,o=[];for(let a=0;a<e.length;++a)e[a].includes(\"/\")?r!==e&&r.push(e[a]):(r===e&&(r=e.slice(0,a)),o.push(e[a]));return!!(G9.default.isMatch(t,r,{dot:!0,nocase:!0})||G9.default.isMatch(t,o,{dot:!0,basename:!0,nocase:!0}))}var KC=class extends ut{constructor(){super(...arguments);this.installIfNeeded=de.Boolean(\"--install-if-needed\",!1,{description:\"Run a preliminary `yarn install` if the package contains build scripts\"});this.dryRun=de.Boolean(\"-n,--dry-run\",!1,{description:\"Print the file paths without actually generating the package archive\"});this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.out=de.String(\"-o,--out\",{description:\"Create the archive at the specified path\"});this.filename=de.String(\"--filename\",{hidden:!0})}static{this.paths=[[\"pack\"]]}static{this.usage=st.Usage({description:\"generate a tarball from the active workspace\",details:\"\\n      This command will turn the active workspace into a compressed archive suitable for publishing. The archive will by default be stored at the root of the workspace (`package.tgz`).\\n\\n      If the `-o,---out` is set the archive will be created at the specified path. The `%s` and `%v` variables can be used within the path and will be respectively replaced by the package name and version.\\n    \",examples:[[\"Create an archive from the active workspace\",\"yarn pack\"],[\"List the files that would be made part of the workspace's archive\",\"yarn pack --dry-run\"],[\"Name and output the archive in a dedicated folder\",\"yarn pack --out /artifacts/%s-%v.tgz\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);await W9(a)&&(this.installIfNeeded?await o.install({cache:await Wr.find(r),report:new Ri}):await o.restoreInstallState());let n=this.out??this.filename,u=typeof n<\"u\"?K.resolve(this.context.cwd,GBt(n,{workspace:a})):K.resolve(a.cwd,\"package.tgz\");return(await Lt.start({configuration:r,stdout:this.context.stdout,json:this.json},async p=>{await Y9(a,{report:p},async()=>{p.reportJson({base:Ae.fromPortablePath(a.cwd)});let h=await SF(a);for(let E of h)p.reportInfo(null,Ae.fromPortablePath(E)),p.reportJson({location:Ae.fromPortablePath(E)});if(!this.dryRun){let E=await K9(a,h),w=ae.createWriteStream(u);E.pipe(w),await new Promise(D=>{w.on(\"finish\",D)})}}),this.dryRun||(p.reportInfo(0,`Package archive generated in ${pe.pretty(r,u,pe.Type.PATH)}`),p.reportJson({output:Ae.fromPortablePath(u)}))})).exitCode()}};function GBt(t,{workspace:e}){let r=t.replace(\"%s\",WBt(e)).replace(\"%v\",YBt(e));return Ae.toPortablePath(r)}function WBt(t){return t.manifest.name!==null?G.slugifyIdent(t.manifest.name):\"package\"}function YBt(t){return t.manifest.version!==null?t.manifest.version:\"unknown\"}var KBt=[\"dependencies\",\"devDependencies\",\"peerDependencies\"],VBt=\"workspace:\",zBt=(t,e)=>{e.publishConfig&&(e.publishConfig.type&&(e.type=e.publishConfig.type),e.publishConfig.main&&(e.main=e.publishConfig.main),e.publishConfig.browser&&(e.browser=e.publishConfig.browser),e.publishConfig.module&&(e.module=e.publishConfig.module),e.publishConfig.exports&&(e.exports=e.publishConfig.exports),e.publishConfig.imports&&(e.imports=e.publishConfig.imports),e.publishConfig.bin&&(e.bin=e.publishConfig.bin));let r=t.project;for(let o of KBt)for(let a of t.manifest.getForScope(o).values()){let n=r.tryWorkspaceByDescriptor(a),u=G.parseRange(a.range);if(u.protocol===VBt)if(n===null){if(r.tryWorkspaceByIdent(a)===null)throw new zt(21,`${G.prettyDescriptor(r.configuration,a)}: No local workspace found for this range`)}else{let A;G.areDescriptorsEqual(a,n.anchoredDescriptor)||u.selector===\"*\"?A=n.manifest.version??\"0.0.0\":u.selector===\"~\"||u.selector===\"^\"?A=`${u.selector}${n.manifest.version??\"0.0.0\"}`:A=u.selector;let p=o===\"dependencies\"?G.makeDescriptor(a,\"unknown\"):null,h=p!==null&&t.manifest.ensureDependencyMeta(p).optional?\"optionalDependencies\":o;e[h][G.stringifyIdent(a)]=A}}},JBt={hooks:{beforeWorkspacePacking:zBt},commands:[KC]},XBt=JBt;var zBe=ve(\"crypto\"),JBe=et(VBe());async function gvt(t,e,{access:r,tag:o,registry:a,gitHead:n}){let u=t.manifest.name,A=t.manifest.version,p=G.stringifyIdent(u),h=(0,zBe.createHash)(\"sha1\").update(e).digest(\"hex\"),E=JBe.default.fromData(e).toString(),w=r??XBe(t,u),D=await ZBe(t),b=await BA.genPackageManifest(t),C=`${p}-${A}.tgz`,T=new URL(`${uc(a)}/${p}/-/${C}`);return{_id:p,_attachments:{[C]:{content_type:\"application/octet-stream\",data:e.toString(\"base64\"),length:e.length}},name:p,access:w,\"dist-tags\":{[o]:A},versions:{[A]:{...b,_id:`${p}@${A}`,name:p,version:A,gitHead:n,dist:{shasum:h,integrity:E,tarball:T.toString()}}},readme:D}}async function dvt(t){try{let{stdout:e}=await Hr.execvp(\"git\",[\"rev-parse\",\"--revs-only\",\"HEAD\"],{cwd:t});return e.trim()===\"\"?void 0:e.trim()}catch{return}}function XBe(t,e){let r=t.project.configuration;return t.manifest.publishConfig&&typeof t.manifest.publishConfig.access==\"string\"?t.manifest.publishConfig.access:r.get(\"npmPublishAccess\")!==null?r.get(\"npmPublishAccess\"):e.scope?\"restricted\":\"public\"}async function ZBe(t){let e=Ae.toPortablePath(`${t.cwd}/README.md`),r=t.manifest.name,a=`# ${G.stringifyIdent(r)}\n`;try{a=await ae.readFilePromise(e,\"utf8\")}catch(n){if(n.code===\"ENOENT\")return a;throw n}return a}var Z9={npmAlwaysAuth:{description:\"URL of the selected npm registry (note: npm enterprise isn't supported)\",type:\"BOOLEAN\",default:!1},npmAuthIdent:{description:\"Authentication identity for the npm registry (_auth in npm and yarn v1)\",type:\"SECRET\",default:null},npmAuthToken:{description:\"Authentication token for the npm registry (_authToken in npm and yarn v1)\",type:\"SECRET\",default:null}},$Be={npmAuditRegistry:{description:\"Registry to query for audit reports\",type:\"STRING\",default:null},npmPublishRegistry:{description:\"Registry to push packages to\",type:\"STRING\",default:null},npmRegistryServer:{description:\"URL of the selected npm registry (note: npm enterprise isn't supported)\",type:\"STRING\",default:\"https://registry.yarnpkg.com\"}},mvt={configuration:{...Z9,...$Be,npmScopes:{description:\"Settings per package scope\",type:\"MAP\",valueDefinition:{description:\"\",type:\"SHAPE\",properties:{...Z9,...$Be}}},npmRegistries:{description:\"Settings per registry\",type:\"MAP\",normalizeKeys:uc,valueDefinition:{description:\"\",type:\"SHAPE\",properties:{...Z9}}}},fetchers:[bv,rp],resolvers:[kv,Qv,Fv]},yvt=mvt;var lG={};Kt(lG,{NpmAuditCommand:()=>JC,NpmInfoCommand:()=>XC,NpmLoginCommand:()=>ZC,NpmLogoutCommand:()=>eI,NpmPublishCommand:()=>tI,NpmTagAddCommand:()=>nI,NpmTagListCommand:()=>rI,NpmTagRemoveCommand:()=>iI,NpmWhoamiCommand:()=>sI,default:()=>Dvt,npmAuditTypes:()=>Xv,npmAuditUtils:()=>xF});Ke();Ke();Gt();var iG=et(Xo());il();var Xv={};Kt(Xv,{Environment:()=>zv,Severity:()=>Jv});var zv=(o=>(o.All=\"all\",o.Production=\"production\",o.Development=\"development\",o))(zv||{}),Jv=(n=>(n.Info=\"info\",n.Low=\"low\",n.Moderate=\"moderate\",n.High=\"high\",n.Critical=\"critical\",n))(Jv||{});var xF={};Kt(xF,{allSeverities:()=>zC,getPackages:()=>nG,getReportTree:()=>tG,getSeverityInclusions:()=>eG,getTopLevelDependencies:()=>rG});Ke();var eve=et(ni());var zC=[\"info\",\"low\",\"moderate\",\"high\",\"critical\"];function eG(t){if(typeof t>\"u\")return new Set(zC);let e=zC.indexOf(t),r=zC.slice(e);return new Set(r)}function tG(t){let e={},r={children:e};for(let[o,a]of qe.sortMap(Object.entries(t),n=>n[0]))for(let n of qe.sortMap(a,u=>`${u.id}`))e[`${o}/${n.id}`]={value:pe.tuple(pe.Type.IDENT,G.parseIdent(o)),children:{ID:typeof n.id<\"u\"&&{label:\"ID\",value:pe.tuple(pe.Type.ID,n.id)},Issue:{label:\"Issue\",value:pe.tuple(pe.Type.NO_HINT,n.title)},URL:typeof n.url<\"u\"&&{label:\"URL\",value:pe.tuple(pe.Type.URL,n.url)},Severity:{label:\"Severity\",value:pe.tuple(pe.Type.NO_HINT,n.severity)},\"Vulnerable Versions\":{label:\"Vulnerable Versions\",value:pe.tuple(pe.Type.RANGE,n.vulnerable_versions)},\"Tree Versions\":{label:\"Tree Versions\",children:[...n.versions].sort(eve.default.compare).map(u=>({value:pe.tuple(pe.Type.REFERENCE,u)}))},Dependents:{label:\"Dependents\",children:qe.sortMap(n.dependents,u=>G.stringifyLocator(u)).map(u=>({value:pe.tuple(pe.Type.LOCATOR,u)}))}}};return r}function rG(t,e,{all:r,environment:o}){let a=[],n=r?t.workspaces:[e],u=[\"all\",\"production\"].includes(o),A=[\"all\",\"development\"].includes(o);for(let p of n)for(let h of p.anchoredPackage.dependencies.values())(p.manifest.devDependencies.has(h.identHash)?!A:!u)||a.push({workspace:p,dependency:h});return a}function nG(t,e,{recursive:r}){let o=new Map,a=new Set,n=[],u=(A,p)=>{let h=t.storedResolutions.get(p.descriptorHash);if(typeof h>\"u\")throw new Error(\"Assertion failed: The resolution should have been registered\");if(!a.has(h))a.add(h);else return;let E=t.storedPackages.get(h);if(typeof E>\"u\")throw new Error(\"Assertion failed: The package should have been registered\");if(G.ensureDevirtualizedLocator(E).reference.startsWith(\"npm:\")&&E.version!==null){let D=G.stringifyIdent(E),b=qe.getMapWithDefault(o,D);qe.getArrayWithDefault(b,E.version).push(A)}if(r)for(let D of E.dependencies.values())n.push([E,D])};for(let{workspace:A,dependency:p}of e)n.push([A.anchoredLocator,p]);for(;n.length>0;){let[A,p]=n.shift();u(A,p)}return o}var JC=class extends ut{constructor(){super(...arguments);this.all=de.Boolean(\"-A,--all\",!1,{description:\"Audit dependencies from all workspaces\"});this.recursive=de.Boolean(\"-R,--recursive\",!1,{description:\"Audit transitive dependencies as well\"});this.environment=de.String(\"--environment\",\"all\",{description:\"Which environments to cover\",validator:js(zv)});this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.noDeprecations=de.Boolean(\"--no-deprecations\",!1,{description:\"Don't warn about deprecated packages\"});this.severity=de.String(\"--severity\",\"info\",{description:\"Minimal severity requested for packages to be displayed\",validator:js(Jv)});this.excludes=de.Array(\"--exclude\",[],{description:\"Array of glob patterns of packages to exclude from audit\"});this.ignores=de.Array(\"--ignore\",[],{description:\"Array of glob patterns of advisory ID's to ignore in the audit report\"})}static{this.paths=[[\"npm\",\"audit\"]]}static{this.usage=st.Usage({description:\"perform a vulnerability audit against the installed packages\",details:`\n      This command checks for known security reports on the packages you use. The reports are by default extracted from the npm registry, and may or may not be relevant to your actual program (not all vulnerabilities affect all code paths).\n\n      For consistency with our other commands the default is to only check the direct dependencies for the active workspace. To extend this search to all workspaces, use \\`-A,--all\\`. To extend this search to both direct and transitive dependencies, use \\`-R,--recursive\\`.\n\n      Applying the \\`--severity\\` flag will limit the audit table to vulnerabilities of the corresponding severity and above. Valid values are ${zC.map(r=>`\\`${r}\\``).join(\", \")}.\n\n      If the \\`--json\\` flag is set, Yarn will print the output exactly as received from the registry. Regardless of this flag, the process will exit with a non-zero exit code if a report is found for the selected packages.\n\n      If certain packages produce false positives for a particular environment, the \\`--exclude\\` flag can be used to exclude any number of packages from the audit. This can also be set in the configuration file with the \\`npmAuditExcludePackages\\` option.\n\n      If particular advisories are needed to be ignored, the \\`--ignore\\` flag can be used with Advisory ID's to ignore any number of advisories in the audit report. This can also be set in the configuration file with the \\`npmAuditIgnoreAdvisories\\` option.\n\n      To understand the dependency tree requiring vulnerable packages, check the raw report with the \\`--json\\` flag or use \\`yarn why package\\` to get more information as to who depends on them.\n    `,examples:[[\"Checks for known security issues with the installed packages. The output is a list of known issues.\",\"yarn npm audit\"],[\"Audit dependencies in all workspaces\",\"yarn npm audit --all\"],[\"Limit auditing to `dependencies` (excludes `devDependencies`)\",\"yarn npm audit --environment production\"],[\"Show audit report as valid JSON\",\"yarn npm audit --json\"],[\"Audit all direct and transitive dependencies\",\"yarn npm audit --recursive\"],[\"Output moderate (or more severe) vulnerabilities\",\"yarn npm audit --severity moderate\"],[\"Exclude certain packages\",\"yarn npm audit --exclude package1 --exclude package2\"],[\"Ignore specific advisories\",\"yarn npm audit --ignore 1234567 --ignore 7654321\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState();let n=rG(o,a,{all:this.all,environment:this.environment}),u=nG(o,n,{recursive:this.recursive}),A=Array.from(new Set([...r.get(\"npmAuditExcludePackages\"),...this.excludes])),p=Object.create(null);for(let[N,U]of u)A.some(z=>iG.default.isMatch(N,z))||(p[N]=[...U.keys()]);let h=si.getAuditRegistry({configuration:r}),E,w=await pA.start({configuration:r,stdout:this.context.stdout},async()=>{let N=en.post(\"/-/npm/v1/security/advisories/bulk\",p,{authType:en.AuthType.BEST_EFFORT,configuration:r,jsonResponse:!0,registry:h}),U=this.noDeprecations?[]:await Promise.all(Array.from(Object.entries(p),async([te,le])=>{let ce=await en.getPackageMetadata(G.parseIdent(te),{project:o});return qe.mapAndFilter(le,ue=>{let{deprecated:Ie}=ce.versions[ue];return Ie?[te,ue,Ie]:qe.mapAndFilter.skip})})),z=await N;for(let[te,le,ce]of U.flat(1))Object.hasOwn(z,te)&&z[te].some(ue=>Ur.satisfiesWithPrereleases(le,ue.vulnerable_versions))||(z[te]??=[],z[te].push({id:`${te} (deprecation)`,title:ce.trim()||\"This package has been deprecated.\",severity:\"moderate\",vulnerable_versions:le}));E=z});if(w.hasErrors())return w.exitCode();let D=eG(this.severity),b=Array.from(new Set([...r.get(\"npmAuditIgnoreAdvisories\"),...this.ignores])),C=Object.create(null);for(let[N,U]of Object.entries(E)){let z=U.filter(te=>!iG.default.isMatch(`${te.id}`,b)&&D.has(te.severity));z.length>0&&(C[N]=z.map(te=>{let le=u.get(N);if(typeof le>\"u\")throw new Error(\"Assertion failed: Expected the registry to only return packages that were requested\");let ce=[...le.keys()].filter(Ie=>Ur.satisfiesWithPrereleases(Ie,te.vulnerable_versions)),ue=new Map;for(let Ie of ce)for(let he of le.get(Ie))ue.set(he.locatorHash,he);return{...te,versions:ce,dependents:[...ue.values()]}}))}let T=Object.keys(C).length>0;return T?(As.emitTree(tG(C),{configuration:r,json:this.json,stdout:this.context.stdout,separators:2}),1):(await Lt.start({configuration:r,includeFooter:!1,json:this.json,stdout:this.context.stdout},async N=>{N.reportInfo(1,\"No audit suggestions\")}),T?1:0)}};Ke();Ke();Pt();Gt();var sG=et(ni()),oG=ve(\"util\"),XC=class extends ut{constructor(){super(...arguments);this.fields=de.String(\"-f,--fields\",{description:\"A comma-separated list of manifest fields that should be displayed\"});this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.packages=de.Rest()}static{this.paths=[[\"npm\",\"info\"]]}static{this.usage=st.Usage({category:\"Npm-related commands\",description:\"show information about a package\",details:\"\\n      This command fetches information about a package from the npm registry and prints it in a tree format.\\n\\n      The package does not have to be installed locally, but needs to have been published (in particular, local changes will be ignored even for workspaces).\\n\\n      Append `@<range>` to the package argument to provide information specific to the latest version that satisfies the range or to the corresponding tagged version. If the range is invalid or if there is no version satisfying the range, the command will print a warning and fall back to the latest version.\\n\\n      If the `-f,--fields` option is set, it's a comma-separated list of fields which will be used to only display part of the package information.\\n\\n      By default, this command won't return the `dist`, `readme`, and `users` fields, since they are often very long. To explicitly request those fields, explicitly list them with the `--fields` flag or request the output in JSON mode.\\n    \",examples:[[\"Show all available information about react (except the `dist`, `readme`, and `users` fields)\",\"yarn npm info react\"],[\"Show all available information about react as valid JSON (including the `dist`, `readme`, and `users` fields)\",\"yarn npm info react --json\"],[\"Show all available information about react@16.12.0\",\"yarn npm info react@16.12.0\"],[\"Show all available information about react@next\",\"yarn npm info react@next\"],[\"Show the description of react\",\"yarn npm info react --fields description\"],[\"Show all available versions of react\",\"yarn npm info react --fields versions\"],[\"Show the readme of react\",\"yarn npm info react --fields readme\"],[\"Show a few fields of react\",\"yarn npm info react --fields homepage,repository\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o}=await Qt.find(r,this.context.cwd),a=typeof this.fields<\"u\"?new Set([\"name\",...this.fields.split(/\\s*,\\s*/)]):null,n=[],u=!1,A=await Lt.start({configuration:r,includeFooter:!1,json:this.json,stdout:this.context.stdout},async p=>{for(let h of this.packages){let E;if(h===\".\"){let le=o.topLevelWorkspace;if(!le.manifest.name)throw new ot(`Missing ${pe.pretty(r,\"name\",pe.Type.CODE)} field in ${Ae.fromPortablePath(K.join(le.cwd,mr.manifest))}`);E=G.makeDescriptor(le.manifest.name,\"unknown\")}else E=G.parseDescriptor(h);let w=en.getIdentUrl(E),D=aG(await en.get(w,{configuration:r,ident:E,jsonResponse:!0,customErrorMessage:en.customPackageError})),b=Object.keys(D.versions).sort(sG.default.compareLoose),T=D[\"dist-tags\"].latest||b[b.length-1],N=Ur.validRange(E.range);if(N){let le=sG.default.maxSatisfying(b,N);le!==null?T=le:(p.reportWarning(0,`Unmet range ${G.prettyRange(r,E.range)}; falling back to the latest version`),u=!0)}else Object.hasOwn(D[\"dist-tags\"],E.range)?T=D[\"dist-tags\"][E.range]:E.range!==\"unknown\"&&(p.reportWarning(0,`Unknown tag ${G.prettyRange(r,E.range)}; falling back to the latest version`),u=!0);let U=D.versions[T],z={...D,...U,version:T,versions:b},te;if(a!==null){te={};for(let le of a){let ce=z[le];if(typeof ce<\"u\")te[le]=ce;else{p.reportWarning(1,`The ${pe.pretty(r,le,pe.Type.CODE)} field doesn't exist inside ${G.prettyIdent(r,E)}'s information`),u=!0;continue}}}else this.json||(delete z.dist,delete z.readme,delete z.users),te=z;p.reportJson(te),this.json||n.push(te)}});oG.inspect.styles.name=\"cyan\";for(let p of n)(p!==n[0]||u)&&this.context.stdout.write(`\n`),this.context.stdout.write(`${(0,oG.inspect)(p,{depth:1/0,colors:!0,compact:!1})}\n`);return A.exitCode()}};function aG(t){if(Array.isArray(t)){let e=[];for(let r of t)r=aG(r),r&&e.push(r);return e}else if(typeof t==\"object\"&&t!==null){let e={};for(let r of Object.keys(t)){if(r.startsWith(\"_\"))continue;let o=aG(t[r]);o&&(e[r]=o)}return e}else return t||null}Ke();Ke();Gt();var tve=et(Q2()),ZC=class extends ut{constructor(){super(...arguments);this.scope=de.String(\"-s,--scope\",{description:\"Login to the registry configured for a given scope\"});this.publish=de.Boolean(\"--publish\",!1,{description:\"Login to the publish registry\"});this.alwaysAuth=de.Boolean(\"--always-auth\",{description:\"Set the npmAlwaysAuth configuration\"})}static{this.paths=[[\"npm\",\"login\"]]}static{this.usage=st.Usage({category:\"Npm-related commands\",description:\"store new login info to access the npm registry\",details:\"\\n      This command will ask you for your username, password, and 2FA One-Time-Password (when it applies). It will then modify your local configuration (in your home folder, never in the project itself) to reference the new tokens thus generated.\\n\\n      Adding the `-s,--scope` flag will cause the authentication to be done against whatever registry is configured for the associated scope (see also `npmScopes`).\\n\\n      Adding the `--publish` flag will cause the authentication to be done against the registry used when publishing the package (see also `publishConfig.registry` and `npmPublishRegistry`).\\n    \",examples:[[\"Login to the default registry\",\"yarn npm login\"],[\"Login to the registry linked to the @my-scope registry\",\"yarn npm login --scope my-scope\"],[\"Login to the publish registry for the current package\",\"yarn npm login --publish\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=await bF({configuration:r,cwd:this.context.cwd,publish:this.publish,scope:this.scope});return(await Lt.start({configuration:r,stdout:this.context.stdout,includeFooter:!1},async n=>{let u=await Ivt({configuration:r,registry:o,report:n,stdin:this.context.stdin,stdout:this.context.stdout}),A=await Evt(o,u,r);return await Cvt(o,A,{alwaysAuth:this.alwaysAuth,scope:this.scope}),n.reportInfo(0,\"Successfully logged in\")})).exitCode()}};async function bF({scope:t,publish:e,configuration:r,cwd:o}){return t&&e?si.getScopeRegistry(t,{configuration:r,type:si.RegistryType.PUBLISH_REGISTRY}):t?si.getScopeRegistry(t,{configuration:r}):e?si.getPublishRegistry((await aE(r,o)).manifest,{configuration:r}):si.getDefaultRegistry({configuration:r})}async function Evt(t,e,r){let o=`/-/user/org.couchdb.user:${encodeURIComponent(e.name)}`,a={_id:`org.couchdb.user:${e.name}`,name:e.name,password:e.password,type:\"user\",roles:[],date:new Date().toISOString()},n={attemptedAs:e.name,configuration:r,registry:t,jsonResponse:!0,authType:en.AuthType.NO_AUTH};try{return(await en.put(o,a,n)).token}catch(E){if(!(E.originalError?.name===\"HTTPError\"&&E.originalError?.response.statusCode===409))throw E}let u={...n,authType:en.AuthType.NO_AUTH,headers:{authorization:`Basic ${Buffer.from(`${e.name}:${e.password}`).toString(\"base64\")}`}},A=await en.get(o,u);for(let[E,w]of Object.entries(A))(!a[E]||E===\"roles\")&&(a[E]=w);let p=`${o}/-rev/${a._rev}`;return(await en.put(p,a,u)).token}async function Cvt(t,e,{alwaysAuth:r,scope:o}){let a=u=>A=>{let p=qe.isIndexableObject(A)?A:{},h=p[u],E=qe.isIndexableObject(h)?h:{};return{...p,[u]:{...E,...r!==void 0?{npmAlwaysAuth:r}:{},npmAuthToken:e}}},n=o?{npmScopes:a(o)}:{npmRegistries:a(t)};return await Je.updateHomeConfiguration(n)}async function Ivt({configuration:t,registry:e,report:r,stdin:o,stdout:a}){r.reportInfo(0,`Logging in to ${pe.pretty(t,e,pe.Type.URL)}`);let n=!1;if(e.match(/^https:\\/\\/npm\\.pkg\\.github\\.com(\\/|$)/)&&(r.reportInfo(0,\"You seem to be using the GitHub Package Registry. Tokens must be generated with the 'repo', 'write:packages', and 'read:packages' permissions.\"),n=!0),r.reportSeparator(),t.env.YARN_IS_TEST_ENV)return{name:t.env.YARN_INJECT_NPM_USER||\"\",password:t.env.YARN_INJECT_NPM_PASSWORD||\"\"};let u=await(0,tve.prompt)([{type:\"input\",name:\"name\",message:\"Username:\",required:!0,onCancel:()=>process.exit(130),stdin:o,stdout:a},{type:\"password\",name:\"password\",message:n?\"Token:\":\"Password:\",required:!0,onCancel:()=>process.exit(130),stdin:o,stdout:a}]);return r.reportSeparator(),u}Ke();Ke();Gt();var $C=new Set([\"npmAuthIdent\",\"npmAuthToken\"]),eI=class extends ut{constructor(){super(...arguments);this.scope=de.String(\"-s,--scope\",{description:\"Logout of the registry configured for a given scope\"});this.publish=de.Boolean(\"--publish\",!1,{description:\"Logout of the publish registry\"});this.all=de.Boolean(\"-A,--all\",!1,{description:\"Logout of all registries\"})}static{this.paths=[[\"npm\",\"logout\"]]}static{this.usage=st.Usage({category:\"Npm-related commands\",description:\"logout of the npm registry\",details:\"\\n      This command will log you out by modifying your local configuration (in your home folder, never in the project itself) to delete all credentials linked to a registry.\\n\\n      Adding the `-s,--scope` flag will cause the deletion to be done against whatever registry is configured for the associated scope (see also `npmScopes`).\\n\\n      Adding the `--publish` flag will cause the deletion to be done against the registry used when publishing the package (see also `publishConfig.registry` and `npmPublishRegistry`).\\n\\n      Adding the `-A,--all` flag will cause the deletion to be done against all registries and scopes.\\n    \",examples:[[\"Logout of the default registry\",\"yarn npm logout\"],[\"Logout of the @my-scope scope\",\"yarn npm logout --scope my-scope\"],[\"Logout of the publish registry for the current package\",\"yarn npm logout --publish\"],[\"Logout of all registries\",\"yarn npm logout --all\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o=async()=>{let n=await bF({configuration:r,cwd:this.context.cwd,publish:this.publish,scope:this.scope}),u=await Je.find(this.context.cwd,this.context.plugins),A=G.makeIdent(this.scope??null,\"pkg\");return!si.getAuthConfiguration(n,{configuration:u,ident:A}).get(\"npmAuthToken\")};return(await Lt.start({configuration:r,stdout:this.context.stdout},async n=>{if(this.all&&(await Bvt(),n.reportInfo(0,\"Successfully logged out from everything\")),this.scope){await rve(\"npmScopes\",this.scope),await o()?n.reportInfo(0,`Successfully logged out from ${this.scope}`):n.reportWarning(0,\"Scope authentication settings removed, but some other ones settings still apply to it\");return}let u=await bF({configuration:r,cwd:this.context.cwd,publish:this.publish});await rve(\"npmRegistries\",u),await o()?n.reportInfo(0,`Successfully logged out from ${u}`):n.reportWarning(0,\"Registry authentication settings removed, but some other ones settings still apply to it\")})).exitCode()}};function wvt(t,e){let r=t[e];if(!qe.isIndexableObject(r))return!1;let o=new Set(Object.keys(r));if([...$C].every(n=>!o.has(n)))return!1;for(let n of $C)o.delete(n);if(o.size===0)return t[e]=void 0,!0;let a={...r};for(let n of $C)delete a[n];return t[e]=a,!0}async function Bvt(){let t=e=>{let r=!1,o=qe.isIndexableObject(e)?{...e}:{};o.npmAuthToken&&(delete o.npmAuthToken,r=!0);for(let a of Object.keys(o))wvt(o,a)&&(r=!0);if(Object.keys(o).length!==0)return r?o:e};return await Je.updateHomeConfiguration({npmRegistries:t,npmScopes:t})}async function rve(t,e){return await Je.updateHomeConfiguration({[t]:r=>{let o=qe.isIndexableObject(r)?r:{};if(!Object.hasOwn(o,e))return r;let a=o[e],n=qe.isIndexableObject(a)?a:{},u=new Set(Object.keys(n));if([...$C].every(p=>!u.has(p)))return r;for(let p of $C)u.delete(p);if(u.size===0)return Object.keys(o).length===1?void 0:{...o,[e]:void 0};let A={};for(let p of $C)A[p]=void 0;return{...o,[e]:{...n,...A}}}})}Ke();Gt();var tI=class extends ut{constructor(){super(...arguments);this.access=de.String(\"--access\",{description:\"The access for the published package (public or restricted)\"});this.tag=de.String(\"--tag\",\"latest\",{description:\"The tag on the registry that the package should be attached to\"});this.tolerateRepublish=de.Boolean(\"--tolerate-republish\",!1,{description:\"Warn and exit when republishing an already existing version of a package\"});this.otp=de.String(\"--otp\",{description:\"The OTP token to use with the command\"})}static{this.paths=[[\"npm\",\"publish\"]]}static{this.usage=st.Usage({category:\"Npm-related commands\",description:\"publish the active workspace to the npm registry\",details:'\\n      This command will pack the active workspace into a fresh archive and upload it to the npm registry.\\n\\n      The package will by default be attached to the `latest` tag on the registry, but this behavior can be overridden by using the `--tag` option.\\n\\n      Note that for legacy reasons scoped packages are by default published with an access set to `restricted` (aka \"private packages\"). This requires you to register for a paid npm plan. In case you simply wish to publish a public scoped package to the registry (for free), just add the `--access public` flag. This behavior can be enabled by default through the `npmPublishAccess` settings.\\n    ',examples:[[\"Publish the active workspace\",\"yarn npm publish\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);if(a.manifest.private)throw new ot(\"Private workspaces cannot be published\");if(a.manifest.name===null||a.manifest.version===null)throw new ot(\"Workspaces must have valid names and versions to be published on an external registry\");await o.restoreInstallState();let n=a.manifest.name,u=a.manifest.version,A=si.getPublishRegistry(a.manifest,{configuration:r});return(await Lt.start({configuration:r,stdout:this.context.stdout},async h=>{if(this.tolerateRepublish)try{let E=await en.get(en.getIdentUrl(n),{configuration:r,registry:A,ident:n,jsonResponse:!0});if(!Object.hasOwn(E,\"versions\"))throw new zt(15,'Registry returned invalid data for - missing \"versions\" field');if(Object.hasOwn(E.versions,u)){h.reportWarning(0,`Registry already knows about version ${u}; skipping.`);return}}catch(E){if(E.originalError?.response?.statusCode!==404)throw E}await hn.maybeExecuteWorkspaceLifecycleScript(a,\"prepublish\",{report:h}),await BA.prepareForPack(a,{report:h},async()=>{let E=await BA.genPackList(a);for(let T of E)h.reportInfo(null,T);let w=await BA.genPackStream(a,E),D=await qe.bufferStream(w),b=await VC.getGitHead(a.cwd),C=await VC.makePublishBody(a,D,{access:this.access,tag:this.tag,registry:A,gitHead:b});await en.put(en.getIdentUrl(n),C,{configuration:r,registry:A,ident:n,otp:this.otp,jsonResponse:!0})}),h.reportInfo(0,\"Package archive published\")})).exitCode()}};Ke();Gt();var nve=et(ni());Ke();Pt();Gt();var rI=class extends ut{constructor(){super(...arguments);this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.package=de.String({required:!1})}static{this.paths=[[\"npm\",\"tag\",\"list\"]]}static{this.usage=st.Usage({category:\"Npm-related commands\",description:\"list all dist-tags of a package\",details:`\n      This command will list all tags of a package from the npm registry.\n\n      If the package is not specified, Yarn will default to the current workspace.\n    `,examples:[[\"List all tags of package `my-pkg`\",\"yarn npm tag list my-pkg\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n;if(typeof this.package<\"u\")n=G.parseIdent(this.package);else{if(!a)throw new or(o.cwd,this.context.cwd);if(!a.manifest.name)throw new ot(`Missing 'name' field in ${Ae.fromPortablePath(K.join(a.cwd,mr.manifest))}`);n=a.manifest.name}let u=await Zv(n,r),p={children:qe.sortMap(Object.entries(u),([h])=>h).map(([h,E])=>({value:pe.tuple(pe.Type.RESOLUTION,{descriptor:G.makeDescriptor(n,h),locator:G.makeLocator(n,E)})}))};return As.emitTree(p,{configuration:r,json:this.json,stdout:this.context.stdout})}};async function Zv(t,e){let r=`/-/package${en.getIdentUrl(t)}/dist-tags`;return en.get(r,{configuration:e,ident:t,jsonResponse:!0,customErrorMessage:en.customPackageError})}var nI=class extends ut{constructor(){super(...arguments);this.package=de.String();this.tag=de.String()}static{this.paths=[[\"npm\",\"tag\",\"add\"]]}static{this.usage=st.Usage({category:\"Npm-related commands\",description:\"add a tag for a specific version of a package\",details:`\n      This command will add a tag to the npm registry for a specific version of a package. If the tag already exists, it will be overwritten.\n    `,examples:[[\"Add a `beta` tag for version `2.3.4-beta.4` of package `my-pkg`\",\"yarn npm tag add my-pkg@2.3.4-beta.4 beta\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);let n=G.parseDescriptor(this.package,!0),u=n.range;if(!nve.default.valid(u))throw new ot(`The range ${pe.pretty(r,n.range,pe.Type.RANGE)} must be a valid semver version`);let A=si.getPublishRegistry(a.manifest,{configuration:r}),p=pe.pretty(r,n,pe.Type.IDENT),h=pe.pretty(r,u,pe.Type.RANGE),E=pe.pretty(r,this.tag,pe.Type.CODE);return(await Lt.start({configuration:r,stdout:this.context.stdout},async D=>{let b=await Zv(n,r);Object.hasOwn(b,this.tag)&&b[this.tag]===u&&D.reportWarning(0,`Tag ${E} is already set to version ${h}`);let C=`/-/package${en.getIdentUrl(n)}/dist-tags/${encodeURIComponent(this.tag)}`;await en.put(C,u,{configuration:r,registry:A,ident:n,jsonRequest:!0,jsonResponse:!0}),D.reportInfo(0,`Tag ${E} added to version ${h} of package ${p}`)})).exitCode()}};Ke();Gt();var iI=class extends ut{constructor(){super(...arguments);this.package=de.String();this.tag=de.String()}static{this.paths=[[\"npm\",\"tag\",\"remove\"]]}static{this.usage=st.Usage({category:\"Npm-related commands\",description:\"remove a tag from a package\",details:`\n      This command will remove a tag from a package from the npm registry.\n    `,examples:[[\"Remove the `beta` tag from package `my-pkg`\",\"yarn npm tag remove my-pkg beta\"]]})}async execute(){if(this.tag===\"latest\")throw new ot(\"The 'latest' tag cannot be removed.\");let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);let n=G.parseIdent(this.package),u=si.getPublishRegistry(a.manifest,{configuration:r}),A=pe.pretty(r,this.tag,pe.Type.CODE),p=pe.pretty(r,n,pe.Type.IDENT),h=await Zv(n,r);if(!Object.hasOwn(h,this.tag))throw new ot(`${A} is not a tag of package ${p}`);return(await Lt.start({configuration:r,stdout:this.context.stdout},async w=>{let D=`/-/package${en.getIdentUrl(n)}/dist-tags/${encodeURIComponent(this.tag)}`;await en.del(D,{configuration:r,registry:u,ident:n,jsonResponse:!0}),w.reportInfo(0,`Tag ${A} removed from package ${p}`)})).exitCode()}};Ke();Ke();Gt();var sI=class extends ut{constructor(){super(...arguments);this.scope=de.String(\"-s,--scope\",{description:\"Print username for the registry configured for a given scope\"});this.publish=de.Boolean(\"--publish\",!1,{description:\"Print username for the publish registry\"})}static{this.paths=[[\"npm\",\"whoami\"]]}static{this.usage=st.Usage({category:\"Npm-related commands\",description:\"display the name of the authenticated user\",details:\"\\n      Print the username associated with the current authentication settings to the standard output.\\n\\n      When using `-s,--scope`, the username printed will be the one that matches the authentication settings of the registry associated with the given scope (those settings can be overriden using the `npmRegistries` map, and the registry associated with the scope is configured via the `npmScopes` map).\\n\\n      When using `--publish`, the registry we'll select will by default be the one used when publishing packages (`publishConfig.registry` or `npmPublishRegistry` if available, otherwise we'll fallback to the regular `npmRegistryServer`).\\n    \",examples:[[\"Print username for the default registry\",\"yarn npm whoami\"],[\"Print username for the registry on a given scope\",\"yarn npm whoami --scope company\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),o;return this.scope&&this.publish?o=si.getScopeRegistry(this.scope,{configuration:r,type:si.RegistryType.PUBLISH_REGISTRY}):this.scope?o=si.getScopeRegistry(this.scope,{configuration:r}):this.publish?o=si.getPublishRegistry((await aE(r,this.context.cwd)).manifest,{configuration:r}):o=si.getDefaultRegistry({configuration:r}),(await Lt.start({configuration:r,stdout:this.context.stdout},async n=>{let u;try{u=await en.get(\"/-/whoami\",{configuration:r,registry:o,authType:en.AuthType.ALWAYS_AUTH,jsonResponse:!0,ident:this.scope?G.makeIdent(this.scope,\"\"):void 0})}catch(A){if(A.response?.statusCode===401||A.response?.statusCode===403){n.reportError(41,\"Authentication failed - your credentials may have expired\");return}else throw A}n.reportInfo(0,u.username)})).exitCode()}};var vvt={configuration:{npmPublishAccess:{description:\"Default access of the published packages\",type:\"STRING\",default:null},npmAuditExcludePackages:{description:\"Array of glob patterns of packages to exclude from npm audit\",type:\"STRING\",default:[],isArray:!0},npmAuditIgnoreAdvisories:{description:\"Array of glob patterns of advisory IDs to exclude from npm audit\",type:\"STRING\",default:[],isArray:!0}},commands:[JC,XC,ZC,eI,tI,nI,rI,iI,sI]},Dvt=vvt;var gG={};Kt(gG,{PatchCommand:()=>AI,PatchCommitCommand:()=>uI,PatchFetcher:()=>nD,PatchResolver:()=>iD,default:()=>jvt,patchUtils:()=>Id});Ke();Ke();Pt();sA();var Id={};Kt(Id,{applyPatchFile:()=>QF,diffFolders:()=>pG,ensureUnpatchedDescriptor:()=>cG,ensureUnpatchedLocator:()=>RF,extractPackageToDisk:()=>fG,extractPatchFlags:()=>uve,isParentRequired:()=>AG,isPatchDescriptor:()=>FF,isPatchLocator:()=>i0,loadPatchFiles:()=>rD,makeDescriptor:()=>TF,makeLocator:()=>uG,makePatchHash:()=>hG,parseDescriptor:()=>eD,parseLocator:()=>tD,parsePatchFile:()=>$v,unpatchDescriptor:()=>_vt,unpatchLocator:()=>Hvt});Ke();Pt();Ke();Pt();var Pvt=/^@@ -(\\d+)(,(\\d+))? \\+(\\d+)(,(\\d+))? @@.*/;function oI(t){return K.relative(Bt.root,K.resolve(Bt.root,Ae.toPortablePath(t)))}function Svt(t){let e=t.trim().match(Pvt);if(!e)throw new Error(`Bad header line: '${t}'`);return{original:{start:Math.max(Number(e[1]),1),length:Number(e[3]||1)},patched:{start:Math.max(Number(e[4]),1),length:Number(e[6]||1)}}}var xvt=420,bvt=493;var ive=()=>({semverExclusivity:null,diffLineFromPath:null,diffLineToPath:null,oldMode:null,newMode:null,deletedFileMode:null,newFileMode:null,renameFrom:null,renameTo:null,beforeHash:null,afterHash:null,fromPath:null,toPath:null,hunks:null}),kvt=t=>({header:Svt(t),parts:[]}),Qvt={\"@\":\"header\",\"-\":\"deletion\",\"+\":\"insertion\",\" \":\"context\",\"\\\\\":\"pragma\",undefined:\"context\"};function Fvt(t){let e=[],r=ive(),o=\"parsing header\",a=null,n=null;function u(){a&&(n&&(a.parts.push(n),n=null),r.hunks.push(a),a=null)}function A(){u(),e.push(r),r=ive()}for(let p=0;p<t.length;p++){let h=t[p];if(o===\"parsing header\")if(h.startsWith(\"@@\"))o=\"parsing hunks\",r.hunks=[],p-=1;else if(h.startsWith(\"diff --git \")){r&&r.diffLineFromPath&&A();let E=h.match(/^diff --git a\\/(.*?) b\\/(.*?)\\s*$/);if(!E)throw new Error(`Bad diff line: ${h}`);r.diffLineFromPath=E[1],r.diffLineToPath=E[2]}else if(h.startsWith(\"old mode \"))r.oldMode=h.slice(9).trim();else if(h.startsWith(\"new mode \"))r.newMode=h.slice(9).trim();else if(h.startsWith(\"deleted file mode \"))r.deletedFileMode=h.slice(18).trim();else if(h.startsWith(\"new file mode \"))r.newFileMode=h.slice(14).trim();else if(h.startsWith(\"rename from \"))r.renameFrom=h.slice(12).trim();else if(h.startsWith(\"rename to \"))r.renameTo=h.slice(10).trim();else if(h.startsWith(\"index \")){let E=h.match(/(\\w+)\\.\\.(\\w+)/);if(!E)continue;r.beforeHash=E[1],r.afterHash=E[2]}else h.startsWith(\"semver exclusivity \")?r.semverExclusivity=h.slice(19).trim():h.startsWith(\"--- \")?r.fromPath=h.slice(6).trim():h.startsWith(\"+++ \")&&(r.toPath=h.slice(6).trim());else{let E=Qvt[h[0]]||null;switch(E){case\"header\":u(),a=kvt(h);break;case null:o=\"parsing header\",A(),p-=1;break;case\"pragma\":{if(!h.startsWith(\"\\\\ No newline at end of file\"))throw new Error(`Unrecognized pragma in patch file: ${h}`);if(!n)throw new Error(\"Bad parser state: No newline at EOF pragma encountered without context\");n.noNewlineAtEndOfFile=!0}break;case\"context\":case\"deletion\":case\"insertion\":{if(!a)throw new Error(\"Bad parser state: Hunk lines encountered before hunk header\");n&&n.type!==E&&(a.parts.push(n),n=null),n||(n={type:E,lines:[],noNewlineAtEndOfFile:!1}),n.lines.push(h.slice(1))}break;default:qe.assertNever(E);break}}}A();for(let{hunks:p}of e)if(p)for(let h of p)Tvt(h);return e}function Rvt(t){let e=[];for(let r of t){let{semverExclusivity:o,diffLineFromPath:a,diffLineToPath:n,oldMode:u,newMode:A,deletedFileMode:p,newFileMode:h,renameFrom:E,renameTo:w,beforeHash:D,afterHash:b,fromPath:C,toPath:T,hunks:N}=r,U=E?\"rename\":p?\"file deletion\":h?\"file creation\":N&&N.length>0?\"patch\":\"mode change\",z=null;switch(U){case\"rename\":{if(!E||!w)throw new Error(\"Bad parser state: rename from & to not given\");e.push({type:\"rename\",semverExclusivity:o,fromPath:oI(E),toPath:oI(w)}),z=w}break;case\"file deletion\":{let te=a||C;if(!te)throw new Error(\"Bad parse state: no path given for file deletion\");e.push({type:\"file deletion\",semverExclusivity:o,hunk:N&&N[0]||null,path:oI(te),mode:kF(p),hash:D})}break;case\"file creation\":{let te=n||T;if(!te)throw new Error(\"Bad parse state: no path given for file creation\");e.push({type:\"file creation\",semverExclusivity:o,hunk:N&&N[0]||null,path:oI(te),mode:kF(h),hash:b})}break;case\"patch\":case\"mode change\":z=T||n;break;default:qe.assertNever(U);break}z&&u&&A&&u!==A&&e.push({type:\"mode change\",semverExclusivity:o,path:oI(z),oldMode:kF(u),newMode:kF(A)}),z&&N&&N.length&&e.push({type:\"patch\",semverExclusivity:o,path:oI(z),hunks:N,beforeHash:D,afterHash:b})}if(e.length===0)throw new Error(\"Unable to parse patch file: No changes found. Make sure the patch is a valid UTF8 encoded string\");return e}function kF(t){let e=parseInt(t,8)&511;if(e!==xvt&&e!==bvt)throw new Error(`Unexpected file mode string: ${t}`);return e}function $v(t){let e=t.split(/\\n/g);return e[e.length-1]===\"\"&&e.pop(),Rvt(Fvt(e))}function Tvt(t){let e=0,r=0;for(let{type:o,lines:a}of t.parts)switch(o){case\"context\":r+=a.length,e+=a.length;break;case\"deletion\":e+=a.length;break;case\"insertion\":r+=a.length;break;default:qe.assertNever(o);break}if(e!==t.header.original.length||r!==t.header.patched.length){let o=a=>a<0?a:`+${a}`;throw new Error(`hunk header integrity check failed (expected @@ ${o(t.header.original.length)} ${o(t.header.patched.length)} @@, got @@ ${o(e)} ${o(r)} @@)`)}}Ke();Pt();var aI=class extends Error{constructor(r,o){super(`Cannot apply hunk #${r+1}`);this.hunk=o}};async function lI(t,e,r){let o=await t.lstatPromise(e),a=await r();typeof a<\"u\"&&(e=a),await t.lutimesPromise(e,o.atime,o.mtime)}async function QF(t,{baseFs:e=new _n,dryRun:r=!1,version:o=null}={}){for(let a of t)if(!(a.semverExclusivity!==null&&o!==null&&!Ur.satisfiesWithPrereleases(o,a.semverExclusivity)))switch(a.type){case\"file deletion\":if(r){if(!e.existsSync(a.path))throw new Error(`Trying to delete a file that doesn't exist: ${a.path}`)}else await lI(e,K.dirname(a.path),async()=>{await e.unlinkPromise(a.path)});break;case\"rename\":if(r){if(!e.existsSync(a.fromPath))throw new Error(`Trying to move a file that doesn't exist: ${a.fromPath}`)}else await lI(e,K.dirname(a.fromPath),async()=>{await lI(e,K.dirname(a.toPath),async()=>{await lI(e,a.fromPath,async()=>(await e.movePromise(a.fromPath,a.toPath),a.toPath))})});break;case\"file creation\":if(r){if(e.existsSync(a.path))throw new Error(`Trying to create a file that already exists: ${a.path}`)}else{let n=a.hunk?a.hunk.parts[0].lines.join(`\n`)+(a.hunk.parts[0].noNewlineAtEndOfFile?\"\":`\n`):\"\";await e.mkdirpPromise(K.dirname(a.path),{chmod:493,utimes:[Pi.SAFE_TIME,Pi.SAFE_TIME]}),await e.writeFilePromise(a.path,n,{mode:a.mode}),await e.utimesPromise(a.path,Pi.SAFE_TIME,Pi.SAFE_TIME)}break;case\"patch\":await lI(e,a.path,async()=>{await Ovt(a,{baseFs:e,dryRun:r})});break;case\"mode change\":{let u=(await e.statPromise(a.path)).mode;if(sve(a.newMode)!==sve(u))continue;await lI(e,a.path,async()=>{await e.chmodPromise(a.path,a.newMode)})}break;default:qe.assertNever(a);break}}function sve(t){return(t&64)>0}function ove(t){return t.replace(/\\s+$/,\"\")}function Nvt(t,e){return ove(t)===ove(e)}async function Ovt({hunks:t,path:e},{baseFs:r,dryRun:o=!1}){let a=await r.statSync(e).mode,u=(await r.readFileSync(e,\"utf8\")).split(/\\n/),A=[],p=0,h=0;for(let w of t){let D=Math.max(h,w.header.patched.start+p),b=Math.max(0,D-h),C=Math.max(0,u.length-D-w.header.original.length),T=Math.max(b,C),N=0,U=0,z=null;for(;N<=T;){if(N<=b&&(U=D-N,z=ave(w,u,U),z!==null)){N=-N;break}if(N<=C&&(U=D+N,z=ave(w,u,U),z!==null))break;N+=1}if(z===null)throw new aI(t.indexOf(w),w);A.push(z),p+=N,h=U+w.header.original.length}if(o)return;let E=0;for(let w of A)for(let D of w)switch(D.type){case\"splice\":{let b=D.index+E;u.splice(b,D.numToDelete,...D.linesToInsert),E+=D.linesToInsert.length-D.numToDelete}break;case\"pop\":u.pop();break;case\"push\":u.push(D.line);break;default:qe.assertNever(D);break}await r.writeFilePromise(e,u.join(`\n`),{mode:a})}function ave(t,e,r){let o=[];for(let a of t.parts)switch(a.type){case\"context\":case\"deletion\":{for(let n of a.lines){let u=e[r];if(u==null||!Nvt(u,n))return null;r+=1}a.type===\"deletion\"&&(o.push({type:\"splice\",index:r-a.lines.length,numToDelete:a.lines.length,linesToInsert:[]}),a.noNewlineAtEndOfFile&&o.push({type:\"push\",line:\"\"}))}break;case\"insertion\":o.push({type:\"splice\",index:r,numToDelete:0,linesToInsert:a.lines}),a.noNewlineAtEndOfFile&&o.push({type:\"pop\"});break;default:qe.assertNever(a.type);break}return o}var Uvt=/^builtin<([^>]+)>$/;function cI(t,e){let{protocol:r,source:o,selector:a,params:n}=G.parseRange(t);if(r!==\"patch:\")throw new Error(\"Invalid patch range\");if(o===null)throw new Error(\"Patch locators must explicitly define their source\");let u=a?a.split(/&/).map(E=>Ae.toPortablePath(E)):[],A=n&&typeof n.locator==\"string\"?G.parseLocator(n.locator):null,p=n&&typeof n.version==\"string\"?n.version:null,h=e(o);return{parentLocator:A,sourceItem:h,patchPaths:u,sourceVersion:p}}function FF(t){return t.range.startsWith(\"patch:\")}function i0(t){return t.reference.startsWith(\"patch:\")}function eD(t){let{sourceItem:e,...r}=cI(t.range,G.parseDescriptor);return{...r,sourceDescriptor:e}}function tD(t){let{sourceItem:e,...r}=cI(t.reference,G.parseLocator);return{...r,sourceLocator:e}}function _vt(t){let{sourceItem:e}=cI(t.range,G.parseDescriptor);return e}function Hvt(t){let{sourceItem:e}=cI(t.reference,G.parseLocator);return e}function cG(t){if(!FF(t))return t;let{sourceItem:e}=cI(t.range,G.parseDescriptor);return e}function RF(t){if(!i0(t))return t;let{sourceItem:e}=cI(t.reference,G.parseLocator);return e}function lve({parentLocator:t,sourceItem:e,patchPaths:r,sourceVersion:o,patchHash:a},n){let u=t!==null?{locator:G.stringifyLocator(t)}:{},A=typeof o<\"u\"?{version:o}:{},p=typeof a<\"u\"?{hash:a}:{};return G.makeRange({protocol:\"patch:\",source:n(e),selector:r.join(\"&\"),params:{...A,...p,...u}})}function TF(t,{parentLocator:e,sourceDescriptor:r,patchPaths:o}){return G.makeDescriptor(t,lve({parentLocator:e,sourceItem:r,patchPaths:o},G.stringifyDescriptor))}function uG(t,{parentLocator:e,sourcePackage:r,patchPaths:o,patchHash:a}){return G.makeLocator(t,lve({parentLocator:e,sourceItem:r,sourceVersion:r.version,patchPaths:o,patchHash:a},G.stringifyLocator))}function cve({onAbsolute:t,onRelative:e,onProject:r,onBuiltin:o},a){let n=a.lastIndexOf(\"!\");n!==-1&&(a=a.slice(n+1));let u=a.match(Uvt);return u!==null?o(u[1]):a.startsWith(\"~/\")?r(a.slice(2)):K.isAbsolute(a)?t(a):e(a)}function uve(t){let e=t.lastIndexOf(\"!\");return{optional:(e!==-1?new Set(t.slice(0,e).split(/!/)):new Set).has(\"optional\")}}function AG(t){return cve({onAbsolute:()=>!1,onRelative:()=>!0,onProject:()=>!1,onBuiltin:()=>!1},t)}async function rD(t,e,r){let o=t!==null?await r.fetcher.fetch(t,r):null,a=o&&o.localPath?{packageFs:new En(Bt.root),prefixPath:K.relative(Bt.root,o.localPath)}:o;o&&o!==a&&o.releaseFs&&o.releaseFs();let n=await qe.releaseAfterUseAsync(async()=>await Promise.all(e.map(async u=>{let A=uve(u),p=await cve({onAbsolute:async h=>await ae.readFilePromise(h,\"utf8\"),onRelative:async h=>{if(a===null)throw new Error(\"Assertion failed: The parent locator should have been fetched\");return await a.packageFs.readFilePromise(K.join(a.prefixPath,h),\"utf8\")},onProject:async h=>await ae.readFilePromise(K.join(r.project.cwd,h),\"utf8\"),onBuiltin:async h=>await r.project.configuration.firstHook(E=>E.getBuiltinPatch,r.project,h)},u);return{...A,source:p}})));for(let u of n)typeof u.source==\"string\"&&(u.source=u.source.replace(/\\r\\n?/g,`\n`));return n}async function fG(t,{cache:e,project:r}){let o=r.storedPackages.get(t.locatorHash);if(typeof o>\"u\")throw new Error(\"Assertion failed: Expected the package to be registered\");let a=RF(t),n=r.storedChecksums,u=new Ri,A=await ae.mktempPromise(),p=K.join(A,\"source\"),h=K.join(A,\"user\"),E=K.join(A,\".yarn-patch.json\"),w=r.configuration.makeFetcher(),D=[];try{let b,C;if(t.locatorHash===a.locatorHash){let T=await w.fetch(t,{cache:e,project:r,fetcher:w,checksums:n,report:u});D.push(()=>T.releaseFs?.()),b=T,C=T}else b=await w.fetch(t,{cache:e,project:r,fetcher:w,checksums:n,report:u}),D.push(()=>b.releaseFs?.()),C=await w.fetch(t,{cache:e,project:r,fetcher:w,checksums:n,report:u}),D.push(()=>C.releaseFs?.());await Promise.all([ae.copyPromise(p,b.prefixPath,{baseFs:b.packageFs}),ae.copyPromise(h,C.prefixPath,{baseFs:C.packageFs}),ae.writeJsonPromise(E,{locator:G.stringifyLocator(t),version:o.version})])}finally{for(let b of D)b()}return ae.detachTemp(A),h}async function pG(t,e){let r=Ae.fromPortablePath(t).replace(/\\\\/g,\"/\"),o=Ae.fromPortablePath(e).replace(/\\\\/g,\"/\"),{stdout:a,stderr:n}=await Hr.execvp(\"git\",[\"-c\",\"core.safecrlf=false\",\"diff\",\"--src-prefix=a/\",\"--dst-prefix=b/\",\"--ignore-cr-at-eol\",\"--full-index\",\"--no-index\",\"--no-renames\",\"--text\",r,o],{cwd:Ae.toPortablePath(process.cwd()),env:{...process.env,GIT_CONFIG_NOSYSTEM:\"1\",HOME:\"\",XDG_CONFIG_HOME:\"\",USERPROFILE:\"\"}});if(n.length>0)throw new Error(`Unable to diff directories. Make sure you have a recent version of 'git' available in PATH.\nThe following error was reported by 'git':\n${n}`);let u=r.startsWith(\"/\")?A=>A.slice(1):A=>A;return a.replace(new RegExp(`(a|b)(${qe.escapeRegExp(`/${u(r)}/`)})`,\"g\"),\"$1/\").replace(new RegExp(`(a|b)${qe.escapeRegExp(`/${u(o)}/`)}`,\"g\"),\"$1/\").replace(new RegExp(qe.escapeRegExp(`${r}/`),\"g\"),\"\").replace(new RegExp(qe.escapeRegExp(`${o}/`),\"g\"),\"\")}function hG(t,e){let r=[];for(let{source:o}of t){if(o===null)continue;let a=$v(o);for(let n of a){let{semverExclusivity:u,...A}=n;u!==null&&e!==null&&!Ur.satisfiesWithPrereleases(e,u)||r.push(JSON.stringify(A))}}return bn.makeHash(`${3}`,...r).slice(0,6)}Ke();function Ave(t,{configuration:e,report:r}){for(let o of t.parts)for(let a of o.lines)switch(o.type){case\"context\":r.reportInfo(null,`  ${pe.pretty(e,a,\"grey\")}`);break;case\"deletion\":r.reportError(28,`- ${pe.pretty(e,a,pe.Type.REMOVED)}`);break;case\"insertion\":r.reportError(28,`+ ${pe.pretty(e,a,pe.Type.ADDED)}`);break;default:qe.assertNever(o.type)}}var nD=class{supports(e,r){return!!i0(e)}getLocalPath(e,r){return null}async fetch(e,r){let o=r.checksums.get(e.locatorHash)||null,[a,n,u]=await r.cache.fetchPackageFromCache(e,o,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the disk`),loader:()=>this.patchPackage(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),localPath:this.getLocalPath(e,r),checksum:u}}async patchPackage(e,r){let{parentLocator:o,sourceLocator:a,sourceVersion:n,patchPaths:u}=tD(e),A=await rD(o,u,r),p=await ae.mktempPromise(),h=K.join(p,\"current.zip\"),E=await r.fetcher.fetch(a,r),w=G.getIdentVendorPath(e),D=new Zi(h,{create:!0,level:r.project.configuration.get(\"compressionLevel\")});await qe.releaseAfterUseAsync(async()=>{await D.copyPromise(w,E.prefixPath,{baseFs:E.packageFs,stableSort:!0})},E.releaseFs),D.saveAndClose();for(let{source:b,optional:C}of A){if(b===null)continue;let T=new Zi(h,{level:r.project.configuration.get(\"compressionLevel\")}),N=new En(K.resolve(Bt.root,w),{baseFs:T});try{await QF($v(b),{baseFs:N,version:n})}catch(U){if(!(U instanceof aI))throw U;let z=r.project.configuration.get(\"enableInlineHunks\"),te=!z&&!C?\" (set enableInlineHunks for details)\":\"\",le=`${G.prettyLocator(r.project.configuration,e)}: ${U.message}${te}`,ce=ue=>{z&&Ave(U.hunk,{configuration:r.project.configuration,report:ue})};if(T.discardAndClose(),C){r.report.reportWarningOnce(66,le,{reportExtra:ce});continue}else throw new zt(66,le,ce)}T.saveAndClose()}return new Zi(h,{level:r.project.configuration.get(\"compressionLevel\")})}};Ke();var iD=class{supportsDescriptor(e,r){return!!FF(e)}supportsLocator(e,r){return!!i0(e)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,o){let{patchPaths:a}=eD(e);return a.every(n=>!AG(n))?e:G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){let{sourceDescriptor:o}=eD(e);return{sourceDescriptor:r.project.configuration.normalizeDependency(o)}}async getCandidates(e,r,o){if(!o.fetchOptions)throw new Error(\"Assertion failed: This resolver cannot be used unless a fetcher is configured\");let{parentLocator:a,patchPaths:n}=eD(e),u=await rD(a,n,o.fetchOptions),A=r.sourceDescriptor;if(typeof A>\"u\")throw new Error(\"Assertion failed: The dependency should have been resolved\");let p=hG(u,A.version);return[uG(e,{parentLocator:a,sourcePackage:A,patchPaths:n,patchHash:p})]}async getSatisfying(e,r,o,a){let[n]=await this.getCandidates(e,r,a);return{locators:o.filter(u=>u.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){let{sourceLocator:o}=tD(e);return{...await r.resolver.resolve(o,r),...e}}};Ke();Pt();Gt();var uI=class extends ut{constructor(){super(...arguments);this.save=de.Boolean(\"-s,--save\",!1,{description:\"Add the patch to your resolution entries\"});this.patchFolder=de.String()}static{this.paths=[[\"patch-commit\"]]}static{this.usage=st.Usage({description:\"generate a patch out of a directory\",details:\"\\n      By default, this will print a patchfile on stdout based on the diff between the folder passed in and the original version of the package. Such file is suitable for consumption with the `patch:` protocol.\\n\\n      With the `-s,--save` option set, the patchfile won't be printed on stdout anymore and will instead be stored within a local file (by default kept within `.yarn/patches`, but configurable via the `patchFolder` setting). A `resolutions` entry will also be added to your top-level manifest, referencing the patched package via the `patch:` protocol.\\n\\n      Note that only folders generated by `yarn patch` are accepted as valid input for `yarn patch-commit`.\\n    \"})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState();let n=K.resolve(this.context.cwd,Ae.toPortablePath(this.patchFolder)),u=K.join(n,\"../source\"),A=K.join(n,\"../.yarn-patch.json\");if(!ae.existsSync(u))throw new ot(\"The argument folder didn't get created by 'yarn patch'\");let p=await pG(u,n),h=await ae.readJsonPromise(A),E=G.parseLocator(h.locator,!0);if(!o.storedPackages.has(E.locatorHash))throw new ot(\"No package found in the project for the given locator\");if(!this.save){this.context.stdout.write(p);return}let w=r.get(\"patchFolder\"),D=K.join(w,`${G.slugifyLocator(E)}.patch`);await ae.mkdirPromise(w,{recursive:!0}),await ae.writeFilePromise(D,p);let b=[],C=new Map;for(let T of o.storedPackages.values()){if(G.isVirtualLocator(T))continue;let N=T.dependencies.get(E.identHash);if(!N)continue;let U=G.ensureDevirtualizedDescriptor(N),z=cG(U),te=o.storedResolutions.get(z.descriptorHash);if(!te)throw new Error(\"Assertion failed: Expected the resolution to have been registered\");if(!o.storedPackages.get(te))throw new Error(\"Assertion failed: Expected the package to have been registered\");let ce=o.tryWorkspaceByLocator(T);if(ce)b.push(ce);else{let ue=o.originalPackages.get(T.locatorHash);if(!ue)throw new Error(\"Assertion failed: Expected the original package to have been registered\");let Ie=ue.dependencies.get(N.identHash);if(!Ie)throw new Error(\"Assertion failed: Expected the original dependency to have been registered\");C.set(Ie.descriptorHash,Ie)}}for(let T of b)for(let N of _t.hardDependencies){let U=T.manifest[N].get(E.identHash);if(!U)continue;let z=TF(U,{parentLocator:null,sourceDescriptor:G.convertLocatorToDescriptor(E),patchPaths:[K.join(mr.home,K.relative(o.cwd,D))]});T.manifest[N].set(U.identHash,z)}for(let T of C.values()){let N=TF(T,{parentLocator:null,sourceDescriptor:G.convertLocatorToDescriptor(E),patchPaths:[K.join(mr.home,K.relative(o.cwd,D))]});o.topLevelWorkspace.manifest.resolutions.push({pattern:{descriptor:{fullName:G.stringifyIdent(N),description:T.range}},reference:N.range})}await o.persist()}};Ke();Pt();Gt();var AI=class extends ut{constructor(){super(...arguments);this.update=de.Boolean(\"-u,--update\",!1,{description:\"Reapply local patches that already apply to this packages\"});this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.package=de.String()}static{this.paths=[[\"patch\"]]}static{this.usage=st.Usage({description:\"prepare a package for patching\",details:\"\\n      This command will cause a package to be extracted in a temporary directory intended to be editable at will.\\n\\n      Once you're done with your changes, run `yarn patch-commit -s path` (with `path` being the temporary directory you received) to generate a patchfile and register it into your top-level manifest via the `patch:` protocol. Run `yarn patch-commit -h` for more details.\\n\\n      Calling the command when you already have a patch won't import it by default (in other words, the default behavior is to reset existing patches). However, adding the `-u,--update` flag will import any current patch.\\n    \"})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Wr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState();let u=G.parseLocator(this.package);if(u.reference===\"unknown\"){let A=qe.mapAndFilter([...o.storedPackages.values()],p=>p.identHash!==u.identHash?qe.mapAndFilter.skip:G.isVirtualLocator(p)?qe.mapAndFilter.skip:i0(p)!==this.update?qe.mapAndFilter.skip:p);if(A.length===0)throw new ot(\"No package found in the project for the given locator\");if(A.length>1)throw new ot(`Multiple candidate packages found; explicitly choose one of them (use \\`yarn why <package>\\` to get more information as to who depends on them):\n${A.map(p=>`\n- ${G.prettyLocator(r,p)}`).join(\"\")}`);u=A[0]}if(!o.storedPackages.has(u.locatorHash))throw new ot(\"No package found in the project for the given locator\");await Lt.start({configuration:r,json:this.json,stdout:this.context.stdout},async A=>{let p=RF(u),h=await fG(u,{cache:n,project:o});A.reportJson({locator:G.stringifyLocator(p),path:Ae.fromPortablePath(h)});let E=this.update?\" along with its current modifications\":\"\";A.reportInfo(0,`Package ${G.prettyLocator(r,p)} got extracted with success${E}!`),A.reportInfo(0,`You can now edit the following folder: ${pe.pretty(r,Ae.fromPortablePath(h),\"magenta\")}`),A.reportInfo(0,`Once you are done run ${pe.pretty(r,`yarn patch-commit -s ${process.platform===\"win32\"?'\"':\"\"}${Ae.fromPortablePath(h)}${process.platform===\"win32\"?'\"':\"\"}`,\"cyan\")} and Yarn will store a patchfile based on your changes.`)})}};var qvt={configuration:{enableInlineHunks:{description:\"If true, the installs will print unmatched patch hunks\",type:\"BOOLEAN\",default:!1},patchFolder:{description:\"Folder where the patch files must be written\",type:\"ABSOLUTE_PATH\",default:\"./.yarn/patches\"}},commands:[uI,AI],fetchers:[nD],resolvers:[iD]},jvt=qvt;var yG={};Kt(yG,{PnpmLinker:()=>sD,default:()=>Vvt});Ke();Pt();Gt();var sD=class{getCustomDataKey(){return JSON.stringify({name:\"PnpmLinker\",version:3})}supportsPackage(e,r){return this.isEnabled(r)}async findPackageLocation(e,r){if(!this.isEnabled(r))throw new Error(\"Assertion failed: Expected the pnpm linker to be enabled\");let o=this.getCustomDataKey(),a=r.project.linkersCustomData.get(o);if(!a)throw new ot(`The project in ${pe.pretty(r.project.configuration,`${r.project.cwd}/package.json`,pe.Type.PATH)} doesn't seem to have been installed - running an install there might help`);let n=a.pathsByLocator.get(e.locatorHash);if(typeof n>\"u\")throw new ot(`Couldn't find ${G.prettyLocator(r.project.configuration,e)} in the currently installed pnpm map - running an install might help`);return n.packageLocation}async findPackageLocator(e,r){if(!this.isEnabled(r))return null;let o=this.getCustomDataKey(),a=r.project.linkersCustomData.get(o);if(!a)throw new ot(`The project in ${pe.pretty(r.project.configuration,`${r.project.cwd}/package.json`,pe.Type.PATH)} doesn't seem to have been installed - running an install there might help`);let n=e.match(/(^.*\\/node_modules\\/(@[^/]*\\/)?[^/]+)(\\/.*$)/);if(n){let p=a.locatorByPath.get(n[1]);if(p)return p}let u=e,A=e;do{A=u,u=K.dirname(A);let p=a.locatorByPath.get(A);if(p)return p}while(u!==A);return null}makeInstaller(e){return new dG(e)}isEnabled(e){return e.project.configuration.get(\"nodeLinker\")===\"pnpm\"}},dG=class{constructor(e){this.opts=e;this.asyncActions=new qe.AsyncActions(10);this.customData={pathsByLocator:new Map,locatorByPath:new Map};this.indexFolderPromise=$D(ae,{indexPath:K.join(e.project.configuration.get(\"globalFolder\"),\"index\")})}attachCustomData(e){}async installPackage(e,r,o){switch(e.linkType){case\"SOFT\":return this.installPackageSoft(e,r,o);case\"HARD\":return this.installPackageHard(e,r,o)}throw new Error(\"Assertion failed: Unsupported package link type\")}async installPackageSoft(e,r,o){let a=K.resolve(r.packageFs.getRealPath(),r.prefixPath),n=this.opts.project.tryWorkspaceByLocator(e)?K.join(a,mr.nodeModules):null;return this.customData.pathsByLocator.set(e.locatorHash,{packageLocation:a,dependenciesLocation:n}),{packageLocation:a,buildRequest:null}}async installPackageHard(e,r,o){let a=Gvt(e,{project:this.opts.project}),n=a.packageLocation;this.customData.locatorByPath.set(n,G.stringifyLocator(e)),this.customData.pathsByLocator.set(e.locatorHash,a),o.holdFetchResult(this.asyncActions.set(e.locatorHash,async()=>{await ae.mkdirPromise(n,{recursive:!0}),await ae.copyPromise(n,r.prefixPath,{baseFs:r.packageFs,overwrite:!1,linkStrategy:{type:\"HardlinkFromIndex\",indexPath:await this.indexFolderPromise,autoRepair:!0}})}));let A=G.isVirtualLocator(e)?G.devirtualizeLocator(e):e,p={manifest:await _t.tryFind(r.prefixPath,{baseFs:r.packageFs})??new _t,misc:{hasBindingGyp:CA.hasBindingGyp(r)}},h=this.opts.project.getDependencyMeta(A,e.version),E=CA.extractBuildRequest(e,p,h,{configuration:this.opts.project.configuration});return{packageLocation:n,buildRequest:E}}async attachInternalDependencies(e,r){if(this.opts.project.configuration.get(\"nodeLinker\")!==\"pnpm\"||!fve(e,{project:this.opts.project}))return;let o=this.customData.pathsByLocator.get(e.locatorHash);if(typeof o>\"u\")throw new Error(`Assertion failed: Expected the package to have been registered (${G.stringifyLocator(e)})`);let{dependenciesLocation:a}=o;a&&this.asyncActions.reduce(e.locatorHash,async n=>{await ae.mkdirPromise(a,{recursive:!0});let u=await Wvt(a),A=new Map(u),p=[n],h=(w,D)=>{let b=D;fve(D,{project:this.opts.project})||(this.opts.report.reportWarningOnce(0,\"The pnpm linker doesn't support providing different versions to workspaces' peer dependencies\"),b=G.devirtualizeLocator(D));let C=this.customData.pathsByLocator.get(b.locatorHash);if(typeof C>\"u\")throw new Error(`Assertion failed: Expected the package to have been registered (${G.stringifyLocator(D)})`);let T=G.stringifyIdent(w),N=K.join(a,T),U=K.relative(K.dirname(N),C.packageLocation),z=A.get(T);A.delete(T),p.push(Promise.resolve().then(async()=>{if(z){if(z.isSymbolicLink()&&await ae.readlinkPromise(N)===U)return;await ae.removePromise(N)}await ae.mkdirpPromise(K.dirname(N)),process.platform==\"win32\"&&this.opts.project.configuration.get(\"winLinkType\")===\"junctions\"?await ae.symlinkPromise(C.packageLocation,N,\"junction\"):await ae.symlinkPromise(U,N)}))},E=!1;for(let[w,D]of r)w.identHash===e.identHash&&(E=!0),h(w,D);!E&&!this.opts.project.tryWorkspaceByLocator(e)&&h(G.convertLocatorToDescriptor(e),e),p.push(Yvt(a,A)),await Promise.all(p)})}async attachExternalDependents(e,r){throw new Error(\"External dependencies haven't been implemented for the pnpm linker\")}async finalizeInstall(){let e=hve(this.opts.project);if(this.opts.project.configuration.get(\"nodeLinker\")!==\"pnpm\")await ae.removePromise(e);else{let r;try{r=new Set(await ae.readdirPromise(e))}catch{r=new Set}for(let{dependenciesLocation:o}of this.customData.pathsByLocator.values()){if(!o)continue;let a=K.contains(e,o);if(a===null)continue;let[n]=a.split(K.sep);r.delete(n)}await Promise.all([...r].map(async o=>{await ae.removePromise(K.join(e,o))}))}return await this.asyncActions.wait(),await mG(e),this.opts.project.configuration.get(\"nodeLinker\")!==\"node-modules\"&&await mG(pve(this.opts.project)),{customData:this.customData}}};function pve(t){return K.join(t.cwd,mr.nodeModules)}function hve(t){return K.join(pve(t),\".store\")}function Gvt(t,{project:e}){let r=G.slugifyLocator(t),o=hve(e),a=K.join(o,r,\"package\"),n=K.join(o,r,mr.nodeModules);return{packageLocation:a,dependenciesLocation:n}}function fve(t,{project:e}){return!G.isVirtualLocator(t)||!e.tryWorkspaceByLocator(t)}async function Wvt(t){let e=new Map,r=[];try{r=await ae.readdirPromise(t,{withFileTypes:!0})}catch(o){if(o.code!==\"ENOENT\")throw o}try{for(let o of r)if(!o.name.startsWith(\".\"))if(o.name.startsWith(\"@\")){let a=await ae.readdirPromise(K.join(t,o.name),{withFileTypes:!0});if(a.length===0)e.set(o.name,o);else for(let n of a)e.set(`${o.name}/${n.name}`,n)}else e.set(o.name,o)}catch(o){if(o.code!==\"ENOENT\")throw o}return e}async function Yvt(t,e){let r=[],o=new Set;for(let a of e.keys()){r.push(ae.removePromise(K.join(t,a)));let n=G.tryParseIdent(a)?.scope;n&&o.add(`@${n}`)}return Promise.all(r).then(()=>Promise.all([...o].map(a=>mG(K.join(t,a)))))}async function mG(t){try{await ae.rmdirPromise(t)}catch(e){if(e.code!==\"ENOENT\"&&e.code!==\"ENOTEMPTY\")throw e}}var Kvt={linkers:[sD]},Vvt=Kvt;var DG={};Kt(DG,{StageCommand:()=>fI,default:()=>sDt,stageUtils:()=>NF});Ke();Pt();Gt();Ke();Pt();var NF={};Kt(NF,{ActionType:()=>EG,checkConsensus:()=>LF,expandDirectory:()=>wG,findConsensus:()=>BG,findVcsRoot:()=>CG,genCommitMessage:()=>vG,getCommitPrefix:()=>gve,isYarnFile:()=>IG});Pt();var EG=(n=>(n[n.CREATE=0]=\"CREATE\",n[n.DELETE=1]=\"DELETE\",n[n.ADD=2]=\"ADD\",n[n.REMOVE=3]=\"REMOVE\",n[n.MODIFY=4]=\"MODIFY\",n))(EG||{});async function CG(t,{marker:e}){do if(!ae.existsSync(K.join(t,e)))t=K.dirname(t);else return t;while(t!==\"/\");return null}function IG(t,{roots:e,names:r}){if(r.has(K.basename(t)))return!0;do if(!e.has(t))t=K.dirname(t);else return!0;while(t!==\"/\");return!1}function wG(t){let e=[],r=[t];for(;r.length>0;){let o=r.pop(),a=ae.readdirSync(o);for(let n of a){let u=K.resolve(o,n);ae.lstatSync(u).isDirectory()?r.push(u):e.push(u)}}return e}function LF(t,e){let r=0,o=0;for(let a of t)a!==\"wip\"&&(e.test(a)?r+=1:o+=1);return r>=o}function BG(t){let e=LF(t,/^(\\w\\(\\w+\\):\\s*)?\\w+s/),r=LF(t,/^(\\w\\(\\w+\\):\\s*)?[A-Z]/),o=LF(t,/^\\w\\(\\w+\\):/);return{useThirdPerson:e,useUpperCase:r,useComponent:o}}function gve(t){return t.useComponent?\"chore(yarn): \":\"\"}var zvt=new Map([[0,\"create\"],[1,\"delete\"],[2,\"add\"],[3,\"remove\"],[4,\"update\"]]);function vG(t,e){let r=gve(t),o=[],a=e.slice().sort((n,u)=>n[0]-u[0]);for(;a.length>0;){let[n,u]=a.shift(),A=zvt.get(n);t.useUpperCase&&o.length===0&&(A=`${A[0].toUpperCase()}${A.slice(1)}`),t.useThirdPerson&&(A+=\"s\");let p=[u];for(;a.length>0&&a[0][0]===n;){let[,E]=a.shift();p.push(E)}p.sort();let h=p.shift();p.length===1?h+=\" (and one other)\":p.length>1&&(h+=` (and ${p.length} others)`),o.push(`${A} ${h}`)}return`${r}${o.join(\", \")}`}var Jvt=\"Commit generated via `yarn stage`\",Xvt=11;async function dve(t){let{code:e,stdout:r}=await Hr.execvp(\"git\",[\"log\",\"-1\",\"--pretty=format:%H\"],{cwd:t});return e===0?r.trim():null}async function Zvt(t,e){let r=[],o=e.filter(h=>K.basename(h.path)===\"package.json\");for(let{action:h,path:E}of o){let w=K.relative(t,E);if(h===4){let D=await dve(t),{stdout:b}=await Hr.execvp(\"git\",[\"show\",`${D}:${w}`],{cwd:t,strict:!0}),C=await _t.fromText(b),T=await _t.fromFile(E),N=new Map([...T.dependencies,...T.devDependencies]),U=new Map([...C.dependencies,...C.devDependencies]);for(let[z,te]of U){let le=G.stringifyIdent(te),ce=N.get(z);ce?ce.range!==te.range&&r.push([4,`${le} to ${ce.range}`]):r.push([3,le])}for(let[z,te]of N)U.has(z)||r.push([2,G.stringifyIdent(te)])}else if(h===0){let D=await _t.fromFile(E);D.name?r.push([0,G.stringifyIdent(D.name)]):r.push([0,\"a package\"])}else if(h===1){let D=await dve(t),{stdout:b}=await Hr.execvp(\"git\",[\"show\",`${D}:${w}`],{cwd:t,strict:!0}),C=await _t.fromText(b);C.name?r.push([1,G.stringifyIdent(C.name)]):r.push([1,\"a package\"])}else throw new Error(\"Assertion failed: Unsupported action type\")}let{code:a,stdout:n}=await Hr.execvp(\"git\",[\"log\",`-${Xvt}`,\"--pretty=format:%s\"],{cwd:t}),u=a===0?n.split(/\\n/g).filter(h=>h!==\"\"):[],A=BG(u);return vG(A,r)}var $vt={0:[\" A \",\"?? \"],4:[\" M \"],1:[\" D \"]},eDt={0:[\"A  \"],4:[\"M  \"],1:[\"D  \"]},mve={async findRoot(t){return await CG(t,{marker:\".git\"})},async filterChanges(t,e,r,o){let{stdout:a}=await Hr.execvp(\"git\",[\"status\",\"-s\"],{cwd:t,strict:!0}),n=a.toString().split(/\\n/g),u=o?.staged?eDt:$vt;return[].concat(...n.map(p=>{if(p===\"\")return[];let h=p.slice(0,3),E=K.resolve(t,p.slice(3));if(!o?.staged&&h===\"?? \"&&p.endsWith(\"/\"))return wG(E).map(w=>({action:0,path:w}));{let D=[0,4,1].find(b=>u[b].includes(h));return D!==void 0?[{action:D,path:E}]:[]}})).filter(p=>IG(p.path,{roots:e,names:r}))},async genCommitMessage(t,e){return await Zvt(t,e)},async makeStage(t,e){let r=e.map(o=>Ae.fromPortablePath(o.path));await Hr.execvp(\"git\",[\"add\",\"--\",...r],{cwd:t,strict:!0})},async makeCommit(t,e,r){let o=e.map(a=>Ae.fromPortablePath(a.path));await Hr.execvp(\"git\",[\"add\",\"-N\",\"--\",...o],{cwd:t,strict:!0}),await Hr.execvp(\"git\",[\"commit\",\"-m\",`${r}\n\n${Jvt}\n`,\"--\",...o],{cwd:t,strict:!0})},async makeReset(t,e){let r=e.map(o=>Ae.fromPortablePath(o.path));await Hr.execvp(\"git\",[\"reset\",\"HEAD\",\"--\",...r],{cwd:t,strict:!0})}};var tDt=[mve],fI=class extends ut{constructor(){super(...arguments);this.commit=de.Boolean(\"-c,--commit\",!1,{description:\"Commit the staged files\"});this.reset=de.Boolean(\"-r,--reset\",!1,{description:\"Remove all files from the staging area\"});this.dryRun=de.Boolean(\"-n,--dry-run\",!1,{description:\"Print the commit message and the list of modified files without staging / committing\"});this.update=de.Boolean(\"-u,--update\",!1,{hidden:!0})}static{this.paths=[[\"stage\"]]}static{this.usage=st.Usage({description:\"add all yarn files to your vcs\",details:\"\\n      This command will add to your staging area the files belonging to Yarn (typically any modified `package.json` and `.yarnrc.yml` files, but also linker-generated files, cache data, etc). It will take your ignore list into account, so the cache files won't be added if the cache is ignored in a `.gitignore` file (assuming you use Git).\\n\\n      Running `--reset` will instead remove them from the staging area (the changes will still be there, but won't be committed until you stage them back).\\n\\n      Since the staging area is a non-existent concept in Mercurial, Yarn will always create a new commit when running this command on Mercurial repositories. You can get this behavior when using Git by using the `--commit` flag which will directly create a commit.\\n    \",examples:[[\"Adds all modified project files to the staging area\",\"yarn stage\"],[\"Creates a new commit containing all modified project files\",\"yarn stage --commit\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o}=await Qt.find(r,this.context.cwd),{driver:a,root:n}=await rDt(o.cwd),u=[r.get(\"cacheFolder\"),r.get(\"globalFolder\"),r.get(\"virtualFolder\"),r.get(\"yarnPath\")];await r.triggerHook(w=>w.populateYarnPaths,o,w=>{u.push(w)});let A=new Set;for(let w of u)for(let D of nDt(n,w))A.add(D);let p=new Set([r.get(\"rcFilename\"),mr.lockfile,mr.manifest]),h=await a.filterChanges(n,A,p),E=await a.genCommitMessage(n,h);if(this.dryRun)if(this.commit)this.context.stdout.write(`${E}\n`);else for(let w of h)this.context.stdout.write(`${Ae.fromPortablePath(w.path)}\n`);else if(this.reset){let w=await a.filterChanges(n,A,p,{staged:!0});w.length===0?this.context.stdout.write(\"No staged changes found!\"):await a.makeReset(n,w)}else h.length===0?this.context.stdout.write(\"No changes found!\"):this.commit?await a.makeCommit(n,h,E):(await a.makeStage(n,h),this.context.stdout.write(E))}};async function rDt(t){let e=null,r=null;for(let o of tDt)if((r=await o.findRoot(t))!==null){e=o;break}if(e===null||r===null)throw new ot(\"No stage driver has been found for your current project\");return{driver:e,root:r}}function nDt(t,e){let r=[];if(e===null)return r;for(;;){(e===t||e.startsWith(`${t}/`))&&r.push(e);let o;try{o=ae.statSync(e)}catch{break}if(o.isSymbolicLink())e=K.resolve(K.dirname(e),ae.readlinkSync(e));else break}return r}var iDt={commands:[fI]},sDt=iDt;var PG={};Kt(PG,{default:()=>pDt});Ke();Ke();Pt();var Cve=et(ni());Ke();var yve=et(N6()),oDt=\"e8e1bd300d860104bb8c58453ffa1eb4\",aDt=\"OFCNCOG2CU\",Eve=async(t,e)=>{let r=G.stringifyIdent(t),a=lDt(e).initIndex(\"npm-search\");try{return(await a.getObject(r,{attributesToRetrieve:[\"types\"]})).types?.ts===\"definitely-typed\"}catch{return!1}},lDt=t=>(0,yve.default)(aDt,oDt,{requester:{async send(r){try{let o=await on.request(r.url,r.data||null,{configuration:t,headers:r.headers});return{content:o.body,isTimedOut:!1,status:o.statusCode}}catch(o){return{content:o.response.body,isTimedOut:!1,status:o.response.statusCode}}}}});var Ive=t=>t.scope?`${t.scope}__${t.name}`:`${t.name}`,cDt=async(t,e,r,o)=>{if(r.scope===\"types\")return;let{project:a}=t,{configuration:n}=a;if(!(n.get(\"tsEnableAutoTypes\")??(ae.existsSync(K.join(t.cwd,\"tsconfig.json\"))||ae.existsSync(K.join(a.cwd,\"tsconfig.json\")))))return;let A=n.makeResolver(),p={project:a,resolver:A,report:new Ri};if(!await Eve(r,n))return;let E=Ive(r),w=G.parseRange(r.range).selector;if(!Ur.validRange(w)){let N=n.normalizeDependency(r),U=await A.getCandidates(N,{},p);w=G.parseRange(U[0].reference).selector}let D=Cve.default.coerce(w);if(D===null)return;let b=`${nu.Modifier.CARET}${D.major}`,C=G.makeDescriptor(G.makeIdent(\"types\",E),b),T=qe.mapAndFind(a.workspaces,N=>{let U=N.manifest.dependencies.get(r.identHash)?.descriptorHash,z=N.manifest.devDependencies.get(r.identHash)?.descriptorHash;if(U!==r.descriptorHash&&z!==r.descriptorHash)return qe.mapAndFind.skip;let te=[];for(let le of _t.allDependencies){let ce=N.manifest[le].get(C.identHash);typeof ce>\"u\"||te.push([le,ce])}return te.length===0?qe.mapAndFind.skip:te});if(typeof T<\"u\")for(let[N,U]of T)t.manifest[N].set(U.identHash,U);else{try{let N=n.normalizeDependency(C);if((await A.getCandidates(N,{},p)).length===0)return}catch{return}t.manifest[nu.Target.DEVELOPMENT].set(C.identHash,C)}},uDt=async(t,e,r)=>{if(r.scope===\"types\")return;let{project:o}=t,{configuration:a}=o;if(!(a.get(\"tsEnableAutoTypes\")??(ae.existsSync(K.join(t.cwd,\"tsconfig.json\"))||ae.existsSync(K.join(o.cwd,\"tsconfig.json\")))))return;let u=Ive(r),A=G.makeIdent(\"types\",u);for(let p of _t.allDependencies)typeof t.manifest[p].get(A.identHash)>\"u\"||t.manifest[p].delete(A.identHash)},ADt=(t,e)=>{e.publishConfig&&e.publishConfig.typings&&(e.typings=e.publishConfig.typings),e.publishConfig&&e.publishConfig.types&&(e.types=e.publishConfig.types)},fDt={configuration:{tsEnableAutoTypes:{description:\"Whether Yarn should auto-install @types/ dependencies on 'yarn add'\",type:\"BOOLEAN\",isNullable:!0,default:null}},hooks:{afterWorkspaceDependencyAddition:cDt,afterWorkspaceDependencyRemoval:uDt,beforeWorkspacePacking:ADt}},pDt=fDt;var QG={};Kt(QG,{VersionApplyCommand:()=>mI,VersionCheckCommand:()=>yI,VersionCommand:()=>EI,default:()=>FDt,versionUtils:()=>dI});Ke();Ke();Gt();var dI={};Kt(dI,{Decision:()=>hI,applyPrerelease:()=>Sve,applyReleases:()=>kG,applyStrategy:()=>MF,clearVersionFiles:()=>SG,getUndecidedDependentWorkspaces:()=>aD,getUndecidedWorkspaces:()=>OF,openVersionFile:()=>gI,requireMoreDecisions:()=>bDt,resolveVersionFiles:()=>oD,suggestStrategy:()=>bG,updateVersionFiles:()=>xG,validateReleaseDecision:()=>pI});Ke();Pt();Ol();Gt();var Pve=et(Dve()),PA=et(ni()),xDt=/^(>=|[~^]|)(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(-(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\\+[0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)?$/,hI=(u=>(u.UNDECIDED=\"undecided\",u.DECLINE=\"decline\",u.MAJOR=\"major\",u.MINOR=\"minor\",u.PATCH=\"patch\",u.PRERELEASE=\"prerelease\",u))(hI||{});function pI(t){let e=PA.default.valid(t);return e||qe.validateEnum((0,Pve.default)(hI,\"UNDECIDED\"),t)}async function oD(t,{prerelease:e=null}={}){let r=new Map,o=t.configuration.get(\"deferredVersionFolder\");if(!ae.existsSync(o))return r;let a=await ae.readdirPromise(o);for(let n of a){if(!n.endsWith(\".yml\"))continue;let u=K.join(o,n),A=await ae.readFilePromise(u,\"utf8\"),p=Ki(A);for(let[h,E]of Object.entries(p.releases||{})){if(E===\"decline\")continue;let w=G.parseIdent(h),D=t.tryWorkspaceByIdent(w);if(D===null)throw new Error(`Assertion failed: Expected a release definition file to only reference existing workspaces (${K.basename(u)} references ${h})`);if(D.manifest.version===null)throw new Error(`Assertion failed: Expected the workspace to have a version (${G.prettyLocator(t.configuration,D.anchoredLocator)})`);let b=D.manifest.raw.stableVersion??D.manifest.version,C=r.get(D),T=MF(b,pI(E));if(T===null)throw new Error(`Assertion failed: Expected ${b} to support being bumped via strategy ${E}`);let N=typeof C<\"u\"?PA.default.gt(T,C)?T:C:T;r.set(D,N)}}return e&&(r=new Map([...r].map(([n,u])=>[n,Sve(u,{current:n.manifest.version,prerelease:e})]))),r}async function SG(t){let e=t.configuration.get(\"deferredVersionFolder\");ae.existsSync(e)&&await ae.removePromise(e)}async function xG(t,e){let r=new Set(e),o=t.configuration.get(\"deferredVersionFolder\");if(!ae.existsSync(o))return;let a=await ae.readdirPromise(o);for(let n of a){if(!n.endsWith(\".yml\"))continue;let u=K.join(o,n),A=await ae.readFilePromise(u,\"utf8\"),p=Ki(A),h=p?.releases;if(h){for(let E of Object.keys(h)){let w=G.parseIdent(E),D=t.tryWorkspaceByIdent(w);(D===null||r.has(D))&&delete p.releases[E]}Object.keys(p.releases).length>0?await ae.changeFilePromise(u,Pa(new Pa.PreserveOrdering(p))):await ae.unlinkPromise(u)}}}async function gI(t,{allowEmpty:e=!1}={}){let r=t.configuration;if(r.projectCwd===null)throw new ot(\"This command can only be run from within a Yarn project\");let o=await ra.fetchRoot(r.projectCwd),a=o!==null?await ra.fetchBase(o,{baseRefs:r.get(\"changesetBaseRefs\")}):null,n=o!==null?await ra.fetchChangedFiles(o,{base:a.hash,project:t}):[],u=r.get(\"deferredVersionFolder\"),A=n.filter(b=>K.contains(u,b)!==null);if(A.length>1)throw new ot(`Your current branch contains multiple versioning files; this isn't supported:\n- ${A.map(b=>Ae.fromPortablePath(b)).join(`\n- `)}`);let p=new Set(qe.mapAndFilter(n,b=>{let C=t.tryWorkspaceByFilePath(b);return C===null?qe.mapAndFilter.skip:C}));if(A.length===0&&p.size===0&&!e)return null;let h=A.length===1?A[0]:K.join(u,`${bn.makeHash(Math.random().toString()).slice(0,8)}.yml`),E=ae.existsSync(h)?await ae.readFilePromise(h,\"utf8\"):\"{}\",w=Ki(E),D=new Map;for(let b of w.declined||[]){let C=G.parseIdent(b),T=t.getWorkspaceByIdent(C);D.set(T,\"decline\")}for(let[b,C]of Object.entries(w.releases||{})){let T=G.parseIdent(b),N=t.getWorkspaceByIdent(T);D.set(N,pI(C))}return{project:t,root:o,baseHash:a!==null?a.hash:null,baseTitle:a!==null?a.title:null,changedFiles:new Set(n),changedWorkspaces:p,releaseRoots:new Set([...p].filter(b=>b.manifest.version!==null)),releases:D,async saveAll(){let b={},C=[],T=[];for(let N of t.workspaces){if(N.manifest.version===null)continue;let U=G.stringifyIdent(N.anchoredLocator),z=D.get(N);z===\"decline\"?C.push(U):typeof z<\"u\"?b[U]=pI(z):p.has(N)&&T.push(U)}await ae.mkdirPromise(K.dirname(h),{recursive:!0}),await ae.changeFilePromise(h,Pa(new Pa.PreserveOrdering({releases:Object.keys(b).length>0?b:void 0,declined:C.length>0?C:void 0,undecided:T.length>0?T:void 0})))}}}function bDt(t){return OF(t).size>0||aD(t).length>0}function OF(t){let e=new Set;for(let r of t.changedWorkspaces)r.manifest.version!==null&&(t.releases.has(r)||e.add(r));return e}function aD(t,{include:e=new Set}={}){let r=[],o=new Map(qe.mapAndFilter([...t.releases],([n,u])=>u===\"decline\"?qe.mapAndFilter.skip:[n.anchoredLocator.locatorHash,n])),a=new Map(qe.mapAndFilter([...t.releases],([n,u])=>u!==\"decline\"?qe.mapAndFilter.skip:[n.anchoredLocator.locatorHash,n]));for(let n of t.project.workspaces)if(!(!e.has(n)&&(a.has(n.anchoredLocator.locatorHash)||o.has(n.anchoredLocator.locatorHash)))&&n.manifest.version!==null)for(let u of _t.hardDependencies)for(let A of n.manifest.getForScope(u).values()){let p=t.project.tryWorkspaceByDescriptor(A);p!==null&&o.has(p.anchoredLocator.locatorHash)&&r.push([n,p])}return r}function bG(t,e){let r=PA.default.clean(e);for(let o of Object.values(hI))if(o!==\"undecided\"&&o!==\"decline\"&&PA.default.inc(t,o)===r)return o;return null}function MF(t,e){if(PA.default.valid(e))return e;if(t===null)throw new ot(`Cannot apply the release strategy \"${e}\" unless the workspace already has a valid version`);if(!PA.default.valid(t))throw new ot(`Cannot apply the release strategy \"${e}\" on a non-semver version (${t})`);let r=PA.default.inc(t,e);if(r===null)throw new ot(`Cannot apply the release strategy \"${e}\" on the specified version (${t})`);return r}function kG(t,e,{report:r}){let o=new Map;for(let a of t.workspaces)for(let n of _t.allDependencies)for(let u of a.manifest[n].values()){let A=t.tryWorkspaceByDescriptor(u);if(A===null||!e.has(A))continue;qe.getArrayWithDefault(o,A).push([a,n,u.identHash])}for(let[a,n]of e){let u=a.manifest.version;a.manifest.version=n,PA.default.prerelease(n)===null?delete a.manifest.raw.stableVersion:a.manifest.raw.stableVersion||(a.manifest.raw.stableVersion=u);let A=a.manifest.name!==null?G.stringifyIdent(a.manifest.name):null;r.reportInfo(0,`${G.prettyLocator(t.configuration,a.anchoredLocator)}: Bumped to ${n}`),r.reportJson({cwd:Ae.fromPortablePath(a.cwd),ident:A,oldVersion:u,newVersion:n});let p=o.get(a);if(!(typeof p>\"u\"))for(let[h,E,w]of p){let D=h.manifest[E].get(w);if(typeof D>\"u\")throw new Error(\"Assertion failed: The dependency should have existed\");let b=D.range,C=!1;if(b.startsWith(ci.protocol)&&(b=b.slice(ci.protocol.length),C=!0,b===a.relativeCwd))continue;let T=b.match(xDt);if(!T){r.reportWarning(0,`Couldn't auto-upgrade range ${b} (in ${G.prettyLocator(t.configuration,h.anchoredLocator)})`);continue}let N=`${T[1]}${n}`;C&&(N=`${ci.protocol}${N}`);let U=G.makeDescriptor(D,N);h.manifest[E].set(w,U)}}}var kDt=new Map([[\"%n\",{extract:t=>t.length>=1?[t[0],t.slice(1)]:null,generate:(t=0)=>`${t+1}`}]]);function Sve(t,{current:e,prerelease:r}){let o=new PA.default.SemVer(e),a=o.prerelease.slice(),n=[];o.prerelease=[],o.format()!==t&&(a.length=0);let u=!0,A=r.split(/\\./g);for(let p of A){let h=kDt.get(p);if(typeof h>\"u\")n.push(p),a[0]===p?a.shift():u=!1;else{let E=u?h.extract(a):null;E!==null&&typeof E[0]==\"number\"?(n.push(h.generate(E[0])),a=E[1]):(n.push(h.generate()),u=!1)}}return o.prerelease&&(o.prerelease=[]),`${t}-${n.join(\".\")}`}var mI=class extends ut{constructor(){super(...arguments);this.all=de.Boolean(\"--all\",!1,{description:\"Apply the deferred version changes on all workspaces\"});this.dryRun=de.Boolean(\"--dry-run\",!1,{description:\"Print the versions without actually generating the package archive\"});this.prerelease=de.String(\"--prerelease\",{description:\"Add a prerelease identifier to new versions\",tolerateBoolean:!0});this.recursive=de.Boolean(\"-R,--recursive\",{description:\"Release the transitive workspaces as well\"});this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"})}static{this.paths=[[\"version\",\"apply\"]]}static{this.usage=st.Usage({category:\"Release-related commands\",description:\"apply all the deferred version bumps at once\",details:`\n      This command will apply the deferred version changes and remove their definitions from the repository.\n\n      Note that if \\`--prerelease\\` is set, the given prerelease identifier (by default \\`rc.%n\\`) will be used on all new versions and the version definitions will be kept as-is.\n\n      By default only the current workspace will be bumped, but you can configure this behavior by using one of:\n\n      - \\`--recursive\\` to also apply the version bump on its dependencies\n      - \\`--all\\` to apply the version bump on all packages in the repository\n\n      Note that this command will also update the \\`workspace:\\` references across all your local workspaces, thus ensuring that they keep referring to the same workspaces even after the version bump.\n    `,examples:[[\"Apply the version change to the local workspace\",\"yarn version apply\"],[\"Apply the version change to all the workspaces in the local workspace\",\"yarn version apply --all\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Wr.find(r);if(!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState({restoreResolutions:!1});let u=await Lt.start({configuration:r,json:this.json,stdout:this.context.stdout},async A=>{let p=this.prerelease?typeof this.prerelease!=\"boolean\"?this.prerelease:\"rc.%n\":null,h=await oD(o,{prerelease:p}),E=new Map;if(this.all)E=h;else{let w=this.recursive?a.getRecursiveWorkspaceDependencies():[a];for(let D of w){let b=h.get(D);typeof b<\"u\"&&E.set(D,b)}}if(E.size===0){let w=h.size>0?\" Did you want to add --all?\":\"\";A.reportWarning(0,`The current workspace doesn't seem to require a version bump.${w}`);return}kG(o,E,{report:A}),this.dryRun||(p||(this.all?await SG(o):await xG(o,[...E.keys()])),A.reportSeparator())});return this.dryRun||u.hasErrors()?u.exitCode():await o.installWithNewReport({json:this.json,stdout:this.context.stdout},{cache:n})}};Ke();Pt();Gt();var UF=et(ni());var yI=class extends ut{constructor(){super(...arguments);this.interactive=de.Boolean(\"-i,--interactive\",{description:\"Open an interactive interface used to set version bumps\"})}static{this.paths=[[\"version\",\"check\"]]}static{this.usage=st.Usage({category:\"Release-related commands\",description:\"check that all the relevant packages have been bumped\",details:\"\\n      **Warning:** This command currently requires Git.\\n\\n      This command will check that all the packages covered by the files listed in argument have been properly bumped or declined to bump.\\n\\n      In the case of a bump, the check will also cover transitive packages - meaning that should `Foo` be bumped, a package `Bar` depending on `Foo` will require a decision as to whether `Bar` will need to be bumped. This check doesn't cross packages that have declined to bump.\\n\\n      In case no arguments are passed to the function, the list of modified files will be generated by comparing the HEAD against `master`.\\n    \",examples:[[\"Check whether the modified packages need a bump\",\"yarn version check\"]]})}async execute(){return this.interactive?await this.executeInteractive():await this.executeStandard()}async executeInteractive(){AC(this.context);let{Gem:r}=await Promise.resolve().then(()=>(UQ(),oj)),{ScrollableItems:o}=await Promise.resolve().then(()=>(jQ(),qQ)),{FocusRequest:a}=await Promise.resolve().then(()=>(lj(),Qwe)),{useListInput:n}=await Promise.resolve().then(()=>(HQ(),Fwe)),{renderForm:u}=await Promise.resolve().then(()=>(KQ(),YQ)),{Box:A,Text:p}=await Promise.resolve().then(()=>et(ac())),{default:h,useCallback:E,useState:w}=await Promise.resolve().then(()=>et(ln())),D=await Je.find(this.context.cwd,this.context.plugins),{project:b,workspace:C}=await Qt.find(D,this.context.cwd);if(!C)throw new or(b.cwd,this.context.cwd);await b.restoreInstallState();let T=await gI(b);if(T===null||T.releaseRoots.size===0)return 0;if(T.root===null)throw new ot(\"This command can only be run on Git repositories\");let N=()=>h.createElement(A,{flexDirection:\"row\",paddingBottom:1},h.createElement(A,{flexDirection:\"column\",width:60},h.createElement(A,null,h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<up>\"),\"/\",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<down>\"),\" to select workspaces.\")),h.createElement(A,null,h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<left>\"),\"/\",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<right>\"),\" to select release strategies.\"))),h.createElement(A,{flexDirection:\"column\"},h.createElement(A,{marginLeft:1},h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<enter>\"),\" to save.\")),h.createElement(A,{marginLeft:1},h.createElement(p,null,\"Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<ctrl+c>\"),\" to abort.\")))),U=({workspace:Ie,active:he,decision:De,setDecision:Ee})=>{let g=Ie.manifest.raw.stableVersion??Ie.manifest.version;if(g===null)throw new Error(`Assertion failed: The version should have been set (${G.prettyLocator(D,Ie.anchoredLocator)})`);if(UF.default.prerelease(g)!==null)throw new Error(`Assertion failed: Prerelease identifiers shouldn't be found (${g})`);let me=[\"undecided\",\"decline\",\"patch\",\"minor\",\"major\"];n(De,me,{active:he,minus:\"left\",plus:\"right\",set:Ee});let Ce=De===\"undecided\"?h.createElement(p,{color:\"yellow\"},g):De===\"decline\"?h.createElement(p,{color:\"green\"},g):h.createElement(p,null,h.createElement(p,{color:\"magenta\"},g),\" \\u2192 \",h.createElement(p,{color:\"green\"},UF.default.valid(De)?De:UF.default.inc(g,De)));return h.createElement(A,{flexDirection:\"column\"},h.createElement(A,null,h.createElement(p,null,G.prettyLocator(D,Ie.anchoredLocator),\" - \",Ce)),h.createElement(A,null,me.map(fe=>h.createElement(A,{key:fe,paddingLeft:2},h.createElement(p,null,h.createElement(r,{active:fe===De}),\" \",fe)))))},z=Ie=>{let he=new Set(T.releaseRoots),De=new Map([...Ie].filter(([Ee])=>he.has(Ee)));for(;;){let Ee=aD({project:T.project,releases:De}),g=!1;if(Ee.length>0){for(let[me]of Ee)if(!he.has(me)){he.add(me),g=!0;let Ce=Ie.get(me);typeof Ce<\"u\"&&De.set(me,Ce)}}if(!g)break}return{relevantWorkspaces:he,relevantReleases:De}},te=()=>{let[Ie,he]=w(()=>new Map(T.releases)),De=E((Ee,g)=>{let me=new Map(Ie);g!==\"undecided\"?me.set(Ee,g):me.delete(Ee);let{relevantReleases:Ce}=z(me);he(Ce)},[Ie,he]);return[Ie,De]},le=({workspaces:Ie,releases:he})=>{let De=[];De.push(`${Ie.size} total`);let Ee=0,g=0;for(let me of Ie){let Ce=he.get(me);typeof Ce>\"u\"?g+=1:Ce!==\"decline\"&&(Ee+=1)}return De.push(`${Ee} release${Ee===1?\"\":\"s\"}`),De.push(`${g} remaining`),h.createElement(p,{color:\"yellow\"},De.join(\", \"))},ue=await u(({useSubmit:Ie})=>{let[he,De]=te();Ie(he);let{relevantWorkspaces:Ee}=z(he),g=new Set([...Ee].filter(ie=>!T.releaseRoots.has(ie))),[me,Ce]=w(0),fe=E(ie=>{switch(ie){case a.BEFORE:Ce(me-1);break;case a.AFTER:Ce(me+1);break}},[me,Ce]);return h.createElement(A,{flexDirection:\"column\"},h.createElement(N,null),h.createElement(A,null,h.createElement(p,{wrap:\"wrap\"},\"The following files have been modified in your local checkout.\")),h.createElement(A,{flexDirection:\"column\",marginTop:1,paddingLeft:2},[...T.changedFiles].map(ie=>h.createElement(A,{key:ie},h.createElement(p,null,h.createElement(p,{color:\"grey\"},Ae.fromPortablePath(T.root)),Ae.sep,Ae.relative(Ae.fromPortablePath(T.root),Ae.fromPortablePath(ie)))))),T.releaseRoots.size>0&&h.createElement(h.Fragment,null,h.createElement(A,{marginTop:1},h.createElement(p,{wrap:\"wrap\"},\"Because of those files having been modified, the following workspaces may need to be released again (note that private workspaces are also shown here, because even though they won't be published, releasing them will allow us to flag their dependents for potential re-release):\")),g.size>3?h.createElement(A,{marginTop:1},h.createElement(le,{workspaces:T.releaseRoots,releases:he})):null,h.createElement(A,{marginTop:1,flexDirection:\"column\"},h.createElement(o,{active:me%2===0,radius:1,size:2,onFocusRequest:fe},[...T.releaseRoots].map(ie=>h.createElement(U,{key:ie.cwd,workspace:ie,decision:he.get(ie)||\"undecided\",setDecision:Z=>De(ie,Z)}))))),g.size>0?h.createElement(h.Fragment,null,h.createElement(A,{marginTop:1},h.createElement(p,{wrap:\"wrap\"},\"The following workspaces depend on other workspaces that have been marked for release, and thus may need to be released as well:\")),h.createElement(A,null,h.createElement(p,null,\"(Press \",h.createElement(p,{bold:!0,color:\"cyanBright\"},\"<tab>\"),\" to move the focus between the workspace groups.)\")),g.size>5?h.createElement(A,{marginTop:1},h.createElement(le,{workspaces:g,releases:he})):null,h.createElement(A,{marginTop:1,flexDirection:\"column\"},h.createElement(o,{active:me%2===1,radius:2,size:2,onFocusRequest:fe},[...g].map(ie=>h.createElement(U,{key:ie.cwd,workspace:ie,decision:he.get(ie)||\"undecided\",setDecision:Z=>De(ie,Z)}))))):null)},{versionFile:T},{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});if(typeof ue>\"u\")return 1;T.releases.clear();for(let[Ie,he]of ue)T.releases.set(Ie,he);await T.saveAll()}async executeStandard(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);return await o.restoreInstallState(),(await Lt.start({configuration:r,stdout:this.context.stdout},async u=>{let A=await gI(o);if(A===null||A.releaseRoots.size===0)return;if(A.root===null)throw new ot(\"This command can only be run on Git repositories\");if(u.reportInfo(0,`Your PR was started right after ${pe.pretty(r,A.baseHash.slice(0,7),\"yellow\")} ${pe.pretty(r,A.baseTitle,\"magenta\")}`),A.changedFiles.size>0){u.reportInfo(0,\"You have changed the following files since then:\"),u.reportSeparator();for(let D of A.changedFiles)u.reportInfo(null,`${pe.pretty(r,Ae.fromPortablePath(A.root),\"gray\")}${Ae.sep}${Ae.relative(Ae.fromPortablePath(A.root),Ae.fromPortablePath(D))}`)}let p=!1,h=!1,E=OF(A);if(E.size>0){p||u.reportSeparator();for(let D of E)u.reportError(0,`${G.prettyLocator(r,D.anchoredLocator)} has been modified but doesn't have a release strategy attached`);p=!0}let w=aD(A);for(let[D,b]of w)h||u.reportSeparator(),u.reportError(0,`${G.prettyLocator(r,D.anchoredLocator)} doesn't have a release strategy attached, but depends on ${G.prettyWorkspace(r,b)} which is planned for release.`),h=!0;(p||h)&&(u.reportSeparator(),u.reportInfo(0,\"This command detected that at least some workspaces have received modifications without explicit instructions as to how they had to be released (if needed).\"),u.reportInfo(0,\"To correct these errors, run `yarn version check --interactive` then follow the instructions.\"))})).exitCode()}};Ke();Gt();var _F=et(ni());var EI=class extends ut{constructor(){super(...arguments);this.deferred=de.Boolean(\"-d,--deferred\",{description:\"Prepare the version to be bumped during the next release cycle\"});this.immediate=de.Boolean(\"-i,--immediate\",{description:\"Bump the version immediately\"});this.strategy=de.String()}static{this.paths=[[\"version\"]]}static{this.usage=st.Usage({category:\"Release-related commands\",description:\"apply a new version to the current package\",details:\"\\n      This command will bump the version number for the given package, following the specified strategy:\\n\\n      - If `major`, the first number from the semver range will be increased (`X.0.0`).\\n      - If `minor`, the second number from the semver range will be increased (`0.X.0`).\\n      - If `patch`, the third number from the semver range will be increased (`0.0.X`).\\n      - If prefixed by `pre` (`premajor`, ...), a `-0` suffix will be set (`0.0.0-0`).\\n      - If `prerelease`, the suffix will be increased (`0.0.0-X`); the third number from the semver range will also be increased if there was no suffix in the previous version.\\n      - If `decline`, the nonce will be increased for `yarn version check` to pass without version bump.\\n      - If a valid semver range, it will be used as new version.\\n      - If unspecified, Yarn will ask you for guidance.\\n\\n      For more information about the `--deferred` flag, consult our documentation (https://yarnpkg.com/features/release-workflow#deferred-versioning).\\n    \",examples:[[\"Immediately bump the version to the next major\",\"yarn version major\"],[\"Prepare the version to be bumped to the next major\",\"yarn version major --deferred\"]]})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!a)throw new or(o.cwd,this.context.cwd);let n=r.get(\"preferDeferredVersions\");this.deferred&&(n=!0),this.immediate&&(n=!1);let u=_F.default.valid(this.strategy),A=this.strategy===\"decline\",p;if(u)if(a.manifest.version!==null){let E=bG(a.manifest.version,this.strategy);E!==null?p=E:p=this.strategy}else p=this.strategy;else{let E=a.manifest.version;if(!A){if(E===null)throw new ot(\"Can't bump the version if there wasn't a version to begin with - use 0.0.0 as initial version then run the command again.\");if(typeof E!=\"string\"||!_F.default.valid(E))throw new ot(`Can't bump the version (${E}) if it's not valid semver`)}p=pI(this.strategy)}if(!n){let w=(await oD(o)).get(a);if(typeof w<\"u\"&&p!==\"decline\"){let D=MF(a.manifest.version,p);if(_F.default.lt(D,w))throw new ot(`Can't bump the version to one that would be lower than the current deferred one (${w})`)}}let h=await gI(o,{allowEmpty:!0});return h.releases.set(a,p),await h.saveAll(),n?0:await this.cli.run([\"version\",\"apply\"])}};var QDt={configuration:{deferredVersionFolder:{description:\"Folder where are stored the versioning files\",type:\"ABSOLUTE_PATH\",default:\"./.yarn/versions\"},preferDeferredVersions:{description:\"If true, running `yarn version` will assume the `--deferred` flag unless `--immediate` is set\",type:\"BOOLEAN\",default:!1}},commands:[mI,yI,EI]},FDt=QDt;var FG={};Kt(FG,{WorkspacesFocusCommand:()=>CI,WorkspacesForeachCommand:()=>wI,default:()=>LDt});Ke();Ke();Gt();var CI=class extends ut{constructor(){super(...arguments);this.json=de.Boolean(\"--json\",!1,{description:\"Format the output as an NDJSON stream\"});this.production=de.Boolean(\"--production\",!1,{description:\"Only install regular dependencies by omitting dev dependencies\"});this.all=de.Boolean(\"-A,--all\",!1,{description:\"Install the entire project\"});this.workspaces=de.Rest()}static{this.paths=[[\"workspaces\",\"focus\"]]}static{this.usage=st.Usage({category:\"Workspace-related commands\",description:\"install a single workspace and its dependencies\",details:\"\\n      This command will run an install as if the specified workspaces (and all other workspaces they depend on) were the only ones in the project. If no workspaces are explicitly listed, the active one will be assumed.\\n\\n      Note that this command is only very moderately useful when using zero-installs, since the cache will contain all the packages anyway - meaning that the only difference between a full install and a focused install would just be a few extra lines in the `.pnp.cjs` file, at the cost of introducing an extra complexity.\\n\\n      If the `-A,--all` flag is set, the entire project will be installed. Combine with `--production` to replicate the old `yarn install --production`.\\n    \"})}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd),n=await Wr.find(r);await o.restoreInstallState({restoreResolutions:!1});let u;if(this.all)u=new Set(o.workspaces);else if(this.workspaces.length===0){if(!a)throw new or(o.cwd,this.context.cwd);u=new Set([a])}else u=new Set(this.workspaces.map(A=>o.getWorkspaceByIdent(G.parseIdent(A))));for(let A of u)for(let p of this.production?[\"dependencies\"]:_t.hardDependencies)for(let h of A.manifest.getForScope(p).values()){let E=o.tryWorkspaceByDescriptor(h);E!==null&&u.add(E)}for(let A of o.workspaces)u.has(A)?this.production&&A.manifest.devDependencies.clear():(A.manifest.installConfig=A.manifest.installConfig||{},A.manifest.installConfig.selfReferences=!1,A.manifest.dependencies.clear(),A.manifest.devDependencies.clear(),A.manifest.peerDependencies.clear(),A.manifest.scripts.clear());return await o.installWithNewReport({json:this.json,stdout:this.context.stdout},{cache:n,persistProject:!1})}};Ke();Ke();Ke();Gt();var II=et(Xo()),bve=et(lg());il();var wI=class extends ut{constructor(){super(...arguments);this.from=de.Array(\"--from\",{description:\"An array of glob pattern idents or paths from which to base any recursion\"});this.all=de.Boolean(\"-A,--all\",{description:\"Run the command on all workspaces of a project\"});this.recursive=de.Boolean(\"-R,--recursive\",{description:\"Run the command on the current workspace and all of its recursive dependencies\"});this.worktree=de.Boolean(\"-W,--worktree\",{description:\"Run the command on all workspaces of the current worktree\"});this.verbose=de.Counter(\"-v,--verbose\",{description:\"Increase level of logging verbosity up to 2 times\"});this.parallel=de.Boolean(\"-p,--parallel\",!1,{description:\"Run the commands in parallel\"});this.interlaced=de.Boolean(\"-i,--interlaced\",!1,{description:\"Print the output of commands in real-time instead of buffering it\"});this.jobs=de.String(\"-j,--jobs\",{description:\"The maximum number of parallel tasks that the execution will be limited to; or `unlimited`\",validator:pL([js([\"unlimited\"]),vw(fL(),[gL(),hL(1)])])});this.topological=de.Boolean(\"-t,--topological\",!1,{description:\"Run the command after all workspaces it depends on (regular) have finished\"});this.topologicalDev=de.Boolean(\"--topological-dev\",!1,{description:\"Run the command after all workspaces it depends on (regular + dev) have finished\"});this.include=de.Array(\"--include\",[],{description:\"An array of glob pattern idents or paths; only matching workspaces will be traversed\"});this.exclude=de.Array(\"--exclude\",[],{description:\"An array of glob pattern idents or paths; matching workspaces won't be traversed\"});this.publicOnly=de.Boolean(\"--no-private\",{description:\"Avoid running the command on private workspaces\"});this.since=de.String(\"--since\",{description:\"Only include workspaces that have been changed since the specified ref.\",tolerateBoolean:!0});this.dryRun=de.Boolean(\"-n,--dry-run\",{description:\"Print the commands that would be run, without actually running them\"});this.commandName=de.String();this.args=de.Proxy()}static{this.paths=[[\"workspaces\",\"foreach\"]]}static{this.usage=st.Usage({category:\"Workspace-related commands\",description:\"run a command on all workspaces\",details:\"\\n      This command will run a given sub-command on current and all its descendant workspaces. Various flags can alter the exact behavior of the command:\\n\\n      - If `-p,--parallel` is set, the commands will be ran in parallel; they'll by default be limited to a number of parallel tasks roughly equal to half your core number, but that can be overridden via `-j,--jobs`, or disabled by setting `-j unlimited`.\\n\\n      - If `-p,--parallel` and `-i,--interlaced` are both set, Yarn will print the lines from the output as it receives them. If `-i,--interlaced` wasn't set, it would instead buffer the output from each process and print the resulting buffers only after their source processes have exited.\\n\\n      - If `-t,--topological` is set, Yarn will only run the command after all workspaces that it depends on through the `dependencies` field have successfully finished executing. If `--topological-dev` is set, both the `dependencies` and `devDependencies` fields will be considered when figuring out the wait points.\\n\\n      - If `-A,--all` is set, Yarn will run the command on all the workspaces of a project.\\n\\n      - If `-R,--recursive` is set, Yarn will find workspaces to run the command on by recursively evaluating `dependencies` and `devDependencies` fields, instead of looking at the `workspaces` fields.\\n\\n      - If `-W,--worktree` is set, Yarn will find workspaces to run the command on by looking at the current worktree.\\n\\n      - If `--from` is set, Yarn will use the packages matching the 'from' glob as the starting point for any recursive search.\\n\\n      - If `--since` is set, Yarn will only run the command on workspaces that have been modified since the specified ref. By default Yarn will use the refs specified by the `changesetBaseRefs` configuration option.\\n\\n      - If `--dry-run` is set, Yarn will explain what it would do without actually doing anything.\\n\\n      - The command may apply to only some workspaces through the use of `--include` which acts as a whitelist. The `--exclude` flag will do the opposite and will be a list of packages that mustn't execute the script. Both flags accept glob patterns (if valid Idents and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them.\\n\\n      The `-v,--verbose` flag can be passed up to twice: once to prefix output lines with the originating workspace's name, and again to include start/finish/timing log lines. Maximum verbosity is enabled by default in terminal environments.\\n\\n      If the command is `run` and the script being run does not exist the child workspace will be skipped without error.\\n    \",examples:[[\"Publish all packages\",\"yarn workspaces foreach -A npm publish --tolerate-republish\"],[\"Run the build script on all descendant packages\",\"yarn workspaces foreach -A run build\"],[\"Run the build script on current and all descendant packages in parallel, building package dependencies first\",\"yarn workspaces foreach -Apt run build\"],[\"Run the build script on several packages and all their dependencies, building dependencies first\",\"yarn workspaces foreach -Rpt --from '{workspace-a,workspace-b}' run build\"]]})}static{this.schema=[Pw(\"all\",Ku.Forbids,[\"from\",\"recursive\",\"since\",\"worktree\"],{missingIf:\"undefined\"}),dL([\"all\",\"recursive\",\"since\",\"worktree\"],{missingIf:\"undefined\"})]}async execute(){let r=await Je.find(this.context.cwd,this.context.plugins),{project:o,workspace:a}=await Qt.find(r,this.context.cwd);if(!this.all&&!a)throw new or(o.cwd,this.context.cwd);await o.restoreInstallState();let n=this.cli.process([this.commandName,...this.args]),u=n.path.length===1&&n.path[0]===\"run\"&&typeof n.scriptName<\"u\"?n.scriptName:null;if(n.path.length===0)throw new ot(\"Invalid subcommand name for iteration - use the 'run' keyword if you wish to execute a script\");let A=Ee=>{this.dryRun&&this.context.stdout.write(`${Ee}\n`)},p=()=>{let Ee=this.from.map(g=>II.default.matcher(g));return o.workspaces.filter(g=>{let me=G.stringifyIdent(g.anchoredLocator),Ce=g.relativeCwd;return Ee.some(fe=>fe(me)||fe(Ce))})},h=[];if(this.since?(A(\"Option --since is set; selecting the changed workspaces as root for workspace selection\"),h=Array.from(await ra.fetchChangedWorkspaces({ref:this.since,project:o}))):this.from?(A(\"Option --from is set; selecting the specified workspaces\"),h=[...p()]):this.worktree?(A(\"Option --worktree is set; selecting the current workspace\"),h=[a]):this.recursive?(A(\"Option --recursive is set; selecting the current workspace\"),h=[a]):this.all&&(A(\"Option --all is set; selecting all workspaces\"),h=[...o.workspaces]),this.dryRun&&!this.all){for(let Ee of h)A(`\n- ${Ee.relativeCwd}\n  ${G.prettyLocator(r,Ee.anchoredLocator)}`);h.length>0&&A(\"\")}let E;if(this.recursive?this.since?(A(\"Option --recursive --since is set; recursively selecting all dependent workspaces\"),E=new Set(h.map(Ee=>[...Ee.getRecursiveWorkspaceDependents()]).flat())):(A(\"Option --recursive is set; recursively selecting all transitive dependencies\"),E=new Set(h.map(Ee=>[...Ee.getRecursiveWorkspaceDependencies()]).flat())):this.worktree?(A(\"Option --worktree is set; recursively selecting all nested workspaces\"),E=new Set(h.map(Ee=>[...Ee.getRecursiveWorkspaceChildren()]).flat())):E=null,E!==null&&(h=[...new Set([...h,...E])],this.dryRun))for(let Ee of E)A(`\n- ${Ee.relativeCwd}\n  ${G.prettyLocator(r,Ee.anchoredLocator)}`);let w=[],D=!1;if(u?.includes(\":\")){for(let Ee of o.workspaces)if(Ee.manifest.scripts.has(u)&&(D=!D,D===!1))break}for(let Ee of h){if(u&&!Ee.manifest.scripts.has(u)&&!D&&!(await hn.getWorkspaceAccessibleBinaries(Ee)).has(u)){A(`Excluding ${Ee.relativeCwd} because it doesn't have a \"${u}\" script`);continue}if(!(u===r.env.npm_lifecycle_event&&Ee.cwd===a.cwd)){if(this.include.length>0&&!II.default.isMatch(G.stringifyIdent(Ee.anchoredLocator),this.include)&&!II.default.isMatch(Ee.relativeCwd,this.include)){A(`Excluding ${Ee.relativeCwd} because it doesn't match the --include filter`);continue}if(this.exclude.length>0&&(II.default.isMatch(G.stringifyIdent(Ee.anchoredLocator),this.exclude)||II.default.isMatch(Ee.relativeCwd,this.exclude))){A(`Excluding ${Ee.relativeCwd} because it matches the --include filter`);continue}if(this.publicOnly&&Ee.manifest.private===!0){A(`Excluding ${Ee.relativeCwd} because it's a private workspace and --no-private was set`);continue}w.push(Ee)}}if(this.dryRun)return 0;let b=this.verbose??(this.context.stdout.isTTY?1/0:0),C=b>0,T=b>1,N=this.parallel?this.jobs===\"unlimited\"?1/0:Number(this.jobs)||Math.ceil(Xi.availableParallelism()/2):1,U=N===1?!1:this.parallel,z=U?this.interlaced:!0,te=(0,bve.default)(N),le=new Map,ce=new Set,ue=0,Ie=null,he=!1,De=await Lt.start({configuration:r,stdout:this.context.stdout,includePrefix:!1},async Ee=>{let g=async(me,{commandIndex:Ce})=>{if(he)return-1;!U&&T&&Ce>1&&Ee.reportSeparator();let fe=RDt(me,{configuration:r,label:C,commandIndex:Ce}),[ie,Z]=xve(Ee,{prefix:fe,interlaced:z}),[Pe,Re]=xve(Ee,{prefix:fe,interlaced:z});try{T&&Ee.reportInfo(null,`${fe?`${fe} `:\"\"}Process started`);let ht=Date.now(),q=await this.cli.run([this.commandName,...this.args],{cwd:me.cwd,stdout:ie,stderr:Pe})||0;ie.end(),Pe.end(),await Z,await Re;let nt=Date.now();if(T){let Le=r.get(\"enableTimers\")?`, completed in ${pe.pretty(r,nt-ht,pe.Type.DURATION)}`:\"\";Ee.reportInfo(null,`${fe?`${fe} `:\"\"}Process exited (exit code ${q})${Le}`)}return q===130&&(he=!0,Ie=q),q}catch(ht){throw ie.end(),Pe.end(),await Z,await Re,ht}};for(let me of w)le.set(me.anchoredLocator.locatorHash,me);for(;le.size>0&&!Ee.hasErrors();){let me=[];for(let[Z,Pe]of le){if(ce.has(Pe.anchoredDescriptor.descriptorHash))continue;let Re=!0;if(this.topological||this.topologicalDev){let ht=this.topologicalDev?new Map([...Pe.manifest.dependencies,...Pe.manifest.devDependencies]):Pe.manifest.dependencies;for(let q of ht.values()){let nt=o.tryWorkspaceByDescriptor(q);if(Re=nt===null||!le.has(nt.anchoredLocator.locatorHash),!Re)break}}if(Re&&(ce.add(Pe.anchoredDescriptor.descriptorHash),me.push(te(async()=>{let ht=await g(Pe,{commandIndex:++ue});return le.delete(Z),ce.delete(Pe.anchoredDescriptor.descriptorHash),{workspace:Pe,exitCode:ht}})),!U))break}if(me.length===0){let Z=Array.from(le.values()).map(Pe=>G.prettyLocator(r,Pe.anchoredLocator)).join(\", \");Ee.reportError(3,`Dependency cycle detected (${Z})`);return}let Ce=await Promise.all(me);Ce.forEach(({workspace:Z,exitCode:Pe})=>{Pe!==0&&Ee.reportError(0,`The command failed in workspace ${G.prettyLocator(r,Z.anchoredLocator)} with exit code ${Pe}`)});let ie=Ce.map(Z=>Z.exitCode).find(Z=>Z!==0);(this.topological||this.topologicalDev)&&typeof ie<\"u\"&&Ee.reportError(0,\"The command failed for workspaces that are depended upon by other workspaces; can't satisfy the dependency graph\")}});return Ie!==null?Ie:De.exitCode()}};function xve(t,{prefix:e,interlaced:r}){let o=t.createStreamReporter(e),a=new qe.DefaultStream;a.pipe(o,{end:!1}),a.on(\"finish\",()=>{o.end()});let n=new Promise(A=>{o.on(\"finish\",()=>{A(a.active)})});if(r)return[a,n];let u=new qe.BufferStream;return u.pipe(a,{end:!1}),u.on(\"finish\",()=>{a.end()}),[u,n]}function RDt(t,{configuration:e,commandIndex:r,label:o}){if(!o)return null;let n=`[${G.stringifyIdent(t.anchoredLocator)}]:`,u=[\"#2E86AB\",\"#A23B72\",\"#F18F01\",\"#C73E1D\",\"#CCE2A3\"],A=u[r%u.length];return pe.pretty(e,n,A)}var TDt={commands:[CI,wI]},LDt=TDt;var lE=()=>({modules:new Map([[\"@yarnpkg/cli\",S2],[\"@yarnpkg/core\",P2],[\"@yarnpkg/fslib\",Aw],[\"@yarnpkg/libzip\",V1],[\"@yarnpkg/parsers\",Ew],[\"@yarnpkg/shell\",e2],[\"clipanion\",Qw],[\"semver\",NDt],[\"typanion\",Yo],[\"@yarnpkg/plugin-essentials\",MH],[\"@yarnpkg/plugin-compat\",jH],[\"@yarnpkg/plugin-constraints\",a6],[\"@yarnpkg/plugin-dlx\",l6],[\"@yarnpkg/plugin-exec\",A6],[\"@yarnpkg/plugin-file\",p6],[\"@yarnpkg/plugin-git\",OH],[\"@yarnpkg/plugin-github\",d6],[\"@yarnpkg/plugin-http\",m6],[\"@yarnpkg/plugin-init\",y6],[\"@yarnpkg/plugin-interactive-tools\",mj],[\"@yarnpkg/plugin-link\",yj],[\"@yarnpkg/plugin-nm\",t9],[\"@yarnpkg/plugin-npm\",$9],[\"@yarnpkg/plugin-npm-cli\",lG],[\"@yarnpkg/plugin-pack\",V9],[\"@yarnpkg/plugin-patch\",gG],[\"@yarnpkg/plugin-pnp\",jj],[\"@yarnpkg/plugin-pnpm\",yG],[\"@yarnpkg/plugin-stage\",DG],[\"@yarnpkg/plugin-typescript\",PG],[\"@yarnpkg/plugin-version\",QG],[\"@yarnpkg/plugin-workspace-tools\",FG]]),plugins:new Set([\"@yarnpkg/plugin-essentials\",\"@yarnpkg/plugin-compat\",\"@yarnpkg/plugin-constraints\",\"@yarnpkg/plugin-dlx\",\"@yarnpkg/plugin-exec\",\"@yarnpkg/plugin-file\",\"@yarnpkg/plugin-git\",\"@yarnpkg/plugin-github\",\"@yarnpkg/plugin-http\",\"@yarnpkg/plugin-init\",\"@yarnpkg/plugin-interactive-tools\",\"@yarnpkg/plugin-link\",\"@yarnpkg/plugin-nm\",\"@yarnpkg/plugin-npm\",\"@yarnpkg/plugin-npm-cli\",\"@yarnpkg/plugin-pack\",\"@yarnpkg/plugin-patch\",\"@yarnpkg/plugin-pnp\",\"@yarnpkg/plugin-pnpm\",\"@yarnpkg/plugin-stage\",\"@yarnpkg/plugin-typescript\",\"@yarnpkg/plugin-version\",\"@yarnpkg/plugin-workspace-tools\"])});function Fve({cwd:t,pluginConfiguration:e}){let r=new Vo({binaryLabel:\"Yarn Package Manager\",binaryName:\"yarn\",binaryVersion:nn??\"<unknown>\"});return Object.assign(r,{defaultContext:{...Vo.defaultContext,cwd:t,plugins:e,quiet:!1,stdin:process.stdin,stdout:process.stdout,stderr:process.stderr}})}function ODt(t){if(qe.parseOptionalBoolean(process.env.YARN_IGNORE_NODE))return!0;let r=process.versions.node,o=\">=18.12.0\";if(Ur.satisfiesWithPrereleases(r,o))return!0;let a=new ot(`This tool requires a Node version compatible with ${o} (got ${r}). Upgrade Node, or set \\`YARN_IGNORE_NODE=1\\` in your environment.`);return Vo.defaultContext.stdout.write(t.error(a)),!1}async function Rve({selfPath:t,pluginConfiguration:e}){return await Je.find(Ae.toPortablePath(process.cwd()),e,{strict:!1,usePathCheck:t})}function MDt(t,e,{yarnPath:r}){if(!ae.existsSync(r))return t.error(new Error(`The \"yarn-path\" option has been set, but the specified location doesn't exist (${r}).`)),1;process.on(\"SIGINT\",()=>{});let o={stdio:\"inherit\",env:{...process.env,YARN_IGNORE_PATH:\"1\"}};try{(0,kve.execFileSync)(process.execPath,[Ae.fromPortablePath(r),...e],o)}catch(a){return a.status??1}return 0}function UDt(t,e){let r=null,o=e;return e.length>=2&&e[0]===\"--cwd\"?(r=Ae.toPortablePath(e[1]),o=e.slice(2)):e.length>=1&&e[0].startsWith(\"--cwd=\")?(r=Ae.toPortablePath(e[0].slice(6)),o=e.slice(1)):e[0]===\"add\"&&e[e.length-2]===\"--cwd\"&&(r=Ae.toPortablePath(e[e.length-1]),o=e.slice(0,e.length-2)),t.defaultContext.cwd=r!==null?K.resolve(r):K.cwd(),o}function _Dt(t,{configuration:e}){if(!e.get(\"enableTelemetry\")||Qve.isCI||!process.stdout.isTTY)return;Je.telemetry=new sE(e,\"puba9cdc10ec5790a2cf4969dd413a47270\");let o=/^@yarnpkg\\/plugin-(.*)$/;for(let a of e.plugins.keys())oE.has(a.match(o)?.[1]??\"\")&&Je.telemetry?.reportPluginName(a);t.binaryVersion&&Je.telemetry.reportVersion(t.binaryVersion)}function Tve(t,{configuration:e}){for(let r of e.plugins.values())for(let o of r.commands||[])t.register(o)}async function HDt(t,e,{selfPath:r,pluginConfiguration:o}){if(!ODt(t))return 1;let a=await Rve({selfPath:r,pluginConfiguration:o}),n=a.get(\"yarnPath\"),u=a.get(\"ignorePath\");if(n&&!u)return MDt(t,e,{yarnPath:n});delete process.env.YARN_IGNORE_PATH;let A=UDt(t,e);_Dt(t,{configuration:a}),Tve(t,{configuration:a});let p=t.process(A,t.defaultContext);return p.help||Je.telemetry?.reportCommandName(p.path.join(\" \")),await t.run(p,t.defaultContext)}async function qhe({cwd:t=K.cwd(),pluginConfiguration:e=lE()}={}){let r=Fve({cwd:t,pluginConfiguration:e}),o=await Rve({pluginConfiguration:e,selfPath:null});return Tve(r,{configuration:o}),r}async function Nk(t,{cwd:e=K.cwd(),selfPath:r,pluginConfiguration:o}){let a=Fve({cwd:e,pluginConfiguration:o});function n(){Vo.defaultContext.stdout.write(`ERROR: Yarn is terminating due to an unexpected empty event loop.\nPlease report this issue at https://github.com/yarnpkg/berry/issues.`)}process.once(\"beforeExit\",n);try{process.exitCode=42,process.exitCode=await HDt(a,t,{selfPath:r,pluginConfiguration:o})}catch(u){Vo.defaultContext.stdout.write(a.error(u)),process.exitCode=1}finally{process.off(\"beforeExit\",n),await ae.rmtempPromise()}}Nk(process.argv.slice(2),{cwd:K.cwd(),selfPath:Ae.toPortablePath(Ae.resolve(process.argv[1])),pluginConfiguration:lE()});})();\n/**\n  @license\n  Copyright (c) 2015, Rebecca Turner\n\n  Permission to use, copy, modify, and/or distribute this software for any\n  purpose with or without fee is hereby granted, provided that the above\n  copyright notice and this permission notice appear in all copies.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n  REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\n  FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n  INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\n  LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\n  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n  PERFORMANCE OF THIS SOFTWARE.\n */\n/**\n  @license\n  Copyright Node.js contributors. All rights reserved.\n\n  Permission is hereby granted, free of charge, to any person obtaining a copy\n  of this software and associated documentation files (the \"Software\"), to\n  deal in the Software without restriction, including without limitation the\n  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n  sell copies of the Software, and to permit persons to whom the Software is\n  furnished to do so, subject to the following conditions:\n\n  The above copyright notice and this permission notice shall be included in\n  all copies or substantial portions of the Software.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n  IN THE SOFTWARE.\n*/\n/**\n  @license\n  The MIT License (MIT)\n\n  Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com)\n\n  Permission is hereby granted, free of charge, to any person obtaining a copy\n  of this software and associated documentation files (the \"Software\"), to deal\n  in the Software without restriction, including without limitation the rights\n  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  copies of the Software, and to permit persons to whom the Software is\n  furnished to do so, subject to the following conditions:\n\n  The above copyright notice and this permission notice shall be included in\n  all copies or substantial portions of the Software.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  THE SOFTWARE.\n*/\n/**\n  @license\n  Copyright Joyent, Inc. and other Node contributors.\n\n  Permission is hereby granted, free of charge, to any person obtaining a\n  copy of this software and associated documentation files (the\n  \"Software\"), to deal in the Software without restriction, including\n  without limitation the rights to use, copy, modify, merge, publish,\n  distribute, sublicense, and/or sell copies of the Software, and to permit\n  persons to whom the Software is furnished to do so, subject to the\n  following conditions:\n\n  The above copyright notice and this permission notice shall be included\n  in all copies or substantial portions of the Software.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n  NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n  OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n  USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n/*! Bundled license information:\n\nis-number/index.js:\n  (*!\n   * is-number <https://github.com/jonschlinkert/is-number>\n   *\n   * Copyright (c) 2014-present, Jon Schlinkert.\n   * Released under the MIT License.\n   *)\n\nto-regex-range/index.js:\n  (*!\n   * to-regex-range <https://github.com/micromatch/to-regex-range>\n   *\n   * Copyright (c) 2015-present, Jon Schlinkert.\n   * Released under the MIT License.\n   *)\n\nfill-range/index.js:\n  (*!\n   * fill-range <https://github.com/jonschlinkert/fill-range>\n   *\n   * Copyright (c) 2014-present, Jon Schlinkert.\n   * Licensed under the MIT License.\n   *)\n\nis-extglob/index.js:\n  (*!\n   * is-extglob <https://github.com/jonschlinkert/is-extglob>\n   *\n   * Copyright (c) 2014-2016, Jon Schlinkert.\n   * Licensed under the MIT License.\n   *)\n\nis-glob/index.js:\n  (*!\n   * is-glob <https://github.com/jonschlinkert/is-glob>\n   *\n   * Copyright (c) 2014-2017, Jon Schlinkert.\n   * Released under the MIT License.\n   *)\n\nqueue-microtask/index.js:\n  (*! queue-microtask. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)\n\nrun-parallel/index.js:\n  (*! run-parallel. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)\n\ngit-url-parse/lib/index.js:\n  (*!\n   * buildToken\n   * Builds OAuth token prefix (helper function)\n   *\n   * @name buildToken\n   * @function\n   * @param {GitUrl} obj The parsed Git url object.\n   * @return {String} token prefix\n   *)\n\nobject-assign/index.js:\n  (*\n  object-assign\n  (c) Sindre Sorhus\n  @license MIT\n  *)\n\nreact/cjs/react.production.min.js:\n  (** @license React v17.0.2\n   * react.production.min.js\n   *\n   * Copyright (c) Facebook, Inc. and its affiliates.\n   *\n   * This source code is licensed under the MIT license found in the\n   * LICENSE file in the root directory of this source tree.\n   *)\n\nscheduler/cjs/scheduler.production.min.js:\n  (** @license React v0.20.2\n   * scheduler.production.min.js\n   *\n   * Copyright (c) Facebook, Inc. and its affiliates.\n   *\n   * This source code is licensed under the MIT license found in the\n   * LICENSE file in the root directory of this source tree.\n   *)\n\nreact-reconciler/cjs/react-reconciler.production.min.js:\n  (** @license React v0.26.2\n   * react-reconciler.production.min.js\n   *\n   * Copyright (c) Facebook, Inc. and its affiliates.\n   *\n   * This source code is licensed under the MIT license found in the\n   * LICENSE file in the root directory of this source tree.\n   *)\n\nis-windows/index.js:\n  (*!\n   * is-windows <https://github.com/jonschlinkert/is-windows>\n   *\n   * Copyright © 2015-2018, Jon Schlinkert.\n   * Released under the MIT License.\n   *)\n*/\n"
  },
  {
    "path": "wren-ui/.yarnrc.yml",
    "content": "nodeLinker: node-modules\n\nyarnPath: .yarn/releases/yarn-4.5.3.cjs\n"
  },
  {
    "path": "wren-ui/Dockerfile",
    "content": "FROM node:18-bookworm-slim AS base\n\n# Install required packages\nRUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*\n\n# Next.js collects completely anonymous telemetry data about general usage.\n# Learn more here: https://nextjs.org/telemetry\n# Uncomment the following line in case you want to disable telemetry during the build.\nENV NEXT_TELEMETRY_DISABLED 1\nENV NODE_ENV production\n\nWORKDIR /app\n\n# Enable corepack to manage yarn versions and set the correct yarn version\nRUN corepack enable\nCOPY .yarnrc.yml package.json yarn.lock ./\nCOPY .yarn/releases/yarn-4.5.3.cjs .yarn/releases/yarn-4.5.3.cjs\nRUN corepack prepare yarn@4.5.3 --activate\n\nFROM base AS deps\nWORKDIR /app\n\n# Install dependencies based on the preferred package manager\nRUN yarn install --immutable\nRUN yarn add sharp\n\n# Rebuild the source code only when needed\nFROM base AS builder\nWORKDIR /app\nCOPY --from=deps /app/node_modules ./node_modules\nCOPY public ./public\nCOPY src ./src\nCOPY .eslintrc.json ./\nCOPY .eslintignore ./\nCOPY .prettierrc ./\nCOPY next.config.js ./\nCOPY tsconfig.json ./\n\nRUN yarn build\n\n# Production image, copy all the files and run next\nFROM base AS runner\nWORKDIR /app\n\nCOPY --from=builder /app/public ./public\n\n# Set the correct permission for prerender cache\nRUN mkdir .next\n\n# Automatically leverage output traces to reduce image size\n# https://nextjs.org/docs/advanced-features/output-file-tracing\nCOPY --from=builder /app/.next/standalone ./\nCOPY --from=builder /app/.next/static ./.next/static\nCOPY migrations ./migrations\nCOPY knexfile.js ./knexfile.js\n\n# Copy knex and its dependencies from builder to runner\nCOPY --from=builder /app/node_modules/knex ./node_modules/knex\nCOPY --from=builder /app/node_modules/rechoir ./node_modules/rechoir\nCOPY --from=builder /app/node_modules/resolve ./node_modules/resolve\nCOPY --from=builder /app/node_modules/is-core-module ./node_modules/is-core-module\nCOPY --from=builder /app/node_modules/hasown ./node_modules/hasown\nCOPY --from=builder /app/node_modules/function-bind ./node_modules/function-bind\nCOPY --from=builder /app/node_modules/interpret ./node_modules/interpret\nCOPY --from=builder /app/node_modules/resolve-from ./node_modules/resolve-from\nCOPY --from=builder /app/node_modules/tildify ./node_modules/tildify\nCOPY --from=builder /app/node_modules/getopts ./node_modules/getopts\nCOPY --from=builder /app/node_modules/escalade/sync ./node_modules/escalade/sync\nCOPY --from=builder /app/node_modules/.yarn-state.yml ./node_modules/.yarn-state.yml\n\nEXPOSE 3000\n\nENV PORT 3000\n\n# server.js is created by next build from the standalone output\n# https://nextjs.org/docs/pages/api-reference/next-config-js/output\nCMD yarn knex migrate:latest && HOSTNAME=\"0.0.0.0\" node server.js\n"
  },
  {
    "path": "wren-ui/README.md",
    "content": "This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).\n\n## Start wren-ui from source code\n\nStep 1. Make sure your node version is 18\n```bash\nnode -v\n```\n\nStep 2. Install dependencies:\n\n```bash\nyarn \n```\n\nStep 3(Optional). Switching database\n\nWren-ui uses SQLite as our default database. To use Postgres as the database of wren-ui, you need to set the two environment variable below.\n\n```bash\n# windows\nSET DB_TYPE=pg\nSET PG_URL=postgres://user:password@localhost:5432/dbname \n\n# linux or mac\nexport DB_TYPE=pg\nexport PG_URL=postgres://user:password@localhost:5432/dbname\n```\n-  `PG_URL` is the connection string of your postgres database.\n\nTo switch back to using SQLite, you can reassign the `DB_TYPE` to `sqlite`.\n```\n# windows\nSET DB_TYPE=sqlite\nSET SQLITE_FILE={your_sqlite_file_path} # default is ./db.sqlite3\n\n# linux or mac\nexport DB_TYPE=sqlite\nexport SQLITE_FILE={your_sqlite_file_path}\n```\n\nStep 4. Run migrations:\n\n```bash\nyarn migrate\n# or\nnpm run migrate\n```\n\n\nStep 5. Run the development server:\n\n```bash\n# Execute this if you start wren-engine and ibis-server via docker\n# Linux or MacOS\nexport OTHER_SERVICE_USING_DOCKER=true\nexport EXPERIMENTAL_ENGINE_RUST_VERSION=false # set to true if you want to use the experimental Rust version of the Wren Engine\n# Windows\nSET OTHER_SERVICE_USING_DOCKER=true\nSET EXPERIMENTAL_ENGINE_RUST_VERSION=false # set to true if you want to use the experimental Rust version of the Wren Engine\n\n# Run the development server\nyarn dev\n# or\nnpm run dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) with your browser to see the result.\n\n\n## Development wren-ui module on local\nThere are many modules in Wren AI, to develop wren-ui, you can start other modules(services) via docker-compose.\nIn the [Start wren-ui from source code](#Start-wren-ui-from-source-code) section, you've know how to start wren-ui from the source code to develop.\nTo start other modules via docker-compose, you can follow the steps below.\n\nStep 1. Prepare you .env file\nIn the WrenAI/docker folder, you can find the .env.example file. You can copy this file to .env.local file.\n\n```bash\n# assume current directory is wren-ui\ncd ../docker\ncp .env.example .env.local\n```\nStep 2. Modify your .env.local file\nYou need to fill the `OPENAI_API_KEY` with your OPENAI api key before starting.\n\nYou can also change the `WREN_ENGINE_VERSION`, `WREN_AI_SERVICE_VERSION`, `IBIS_SERVER_VERSION` to the version you want to use.\n\n\nStep 3. Start the services via docker-compose\n```bash\n# current directory is WrenAI/docker\ndocker-compose -f docker-compose-dev.yaml --env-file .env.example up\n\n# you can add a -d flag to run the services in the background\ndocker-compose -f docker-compose-dev.yaml --env-file .env.example up -d\n# then stop the services via\ndocker-compose -f docker-compose-dev.yaml --env-file .env.example down\n```\n\nStep 4. Start wren-ui from source code\nrefer to [Start wren-ui from source code](#Start-wren-ui-from-source-code) section to start wren-ui from source code.\n\nStep 5. (Optional) Develop other modules along with wren-ui\n\nAs mentioned above, you can use docker-compose to start other modules. The same applies when developing other modules.\nFrom the perspective of wren-ui, if you want to develop other modules at the same time, you can stop the container then spin up the module from the source code.\n\neg: If you want to develop ai-service module, you can stop the ai-service container then start the ai-service from the source code.\n```yaml\n# docker/docker-compose-dev.yaml\nwren-engine:\n    image: ghcr.io/canner/wren-engine:${WREN_ENGINE_VERSION}\n    pull_policy: always\n    platform: ${PLATFORM}\n    expose:\n      - ${WREN_ENGINE_SQL_PORT}\n    ports:\n      - ${WREN_ENGINE_PORT}:${WREN_ENGINE_PORT}\n    volumes:\n      - data:/usr/src/app/etc\n    networks:\n      - wren\n    depends_on:\n      - bootstrap\n    ...\n# comment out the ai-service service\nwren-ai-service:\n    image: ghcr.io/canner/wren-ai-service:${WREN_AI_SERVICE_VERSION}\n    pull_policy: always\n    platform: ${PLATFORM}\n    ports:\n      - ${AI_SERVICE_FORWARD_PORT}:${WREN_AI_SERVICE_PORT}\n    environment:\n      WREN_UI_ENDPOINT: http://host.docker.internal:${WREN_UI_PORT}\n      # sometimes the console won't show print messages,\n      # using PYTHONUNBUFFERED: 1 can fix this\n      PYTHONUNBUFFERED: 1\n      CONFIG_PATH: /app/data/config.yaml\n    env_file:\n      - ${PROJECT_DIR}/.env\n    volumes:\n      - ${PROJECT_DIR}/config.yaml:/app/data/config.yaml\n    networks:\n      - wren\n    depends_on:\n      - qdrant\n\nibis-server:\n    image: ghcr.io/canner/wren-engine-ibis:${IBIS_SERVER_VERSION}\n    ...\n```\nThen refer to the README.md or CONTRIBUTION.md file the module for starting the module from the source code. \n\neg: refer to the [ai-service README](https://github.com/Canner/WrenAI/blob/main/wren-ai-service/README.md#start-the-service-for-development) to start the ai-service from the source code.\n\n\n\n## FAQ\n### Can I have multiple project at the same time in Wren AI?\nWe currently do not support multiple projects in Wren AI. You can only have one project at a time.\nBut there is a workaround for this. Since Wren Engine is stateless and we store your semantic model in the database(Sqlite or Postgres), \nyou can switch between projects by switching the database and make sure you deploying after server started.\n\n> Tip: Define the `DB_TYPE` and `SQLITE_FILE` or `PG_URL` variable to specify which database you intend to use.\n\neg: \n```bash\n# start your first project using default database(sqlite by defulat)\nyarn migrate\nyarn dev\n\n# ... after onboarding and lots of hard work, you want to switch to another project \n# stop the server\n\n# set another sqlite file\nexport SQLITE_FILE=./new_project.sqlite\nyarn migrate\nyarn dev\n\n# In the Browser, ... after another onboarding process and hard work\n# you can switch back to the first project by setting the first sqlite file\nexport SQLITE_FILE=./first_project.sqlite\n\nyarn dev  # no need to do migration again\n\n# in the modeling page, click the deploy button to deploy the project to the wren-ai-service.\n# your Wren AI is ready to answer your question.\n```\n\n## Learn More\n\nTo learn more about Next.js, take a look at the following resources:\n\n- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.\n- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.\n\nYou can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!"
  },
  {
    "path": "wren-ui/codegen.yaml",
    "content": "overwrite: true\nschema:\n  [\n    'http://localhost:3000/api/graphql'\n  ]\ngenerates:\n  ./src/apollo/client/graphql/__types__.ts:\n    plugins:\n      - typescript\n      - typescript-operations\n      - typescript-react-apollo\n    config:\n      namingConvention:\n        enumValues: keep\n  ./:\n    preset: near-operation-file\n    presetConfig:\n      extension: .generated.ts\n      baseTypesPath: ./src/apollo/client/graphql/__types__.ts\n    documents: ./src/apollo/client/graphql/!(*.generated).{ts,tsx}\n    plugins:\n      - typescript-operations\n      - typescript-react-apollo\n"
  },
  {
    "path": "wren-ui/e2e/README.md",
    "content": "## How to run e2e test locally\n\n1. Make sure you have start all Wren AI services. ([How to start](https://github.com/Canner/WrenAI/blob/main/docker/README.md#how-to-start))\n\n2. Create a `e2e.config.json` file under `wren-ui/e2e` folder and replace all data sources needed values in `./config.ts`.\n\n   ```ts\n   // Replace the default test config with your own e2e.config.json\n   const defaultTestConfig = {\n     bigQuery: {\n       projectId: 'wrenai',\n       datasetId: 'wrenai.tpch_sf1',\n       // The credential file should be under \"wren-ui\" folder\n       // For example: .tmp/credential.json\n       credentialPath: 'bigquery-credential-path',\n     },\n     duckDb: {\n       sqlCsvPath: 'https://duckdb.org/data/flights.csv',\n     },\n     postgreSql: {\n       host: 'postgresql-host',\n       port: '5432',\n       username: 'postgresql-username',\n       password: 'postgresql-password',\n       database: 'postgresql-database',\n       ssl: false,\n     },\n     mysql: {\n       host: 'mysql-host',\n       port: '3306',\n       username: 'mysql-username',\n       password: 'mysql-password',\n       database: 'mysql-database',\n     },\n     sqlServer: {\n       host: 'sqlServer-host',\n       port: '1433',\n       username: 'sqlServer-username',\n       password: 'sqlServer-password',\n       database: 'sqlServer-database',\n     },\n     trino: {\n       host: 'trino-host',\n       port: '8081',\n       catalog: 'trino-catalog',\n       schema: 'trino-schema',\n       username: 'trino-username',\n       password: 'trino-password',\n     },\n   };\n   ```\n\n3. Build UI before starting e2e server\n\n   ```bash\n   yarn build\n   ```\n\n   > Ensure port 3000 is available for E2E testing. The AI service needs WREN_UI_ENDPOINT to connect to this port for accurate and reliable test results.\n\n4. Run test\n\n   ```bash\n   yarn test:e2e\n   ```\n\n   Run test with browser open\n\n   ```bash\n   yarn test:e2e --headed\n   ```\n\n## How to develop\n\n- Write test with interactive UI mode\n\n  ```bash\n  yarn test:e2e --ui\n  ```\n\n- Write test with debug mode\n\n  ```bash\n  yarn test:e2e --debug\n  ```\n\n- Generate test scripts\n\n  ```\n  npx playwright codegen http://localhost:3000\n  ```\n"
  },
  {
    "path": "wren-ui/e2e/commonTests/home.ts",
    "content": "import { Page, expect } from '@playwright/test';\nimport * as helper from '../helper';\nimport {\n  AskingTask,\n  AskingTaskStatus,\n} from '@/apollo/client/graphql/__types__';\nimport * as modelingHelper from './modeling';\n\nexport const checkAskingProcess = async (page: Page, question: string) => {\n  // check process state\n  await expect(page.getByTestId('prompt__result')).toBeVisible();\n  await expect(page.getByRole('button', { name: 'Stop' })).toBeVisible();\n  await expect(page.getByPlaceholder('Ask to explore your data')).toHaveValue(\n    question,\n  );\n  await expect(page.getByRole('button', { name: 'Ask' })).toBeDisabled();\n};\n\nexport const waitingForAskingTask = async (page: Page) => {\n  await helper.waitForGraphQLResponse({ page }, 'askingTask', (data) =>\n    [AskingTaskStatus.FAILED, AskingTaskStatus.FINISHED].includes(data?.status),\n  );\n};\n\nexport const checkCandidatesResult = async (page: Page) => {\n  await expect(\n    page.locator('div').filter({ hasText: 'result(s) found' }).last(),\n  ).toBeVisible();\n  await expect(page.getByText('result(s) found')).toBeVisible();\n};\n\nexport const getFirstCandidatesResultSummary = async (page: Page) => {\n  const candidatesResultHandle = await page.evaluateHandle(\n    (document) => {\n      const nodes: any = Array.from(\n        document.querySelectorAll('div[role=\"row\"]'),\n      );\n      const node = nodes[nodes.length - 1];\n      const firstResult = node.firstElementChild.lastElementChild;\n\n      return firstResult.childNodes[1].innerText;\n    },\n    await page.evaluateHandle(() => document),\n  );\n\n  const firstResultSummary = await candidatesResultHandle.jsonValue();\n  await candidatesResultHandle.dispose();\n\n  return firstResultSummary;\n};\n\nexport const checkThreadResponseSkeletonLoading = async (page: Page) => {\n  await expect(page.locator('.ant-skeleton-content').last()).toBeVisible({\n    timeout: 60000,\n  });\n  await expect(page.locator('.ant-skeleton-content').last()).toBeHidden({\n    timeout: 60000,\n  });\n};\n\nconst checkThreadResponseBreakdownContent = async (page: Page) => {\n  // switch to the View SQL tab\n  await page\n    .locator('div')\n    .filter({ hasText: /^View SQL$/ })\n    .last()\n    .click();\n\n  // View SQL tab content\n  await expect(\n    page.getByLabel('View SQL').locator('.ant-skeleton-content').last(),\n  ).toBeVisible();\n\n  await expect(\n    page.getByLabel('View SQL').locator('.ant-skeleton-content').last(),\n  ).toBeHidden({ timeout: 60000 });\n\n  // check show preview data table as default open\n  await expect(\n    page.getByLabel('View SQL').locator('.ant-table').last(),\n  ).toBeVisible();\n  await expect(page.getByText('Showing up to 500 rows').last()).toBeVisible();\n\n  // check up-circle icon with Collapse button\n  await expect(\n    page.getByLabel('View SQL').getByLabel('up-circle').locator('svg').last(),\n  ).toBeVisible();\n  await expect(\n    page\n      .getByLabel('View SQL')\n      .getByRole('button', { name: 'Collapse' })\n      .last(),\n  ).toBeVisible();\n\n  // click View Full SQL button\n  await page\n    .getByLabel('View SQL')\n    .getByRole('button', { name: 'View Full SQL' })\n    .last()\n    .click();\n  await expect(\n    page.getByLabel('View SQL').locator('.ace_editor'),\n  ).toBeVisible();\n\n  // check collapse and copy button\n  await expect(\n    page.getByLabel('View SQL').getByLabel('up-circle').locator('svg').last(),\n  ).toBeVisible();\n  await expect(\n    page\n      .getByLabel('View SQL')\n      .getByRole('button', { name: 'Collapse' })\n      .last(),\n  ).toBeVisible();\n  await expect(\n    page.getByLabel('View SQL').getByLabel('copy').locator('svg'),\n  ).toBeVisible();\n  await expect(\n    page.getByLabel('View SQL').getByRole('button', { name: 'Copy' }),\n  ).toBeVisible();\n};\n\nexport const askSuggestionQuestionTest = async ({\n  page,\n  suggestedQuestion,\n}) => {\n  await page.goto('/home');\n  await expect(page).toHaveURL('/home', { timeout: 60000 });\n\n  await page.getByText(suggestedQuestion).click();\n\n  // check asking process state and wait for asking task to finish\n  await checkAskingProcess(page, suggestedQuestion);\n  await waitingForAskingTask(page);\n  await checkThreadResponseSkeletonLoading(page);\n\n  // check question block\n  await expect(page.getByLabel('message').locator('svg')).toBeVisible();\n  await expect(\n    page.getByRole('heading', { name: suggestedQuestion }),\n  ).toBeVisible();\n\n  // check answer result basic UI elements\n  await expect(\n    page.locator('#rc-tabs-0-tab-answer').getByText('Answer'),\n  ).toBeVisible();\n  await expect(\n    page.locator('#rc-tabs-0-tab-view-sql').getByText('View SQL'),\n  ).toBeVisible();\n\n  // check save icon button\n  await expect(page.getByLabel('save').locator('svg')).toBeVisible();\n  await expect(\n    page.getByRole('button', { name: 'Save as View' }),\n  ).toBeVisible();\n\n  // Answer tab content\n  await expect(page.getByLabel('Answer').locator('div').first()).toBeVisible();\n\n  await checkThreadResponseBreakdownContent(page);\n};\n\nexport const followUpQuestionTest = async ({ page, question }) => {\n  await page.goto('/home');\n  await expect(page).toHaveURL('/home', { timeout: 60000 });\n\n  // click existing thread\n  await page.locator('.adm-treeTitle__title').first().click();\n  await expect(page).toHaveURL(/.*\\/home\\/\\d+/, { timeout: 60000 });\n\n  // ask follow up question\n  await page.getByPlaceholder('Ask to explore your data').fill(question);\n  await page.getByRole('button', { name: 'Ask' }).click();\n\n  // check asking process state and wait for asking task to finish\n  await checkAskingProcess(page, question);\n  await waitingForAskingTask(page);\n  await checkThreadResponseSkeletonLoading(page);\n\n  // check question block\n  await expect(page.getByLabel('message').locator('svg').last()).toBeVisible();\n  await expect(page.getByRole('heading', { name: question })).toBeVisible();\n\n  await checkThreadResponseBreakdownContent(page);\n};\n\nexport const saveAsView = async (\n  { page, baseURL }: { page: Page; baseURL: string },\n  { question, viewName }: { question: string; viewName: string },\n) => {\n  await page.goto('/home');\n  await expect(page).toHaveURL('/home', { timeout: 60000 });\n\n  await page.getByPlaceholder('Ask to explore your data').fill(question);\n  await page.getByRole('button', { name: 'Ask' }).click();\n\n  // check asking process state and wait for asking task to finish\n  await checkAskingProcess(page, question);\n  await waitingForAskingTask(page);\n  await checkThreadResponseSkeletonLoading(page);\n\n  // click save as view button\n  await page.getByRole('button', { name: 'Save as View' }).click();\n\n  // check save as view modal\n  await expect(page.locator('.ant-modal-mask')).toBeVisible();\n  await expect(page.locator('div.ant-modal')).toBeVisible();\n  await expect(\n    page.locator('div.ant-modal-title').filter({ hasText: 'Save as View' }),\n  ).toBeVisible();\n  await expect(\n    page.getByLabel('Save as View').getByLabel('Close', { exact: true }),\n  ).toBeVisible();\n  await expect(\n    page.getByText(\n      'After saving, make sure you go to \"Modeling Page\" to deploy all saved views.',\n    ),\n  ).toBeVisible();\n\n  // save as View process\n  await page.getByLabel('Name').click();\n  await page.getByLabel('Name').fill(viewName);\n\n  await page.getByRole('button', { name: 'Save', exact: true }).click();\n\n  // check save as view success\n  await expect(page.getByText('Successfully created view.')).toBeVisible();\n\n  // go to modeling page\n  await page.getByRole('button', { name: 'Modeling' }).click();\n  await expect(page).toHaveURL('/modeling', { timeout: 60000 });\n\n  // deploy MDL with view\n  await expect(page.getByRole('button', { name: 'Deploy' })).toBeEnabled();\n  await modelingHelper.executeDeploy({ page, baseURL });\n\n  await page.getByRole('button', { name: 'Home', exact: true }).click();\n  await expect(page).toHaveURL('/home', { timeout: 60000 });\n\n  // ask the saved view question\n  await page.getByPlaceholder('Ask to explore your data').fill(question);\n  await page.getByRole('button', { name: 'Ask' }).click();\n\n  // check asking process state and wait for asking task to finish\n  await checkAskingProcess(page, question);\n  await waitingForAskingTask(page);\n  await checkThreadResponseSkeletonLoading(page);\n\n  // check offer view info for thread response UI\n  await expect(page.getByText('Generated from saved view')).toBeVisible();\n  await expect(page.getByRole('link', { name: viewName })).toBeVisible();\n\n  // click the view name link will open a new tab and go to the view metadata of the modeling page\n  const newWebPagePromise = page.waitForEvent('popup');\n  await page.getByRole('link', { name: viewName }).click();\n  const modelingPage = await newWebPagePromise;\n\n  // check view metadata\n  await expect(\n    modelingPage\n      .locator('div.ant-drawer-title')\n      .filter({ hasText: new RegExp(`^${viewName}$`) }),\n  ).toBeVisible();\n  await expect(\n    modelingPage.getByTestId('metadata__name').getByText(viewName),\n  ).toBeVisible();\n  await modelingPage\n    .locator('div.ant-drawer')\n    .getByLabel('Close', { exact: true })\n    .click();\n\n  // check view node in diagram\n  await expect(\n    modelingPage.getByRole('complementary').getByText(viewName),\n  ).toBeVisible();\n  await modelingPage.getByRole('complementary').getByText(viewName).click();\n  await expect(\n    modelingPage.getByTestId(`diagram__view-node__${viewName}`),\n  ).toBeVisible();\n};\n"
  },
  {
    "path": "wren-ui/e2e/commonTests/modeling.ts",
    "content": "import { Page, expect } from '@playwright/test';\ninterface Relationship {\n  fromFieldModelDisplayName: string;\n  fromFieldColumnDisplayName: string;\n  toFieldModelDisplayName: string;\n  toFieldColumnDisplayName: string;\n  relationshipType: string;\n}\n\nexport const checkDeploySynced = async ({ page }) => {\n  await page.goto('/modeling');\n  await expect(page).toHaveURL('/modeling', { timeout: 60000 });\n\n  await expect(page.getByLabel('check-circle').locator('svg')).toBeVisible();\n  await expect(page.getByText('Synced')).toBeVisible();\n  await expect(page.getByRole('button', { name: 'Deploy' })).toBeDisabled();\n};\n\nexport const checkDeployUndeployedChanges = async ({ page, baseURL }) => {\n  if (page.url() !== `${baseURL}/modeling`) {\n    await page.goto('/modeling');\n    await expect(page).toHaveURL('/modeling', { timeout: 60000 });\n  }\n\n  await expect(page.getByLabel('warning').locator('svg')).toBeVisible();\n  await expect(page.getByText('Undeployed changes')).toBeVisible();\n  await expect(page.getByRole('button', { name: 'Deploy' })).toBeVisible();\n  await expect(page.getByRole('button', { name: 'Deploy' })).toBeEnabled();\n};\n\nexport const executeDeploy = async ({ page, baseURL }) => {\n  if (page.url() !== `${baseURL}/modeling`) {\n    await page.goto('/modeling');\n    await expect(page).toHaveURL('/modeling', { timeout: 60000 });\n  }\n\n  await page.getByRole('button', { name: 'Deploy' }).click();\n  await expect(\n    page.getByRole('img', { name: 'loading' }).locator('svg'),\n  ).toBeVisible();\n  await expect(page.getByText('Deploying...')).toBeVisible();\n  await expect(page.getByText('Deploying...')).toBeVisible({\n    visible: false,\n    timeout: 60000,\n  });\n};\n\nexport const executeModelCRUD = async (\n  page: Page,\n  {\n    modelDisplayName,\n    modelReferenceName,\n    primaryKeyColumn,\n  }: {\n    modelDisplayName: string;\n    modelReferenceName: string;\n    primaryKeyColumn: string;\n  },\n) => {\n  await page.goto('/modeling');\n  await expect(page).toHaveURL('/modeling', { timeout: 60000 });\n\n  // click the model of sidebar\n  await page\n    .getByRole('complementary')\n    .getByText(modelDisplayName, { exact: true })\n    .click();\n\n  // delete the model\n  await page\n    .locator('div')\n    .filter({ hasText: new RegExp(`^${modelDisplayName}$`) })\n    .getByRole('button')\n    .click();\n  await page.getByText('Delete', { exact: true }).click();\n  await expect(\n    page\n      .getByRole('dialog')\n      .locator('div')\n      .filter({ hasText: 'Are you sure you want to delete this model?' })\n      .nth(1),\n  ).toBeVisible();\n  await page.getByRole('button', { name: 'Delete' }).click();\n\n  // check model deleted\n  await expect(page.getByText('Successfully deleted model.')).toBeVisible();\n  await expect(\n    page\n      .getByRole('complementary')\n      .getByText(modelDisplayName, { exact: true }),\n  ).toBeHidden();\n\n  // add the model back\n  await page.getByTestId('add-model').click();\n\n  // chkeck Model drawer open\n  await expect(page.locator('.ant-drawer-mask')).toBeVisible();\n  await expect(\n    page\n      .locator('div')\n      .filter({ hasText: /^Create a data model$/ })\n      .first(),\n  ).toBeVisible();\n\n  // select resource table and some columns\n  await page.getByLabel('Select a table').click();\n  await page\n    .getByTitle(modelReferenceName, { exact: true })\n    .locator('div')\n    .click();\n\n  await page\n    .getByRole('row', { name: new RegExp(`^${primaryKeyColumn} .*`) })\n    .getByLabel('')\n    .check();\n\n  await page.getByRole('button', { name: 'right' }).click();\n\n  // set primary key\n  await page.getByLabel('Select primary key').click();\n  await page\n    .locator('form')\n    .getByTitle(primaryKeyColumn, { exact: true })\n    .locator('div')\n    .click();\n\n  await page.getByRole('button', { name: 'Submit' }).click();\n\n  // check model added\n  await expect(page.getByText('Successfully created model.')).toBeVisible();\n  await expect(\n    page\n      .getByRole('complementary')\n      .getByText(modelReferenceName, { exact: true }),\n  ).toBeVisible();\n  await expect(\n    page.getByTestId(`diagram__model-node__${modelReferenceName}`),\n  ).toBeVisible();\n\n  // update columns\n  await page\n    .locator('div')\n    .filter({ hasText: new RegExp(`^${modelReferenceName}$`) })\n    .getByRole('button')\n    .click();\n  await page.getByText('Update Columns').click();\n\n  // select all columns\n  await page.getByLabel('', { exact: true }).first().check();\n  await page.getByRole('button', { name: 'right' }).click();\n\n  await page.getByRole('button', { name: 'Submit' }).click();\n\n  await expect(page.getByText('Successfully updated model.')).toBeVisible();\n};\n\nexport const addRelationship = async (\n  page: Page,\n  {\n    fromFieldModelDisplayName,\n    fromFieldColumnDisplayName,\n    toFieldModelDisplayName,\n    toFieldColumnDisplayName,\n    relationshipType,\n  }: Relationship,\n) => {\n  // add relationship\n  await page\n    .getByTestId(`diagram__model-node__${fromFieldModelDisplayName}`)\n    .locator('div')\n    .filter({ hasText: /^Relationships$/ })\n    .getByRole('button')\n    .first()\n    .click();\n\n  // check relationship modal open\n  await expect(\n    page\n      .locator('div')\n      .filter({\n        hasText: 'Add relationship',\n      })\n      .nth(2),\n  ).toBeVisible();\n  await expect(page.getByText('Add relationship')).toBeVisible();\n\n  // set from field\n  await page.getByTestId('common__fields-select').first().click();\n  await page\n    .getByTestId('common__fields__select-option')\n    .filter({ hasText: fromFieldColumnDisplayName })\n    .click();\n\n  // set to field\n  await page.getByTestId('common__models-select').last().click();\n  await page\n    .getByTestId('common__models__select-option')\n    .filter({ hasText: toFieldModelDisplayName })\n    .click();\n  await page.getByTestId('common__fields-select').last().click();\n  await page\n    .getByTestId('common__fields__select-option')\n    .filter({ hasText: toFieldColumnDisplayName })\n    .last()\n    .click();\n\n  // set relationship type\n  await page.getByTestId('relationship-form__type-select').click();\n  await page.getByTitle(relationshipType).locator('div').click();\n\n  await page.getByRole('button', { name: 'Submit' }).click();\n\n  await expect(\n    page.getByText('Successfully created relationship.'),\n  ).toBeVisible();\n  await expect(\n    page\n      .getByTestId(`diagram__model-node__${fromFieldModelDisplayName}`)\n      .getByTitle(toFieldModelDisplayName, { exact: true }),\n  ).toBeVisible();\n};\n\nexport const executeRelationshipCRUD = async (\n  page: Page,\n  {\n    fromFieldModelDisplayName,\n    fromFieldColumnDisplayName,\n    toFieldModelDisplayName,\n    toFieldColumnDisplayName,\n    relationshipType,\n  }: Relationship,\n) => {\n  await page.goto('/modeling');\n  await expect(page).toHaveURL('/modeling', { timeout: 60000 });\n\n  await page\n    .getByRole('complementary')\n    .getByText(fromFieldModelDisplayName, { exact: true })\n    .click();\n\n  // delete relationship\n  await page\n    .getByTestId(`diagram__model-node__${fromFieldModelDisplayName}`)\n    .getByRole('button', { name: 'more' })\n    .nth(1)\n    .click();\n  await page.getByText('Delete', { exact: true }).click();\n\n  // check delete relationship modal open\n  await expect(\n    page\n      .getByRole('dialog')\n      .locator('div')\n      .filter({\n        hasText: 'Are you sure you want to delete this relationship?',\n      })\n      .nth(1),\n  ).toBeVisible();\n  await expect(\n    page.getByText('Are you sure you want to delete this relationship?'),\n  ).toBeVisible();\n  await expect(page.getByRole('button', { name: 'Cancel' })).toBeVisible();\n  await expect(page.getByRole('button', { name: 'Delete' })).toBeVisible();\n\n  await page.getByRole('button', { name: 'Delete' }).click();\n\n  // check relationship deleted\n  await expect(\n    page.getByText('Successfully deleted relationship.'),\n  ).toBeVisible();\n  await expect(\n    page\n      .getByTestId(`diagram__model-node__${fromFieldModelDisplayName}`)\n      .getByTitle(toFieldModelDisplayName, { exact: true }),\n  ).toBeHidden();\n\n  // add relationship\n  await addRelationship(page, {\n    fromFieldModelDisplayName,\n    fromFieldColumnDisplayName,\n    toFieldModelDisplayName,\n    toFieldColumnDisplayName,\n    relationshipType: 'One-to-one',\n  });\n\n  // update relationship\n  await page\n    .getByRole('complementary')\n    .getByText(fromFieldModelDisplayName, { exact: true })\n    .click();\n  await page\n    .getByTestId(`diagram__model-node__${fromFieldModelDisplayName}`)\n    .getByRole('button', { name: 'more' })\n    .nth(1)\n    .click();\n\n  await page.getByText('Edit').click();\n  await expect(\n    page\n      .locator('div')\n      .filter({\n        hasText: 'Update relationship',\n      })\n      .nth(2),\n  ).toBeVisible();\n  await expect(page.getByText('Update relationship')).toBeVisible();\n\n  await page.getByTestId('relationship-form__type-select').click();\n  await page.getByTitle(relationshipType).locator('div').click();\n\n  await page.getByRole('button', { name: 'Submit' }).click();\n\n  // check relationship updated\n  await expect(\n    page.getByText('Successfully updated relationship.'),\n  ).toBeVisible();\n};\n\nexport const updateModelMetadata = async (\n  page: Page,\n  {\n    modelDisplayName,\n    modelDescription,\n    newModelDisplayName,\n    newModelDescription,\n  }: {\n    modelDisplayName: string;\n    modelDescription: string;\n    newModelDisplayName: string;\n    newModelDescription: string;\n  },\n) => {\n  await page.goto('/modeling');\n  await expect(page).toHaveURL('/modeling', { timeout: 60000 });\n\n  await page\n    .getByRole('complementary')\n    .getByText(modelDisplayName, { exact: true })\n    .click();\n\n  // click node to open metadata drawer\n  await page.getByTestId(`diagram__model-node__${modelDisplayName}`).click();\n\n  const modelDescriptionString = modelDescription || '-';\n  const newModelDescriptionString = newModelDescription || '-';\n\n  // check metadata drawer info\n  await expect(page.locator('.ant-drawer-mask')).toBeVisible();\n  await expect(page.getByLabel('Close', { exact: true })).toBeVisible();\n  await expect(\n    page\n      .locator('div.ant-drawer-title')\n      .filter({ hasText: new RegExp(`^${modelDisplayName}$`) }),\n  ).toBeVisible();\n  await expect(\n    page.getByRole('cell', { name: 'Name' }).locator('div'),\n  ).toHaveText(modelDisplayName);\n  await expect(page.getByTestId('metadata__alias').locator('div')).toHaveText(\n    modelDisplayName,\n  );\n  await expect(\n    page.getByTestId('metadata__description').locator('div'),\n  ).toHaveText(modelDescriptionString);\n\n  // click edit metadata button\n  await page.getByRole('button', { name: 'Edit' }).click();\n\n  // check edit metadata modal\n  await expect(page.locator('.ant-modal-mask')).toBeVisible();\n  await expect(page.locator('div.ant-modal')).toBeVisible();\n  await expect(\n    page.locator('div.ant-modal-title').filter({ hasText: 'Edit metadata' }),\n  ).toBeVisible();\n  await expect(\n    page.getByLabel('Edit metadata').getByLabel('Close', { exact: true }),\n  ).toBeVisible();\n\n  // update metadata process\n  // update alias\n  await page\n    .getByTestId('edit-metadata__alias')\n    .getByText(modelDisplayName, { exact: true })\n    .click();\n  await page.locator('#displayName').press('ControlOrMeta+a');\n  await page.locator('#displayName').fill(newModelDisplayName);\n\n  // update description\n  await page\n    .getByTestId('edit-metadata__description')\n    .getByText(modelDescriptionString, { exact: true })\n    .click();\n  await page.locator('#description').press('ControlOrMeta+a');\n  await page.locator('#description').fill(newModelDescription);\n\n  await expect(page.getByRole('button', { name: 'Cancel' })).toBeVisible();\n  await expect(page.getByRole('button', { name: 'Submit' })).toBeVisible();\n  await page.getByRole('button', { name: 'Submit' }).click();\n\n  // check metadata for metadata drawer\n  await expect(\n    page.getByText('Successfully updated model metadata.'),\n  ).toBeVisible();\n  await expect(\n    page\n      .locator('div.ant-drawer-title')\n      .filter({ hasText: new RegExp(`^${newModelDisplayName}$`) }),\n  ).toBeVisible();\n  await expect(\n    page.getByRole('cell', { name: 'Name' }).locator('div').first(),\n  ).toHaveText(modelDisplayName);\n  await expect(\n    page.getByTestId('metadata__name').locator('div').first(),\n  ).toHaveText(modelDisplayName);\n  await expect(page.getByTestId('metadata__alias').locator('div')).toHaveText(\n    newModelDisplayName,\n  );\n  await expect(\n    page.getByTestId('metadata__description').locator('div'),\n  ).toHaveText(newModelDescriptionString);\n\n  // close metadata drawer\n  await page\n    .locator('div.ant-drawer')\n    .getByLabel('Close', { exact: true })\n    .click();\n\n  // check info for modeling page\n  await expect(\n    page.getByRole('complementary').getByText(newModelDisplayName),\n  ).toBeVisible();\n  await page.getByRole('complementary').getByText(newModelDisplayName).click();\n  await expect(\n    page.getByTestId(`diagram__model-node__${newModelDisplayName}`),\n  ).toBeVisible();\n};\n\nexport const updateViewMetadata = async (\n  { page, baseURL }: { page: Page; baseURL: string },\n  {\n    viewDisplayName,\n    viewDescription,\n    newViewDisplayName,\n    newViewDescription,\n  }: {\n    viewDisplayName: string;\n    viewDescription: string;\n    newViewDisplayName: string;\n    newViewDescription: string;\n  },\n) => {\n  await page.goto('/modeling');\n  await expect(page).toHaveURL('/modeling', { timeout: 60000 });\n\n  // will show '-' if viewDescription is empty string\n  const viewDescriptionString = viewDescription || '-';\n  const newViewDescriptionString = newViewDescription || '-';\n\n  await page\n    .getByRole('complementary')\n    .getByText(viewDisplayName, { exact: true })\n    .click();\n\n  // click node to open metadata drawer\n  await page.getByTestId(`diagram__view-node__${viewDisplayName}`).click();\n\n  // check metadata drawer info\n  await expect(page.locator('.ant-drawer-mask')).toBeVisible();\n  await expect(page.getByLabel('Close', { exact: true })).toBeVisible();\n  await expect(\n    page\n      .locator('div.ant-drawer-title')\n      .filter({ hasText: new RegExp(`^${viewDisplayName}$`) }),\n  ).toBeVisible();\n  await expect(page.getByRole('button', { name: 'Edit' })).toBeVisible();\n\n  await expect(\n    page.getByTestId('metadata__name').getByText(viewDisplayName),\n  ).toBeVisible();\n  await expect(\n    page.getByTestId('metadata__description').getByText(viewDescriptionString),\n  ).toBeVisible();\n\n  // click edit metadata button\n  await page.getByRole('button', { name: 'Edit' }).click();\n\n  // check edit metadata modal\n  await expect(page.locator('.ant-modal-mask')).toBeVisible();\n  await expect(page.locator('div.ant-modal')).toBeVisible();\n  await expect(\n    page.locator('div.ant-modal-title').filter({ hasText: 'Edit metadata' }),\n  ).toBeVisible();\n  await expect(\n    page.getByLabel('Edit metadata').getByLabel('Close', { exact: true }),\n  ).toBeVisible();\n\n  // update metadata process\n  // update name (view alias name)\n  await page\n    .getByTestId('edit-metadata__name')\n    .getByText(viewDisplayName, { exact: true })\n    .click();\n  await page.locator('#displayName').fill(newViewDisplayName);\n\n  // update description\n  await page\n    .getByTestId('edit-metadata__description')\n    .getByText(viewDescriptionString, { exact: true })\n    .click();\n  await page.locator('#description').fill(newViewDescription);\n\n  await expect(page.getByRole('button', { name: 'Cancel' })).toBeVisible();\n  await expect(page.getByRole('button', { name: 'Submit' })).toBeVisible();\n  await page.getByRole('button', { name: 'Submit' }).click();\n\n  // check metadata for metadata drawer\n  await expect(\n    page.getByText('Successfully updated view metadata.'),\n  ).toBeVisible();\n  await expect(\n    page\n      .locator('div.ant-drawer-title')\n      .filter({ hasText: new RegExp(`^${newViewDisplayName}$`) }),\n  ).toBeVisible();\n\n  await expect(page.getByTestId('metadata__name').locator('div')).toHaveText(\n    newViewDisplayName,\n  );\n  await expect(\n    page.getByTestId('metadata__description').locator('div'),\n  ).toHaveText(newViewDescriptionString);\n\n  // close metadata drawer\n  await page\n    .locator('div.ant-drawer')\n    .getByLabel('Close', { exact: true })\n    .click();\n\n  // check info for modeling page\n  await expect(\n    page.getByRole('complementary').getByText(newViewDisplayName),\n  ).toBeVisible();\n  await page.getByRole('complementary').getByText(newViewDisplayName).click();\n  await expect(\n    page.getByTestId(`diagram__view-node__${newViewDisplayName}`),\n  ).toBeVisible();\n\n  await checkDeployUndeployedChanges({ page, baseURL });\n};\n\nexport const addCalculatedField = async (\n  page: Page,\n  {\n    calculatedFieldName,\n    expression,\n    modelDisplayName,\n    toFieldModelDisplayName,\n    toFieldColumnDisplayName,\n  }: {\n    calculatedFieldName: string;\n    expression: string;\n    modelDisplayName: string;\n    toFieldModelDisplayName: string;\n    toFieldColumnDisplayName: string;\n  },\n) => {\n  // click the model of sidebar to zoom in\n  await page\n    .getByRole('complementary')\n    .getByText(modelDisplayName, { exact: true })\n    .click();\n\n  // add calculated field\n  await page\n    .getByTestId(`diagram__model-node__${modelDisplayName}`)\n    .locator('div')\n    .filter({ hasText: /^Calculated Fields$/ })\n    .getByRole('button')\n    .first()\n    .click();\n\n  await expect(page.locator('.ant-modal-mask')).toBeVisible();\n  await expect(page.locator('div.ant-modal')).toBeVisible();\n  await expect(\n    page\n      .locator('div.ant-modal-title')\n      .filter({ hasText: 'Add calculated field' }),\n  ).toBeVisible();\n  await expect(\n    page\n      .getByLabel('Add calculated field')\n      .getByLabel('Close', { exact: true }),\n  ).toBeVisible();\n\n  await page.getByLabel('Name').click();\n  await page.getByLabel('Name').fill(calculatedFieldName);\n\n  await page.getByTestId('common__descriptive-select').click();\n  await page.getByTitle(expression).locator('div').click();\n\n  await expect(page.getByTestId('common__lineage')).toBeVisible();\n\n  await expect(\n    page\n      .getByTestId('common__lineage-field-block')\n      .getByText(modelDisplayName, { exact: true }),\n  ).toBeVisible();\n\n  await page.getByTestId('common__lineage-fields-select').click();\n\n  // for skip disabled item\n  await page.getByTestId('common__lineage-fields-select').press('ArrowDown');\n  await page\n    .getByTestId('common__fields__select-option')\n    .filter({ hasText: toFieldModelDisplayName })\n    .scrollIntoViewIfNeeded();\n  await page\n    .getByTestId('common__fields__select-option')\n    .filter({ hasText: toFieldModelDisplayName })\n    .click();\n\n  await expect(\n    page\n      .getByTestId('common__lineage-field-block')\n      .getByText(toFieldModelDisplayName, { exact: true }),\n  ).toHaveCount(2);\n\n  await expect(page.getByText('Please select a field.')).toBeVisible();\n  await page.getByTestId('common__lineage-fields-select').last().click();\n\n  await page\n    .getByTestId('common__fields__select-option')\n    .filter({ hasText: toFieldColumnDisplayName })\n    .scrollIntoViewIfNeeded();\n\n  await page\n    .getByTestId('common__fields__select-option')\n    .filter({ hasText: toFieldColumnDisplayName })\n    .click();\n\n  await page.getByRole('button', { name: 'Save' }).click();\n  await expect(\n    page.getByText('Successfully created calculated field.'),\n  ).toBeVisible();\n};\n\nexport const deleteCalculatedField = async (\n  page: Page,\n  modelDisplayName: string,\n) => {\n  // delete calculated field\n  await page\n    .getByRole('complementary')\n    .getByText(modelDisplayName, { exact: true })\n    .click();\n  await page\n    .getByTestId(`diagram__model-node__${modelDisplayName}`)\n    .getByRole('button', { name: 'more' })\n    .nth(1)\n    .click();\n  await page.getByText('Delete', { exact: true }).click();\n  await page.getByRole('button', { name: 'Delete' }).click();\n  await expect(\n    page.getByText('Successfully deleted calculated field.'),\n  ).toBeVisible();\n};\n"
  },
  {
    "path": "wren-ui/e2e/commonTests/onboarding.ts",
    "content": "import { expect } from '@playwright/test';\n\nexport const setupModels = async ({ page }) => {\n  await page.goto('/setup/models');\n\n  // select all models\n  await page.locator('th').first().click();\n\n  await page.getByRole('button', { name: 'Next' }).click();\n  await expect(page).toHaveURL('/setup/relationships', { timeout: 60000 });\n};\n\nexport const saveRecommendedRelationships = async ({ page }) => {\n  await page.goto('/setup/relationships');\n\n  await page.getByRole('button', { name: 'Finish' }).click();\n  await expect(page).toHaveURL('/modeling', { timeout: 60000 });\n};\n"
  },
  {
    "path": "wren-ui/e2e/config.ts",
    "content": "import fs from 'fs';\nimport path from 'path';\nimport { merge } from 'lodash';\n\nexport const testDbConfig = {\n  client: 'better-sqlite3',\n  connection: 'testdb.sqlite3',\n  useNullAsDefault: true,\n};\n\n// Replace the default test config with your own e2e.config.json\nconst defaultTestConfig = {\n  bigQuery: {\n    projectId: 'wrenai',\n    datasetId: 'wrenai.tpch_sf1',\n    // The credential file should be under \"wren-ui\" folder\n    credentialPath: 'bigquery-credential-path',\n  },\n  duckDb: {\n    sqlCsvPath: 'https://duckdb.org/data/flights.csv',\n  },\n  postgreSql: {\n    host: 'postgresql-host',\n    port: '5432',\n    username: 'postgresql-username',\n    password: 'postgresql-password',\n    database: 'postgresql-database',\n    ssl: false,\n  },\n  mysql: {\n    host: 'mysql-host',\n    port: '3306',\n    username: 'mysql-username',\n    password: 'mysql-password',\n    database: 'mysql-database',\n  },\n  sqlServer: {\n    host: 'sqlserver-host',\n    port: '1433',\n    username: 'sqlserver-username',\n    password: 'sqlserver-password',\n    database: 'sqlserver-database',\n  },\n  trino: {\n    host: 'trino-host',\n    port: '8081',\n    catalog: 'trino-catalog',\n    schema: 'trino-schema',\n    username: 'trino-username',\n    password: 'trino-password',\n  },\n  clickhouse: {\n    host: 'clickhouse-host',\n    port: '8443',\n    username: 'clickhouse-username',\n    password: 'clickhouse-password',\n    database: 'clickhouse-database',\n    ssl: false,\n  },\n  snowflake: {\n    username: 'snowflake-username',\n    password: 'snowflake-password',\n    account: 'snowflake-account',\n    database: 'snowflake-database',\n    schema: 'snowflake-schema',\n  },\n};\n\nlet userTestConfig = {};\ntry {\n  userTestConfig =\n    JSON.parse(\n      fs.readFileSync(path.resolve(__dirname, 'e2e.config.json'), 'utf8'),\n    ) || {};\n} catch (_error: any) {\n  console.log('No e2e config file found.');\n}\n\nexport const getTestConfig = () => {\n  return merge(defaultTestConfig, userTestConfig);\n};\n"
  },
  {
    "path": "wren-ui/e2e/global.setup.ts",
    "content": "import { test as setup } from '@playwright/test';\nimport * as helper from './helper';\n\nsetup('create new database', async () => {\n  console.log('creating new database...');\n  // Initialize the database\n  await helper.migrateDatabase();\n  console.log('created successfully.');\n});\n"
  },
  {
    "path": "wren-ui/e2e/global.teardown.ts",
    "content": "import { test as setup } from '@playwright/test';\nimport * as helper from './helper';\n\nsetup('delete database', async () => {\n  console.log('deleting test database...');\n  // Delete the database\n  await helper.removeDatabase();\n  console.log('deleted successfully.');\n});\n"
  },
  {
    "path": "wren-ui/e2e/helper.ts",
    "content": "import fs from 'fs';\nimport knex from 'knex';\nimport { testDbConfig } from './config';\nimport { Page } from '@playwright/test';\n\nexport const migrateDatabase = async () => {\n  const db = knex(testDbConfig);\n  await db.migrate.latest();\n};\n\nexport const removeDatabase = async () => {\n  const db = knex(testDbConfig);\n  await db.migrate.rollback().then(() => db.destroy());\n  const isDBFileExist = fs.existsSync(testDbConfig.connection);\n  if (isDBFileExist) {\n    fs.unlinkSync(testDbConfig.connection);\n  }\n};\n\nexport const resetDatabase = async () => {\n  const db = knex(testDbConfig);\n  await db.table('project').del();\n  await db.table('model').del();\n  await db.table('model_column').del();\n  await db.table('model_nested_column').del();\n  await db.table('relation').del();\n  await db.table('thread').del();\n  await db.table('thread_response').del();\n  await db.table('view').del();\n\n  // insert learning table data to skip guide\n  await db.table('learning').insert({\n    paths: JSON.stringify(['DATA_MODELING_GUIDE', 'SWITCH_PROJECT_LANGUAGE']),\n  });\n};\n\nexport const waitForGraphQLResponse = async (\n  { page }: { page: Page },\n  queryKey: string,\n  validateResponseData = (data: any) => data !== undefined,\n) => {\n  await page.waitForResponse(\n    async (response) => {\n      try {\n        const responseBody = await response.json();\n        const responseData = responseBody?.data?.[queryKey];\n\n        return (\n          response.url().includes('/api/graphql') &&\n          response.status() === 200 &&\n          responseBody &&\n          validateResponseData(responseData)\n        );\n      } catch (error) {\n        console.error('Error fetching response body:', error);\n      }\n    },\n    { timeout: 100000 },\n  );\n};\n"
  },
  {
    "path": "wren-ui/e2e/specs/connectBigQuery.spec.ts",
    "content": "import { test, expect } from '@playwright/test';\nimport { getTestConfig } from '../config';\nimport * as helper from '../helper';\nimport * as onboarding from '../commonTests/onboarding';\n\nconst testConfig = getTestConfig();\n\ntest.describe('Test BigQuery data source', async () => {\n  test.beforeAll(async () => {\n    await helper.resetDatabase();\n  });\n\n  test('Connect BigQuery data source successfully', async ({ page }) => {\n    await page.goto('/setup/connection');\n\n    await page.locator('button').filter({ hasText: 'BigQuery' }).click();\n\n    await page.getByLabel('Display name').click();\n    await page.getByLabel('Display name').fill('test-bigquery');\n    await page.getByLabel('Project ID').click();\n    await page.getByLabel('Project ID').fill(testConfig.bigQuery.projectId);\n    await page.getByLabel('Dataset ID').click();\n    await page.getByLabel('Dataset ID').fill(testConfig.bigQuery.datasetId);\n\n    const fileChooserPromise = page.waitForEvent('filechooser');\n    await page\n      .locator('button')\n      .filter({ hasText: 'Click to upload JSON key file' })\n      .click();\n    const fileChooser = await fileChooserPromise;\n    await fileChooser.setFiles(testConfig.bigQuery.credentialPath);\n\n    await page.getByRole('button', { name: 'Next' }).click();\n    await expect(page).toHaveURL('/setup/models', { timeout: 60000 });\n  });\n\n  test('Setup all models', onboarding.setupModels);\n\n  test(\n    'Save recommended relationships',\n    onboarding.saveRecommendedRelationships,\n  );\n});\n"
  },
  {
    "path": "wren-ui/e2e/specs/connectClickHouse.spec.ts",
    "content": "import { test, expect } from '@playwright/test';\nimport { getTestConfig } from '../config';\nimport * as helper from '../helper';\nimport * as onboarding from '../commonTests/onboarding';\n\nconst testConfig = getTestConfig();\n\ntest.describe('Test ClickHouse data source', () => {\n  test.beforeAll(async () => {\n    await helper.resetDatabase();\n  });\n\n  test('Connect ClickHouse data source successfully', async ({ page }) => {\n    await page.goto('/setup/connection');\n\n    await page.locator('button').filter({ hasText: 'ClickHouse' }).click();\n\n    await page.getByLabel('Display name').click();\n    await page.getByLabel('Display name').fill('test-clickhouse');\n    await page.getByLabel('Host').click();\n    await page.getByLabel('Host').fill(testConfig.clickhouse.host);\n    await page.getByLabel('Port').click();\n    await page.getByLabel('Port').fill(testConfig.clickhouse.port);\n    await page.getByLabel('Username').click();\n    await page.getByLabel('Username').fill(testConfig.clickhouse.username);\n    await page.getByLabel('Password').click();\n    await page.getByLabel('Password').fill(testConfig.clickhouse.password);\n    await page.getByLabel('Database name').click();\n    await page.getByLabel('Database name').fill(testConfig.clickhouse.database);\n\n    // Check the \"Use SSL\" checkbox if needed\n    if (testConfig.clickhouse.ssl) {\n      await page.getByLabel('Use SSL').click();\n    }\n\n    await page.getByRole('button', { name: 'Next' }).click();\n    await expect(page).toHaveURL('/setup/models', { timeout: 60000 });\n  });\n\n  test('Setup all models', onboarding.setupModels);\n\n  test(\n    'Save recommended relationships',\n    onboarding.saveRecommendedRelationships,\n  );\n});\n"
  },
  {
    "path": "wren-ui/e2e/specs/connectDuckDB.spec.ts",
    "content": "import { test, expect } from '@playwright/test';\nimport { getTestConfig } from '../config';\nimport * as helper from '../helper';\nimport * as onboarding from '../commonTests/onboarding';\n\nconst testConfig = getTestConfig();\n\ntest.describe('Test DuckDB data source', () => {\n  test.beforeAll(async () => {\n    await helper.resetDatabase();\n  });\n\n  test('Connect DuckDB data source successfully', async ({ page }) => {\n    await page.goto('/setup/connection');\n\n    await page.locator('button').filter({ hasText: 'DuckDB' }).click();\n\n    await page.getByLabel('Display name').click();\n    await page.getByLabel('Display name').fill('test-duckdb');\n    await page.getByLabel('Initial SQL statements').click();\n    await page\n      .getByLabel('Initial SQL statements')\n      .fill(\n        `CREATE TABLE ontime AS FROM read_csv('${testConfig.duckDb.sqlCsvPath}');`,\n      );\n    await page.getByRole('button', { name: 'Next' }).click();\n    await expect(page).toHaveURL('/setup/models', { timeout: 60000 });\n  });\n\n  test('Setup all models', onboarding.setupModels);\n\n  test(\n    'Save recommended relationships',\n    onboarding.saveRecommendedRelationships,\n  );\n});\n"
  },
  {
    "path": "wren-ui/e2e/specs/connectMySQL.spec.ts",
    "content": "import { test, expect } from '@playwright/test';\nimport { getTestConfig } from '../config';\nimport * as helper from '../helper';\nimport * as onboarding from '../commonTests/onboarding';\n\nconst testConfig = getTestConfig();\n\ntest.describe('Test MySQL data source', () => {\n  test.beforeAll(async () => {\n    await helper.resetDatabase();\n  });\n\n  test('Connect MySQL data source successfully', async ({ page }) => {\n    await page.goto('/setup/connection');\n\n    await page.locator('button').filter({ hasText: 'MySQL' }).click();\n\n    await page.getByLabel('Display name').click();\n    await page.getByLabel('Display name').fill('test-mysql');\n    await page.getByLabel('Host').click();\n    await page.getByLabel('Host').fill(testConfig.mysql.host);\n    await page.getByLabel('Port').click();\n    await page.getByLabel('Port').fill(testConfig.mysql.port);\n    await page.getByLabel('Username').click();\n    await page.getByLabel('Username').fill(testConfig.mysql.username);\n    await page.getByLabel('Password').click();\n    await page.getByLabel('Password').fill(testConfig.mysql.password);\n    await page.getByLabel('Database name').click();\n    await page.getByLabel('Database name').fill(testConfig.mysql.database);\n\n    await page.getByRole('button', { name: 'Next' }).click();\n    await expect(page).toHaveURL('/setup/models', { timeout: 60000 });\n  });\n\n  test('Setup all models', onboarding.setupModels);\n\n  test(\n    'Save recommended relationships',\n    onboarding.saveRecommendedRelationships,\n  );\n});\n"
  },
  {
    "path": "wren-ui/e2e/specs/connectPostgreSQL.spec.ts",
    "content": "import { test, expect } from '@playwright/test';\nimport { getTestConfig } from '../config';\nimport * as helper from '../helper';\nimport * as onboarding from '../commonTests/onboarding';\n\nconst testConfig = getTestConfig();\n\ntest.describe('Test PostgreSQL data source', () => {\n  test.beforeAll(async () => {\n    await helper.resetDatabase();\n  });\n\n  test('Connect PostgreSQL data source successfully', async ({ page }) => {\n    await page.goto('/setup/connection');\n\n    await page.locator('button').filter({ hasText: 'PostgreSQL' }).click();\n\n    await page.getByLabel('Display name').click();\n    await page.getByLabel('Display name').fill('test-postgresql');\n    await page.getByLabel('Host').click();\n    await page.getByLabel('Host').fill(testConfig.postgreSql.host);\n    await page.getByLabel('Port').click();\n    await page.getByLabel('Port').fill(testConfig.postgreSql.port);\n    await page.getByLabel('Username').click();\n    await page.getByLabel('Username').fill(testConfig.postgreSql.username);\n    await page.getByLabel('Password').click();\n    await page.getByLabel('Password').fill(testConfig.postgreSql.password);\n    await page.getByLabel('Database name').click();\n    await page.getByLabel('Database name').fill(testConfig.postgreSql.database);\n\n    // Check the \"Use SSL\" checkbox if needed\n    if (testConfig.postgreSql.ssl) {\n      await page.getByLabel('Use SSL').click();\n    }\n\n    await page.getByRole('button', { name: 'Next' }).click();\n    await expect(page).toHaveURL('/setup/models', { timeout: 60000 });\n  });\n\n  test('Setup all models', onboarding.setupModels);\n\n  test(\n    'Save recommended relationships',\n    onboarding.saveRecommendedRelationships,\n  );\n});\n"
  },
  {
    "path": "wren-ui/e2e/specs/connectSQLServer.spec.ts",
    "content": "import { test, expect } from '@playwright/test';\nimport { getTestConfig } from '../config';\nimport * as helper from '../helper';\nimport * as onboarding from '../commonTests/onboarding';\n\nconst testConfig = getTestConfig();\n\ntest.describe('Test SQL Server data source', () => {\n  test.beforeAll(async () => {\n    await helper.resetDatabase();\n  });\n\n  test('Connect SQL Server data source successfully', async ({ page }) => {\n    await page.goto('/setup/connection');\n\n    await page.locator('button').filter({ hasText: 'SQL Server' }).click();\n\n    await page.getByLabel('Display name').click();\n    await page.getByLabel('Display name').fill('test-sqlServer');\n    await page.getByLabel('Host').click();\n    await page.getByLabel('Host').fill(testConfig.sqlServer.host);\n    await page.getByLabel('Port').click();\n    await page.getByLabel('Port').fill(testConfig.sqlServer.port);\n    await page.getByLabel('Username').click();\n    await page.getByLabel('Username').fill(testConfig.sqlServer.username);\n    await page.getByLabel('Password').click();\n    await page.getByLabel('Password').fill(testConfig.sqlServer.password);\n    await page.getByLabel('Database name').click();\n    await page.getByLabel('Database name').fill(testConfig.sqlServer.database);\n\n    await page.getByRole('button', { name: 'Next' }).click();\n    await expect(page).toHaveURL('/setup/models', { timeout: 60000 });\n  });\n\n  test('Setup all models', onboarding.setupModels);\n\n  test(\n    'Save recommended relationships',\n    onboarding.saveRecommendedRelationships,\n  );\n});\n"
  },
  {
    "path": "wren-ui/e2e/specs/connectSampleECommerce.spec.ts",
    "content": "import { test, expect } from '@playwright/test';\nimport * as helper from '../helper';\nimport * as homeHelper from '../commonTests/home';\nimport * as modelingHelper from '../commonTests/modeling';\nimport { sampleDatasets } from '@/apollo/server/data';\n\nconst suggestedQuestions = sampleDatasets.ecommerce.questions;\n\ntest.describe('Test E-commerce sample dataset', () => {\n  test.beforeAll(async () => {\n    await helper.resetDatabase();\n  });\n\n  test('Starting E-commerce dataset successfully', async ({ page }) => {\n    await page.goto('/setup/connection');\n    await page.getByRole('button', { name: 'E-commerce' }).click();\n    await expect(page).toHaveURL('/modeling', { timeout: 60000 });\n  });\n\n  test('Check suggested questions', async ({ page }) => {\n    await page.goto('/home');\n    for (const suggestedQuestion of suggestedQuestions) {\n      await expect(page.getByText(suggestedQuestion.question)).toBeVisible();\n    }\n  });\n\n  test(\n    'Check deploy status should be in Synced status',\n    modelingHelper.checkDeploySynced,\n  );\n\n  test('Use suggestion question', async ({ page }) => {\n    // select first suggested question\n    await homeHelper.askSuggestionQuestionTest({\n      page,\n      suggestedQuestion: suggestedQuestions[1].question,\n    });\n  });\n\n  test('Follow up question', async ({ page }) => {\n    await homeHelper.followUpQuestionTest({\n      page,\n      question: suggestedQuestions[2].question,\n    });\n  });\n\n  test('Model CRUD successfully', async ({ page }) => {\n    await modelingHelper.executeModelCRUD(page, {\n      modelDisplayName: 'customers',\n      modelReferenceName: 'olist_customers_dataset',\n      primaryKeyColumn: 'customer_id',\n    });\n  });\n\n  test('Update model metadata successfully', async ({ page }) => {\n    await modelingHelper.updateModelMetadata(page, {\n      modelDisplayName: 'olist_customers_dataset',\n      modelDescription: '',\n      newModelDisplayName: 'customers',\n      newModelDescription: '',\n    });\n  });\n\n  test('Add relationship successfully', async ({ page }) => {\n    await page.goto('/modeling');\n    await expect(page).toHaveURL('/modeling', { timeout: 60000 });\n\n    // Following the previous test, we assume the customers model is created, and it's have not any relationships\n    await modelingHelper.addRelationship(page, {\n      fromFieldModelDisplayName: 'customers',\n      fromFieldColumnDisplayName: 'customer_id',\n      toFieldModelDisplayName: 'orders',\n      toFieldColumnDisplayName: 'customer_id',\n      relationshipType: 'One-to-many',\n    });\n  });\n\n  test(\n    'Check deploy status should be in Undeployed changes status',\n    modelingHelper.checkDeployUndeployedChanges,\n  );\n\n  test('Relationship CRUD successfully', async ({ page }) => {\n    await modelingHelper.executeRelationshipCRUD(page, {\n      fromFieldModelDisplayName: 'customers',\n      fromFieldColumnDisplayName: 'customer_id',\n      toFieldModelDisplayName: 'orders',\n      toFieldColumnDisplayName: 'customer_id',\n      relationshipType: 'One-to-many',\n    });\n  });\n\n  test('Trigger and check deploy MDL successfully', async ({\n    page,\n    baseURL,\n  }) => {\n    await modelingHelper.executeDeploy({ page, baseURL });\n    await modelingHelper.checkDeploySynced({ page });\n  });\n\n  test('Save as view successfully', async ({ page, baseURL }) => {\n    await homeHelper.saveAsView(\n      { page, baseURL },\n      {\n        question:\n          'What are the total sales values for each quarter of each year?',\n        viewName: 'avg review score by city',\n      },\n    );\n  });\n\n  test('Update view metadata successfully', async ({ page, baseURL }) => {\n    await modelingHelper.updateViewMetadata(\n      { page, baseURL },\n      {\n        viewDisplayName: 'avg review score by city',\n        viewDescription: '',\n        newViewDisplayName: 'avg review score per city',\n        newViewDescription:\n          'Average review score for orders placed by customers in each city.',\n      },\n    );\n  });\n\n  test('Calculated Fields CRUD successfully', async ({ page }) => {\n    await page.goto('/modeling');\n    await expect(page).toHaveURL('/modeling', { timeout: 60000 });\n\n    const modelDisplayName = 'orders';\n    const calculatedFieldName = 'Sum of review scores';\n    const expression = 'Sum';\n    const toFieldModelDisplayName = 'order reviews';\n    const toFieldColumnDisplayName = 'review_score';\n\n    const newCfName = 'total product items';\n    const newExpression = 'COUNT';\n    const newToFieldModelDisplayName = 'order items';\n    const newToFieldColumnDisplayName = 'order_id';\n\n    await modelingHelper.addCalculatedField(page, {\n      calculatedFieldName,\n      expression,\n      modelDisplayName,\n      toFieldModelDisplayName,\n      toFieldColumnDisplayName,\n    });\n\n    // update calculated field\n    await page\n      .getByTestId(`diagram__model-node__${modelDisplayName}`)\n      .getByRole('button', { name: 'more' })\n      .nth(1)\n      .click();\n\n    await page.getByText('Edit').click();\n\n    await page.getByLabel('Name').click();\n    await page.getByLabel('Name').fill(newCfName);\n\n    await page.getByTestId('common__descriptive-select').click();\n    await page.getByTitle(newExpression).locator('div').click();\n\n    await page\n      .getByTestId('common__lineage-field-block')\n      .filter({ hasText: modelDisplayName })\n      .getByText(toFieldModelDisplayName, { exact: true })\n      .click();\n\n    await page\n      .getByTestId('common__fields__select-option')\n      .filter({ hasText: newToFieldModelDisplayName })\n      .scrollIntoViewIfNeeded();\n\n    await page\n      .getByTestId('common__fields__select-option')\n      .filter({ hasText: newToFieldModelDisplayName })\n      .click();\n\n    await expect(\n      page\n        .getByTestId('common__lineage-field-block')\n        .getByText(newToFieldModelDisplayName, { exact: true }),\n    ).toHaveCount(2);\n    await expect(page.getByText('Please select a field.')).toBeVisible();\n    await page.getByTestId('common__lineage-fields-select').last().click();\n\n    await page\n      .getByTestId('common__fields__select-option')\n      .filter({ hasText: newToFieldColumnDisplayName })\n      .scrollIntoViewIfNeeded();\n\n    await page\n      .getByTestId('common__fields__select-option')\n      .filter({ hasText: newToFieldColumnDisplayName })\n      .click();\n\n    await page.getByRole('button', { name: 'Save' }).click();\n    await expect(\n      page.getByText('Successfully updated calculated field.'),\n    ).toBeVisible();\n\n    // delete calculated field\n    await modelingHelper.deleteCalculatedField(page, modelDisplayName);\n  });\n});\n"
  },
  {
    "path": "wren-ui/e2e/specs/connectSampleHR.spec.ts",
    "content": "import { test, expect } from '@playwright/test';\nimport * as helper from '../helper';\nimport * as homeHelper from '../commonTests/home';\nimport * as modelingHelper from '../commonTests/modeling';\nimport { sampleDatasets } from '@/apollo/server/data';\n\nconst suggestedQuestions = sampleDatasets.hr.questions;\n\ntest.describe('Test HR sample dataset', () => {\n  test.beforeAll(async () => {\n    await helper.resetDatabase();\n  });\n\n  test('Starting HR dataset successfully', async ({ page }) => {\n    await page.goto('/setup/connection');\n    await page.getByRole('button', { name: 'Human Resource' }).click();\n    await expect(page).toHaveURL('/modeling', { timeout: 60000 });\n  });\n\n  test('Check suggested questions', async ({ page }) => {\n    await page.goto('/home');\n    for (const suggestedQuestion of suggestedQuestions) {\n      await expect(page.getByText(suggestedQuestion.question)).toBeVisible();\n    }\n  });\n\n  test('Use suggestion question', async ({ page, baseURL }) => {\n    // select first suggested question\n    await homeHelper.askSuggestionQuestionTest({\n      page,\n      suggestedQuestion: suggestedQuestions[1].question,\n    });\n  });\n\n  test(\n    'Check deploy status should be in Synced status',\n    modelingHelper.checkDeploySynced,\n  );\n});\n"
  },
  {
    "path": "wren-ui/e2e/specs/connectSnowflake.spec.ts",
    "content": "import { test, expect } from '@playwright/test';\nimport { getTestConfig } from '../config';\nimport * as helper from '../helper';\nimport * as onboarding from '../commonTests/onboarding';\n\nconst testConfig = getTestConfig();\n\ntest.describe('Test Snowflake data source', () => {\n  test.beforeAll(async () => {\n    await helper.resetDatabase();\n  });\n\n  test('Connect Snowflake data source successfully', async ({ page }) => {\n    await page.goto('/setup/connection');\n\n    await page.locator('button').filter({ hasText: 'Snowflake' }).click();\n\n    await page.getByLabel('Display name').click();\n    await page.getByLabel('Display name').fill('test-snowflake');\n    await page.getByLabel('Username').click();\n    await page.getByLabel('Username').fill(testConfig.snowflake.username);\n    await page.getByLabel('Password').click();\n    await page.getByLabel('Password').fill(testConfig.snowflake.password);\n    await page.getByLabel('Account').click();\n    await page.getByLabel('Account').fill(testConfig.snowflake.account);\n    await page.getByLabel('Database name').click();\n    await page.getByLabel('Database name').fill(testConfig.snowflake.database);\n    await page.getByLabel('Schema').click();\n    await page.getByLabel('Schema').fill(testConfig.snowflake.schema);\n\n    await page.getByRole('button', { name: 'Next' }).click();\n    await expect(page).toHaveURL('/setup/models', { timeout: 60000 });\n  });\n\n  test('Setup all models', onboarding.setupModels);\n\n  test(\n    'Save recommended relationships',\n    onboarding.saveRecommendedRelationships,\n  );\n});\n"
  },
  {
    "path": "wren-ui/e2e/specs/connectTrino.spec.ts",
    "content": "import { test, expect } from '@playwright/test';\nimport { getTestConfig } from '../config';\nimport * as helper from '../helper';\nimport * as onboarding from '../commonTests/onboarding';\n\nconst testConfig = getTestConfig();\n\ntest.describe('Test Trino data source', () => {\n  test.beforeAll(async () => {\n    await helper.resetDatabase();\n  });\n\n  test('Connect Trino data source successfully', async ({ page }) => {\n    await page.goto('/setup/connection');\n\n    await page.locator('button').filter({ hasText: 'Trino' }).click();\n\n    await page.getByLabel('Display name').click();\n    await page.getByLabel('Display name').fill('test-trino');\n    await page.getByLabel('Host').click();\n    await page.getByLabel('Host').fill(testConfig.trino.host);\n    await page.getByLabel('Port').click();\n    await page.getByLabel('Port').fill(testConfig.trino.port);\n    await page.getByLabel('Catalog').click();\n    await page.getByLabel('Catalog').fill(testConfig.trino.catalog);\n    await page.getByLabel('Schema').click();\n    await page.getByLabel('Schema').fill(testConfig.trino.schema);\n    await page.getByLabel('Username').click();\n    await page.getByLabel('Username').fill(testConfig.trino.username);\n    await page.getByLabel('Password').click();\n    await page.getByLabel('Password').fill(testConfig.trino.password);\n\n    await page.getByRole('button', { name: 'Next' }).click();\n    await expect(page).toHaveURL('/setup/models', { timeout: 60000 });\n  });\n\n  test('Setup all models', onboarding.setupModels);\n\n  test(\n    'Save recommended relationships',\n    onboarding.saveRecommendedRelationships,\n  );\n});\n"
  },
  {
    "path": "wren-ui/jest.config.js",
    "content": "/** @type {import('ts-jest').JestConfigWithTsJest} */\nmodule.exports = {\n  preset: 'ts-jest',\n  testEnvironment: 'node',\n  moduleNameMapper: {\n    '^@server/(.*)$': '<rootDir>/src/apollo/server/$1',\n  },\n  modulePathIgnorePatterns: ['<rootDir>/e2e/'],\n};\n"
  },
  {
    "path": "wren-ui/knexfile.js",
    "content": "// Update with your config settings.\n\n/**\n * @type { Object.<string, import(\"knex\").Knex.Config> }\n */\nif (process.env.DB_TYPE === 'pg') {\n  console.log('Using Postgres');\n  module.exports = {\n    client: 'pg',\n    connection: process.env.PG_URL,\n  };\n} else {\n  console.log('Using SQLite');\n  module.exports = {\n    client: 'better-sqlite3',\n    connection: process.env.SQLITE_FILE || './db.sqlite3',\n    useNullAsDefault: true,\n  };\n}\n"
  },
  {
    "path": "wren-ui/migrations/20240125070643_create_project_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.createTable('project', (table) => {\n    table.increments('id').comment('ID');\n    table\n      .string('type')\n      .comment(\n        'project datasource type. ex: bigquery, mysql, postgresql, mongodb, etc',\n      );\n    table.string('display_name').comment('project display name');\n    table\n      .text('credentials')\n      .nullable()\n      .comment('database connection credentials');\n\n    // bq\n    table\n      .string('project_id')\n      .nullable()\n      .comment('gcp project id, big query specific');\n    table.string('dataset_id').nullable().comment('big query datasetId');\n\n    // duckdb\n    table\n      .jsonb('init_sql')\n      .nullable()\n      .comment('init sql for establishing duckdb environment');\n    // knex jsonb ref: https://knexjs.org/guide/schema-builder.html#json\n    table\n      .jsonb('extensions')\n      .nullable()\n      .comment(\n        'duckdb extensions, will be a array-like string like, eg: [\"extension1\", \"extension2\"]',\n      );\n    table\n      .jsonb('configurations')\n      .nullable()\n      .comment(\n        'duckdb configurations that can be set in session, eg: { \"key1\": \"value1\", \"key2\": \"value2\" }',\n      );\n\n    // not sure to store or not, the catalog & schema in the manifest\n    table.string('catalog').comment('catalog name');\n    table.string('schema').comment('');\n\n    // sample datset\n    table.string('sample_dataset').nullable().comment('sample dataset name');\n\n    table.timestamps(true, true);\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('project');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240125071855_create_model_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema\n    .createTable('model', (table) => {\n      table.increments('id').comment('ID');\n      table.integer('project_id').comment('Reference to project.id');\n\n      // basic info\n      table.string('display_name').comment('the model display name');\n      table\n        .string('source_table_name')\n        .comment(\n          'referenced table name in the datasource, can not be duplicated in the same project',\n        );\n      table\n        .string('reference_name')\n        .comment(\n          'the name used in MDL structure, should be unique between models in the same project',\n        );\n      table.text('ref_sql').comment('Reference SQL');\n\n      // cache setting\n      table.boolean('cached').comment('model is cached or not');\n      table\n        .string('refresh_time')\n        .comment(\n          'contain a number followed by a time unit (ns, us, ms, s, m, h, d). For example, \"2h\"',\n        )\n        .nullable();\n\n      // model properties\n      table\n        .text('properties')\n        .comment(\n          'model properties, a json string, the description and displayName should be stored here',\n        )\n        .nullable();\n\n      table.timestamps(true, true);\n    })\n    .then(() =>\n      knex.schema.table('model', (table) => {\n        // Explicitly add unique constraint to avoid using the deprecated signature\n        table.unique(['project_id', 'source_table_name'], {\n          indexName: 'project_id_source_table_name_unique',\n          storageEngineIndexType: 'BTREE', // This line is optional and can be adjusted based on your DB's engine\n        });\n        table.unique(['project_id', 'reference_name'], {\n          indexName: 'project_id_reference_name_unique',\n          storageEngineIndexType: 'BTREE', // This line is optional and can be adjusted based on your DB's engine\n        });\n      }),\n    );\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('model');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240125081244_create_model_column_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema\n    .createTable('model_column', (table) => {\n      table.increments('id').comment('ID');\n      table.integer('model_id').comment('Reference to model ID');\n      // column name\n      table.boolean('is_calculated').comment('Is calculated field');\n\n      table.string('display_name').comment('Display name of the column');\n      table\n        .string('source_column_name')\n        .comment('the column name in the datasource');\n      table\n        .string('reference_name')\n        .comment('The name used in the MDL structure and query');\n\n      // aggregation\n      table\n        .text('aggregation')\n        .comment(\n          'Expression for the column, could be custom field or calculated field expression, eg: sum, aggregate',\n        )\n        .nullable();\n      table\n        .text('lineage')\n        .comment(\n          'the selected field in calculated field, array of ids, [relationId 1, relationId 2, columnId], last one should be columnId, while others are relationId',\n        )\n        .nullable();\n      table\n        .text('diagram')\n        .comment('for FE to store the calculated field diagram')\n        .nullable();\n\n      table\n        .string('type')\n        .comment('Data type, refer to the column type in the datasource')\n        .nullable();\n      table.boolean('not_null').comment('Is not null');\n      // is primary key\n      table.boolean('is_pk').comment('Is primary key of the table');\n      table\n        .text('properties')\n        .comment(\n          'column properties, a json string, the description and displayName should be stored here',\n        )\n        .nullable();\n\n      table.timestamps(true, true);\n    })\n    .then(() =>\n      knex.schema.table('model_column', (table) => {\n        // Explicitly add unique constraint to avoid using the deprecated signature\n        table.unique(['model_id', 'source_column_name'], {\n          indexName: 'model_id_source_column_name_unique',\n          storageEngineIndexType: 'BTREE', // This line is optional and can be adjusted based on your DB's engine\n        });\n        table.unique(['model_id', 'reference_name'], {\n          indexName: 'model_id_reference_name_unique',\n          storageEngineIndexType: 'BTREE', // This line is optional and can be adjusted based on your DB's engine\n        });\n      }),\n    );\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('model_column');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240125083821_create_relation_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.createTable('relation', (table) => {\n    table.increments('id').comment('ID');\n    table.integer('project_id').comment('Reference to project.id');\n    table.string('name').comment('relation name').unique();\n    table\n      .string('join_type')\n      .comment('join type, eg:\"ONE_TO_ONE\", \"ONE_TO_MANY\", \"MANY_TO_ONE\"');\n    table\n      .integer('from_column_id')\n      .comment('from column id, \"{fromColumn} {joinType} {toSideColumn}\"');\n    table\n      .integer('to_column_id')\n      .comment('to column id, \"{fromColumn} {joinType} {toSideColumn}\"');\n    table.timestamps(true, true);\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('relation');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240125085655_create_metrics_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.createTable('metric', (table) => {\n    table.increments('id').comment('ID');\n    table.integer('project_id').comment('Reference to project.id');\n    table.string('name').comment('metric name');\n    table.string('type').comment('metric type, ex: \"simple\" or \"cumulative\"');\n\n    // cache setting\n    table.boolean('cached').comment('model is cached or not');\n    table\n      .string('refresh_time')\n      .comment(\n        'contain a number followed by a time unit (ns, us, ms, s, m, h, d). For example, \"2h\"',\n      )\n      .nullable();\n\n    // metric can based on model or another metric\n    table.integer('model_id').comment('Reference to model.id').nullable();\n    table.integer('metric_id').comment('Reference to metric.id').nullable();\n    table\n      .text('properties')\n      .comment(\n        'metric properties, a json string, the description and displayName should be stored here',\n      )\n      .nullable();\n    table.timestamps(true, true);\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('metric');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240126100753_create_metrics_measure_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  // name string\n  // expression string\n  // granularity string, nullable\n\n  return knex.schema.createTable('metric_measure', (table) => {\n    table.increments('id').comment('ID');\n    table.integer('metric_id').comment('Reference to metric ID');\n    table.string('name').comment('Measure name');\n    table\n      .text('expression')\n      .comment('Expression for the measure')\n      .comment(\n        'the expression of measure, eg: \"Sum\", \"Everage\", or customize expression',\n      );\n    table\n      .string('granularity')\n      .comment(\n        'Granularity for the measure, eg: \"day\", \"hour\", \"minute\", \"year\"',\n      )\n      .nullable();\n    table.timestamps(true, true);\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('metric_measure');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240129021453_create_view_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.createTable('view', (table) => {\n    table.increments('id').comment('ID');\n    table.integer('project_id').comment('Reference to project.id');\n\n    // basic info\n    table.string('name').comment('the view name');\n    table.text('statement').comment('the sql statement of this view');\n\n    // cache setting\n    table.boolean('cached').comment('view is cached or not');\n    table\n      .string('refresh_time')\n      .comment(\n        'contain a number followed by a time unit (ns, us, ms, s, m, h, d). For example, \"2h\"',\n      )\n      .nullable();\n\n    // view properties\n    table\n      .text('properties')\n      .comment(\n        'view properties, a json string, the description and displayName should be stored here',\n      )\n      .nullable();\n    table.timestamps(true, true);\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('view');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240319083758_create_deploy_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.createTable('deploy_log', (table) => {\n    table.increments('id').comment('ID');\n    table.integer('project_id').comment('Reference to project.id');\n\n    // basic info\n    table.jsonb('manifest').comment('the deployed manifest');\n    table.string('hash').comment('the hash of the manifest');\n\n    // status\n    table.string('status').nullable().comment('deploy status');\n    table.string('error').nullable().comment('deploy error message');\n\n    // timestamps\n    table.timestamps(true, true);\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('deploy_log');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240327030000_create_ask_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema\n    .createTable('thread', (table) => {\n      table.increments('id').comment('ID');\n      table.integer('project_id').comment('Reference to project.id');\n      table.string('sql').comment('the sql statement of this thread');\n      table.text('summary').comment('the summary of the thread');\n\n      // timestamps\n      table.timestamps(true, true);\n    })\n    .createTable('thread_response', (table) => {\n      table.increments('id').comment('ID');\n      table.integer('thread_id').comment('Reference to thread.id');\n      table.foreign('thread_id').references('thread.id').onDelete('CASCADE');\n\n      // query id from AI service\n      table.string('query_id').comment('the query id generated by AI service');\n\n      // response from AI service\n      table.text('question').comment('the question of the response');\n      table.string('status').comment('the status of the response');\n      table.jsonb('detail').nullable().comment('the detail of the response');\n      table.jsonb('error').nullable().comment('the error message if any');\n\n      // timestamps\n      table.timestamps(true, true);\n    });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('thread_response').dropTable('thread');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240418000000_update_project_table_pg.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\n// add pg related columns to project table\nexports.up = function (knex) {\n  return knex.schema.alterTable('project', (table) => {\n    // pg\n    table\n      .string('host')\n      .nullable()\n      .comment('postgresql host, postgresql specific');\n    table\n      .integer('port')\n      .nullable()\n      .comment('postgresql port, postgresql specific');\n    table\n      .string('database')\n      .nullable()\n      .comment('postgresql database, postgresql specific');\n    table\n      .string('user')\n      .nullable()\n      .comment('postgresql user, postgresql specific');\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.alterTable('project', (table) => {\n    table.dropColumns('host', 'port', 'database', 'user');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240419090558_add_foreign_key_to_model_column_and_metric_measure.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema\n    .alterTable('model_column', (table) => {\n      table.foreign('model_id').references('model.id').onDelete('CASCADE');\n    })\n    .alterTable('metric_measure', (table) => {\n      table.foreign('metric_id').references('metric.id').onDelete('CASCADE');\n    });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema\n    .alterTable('model_column', (table) => {\n      table.dropForeign('model_id');\n    })\n    .alterTable('metric_measure', (table) => {\n      table.dropForeign('metric_id');\n    });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240425000000_add_thread_response_summary.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\n// add summary column to thread_response table\nexports.up = function (knex) {\n  return knex.schema.alterTable('thread_response', (table) => {\n    table\n      .string('summary')\n      .nullable()\n      .comment('the summary of the thread response');\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.alterTable('thread_response', (table) => {\n    table.dropColumns('summary');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240430033014_update_model_column_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  // Drop this column FE is no longer using it.\n  return knex.schema.table('model_column', function (table) {\n    table.dropColumn('diagram');\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.table('model_column', function (table) {\n    table\n      .text('diagram')\n      .comment('for FE to store the calculated field diagram')\n      .nullable();\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240446090560_update_relationship_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema\n    .alterTable('relation', (table) => {\n      table\n        .foreign('from_column_id')\n        .references('model_column.id')\n        .onDelete('CASCADE');\n    })\n    .alterTable('relation', (table) => {\n      table\n        .foreign('to_column_id')\n        .references('model_column.id')\n        .onDelete('CASCADE');\n    });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema\n    .alterTable('relation', (table) => {\n      table.dropForeign('from_column_id');\n    })\n    .alterTable('relation', (table) => {\n      table.dropForeign('to_column_id');\n    });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240502000000_add_properties_to_relationship.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\n// add properties column to relation table\nexports.up = function (knex) {\n  return knex.schema.alterTable('relation', (table) => {\n    table\n      .text('properties')\n      .comment(\n        'column properties, a json string, the description of relationships should be stored here',\n      )\n      .nullable();\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.alterTable('relation', (table) => {\n    table.dropColumns('properties');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240524044348_update_project_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = async function (knex, Promise) {\n  await knex.schema.alterTable('project', (table) => {\n    table.text('init_sql').alter();\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = async function (knex, Promise) {\n  // without rollback script, can not revert text to jsonb in postgres\n  // init sql should be string, not jsonb\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240524071859_update_thread_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = async function (knex, promise) {\n  // drop foreign key constraint before altering column type to prevent data loss\n  await knex.schema.alterTable('thread_response', (table) => {\n    table.dropForeign('thread_id');\n  });\n  await knex.schema.alterTable('thread', (table) => {\n    table.text('sql').alter();\n  });\n  await knex.schema.alterTable('thread_response', (table) => {\n    table.foreign('thread_id').references('thread.id').onDelete('CASCADE');\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = async function (knex, promise) {\n  await knex.schema.alterTable('thread_response', (table) => {\n    table.dropForeign('thread_id');\n  });\n  await knex.schema.alterTable('thread', (table) => {\n    table.string('sql').alter();\n  });\n  await knex.schema.alterTable('thread_response', (table) => {\n    table.foreign('thread_id').references('thread.id').onDelete('CASCADE');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240530062133_update_project_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\n\n// create connectionInfo column in project table\nexports.up = function (knex) {\n  return knex.schema.table('project', (table) => {\n    table\n      .jsonb('connection_info')\n      .nullable()\n      .comment('Connection information for the project');\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.table('project', (table) => {\n    table.dropColumn('connection_info');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240530062809_transfer_project_table_data.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = async function (knex) {\n  const projects = await knex('project').select('*');\n\n  // bigquery data\n  const bigqueryConnectionInfo = projects\n    .filter((project) => project.type === 'BIG_QUERY')\n    .map((project) => {\n      return {\n        id: project.id,\n        connectionInfo: {\n          projectId: project.project_id,\n          datasetId: project.dataset_id,\n          credentials: project.credentials,\n        },\n      };\n    });\n\n  // duckdb data\n  const duckdbConnectionInfo = projects\n    .filter((project) => project.type === 'DUCKDB')\n    .map((project) => {\n      return {\n        id: project.id,\n        connectionInfo: {\n          initSql: project.init_sql || '',\n          configurations: project.configurations || {},\n          extensions: project.extensions || [],\n        },\n      };\n    });\n\n  // postgres data\n  const postgresConnectionInfo = projects\n    .filter((project) => project.type === 'POSTGRES')\n    .map((project) => {\n      const ssl =\n        project.configurations && project.configurations.ssl ? true : false;\n      return {\n        id: project.id,\n        connectionInfo: {\n          host: project.host,\n          port: project.port,\n          database: project.database,\n          user: project.user,\n          password: project.credentials,\n          ssl,\n        },\n      };\n    });\n\n  // update project table\n  for (const project of [\n    ...bigqueryConnectionInfo,\n    ...duckdbConnectionInfo,\n    ...postgresConnectionInfo,\n  ]) {\n    const { id, connectionInfo } = project;\n    if (process.env.DB_TYPE === 'pg') {\n      // postgres\n      await knex('project')\n        .where({ id })\n        .update({ connection_info: connectionInfo });\n    } else {\n      // sqlite\n      await knex('project')\n        .where({ id })\n        .update({ connection_info: JSON.stringify(connectionInfo) });\n    }\n  }\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = async function (knex) {\n  await knex('project').update({ connection_info: null });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240530105955_drop_project_table_columns.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.table('project', (table) => {\n    table.dropColumn('configurations');\n    table.dropColumn('credentials');\n    table.dropColumn('project_id');\n    table.dropColumn('dataset_id');\n    table.dropColumn('init_sql');\n    table.dropColumn('extensions');\n    table.dropColumn('host');\n    table.dropColumn('port');\n    table.dropColumn('database');\n    table.dropColumn('user');\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.table('project', (table) => {\n    table\n      .jsonb('configurations')\n      .nullable()\n      .comment(\n        'duckdb configurations that can be set in session, eg: { \"key1\": \"value1\", \"key2\": \"value2\" }',\n      );\n    table\n      .text('credentials')\n      .nullable()\n      .comment('database connection credentials');\n    table\n      .string('project_id')\n      .nullable()\n      .comment('gcp project id, big query specific');\n    table.string('dataset_id').nullable().comment('big query datasetId');\n    table.text('init_sql');\n    table\n      .jsonb('extensions')\n      .nullable()\n      .comment(\n        'duckdb extensions, will be a array-like string like, eg: [\"extension1\", \"extension2\"]',\n      );\n    table\n      .string('host')\n      .nullable()\n      .comment('postgresql host, postgresql specific');\n    table\n      .integer('port')\n      .nullable()\n      .comment('postgresql port, postgresql specific');\n    table\n      .string('database')\n      .nullable()\n      .comment('postgresql database, postgresql specific');\n    table\n      .string('user')\n      .nullable()\n      .comment('postgresql user, postgresql specific');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240531085916_transfer_model_properties.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = async function (knex) {\n  const projects = await knex('project').select('*');\n  const models = await knex('model').select('*');\n  console.log(`model len:${models.length}`);\n  for (const model of models) {\n    const project = projects.find((p) => p.id === model.project_id);\n    const dataSourceType = project.type;\n    // get schema & catalog if its available\n    let schema = null;\n    let catalog = null;\n    let table = null;\n    switch (dataSourceType) {\n      case 'BIG_QUERY': {\n        const connectionInfo =\n          typeof project.connection_info === 'string'\n            ? JSON.parse(project.connection_info)\n            : project.connection_info;\n        const datasetId = connectionInfo.datasetId;\n        if (!datasetId) continue;\n        const splitDataSetId = datasetId.split('.');\n        schema = splitDataSetId[1];\n        catalog = splitDataSetId[0];\n        table = model.source_table_name;\n        break;\n      }\n      case 'POSTGRES': {\n        const connectionInfo =\n          typeof project.connection_info === 'string'\n            ? JSON.parse(project.connection_info)\n            : project.connection_info;\n        catalog = connectionInfo.database;\n        schema = model.source_table_name.split('.')[0];\n        table = model.source_table_name.split('.')[1];\n        break;\n      }\n      case 'DUCKDB': {\n        // already have schema & catalog in properties\n        table = model.source_table_name;\n        break;\n      }\n    }\n    const oldProperties = model.properties ? JSON.parse(model.properties) : {};\n    const newProperties = {\n      schema,\n      catalog,\n      table,\n      ...oldProperties,\n    };\n    await knex('model')\n      .where({ id: model.id })\n      .update({ properties: JSON.stringify(newProperties) });\n  }\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function () {\n  return Promise.resolve();\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240610070534_create_schema_change_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.createTable('schema_change', (table) => {\n    table.increments('id').comment('ID');\n    table.integer('project_id').comment('Reference to project.id');\n\n    // schema change info\n    table.jsonb('change').nullable();\n    table.jsonb('resolve').nullable();\n\n    // timestamps\n    table.timestamps(true, true);\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('schema_change');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20240928165009_create_model_nested_column.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.createTable('model_nested_column', (table) => {\n    table.increments('id').comment('ID');\n    table.integer('model_id').comment('Reference to model ID');\n    table.integer('column_id').comment('Reference to column ID');\n    table\n      .string('column_path')\n      .comment(\n        'The path of the nested column, array of strings, [sourceColumnName..sourceColumnName(n)]',\n      );\n\n    table.string('display_name').comment('Display name of the nested column');\n    table\n      .string('source_column_name')\n      .comment('the nested column name in the datasource');\n    table\n      .string('reference_name')\n      .comment('The name used in the MDL structure and query');\n    table\n      .string('type')\n      .comment('Data type, refer to the nested column type in the datasource')\n      .nullable();\n    table\n      .text('properties')\n      .comment(\n        'nested column properties, a json string, the description should be stored here',\n      )\n      .nullable();\n\n    table\n      .foreign('column_id')\n      .references('model_column.id')\n      .onDelete('CASCADE');\n    table.timestamps(true, true);\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('model_nested_column');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20241021073019_update_project_language.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.alterTable('project', (table) => {\n    table\n      .string('language')\n      .comment('The project language applied to AI')\n      .defaultTo('EN');\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.alterTable('project', (table) => {\n    table.dropColumn('language');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20241029092204_create_learning_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.createTable('learning', (table) => {\n    table.increments('id').comment('ID');\n    table.string('user_id').comment('The user uuid.');\n    table\n      .text('paths')\n      .comment(\n        'The learning paths of user, array of learning stories, [enum1, enum2, ..enum(n)].',\n      );\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('learning');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20241106232204_update_project_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.alterTable('project', (table) => {\n    table\n      .jsonb('questions')\n      .nullable()\n      .comment('The recommended questions generated by AI');\n    table\n      .string('query_id')\n      .nullable()\n      .comment('The query id of the recommended question pipeline');\n    table\n      .string('questions_status')\n      .nullable()\n      .comment('The status of the recommended question pipeline');\n    table\n      .jsonb('questions_error')\n      .nullable()\n      .comment('The error of the recommended question pipeline');\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.alterTable('project', (table) => {\n    table.dropColumn('questions');\n    table.dropColumn('query_id');\n    table.dropColumn('questions_status');\n    table.dropColumn('questions_error');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20241107171828_update_thread_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.alterTable('thread', (table) => {\n    table\n      .jsonb('questions')\n      .nullable()\n      .comment('The recommended questions generated by AI');\n    table\n      .string('query_id')\n      .nullable()\n      .comment('The query id of the recommended question pipeline');\n    table\n      .string('questions_status')\n      .nullable()\n      .comment('The status of the recommended question pipeline');\n    table\n      .jsonb('questions_error')\n      .nullable()\n      .comment('The error of the recommended question pipeline');\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.alterTable('thread', (table) => {\n    table.dropColumn('questions');\n    table.dropColumn('query_id');\n    table.dropColumn('questions_status');\n    table.dropColumn('questions_error');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20241115031024_drop_thread_response_table_column.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.alterTable('thread_response', function (table) {\n    table.dropColumn('summary');\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.alterTable('thread_response', function (table) {\n    table\n      .string('summary')\n      .nullable()\n      .comment('the summary of the thread response');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20241207000000_update_thread_response_for_answer.js",
    "content": "const constructCteSql = (steps) => {\n  // if empty, return empty string\n  if (steps.length === 0) {\n    return '';\n  }\n\n  // if there's only one step, return the sql directly\n  if (steps.length === 1) {\n    return steps[0].sql;\n  }\n\n  let sql = 'WITH ';\n  steps.forEach((step, index) => {\n    if (index === steps.length - 1) {\n      // if it's the last step, remove the trailing comma.\n      // no need to wrap with WITH\n      sql += `${step.sql}`;\n    } else if (index === steps.length - 2) {\n      // if it's the last two steps, remove the trailing comma.\n      // wrap with CTE\n      sql += `${step.cteName} AS`;\n      sql += `(${step.sql})`;\n    } else {\n      // if it's not the last step, wrap with CTE\n      sql += `${step.cteName} AS`;\n      sql += `(${step.sql}),`;\n    }\n  });\n\n  return sql;\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = async function (knex) {\n  await knex.schema.alterTable('thread_response', (table) => {\n    table.renameColumn('detail', 'breakdown_detail');\n    table\n      .text('sql')\n      .nullable()\n      .comment('the SQL query generated by AI service');\n    table\n      .jsonb('answer_detail')\n      .defaultTo('{}')\n      .comment('AI generated text-based answer detail');\n    table\n      .integer('view_id')\n      .nullable()\n      .comment('the view ID associated with the response');\n  });\n\n  const threadResponses = await knex('thread_response').select(\n    'id',\n    'query_id',\n    'status',\n    'breakdown_detail',\n    'error',\n  );\n\n  for (const response of threadResponses) {\n    let errorDetail;\n    try {\n      errorDetail = JSON.parse(response.error);\n    } catch (_e) {\n      errorDetail = null;\n    }\n\n    let breakdownDetail;\n    try {\n      breakdownDetail = JSON.parse(response.breakdown_detail);\n    } catch (_e) {\n      breakdownDetail = {};\n    }\n\n    const updatedDetail = {\n      queryId: response.query_id,\n      status: response.status,\n      error: errorDetail,\n      ...breakdownDetail,\n    };\n\n    await knex('thread_response')\n      .where('id', response.id)\n      .update({\n        sql: constructCteSql(breakdownDetail?.steps || []),\n        breakdown_detail: JSON.stringify(updatedDetail),\n        answer_detail: null,\n        view_id: breakdownDetail.viewId || null,\n      });\n  }\n\n  await knex.schema.alterTable('thread_response', (table) => {\n    table.dropColumn('query_id');\n    table.dropColumn('status');\n    table.dropColumn('error');\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = async function (knex) {\n  await knex.schema.alterTable('thread_response', (table) => {\n    table.string('query_id').comment('the query id generated by AI service');\n    table.string('status').comment('the status of the response');\n    table.jsonb('error').nullable().comment('the error message if any');\n    table.dropColumn('sql');\n    table.dropColumn('answer_detail');\n  });\n\n  const threadResponses = await knex('thread_response')\n    .select('id', 'breakdown_detail', 'view_id')\n    .whereNotNull('breakdown_detail');\n\n  for (const response of threadResponses) {\n    // Parse the breakdown_detail field from the response\n    let detail;\n    try {\n      detail = JSON.parse(response.breakdown_detail);\n    } catch (_e) {\n      detail = {};\n    }\n\n    // Convert the error detail to a string\n    let errorString;\n    try {\n      errorString = JSON.stringify(detail.error);\n    } catch (_e) {\n      errorString = null;\n    }\n\n    // Update the thread_response table with the parsed details\n    await knex('thread_response')\n      .where('id', response.id)\n      .update({\n        query_id: detail.queryId,\n        status: detail.status,\n        error: errorString,\n        breakdown_detail: JSON.stringify({\n          ...detail,\n          viewId: response.view_id,\n          queryId: undefined,\n          status: undefined,\n          error: undefined,\n        }),\n      });\n  }\n\n  await knex.schema.alterTable('thread_response', (table) => {\n    table.dropColumn('view_id');\n    table.renameColumn('breakdown_detail', 'detail');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20241210072534_update_thread_response_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.alterTable('thread_response', (table) => {\n    table.jsonb('chart_detail').nullable();\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.alterTable('thread_response', (table) => {\n    table.dropColumn('chart_detail');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20241226135712_remove_thread_sql.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = async function (knex) {\n  // drop foreign key constraint before altering column type to prevent data loss\n  await knex.schema.alterTable('thread_response', (table) => {\n    table.dropForeign('thread_id');\n  });\n  await knex.schema.alterTable('thread', (table) => {\n    table.dropColumn('sql');\n  });\n  await knex.schema.alterTable('thread_response', (table) => {\n    table.foreign('thread_id').references('thread.id').onDelete('CASCADE');\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = async function (knex) {\n  await knex.schema.alterTable('thread', (table) => {\n    table.text('sql').nullable();\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20250102074255_create_dashboard_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = async function (knex) {\n  await knex.schema.createTable('dashboard', (table) => {\n    table.increments('id').primary();\n    table\n      .integer('project_id')\n      .notNullable()\n      .comment('Reference to project.id');\n    table.string('name').notNullable().comment('The dashboard name');\n\n    table.foreign('project_id').references('project.id').onDelete('CASCADE');\n    table.index(['project_id']);\n    table.timestamps(true, true);\n  });\n\n  await knex.transaction(async (trx) => {\n    // select all existing projects, should be only one project though\n    const projects = await knex('project').forUpdate();\n    if (projects.length > 0) {\n      const dashboards = projects.map((project) => ({\n        project_id: project.id,\n        name: 'Dashboard',\n      }));\n      await trx('dashboard').insert(dashboards);\n    }\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('dashboard');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20250102074256_create_dashboard_item_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.createTable('dashboard_item', (table) => {\n    table.increments('id').primary();\n    table\n      .integer('dashboard_id')\n      .notNullable()\n      .comment('Reference to dashboard.id');\n    table\n      .string('type')\n      .notNullable()\n      .comment(\n        'The chart type of the dashboard item, such as: bar, table, number, etc',\n      );\n    table\n      .jsonb('layout')\n      .notNullable()\n      .comment(\n        'The layout of the dashboard item, according to which library it is, such as: { x: 0, y: 0, w: 6, h: 6 }',\n      );\n    table\n      .jsonb('detail')\n      .notNullable()\n      .comment(\n        'The detail of the dashboard item, such as: { chartSchema: {...}, sql: \"...\" } ',\n      );\n\n    table\n      .foreign('dashboard_id')\n      .references('dashboard.id')\n      .onDelete('CASCADE');\n    table.index(['dashboard_id', 'type']);\n    table.timestamps(true, true);\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('dashboard_item');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20250102074256_create_sql_pair_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.createTable('sql_pair', (table) => {\n    table.increments('id').primary();\n    table\n      .integer('project_id')\n      .notNullable()\n      .comment('Reference to project.id');\n    table.text('sql').notNullable();\n    table.string('question', 1000).notNullable();\n    table.timestamps(true, true);\n\n    table.foreign('project_id').references('id').inTable('project');\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('sql_pair');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20250311046282_create_instruction_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.createTable('instruction', (table) => {\n    table.increments('id').primary();\n    table\n      .integer('project_id')\n      .notNullable()\n      .comment('Reference to project.id');\n    table.text('instruction').notNullable().comment('The instruction text');\n    table.jsonb('questions').notNullable().comment('The questions array');\n    table\n      .boolean('is_default')\n      .notNullable()\n      .comment('Whether this instruction should be used in each asking');\n    table.timestamps(true, true);\n\n    table.foreign('project_id').references('project.id').onDelete('CASCADE');\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('instruction');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20250320074256_alter_sql_pair_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.alterTable('sql_pair', (table) => {\n    // Drop the existing foreign key constraint\n    table.dropForeign('project_id');\n\n    // Add the foreign key constraint with onDelete CASCADE\n    table\n      .foreign('project_id')\n      .references('id')\n      .inTable('project')\n      .onDelete('CASCADE');\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.alterTable('sql_pair', (table) => {\n    // Drop the foreign key constraint with CASCADE\n    table.dropForeign('project_id');\n\n    // Restore the original foreign key constraint without CASCADE\n    table.foreign('project_id').references('id').inTable('project');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20250422000000_alter_dashboard_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.alterTable('dashboard', function (table) {\n    table.boolean('cache_enabled').defaultTo(true);\n    table.string('schedule_frequency').nullable().defaultTo('NEVER'); // Weekly, Daily, Custom, Never\n    table.string('schedule_cron').nullable().defaultTo(null); // cron expression string\n    table.string('schedule_timezone').nullable().defaultTo(null);\n    table.timestamp('next_scheduled_at').nullable().defaultTo(null); // Next scheduled run timestamp\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.alterTable('dashboard', function (table) {\n    table.dropColumn('cache_enabled');\n    table.dropColumn('schedule_frequency');\n    table.dropColumn('schedule_cron');\n    table.dropColumn('schedule_timezone');\n    table.dropColumn('next_scheduled_at');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20250423000000_create_dashboard_cache_refresh_table.js",
    "content": "exports.up = function (knex) {\n  return knex.schema.createTable('dashboard_item_refresh_job', (table) => {\n    table.increments('id').primary();\n    table.string('hash').notNullable().comment('uuid for the refresh job');\n    table.integer('dashboard_id').notNullable();\n    table.integer('dashboard_item_id').notNullable();\n    table.timestamp('started_at').notNullable();\n    table.timestamp('finished_at');\n    table.string('status').notNullable(); // 'success', 'failed', 'in_progress'\n    table.text('error_message');\n    table.timestamps(true, true);\n\n    // Foreign keys\n    table\n      .foreign('dashboard_id')\n      .references('id')\n      .inTable('dashboard')\n      .onDelete('CASCADE');\n    table\n      .foreign('dashboard_item_id')\n      .references('id')\n      .inTable('dashboard_item')\n      .onDelete('CASCADE');\n\n    // Indexes\n    table.index(['dashboard_id', 'created_at']);\n    table.index(['dashboard_item_id', 'created_at']);\n    table.index('status');\n    table.index('hash');\n  });\n};\n\nexports.down = function (knex) {\n  return knex.schema.dropTable('dashboard_item_refresh_job');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20250509000000_create_asking_task.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.createTable('asking_task', (table) => {\n    table.increments('id').primary();\n    table.string('query_id').notNullable().unique();\n    table.text('question');\n    table.jsonb('detail').defaultTo('{}');\n\n    table\n      .integer('thread_id')\n      .references('id')\n      .inTable('thread')\n      .onDelete('CASCADE');\n\n    table\n      .integer('thread_response_id')\n      .references('id')\n      .inTable('thread_response')\n      .onDelete('CASCADE');\n\n    table.timestamps(true, true);\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('asking_task');\n};\n"
  },
  {
    "path": "wren-ui/migrations/20250509000001_add_task_id_to_thread.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.alterTable('thread_response', (table) => {\n    table\n      .integer('asking_task_id')\n      .nullable()\n      .references('id')\n      .inTable('asking_task')\n      .onDelete('SET NULL');\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.alterTable('thread_response', (table) => {\n    table.dropForeign('asking_task_id');\n    table.dropColumn('asking_task_id');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20250510000000_add_adjustment_to_thread_response.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.alterTable('thread_response', (table) => {\n    table\n      .jsonb('adjustment')\n      .nullable()\n      .comment(\n        'Adjustment data for thread response, including type and payload',\n      );\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.alterTable('thread_response', (table) => {\n    table.dropColumn('adjustment');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20250510000001_alter_dashboard_item_table.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.alterTable('dashboard_item', (table) => {\n    table\n      .string('display_name')\n      .comment('Display name of the dashboard item')\n      .nullable();\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.alterTable('dashboard_item', (table) => {\n    table.dropColumn('display_name');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20250510000002_add_version_to_project.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.alterTable('project', (table) => {\n    table\n      .string('version')\n      .nullable()\n      .comment('data source version information');\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.alterTable('project', (table) => {\n    table.dropColumn('version');\n  });\n};\n"
  },
  {
    "path": "wren-ui/migrations/20250511000000-create-api-history.js",
    "content": "/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.up = function (knex) {\n  return knex.schema.createTable('api_history', (table) => {\n    table.string('id').primary();\n\n    // Project\n    table.integer('project_id').notNullable();\n    table\n      .foreign('project_id')\n      .references('id')\n      .inTable('project')\n      .onDelete('CASCADE');\n\n    // Thread\n    table.string('thread_id');\n\n    // API Type\n    table.string('api_type').notNullable();\n\n    // Request\n    table.jsonb('headers');\n    table.jsonb('request_payload');\n\n    // Response\n    table.jsonb('response_payload');\n\n    // Result\n    table.integer('status_code').notNullable();\n    table.integer('duration_ms').notNullable();\n    table.timestamps(true, true);\n  });\n};\n\n/**\n * @param { import(\"knex\").Knex } knex\n * @returns { Promise<void> }\n */\nexports.down = function (knex) {\n  return knex.schema.dropTable('api_history');\n};\n"
  },
  {
    "path": "wren-ui/next.config.js",
    "content": "/* eslint-disable @typescript-eslint/no-var-requires */\nconst path = require('path');\nconst withLess = require('next-with-less');\nconst withBundleAnalyzer = require('@next/bundle-analyzer')({\n  enabled: process.env.ANALYZE === 'true',\n});\n\nconst resolveAlias = {\n  antd$: path.resolve(__dirname, 'src/import/antd'),\n};\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = withLess({\n  output: 'standalone',\n  staticPageGenerationTimeout: 1000,\n  compiler: {\n    // Enables the styled-components SWC transform\n    styledComponents: {\n      displayName: true,\n      ssr: true,\n    },\n  },\n  lessLoaderOptions: {\n    additionalData: `@import \"@/styles/antd-variables.less\";`,\n  },\n  webpack: (config) => {\n    config.resolve.alias = {\n      ...config.resolve.alias,\n      ...resolveAlias,\n    };\n    return config;\n  },\n  // routes redirect\n  async redirects() {\n    return [\n      {\n        source: '/setup',\n        destination: '/setup/connection',\n        permanent: true,\n      },\n    ];\n  },\n});\n\nmodule.exports = withBundleAnalyzer(nextConfig);\n"
  },
  {
    "path": "wren-ui/openapi.yaml",
    "content": "openapi: 3.0.0\ninfo:\n  title: WrenAI API\n  description: Restful API for interacting with Wren AI\n  version: 1.0.0\nservers:\n  - url: /api/v1\n    description: WrenAI API v1\npaths:\n  /generate_sql:\n    post:\n      summary: Generate SQL from natural language\n      description: Converts a natural language question into a SQL query\n      requestBody:\n        required: true\n        content:\n          application/json:\n            schema:\n              type: object\n              required:\n                - question\n              properties:\n                question:\n                  type: string\n                  description: The natural language question to convert to SQL\n                threadId:\n                  type: string\n                  description: Optional thread ID to maintain conversation context\n                language:\n                  type: string\n                  description: Optional language override for AI responses. If not provided, will use the project's default language. Affects error messages and explanation responses. The format is not strictly enforced, but it is recommended to follow the language list in RFC 5646 (check https://gist.github.com/msikma/8912e62ed866778ff8cd for reference).\n                returnSqlDialect:\n                  type: boolean\n                  description: Whether to return the SQL dialect in the response. If true, the SQL returned will be in the dialect of the database.\n                  default: false\n      responses:\n        '200':\n          description: Successfully generated SQL\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  id:\n                    type: string\n                    description: The unique identifier for the response\n                  sql:\n                    type: string\n                    description: The generated SQL statement\n                  threadId:\n                    type: string\n                    description: ID of the thread (existing or newly created)\n                example:\n                  id: \"1fbc0d64-1c58-45b2-a990-9183bbbcf913\"\n                  sql: \"SELECT * FROM \\\"olist_customers_dataset\\\"\"\n                  threadId: \"9c537507-9cec-46ed-b877-07bfa6322bed\"\n        '400':\n          description: Bad request or unable to generate SQL\n          content:\n            application/json:\n              schema:\n                allOf:\n                  - $ref: '#/components/schemas/ErrorResponse'\n                  - type: object\n                    properties:\n                      explanationQueryId:\n                        type: string\n                        description: ID that can be used with the /stream_explanation endpoint to get a detailed explanation for non-SQL queries\n                example:\n                  id: \"75c13d09-6f86-4e79-a00e-a4f85f73f2d7\"\n                  code: \"NON_SQL_QUERY\"\n                  error: \"User asks about Wren AI's features and capabilities, unrelated to database schema.\"\n                  explanationQueryId: \"71b016c5-42bb-4897-82d6-46f9b0bf7d94\"\n  /run_sql:\n    post:\n      summary: Execute SQL and return results\n      description: Runs a SQL query and returns the results as structured data\n      requestBody:\n        required: true\n        content:\n          application/json:\n            schema:\n              type: object\n              required:\n                - sql\n              properties:\n                sql:\n                  type: string\n                  description: The SQL query to execute\n                threadId:\n                  type: string\n                  description: Optional thread ID for conversation context\n                limit:\n                  type: integer\n                  description: Maximum number of rows to return\n                  default: 1000\n      responses:\n        '200':\n          description: Successfully executed SQL\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  records:\n                    type: array\n                    description: Array of records, each represented as an object\n                    items:\n                      type: object\n                  columns:\n                    type: array\n                    description: Metadata about the result columns\n                    items:\n                      $ref: '#/components/schemas/ColumnMetadata'\n                  threadId:\n                    type: string\n                    description: ID of the thread (existing or newly created)\n                  totalRows:\n                    type: integer\n                    description: The total number of rows returned\n                example:\n                  id: \"09d46224-0068-4ca3-bce4-f1fc85093eb6\"\n                  records: [\n                    {\n                      \"customer_id\": \"00012a2ce6f8dcda20d059ce98491703\",\n                      \"customer_unique_id\": \"248ffe10d632bebe4f7267f1f44844c9\",\n                      \"customer_zip_code_prefix\": \"06273\",\n                      \"customer_city\": \"osasco\",\n                      \"customer_state\": \"SP\"\n                    },\n                    {\n                      \"customer_id\": \"000161a058600d5901f007fab4c27140\",\n                      \"customer_unique_id\": \"b0015e09bb4b6e47c52844fab5fb6638\",\n                      \"customer_zip_code_prefix\": \"35550\",\n                      \"customer_city\": \"itapecerica\",\n                      \"customer_state\": \"MG\"\n                    },\n                    \"... additional records truncated for brevity ...\"\n                  ]\n                  columns: [\n                    {\n                      \"name\": \"customer_id\",\n                      \"type\": \"VARCHAR\"\n                    },\n                    {\n                      \"name\": \"customer_unique_id\",\n                      \"type\": \"VARCHAR\"\n                    },\n                    {\n                      \"name\": \"customer_zip_code_prefix\",\n                      \"type\": \"VARCHAR\"\n                    },\n                    {\n                      \"name\": \"customer_city\",\n                      \"type\": \"VARCHAR\"\n                    },\n                    {\n                      \"name\": \"customer_state\",\n                      \"type\": \"VARCHAR\"\n                    }\n                  ]\n                  threadId: \"503a8ca5-8171-43b5-b45b-86de2849467b\"\n                  totalRows: 10\n        '400':\n          description: Bad request or SQL execution error\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorResponse'\n        '405':\n          description: Method not allowed\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorResponse'\n  /generate_vega_chart:\n    post:\n      summary: Generate Vega visualization chart spec\n      description: Generates a Vega chart spec for data visualization from a question and SQL query\n      requestBody:\n        required: true\n        content:\n          application/json:\n            schema:\n              type: object\n              required:\n                - question\n                - sql\n              properties:\n                question:\n                  type: string\n                  description: The natural language question\n                sql:\n                  type: string\n                  description: The SQL query that produces the data to visualize\n                threadId:\n                  type: string\n                  description: Optional thread ID for conversation context\n                sampleSize:\n                  type: integer\n                  description: Maximum number of rows to include in the visualization\n                  default: 10000\n      responses:\n        '200':\n          description: Successfully generated Vega specification\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  vegaSpec:\n                    type: object\n                    description: The Vega specification with embedded data\n                  threadId:\n                    type: string\n                    description: ID of the thread (existing or newly created)\n                example:\n                  threadId: \"75ab23c8-9124-4560-a125-fbe7e321dcba\"\n                  vegaSpec: {\n                    \"$schema\": \"https://vega.github.io/schema/vega-lite/v5.json\",\n                    \"config\": {\n                      \"mark\": {\n                        \"tooltip\": true\n                      },\n                      \"font\": \"Roboto, Arial, Noto Sans, sans-serif\",\n                      \"padding\": {\n                        \"top\": 30,\n                        \"bottom\": 20,\n                        \"left\": 0,\n                        \"right\": 0\n                      },\n                      \"title\": {\n                        \"color\": \"#262626\",\n                        \"fontSize\": 14\n                      },\n                      \"axis\": {\n                        \"labelFontSize\": 10,\n                        \"gridColor\": \"#d9d9d9\",\n                        \"titleColor\": \"#434343\",\n                        \"labelColor\": \"#65676c\"\n                      },\n                      \"axisX\": {\n                        \"labelAngle\": -45\n                      },\n                      \"bar\": {\n                        \"color\": \"#1570EF\"\n                      }\n                    },\n                    \"title\": \"Total Payments by Customer State\",\n                    \"data\": {\n                      \"values\": [\n                        {\n                          \"customer_state\": \"PR\",\n                          \"total_payment_value\": 811156.38\n                        },\n                        {\n                          \"customer_state\": \"BA\",\n                          \"total_payment_value\": 616645.82\n                        }\n                      ]\n                    },\n                    \"mark\": {\n                      \"type\": \"bar\"\n                    },\n                    \"width\": \"container\",\n                    \"height\": \"container\",\n                    \"encoding\": {\n                      \"x\": {\n                        \"field\": \"customer_state\",\n                        \"type\": \"nominal\",\n                        \"title\": \"Customer State\"\n                      },\n                      \"y\": {\n                        \"field\": \"total_payment_value\",\n                        \"type\": \"quantitative\",\n                        \"title\": \"Total Payment Value\"\n                      },\n                      \"color\": {\n                        \"field\": \"customer_state\",\n                        \"type\": \"nominal\",\n                        \"title\": \"Customer State\"\n                      }\n                    }\n                  }\n        '400':\n          description: Bad request or specification generation error\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorResponse'\n  /stream_explanation:\n    get:\n      summary: Stream an explanation\n      description: Streams an explanation for a non-SQL query using server-sent events\n      parameters:\n        - name: queryId\n          in: query\n          description: The query ID to stream results from\n          required: true\n          schema:\n            type: string\n      responses:\n        '200':\n          description: Stream of explanation events\n          content:\n            text/event-stream:\n              schema:\n                type: string\n                description: Server-sent events stream with explanation chunks\n              example: |\n                data: {\"message\":\"Wren AI is \"}\n\n                data: {\"message\":\"designed to \"}\n\n                data: {\"message\":\"help you analyze \"}\n\n                data: {\"message\":\"your data with \"}\n\n                data: {\"message\":\"natural language queries. I can \"}\n\n                data: {\"message\":\"provide insights about \"}\n\n                data: {\"message\":\"your business data and \"}\n\n                data: {\"message\":\"create visualizations.\"}\n\n                data: {\"done\":true}\n        '500':\n          description: Internal server error\ncomponents:\n  schemas:\n    ErrorResponse:\n      type: object\n      properties:\n        id:\n          type: string\n          description: Unique identifier for the error response\n        error:\n          type: string\n          description: Error message\n        code:\n          type: string\n          description: Error code\n    ColumnMetadata:\n      type: object\n      properties:\n        name:\n          type: string\n          description: Column name\n        type:\n          type: string\n          description: Data type of the column\n        notNull:\n          type: boolean\n          description: Whether the column allows null values\n        properties:\n          type: object\n          description: Additional column properties\n"
  },
  {
    "path": "wren-ui/package.json",
    "content": "{\n  \"name\": \"wren-ui\",\n  \"version\": \"0.32.2\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"TZ=UTC next dev\",\n    \"build\": \"NODE_OPTIONS=--max-old-space-size=8192 next build\",\n    \"start\": \"TZ=UTC next start\",\n    \"lint\": \"yarn check-types && next lint\",\n    \"test\": \"jest\",\n    \"test:e2e\": \"npx playwright install chromium && npx playwright test\",\n    \"check-types\": \"tsc --noEmit\",\n    \"migrate\": \"yarn knex migrate:latest\",\n    \"rollback\": \"yarn knex migrate:rollback\",\n    \"generate-gql\": \"yarn graphql-codegen --config codegen.yaml\"\n  },\n  \"dependencies\": {\n    \"@google-cloud/bigquery\": \"^6.0.3\",\n    \"@google-cloud/storage\": \"^6.10.1\",\n    \"apollo-server-micro\": \"^3.10.2\",\n    \"axios\": \"^1.12.0\",\n    \"bcryptjs\": \"^2.4.3\",\n    \"better-sqlite3\": \"^9.4.3\",\n    \"cron-parser\": \"^5.1.1\",\n    \"graphql\": \"^16.6.0\",\n    \"graphql-type-json\": \"^0.3.2\",\n    \"knex\": \"^3.1.0\",\n    \"lodash\": \"^4.17.23\",\n    \"log4js\": \"^6.9.1\",\n    \"micro\": \"^9.4.1\",\n    \"micro-cors\": \"^0.1.1\",\n    \"next\": \"14.2.35\",\n    \"pg\": \"^8.8.0\",\n    \"pg-cursor\": \"^2.7.4\",\n    \"posthog-node\": \"^4.3.2\",\n    \"sql-formatter\": \"^15.3.0\",\n    \"uuid\": \"^11.1.0\"\n  },\n  \"devDependencies\": {\n    \"@apollo/client\": \"^3.6.9\",\n    \"@graphql-codegen/cli\": \"2.12.0\",\n    \"@graphql-codegen/introspection\": \"2.2.1\",\n    \"@graphql-codegen/near-operation-file-preset\": \"^2.4.1\",\n    \"@graphql-codegen/typescript\": \"2.7.3\",\n    \"@graphql-codegen/typescript-operations\": \"^2.5.3\",\n    \"@graphql-codegen/typescript-react-apollo\": \"3.3.3\",\n    \"@next/bundle-analyzer\": \"^15.3.0\",\n    \"@playwright/test\": \"^1.55.2\",\n    \"@testing-library/react\": \"14.0.0\",\n    \"@types/jest\": \"29.4.4\",\n    \"@types/lodash\": \"^4.14.202\",\n    \"@types/micro-cors\": \"^0.1.5\",\n    \"@types/node\": \"18.16.9\",\n    \"@types/pg\": \"^8.6.5\",\n    \"@types/pg-cursor\": \"^2.7.0\",\n    \"@types/react\": \"18.2.0\",\n    \"@types/react-dom\": \"18.2.0\",\n    \"@types/react-grid-layout\": \"^1.3.5\",\n    \"@types/styled-components\": \"5.1.26\",\n    \"@typescript-eslint/eslint-plugin\": \"6.18.0\",\n    \"@typescript-eslint/parser\": \"6.18.0\",\n    \"ace-builds\": \"^1.32.3\",\n    \"antd\": \"4.20.4\",\n    \"clsx\": \"^2.1.1\",\n    \"cron-parser\": \"^5.1.1\",\n    \"dayjs\": \"^1.11.11\",\n    \"driver.js\": \"^1.3.1\",\n    \"duckdb\": \"^0.10.1\",\n    \"duckdb-async\": \"^0.10.0\",\n    \"eslint\": \"^8\",\n    \"eslint-config-next\": \"14.2.21\",\n    \"eslint-config-prettier\": \"^9.1.0\",\n    \"eslint-plugin-prettier\": \"^5.1.3\",\n    \"jest\": \"29.4.3\",\n    \"less\": \"^4.2.0\",\n    \"less-loader\": \"^12.2.0\",\n    \"next-with-less\": \"^3.0.1\",\n    \"posthog-js\": \"^1.205.0\",\n    \"prettier\": \"^3.2.5\",\n    \"react\": \"18.2.0\",\n    \"react-ace\": \"^10.1.0\",\n    \"react-dom\": \"18.2.0\",\n    \"react-grid-layout\": \"^1.5.0\",\n    \"react-markdown\": \"^9.0.1\",\n    \"reactflow\": \"11.10.3\",\n    \"remark-gfm\": \"^4.0.0\",\n    \"styled-components\": \"5.3.6\",\n    \"styled-icons\": \"^10.47.0\",\n    \"ts-essentials\": \"^9.1.2\",\n    \"ts-jest\": \"29.1.1\",\n    \"ts-node\": \"9.1.1\",\n    \"typescript\": \"5.2.2\",\n    \"vega\": \"^6.2.0\",\n    \"vega-embed\": \"^6.29.0\",\n    \"vega-lite\": \"^6.2.0\"\n  },\n  \"resolutions\": {\n    \"ws\": \"8.17.1\",\n    \"axios\": \"1.12.0\",\n    \"tar-fs\": \"2.1.4\",\n    \"tmp\": \"0.2.4\",\n    \"glob\": \"10.5.0\",\n    \"js-yaml\": \"4.1.1\",\n    \"jws\": \"4.0.1\",\n    \"tar\": \"7.5.7\",\n    \"vega-selections\": \"6.1.2\",\n    \"vega-functions\": \"6.1.1\",\n    \"fast-xml-parser\": \"4.5.4\",\n    \"lodash\": \"4.17.23\"\n  },\n  \"_moduleAliases\": {\n    \"@server\": \"src/apollo/server\"\n  },\n  \"packageManager\": \"yarn@4.5.3\"\n}\n"
  },
  {
    "path": "wren-ui/playwright.config.ts",
    "content": "import { defineConfig, devices } from '@playwright/test';\n\nexport default defineConfig({\n  // Look for test files in the \"tests\" directory, relative to this configuration file.\n  testDir: 'e2e',\n\n  // Each test is given 60 seconds.\n  timeout: 1 * 60 * 1000,\n\n  // Fail the build on CI if you accidentally left test.only in the source code.\n  forbidOnly: false,\n\n  // Retry on CI only.\n  retries: 0,\n\n  // Opt out of parallel tests on CI.\n  workers: 1,\n\n  // Reporter to use\n  reporter: 'html',\n\n  use: {\n    // Base URL to use in actions like `await page.goto('/')`.\n    baseURL: 'http://127.0.0.1:3000',\n\n    // Collect trace when retrying the failed test.\n    trace: 'on-first-retry',\n  },\n  // Configure projects for major browsers.\n  projects: [\n    {\n      name: 'setup db',\n      testMatch: /global\\.setup\\.ts/,\n      teardown: 'cleanup db',\n    },\n    {\n      name: 'cleanup db',\n      testMatch: /global\\.teardown\\.ts/,\n    },\n    {\n      name: 'chromium',\n      use: { ...devices['Desktop Chrome'] },\n      dependencies: ['setup db'],\n    },\n  ],\n  // Run your local dev server before starting the tests.\n  webServer: {\n    command: 'NODE_ENV=test yarn start -p 3000',\n    url: 'http://127.0.0.1:3000',\n    reuseExistingServer: true,\n  },\n});\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/__types__.ts",
    "content": "import { gql } from '@apollo/client';\nexport type Maybe<T> = T | null;\nexport type InputMaybe<T> = Maybe<T>;\nexport type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };\nexport type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };\nexport type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };\n/** All built-in and custom scalars, mapped to their actual values */\nexport type Scalars = {\n  ID: string;\n  String: string;\n  Boolean: boolean;\n  Int: number;\n  Float: number;\n  DialectSQL: any;\n  JSON: any;\n};\n\nexport type AdjustThreadResponseChartInput = {\n  chartType: ChartType;\n  color?: InputMaybe<Scalars['String']>;\n  theta?: InputMaybe<Scalars['String']>;\n  xAxis?: InputMaybe<Scalars['String']>;\n  xOffset?: InputMaybe<Scalars['String']>;\n  yAxis?: InputMaybe<Scalars['String']>;\n};\n\nexport type AdjustThreadResponseInput = {\n  sql?: InputMaybe<Scalars['String']>;\n  sqlGenerationReasoning?: InputMaybe<Scalars['String']>;\n  tables?: InputMaybe<Array<Scalars['String']>>;\n};\n\nexport type AdjustmentTask = {\n  __typename?: 'AdjustmentTask';\n  error?: Maybe<Error>;\n  invalidSql?: Maybe<Scalars['String']>;\n  queryId?: Maybe<Scalars['String']>;\n  sql?: Maybe<Scalars['String']>;\n  status?: Maybe<AskingTaskStatus>;\n  traceId?: Maybe<Scalars['String']>;\n};\n\nexport type ApiHistoryFilterInput = {\n  apiType?: InputMaybe<ApiType>;\n  endDate?: InputMaybe<Scalars['String']>;\n  projectId?: InputMaybe<Scalars['Int']>;\n  startDate?: InputMaybe<Scalars['String']>;\n  statusCode?: InputMaybe<Scalars['Int']>;\n  threadId?: InputMaybe<Scalars['String']>;\n};\n\nexport type ApiHistoryPaginatedResponse = {\n  __typename?: 'ApiHistoryPaginatedResponse';\n  hasMore: Scalars['Boolean'];\n  items: Array<ApiHistoryResponse>;\n  total: Scalars['Int'];\n};\n\nexport type ApiHistoryPaginationInput = {\n  limit: Scalars['Int'];\n  offset: Scalars['Int'];\n};\n\nexport type ApiHistoryResponse = {\n  __typename?: 'ApiHistoryResponse';\n  apiType: ApiType;\n  createdAt: Scalars['String'];\n  durationMs?: Maybe<Scalars['Int']>;\n  headers?: Maybe<Scalars['JSON']>;\n  id: Scalars['String'];\n  projectId: Scalars['Int'];\n  requestPayload?: Maybe<Scalars['JSON']>;\n  responsePayload?: Maybe<Scalars['JSON']>;\n  statusCode?: Maybe<Scalars['Int']>;\n  threadId?: Maybe<Scalars['String']>;\n  updatedAt: Scalars['String'];\n};\n\nexport enum ApiType {\n  ASK = 'ASK',\n  CREATE_INSTRUCTION = 'CREATE_INSTRUCTION',\n  CREATE_SQL_PAIR = 'CREATE_SQL_PAIR',\n  DELETE_INSTRUCTION = 'DELETE_INSTRUCTION',\n  DELETE_SQL_PAIR = 'DELETE_SQL_PAIR',\n  GENERATE_SQL = 'GENERATE_SQL',\n  GENERATE_SUMMARY = 'GENERATE_SUMMARY',\n  GENERATE_VEGA_CHART = 'GENERATE_VEGA_CHART',\n  GET_INSTRUCTIONS = 'GET_INSTRUCTIONS',\n  GET_MODELS = 'GET_MODELS',\n  GET_SQL_PAIRS = 'GET_SQL_PAIRS',\n  RUN_SQL = 'RUN_SQL',\n  STREAM_ASK = 'STREAM_ASK',\n  STREAM_GENERATE_SQL = 'STREAM_GENERATE_SQL',\n  UPDATE_INSTRUCTION = 'UPDATE_INSTRUCTION',\n  UPDATE_SQL_PAIR = 'UPDATE_SQL_PAIR'\n}\n\nexport type AskingTask = {\n  __typename?: 'AskingTask';\n  candidates: Array<ResultCandidate>;\n  error?: Maybe<Error>;\n  intentReasoning?: Maybe<Scalars['String']>;\n  invalidSql?: Maybe<Scalars['String']>;\n  queryId?: Maybe<Scalars['String']>;\n  rephrasedQuestion?: Maybe<Scalars['String']>;\n  retrievedTables?: Maybe<Array<Scalars['String']>>;\n  sqlGenerationReasoning?: Maybe<Scalars['String']>;\n  status: AskingTaskStatus;\n  traceId?: Maybe<Scalars['String']>;\n  type?: Maybe<AskingTaskType>;\n};\n\nexport type AskingTaskInput = {\n  question: Scalars['String'];\n  threadId?: InputMaybe<Scalars['Int']>;\n};\n\nexport enum AskingTaskStatus {\n  CORRECTING = 'CORRECTING',\n  FAILED = 'FAILED',\n  FINISHED = 'FINISHED',\n  GENERATING = 'GENERATING',\n  PLANNING = 'PLANNING',\n  SEARCHING = 'SEARCHING',\n  STOPPED = 'STOPPED',\n  UNDERSTANDING = 'UNDERSTANDING'\n}\n\nexport enum AskingTaskType {\n  GENERAL = 'GENERAL',\n  MISLEADING_QUERY = 'MISLEADING_QUERY',\n  TEXT_TO_SQL = 'TEXT_TO_SQL'\n}\n\nexport enum CacheScheduleDayEnum {\n  FRI = 'FRI',\n  MON = 'MON',\n  SAT = 'SAT',\n  SUN = 'SUN',\n  THU = 'THU',\n  TUE = 'TUE',\n  WED = 'WED'\n}\n\nexport type CalculatedFieldInput = {\n  diagram?: InputMaybe<Scalars['JSON']>;\n  expression: Scalars['String'];\n  lineage: Array<Scalars['Int']>;\n  name: Scalars['String'];\n};\n\nexport type CalculatedFieldValidationResponse = {\n  __typename?: 'CalculatedFieldValidationResponse';\n  message?: Maybe<Scalars['String']>;\n  valid: Scalars['Boolean'];\n};\n\nexport enum ChartTaskStatus {\n  FAILED = 'FAILED',\n  FETCHING = 'FETCHING',\n  FINISHED = 'FINISHED',\n  GENERATING = 'GENERATING',\n  STOPPED = 'STOPPED'\n}\n\nexport enum ChartType {\n  AREA = 'AREA',\n  BAR = 'BAR',\n  GROUPED_BAR = 'GROUPED_BAR',\n  LINE = 'LINE',\n  MULTI_LINE = 'MULTI_LINE',\n  PIE = 'PIE',\n  STACKED_BAR = 'STACKED_BAR'\n}\n\nexport type CompactColumn = {\n  __typename?: 'CompactColumn';\n  name: Scalars['String'];\n  properties?: Maybe<Scalars['JSON']>;\n  type: Scalars['String'];\n};\n\nexport type CompactTable = {\n  __typename?: 'CompactTable';\n  columns: Array<CompactColumn>;\n  name: Scalars['String'];\n  properties?: Maybe<Scalars['JSON']>;\n};\n\nexport type CreateCalculatedFieldInput = {\n  expression: ExpressionName;\n  lineage: Array<Scalars['Int']>;\n  modelId: Scalars['Int'];\n  name: Scalars['String'];\n};\n\nexport type CreateDashboardItemInput = {\n  itemType: DashboardItemType;\n  responseId: Scalars['Int'];\n};\n\nexport type CreateInstructionInput = {\n  instruction: Scalars['String'];\n  isDefault: Scalars['Boolean'];\n  questions: Array<Scalars['String']>;\n};\n\nexport type CreateModelInput = {\n  fields: Array<Scalars['String']>;\n  primaryKey?: InputMaybe<Scalars['String']>;\n  sourceTableName: Scalars['String'];\n};\n\nexport type CreateSimpleMetricInput = {\n  cached: Scalars['Boolean'];\n  description?: InputMaybe<Scalars['String']>;\n  dimension: Array<DimensionInput>;\n  displayName: Scalars['String'];\n  measure: Array<SimpleMeasureInput>;\n  model: Scalars['String'];\n  name: Scalars['String'];\n  properties: Scalars['JSON'];\n  refreshTime?: InputMaybe<Scalars['String']>;\n  timeGrain: Array<TimeGrainInput>;\n};\n\nexport type CreateSqlPairInput = {\n  question: Scalars['String'];\n  sql: Scalars['String'];\n};\n\nexport type CreateThreadInput = {\n  question?: InputMaybe<Scalars['String']>;\n  sql?: InputMaybe<Scalars['String']>;\n  taskId?: InputMaybe<Scalars['String']>;\n};\n\nexport type CreateThreadResponseInput = {\n  question?: InputMaybe<Scalars['String']>;\n  sql?: InputMaybe<Scalars['String']>;\n  taskId?: InputMaybe<Scalars['String']>;\n};\n\nexport type CreateViewInput = {\n  name: Scalars['String'];\n  rephrasedQuestion: Scalars['String'];\n  responseId: Scalars['Int'];\n};\n\nexport type CustomFieldInput = {\n  expression: Scalars['String'];\n  name: Scalars['String'];\n};\n\nexport type Dashboard = {\n  __typename?: 'Dashboard';\n  cacheEnabled: Scalars['Boolean'];\n  id: Scalars['Int'];\n  name: Scalars['String'];\n  nextScheduledAt?: Maybe<Scalars['String']>;\n  projectId: Scalars['Int'];\n  scheduleCron?: Maybe<Scalars['String']>;\n  scheduleFrequency?: Maybe<ScheduleFrequencyEnum>;\n  scheduleTimezone?: Maybe<Scalars['String']>;\n};\n\nexport type DashboardItem = {\n  __typename?: 'DashboardItem';\n  dashboardId: Scalars['Int'];\n  detail: DashboardItemDetail;\n  displayName?: Maybe<Scalars['String']>;\n  id: Scalars['Int'];\n  layout: DashboardItemLayout;\n  type: DashboardItemType;\n};\n\nexport type DashboardItemDetail = {\n  __typename?: 'DashboardItemDetail';\n  chartSchema?: Maybe<Scalars['JSON']>;\n  sql: Scalars['String'];\n};\n\nexport type DashboardItemLayout = {\n  __typename?: 'DashboardItemLayout';\n  h: Scalars['Int'];\n  w: Scalars['Int'];\n  x: Scalars['Int'];\n  y: Scalars['Int'];\n};\n\nexport enum DashboardItemType {\n  AREA = 'AREA',\n  BAR = 'BAR',\n  GROUPED_BAR = 'GROUPED_BAR',\n  LINE = 'LINE',\n  MULTI_LINE = 'MULTI_LINE',\n  NUMBER = 'NUMBER',\n  PIE = 'PIE',\n  STACKED_BAR = 'STACKED_BAR',\n  TABLE = 'TABLE'\n}\n\nexport type DashboardItemWhereInput = {\n  id: Scalars['Int'];\n};\n\nexport type DashboardSchedule = {\n  __typename?: 'DashboardSchedule';\n  cron?: Maybe<Scalars['String']>;\n  day?: Maybe<CacheScheduleDayEnum>;\n  frequency?: Maybe<ScheduleFrequencyEnum>;\n  hour?: Maybe<Scalars['Int']>;\n  minute?: Maybe<Scalars['Int']>;\n  timezone?: Maybe<Scalars['String']>;\n};\n\nexport type DataSource = {\n  __typename?: 'DataSource';\n  properties: Scalars['JSON'];\n  sampleDataset?: Maybe<SampleDatasetName>;\n  type: DataSourceName;\n};\n\nexport type DataSourceInput = {\n  properties: Scalars['JSON'];\n  type: DataSourceName;\n};\n\nexport enum DataSourceName {\n  ATHENA = 'ATHENA',\n  BIG_QUERY = 'BIG_QUERY',\n  CLICK_HOUSE = 'CLICK_HOUSE',\n  DATABRICKS = 'DATABRICKS',\n  DUCKDB = 'DUCKDB',\n  MSSQL = 'MSSQL',\n  MYSQL = 'MYSQL',\n  ORACLE = 'ORACLE',\n  POSTGRES = 'POSTGRES',\n  REDSHIFT = 'REDSHIFT',\n  SNOWFLAKE = 'SNOWFLAKE',\n  TRINO = 'TRINO'\n}\n\nexport enum DatabricksConnectionType {\n  service_principal = 'service_principal',\n  token = 'token'\n}\n\nexport type DeleteDashboardItemInput = {\n  itemId: Scalars['Int'];\n};\n\nexport type DetailStep = {\n  __typename?: 'DetailStep';\n  cteName?: Maybe<Scalars['String']>;\n  sql: Scalars['String'];\n  summary: Scalars['String'];\n};\n\nexport type DetailedAffectedCalculatedFields = {\n  __typename?: 'DetailedAffectedCalculatedFields';\n  displayName: Scalars['String'];\n  referenceName: Scalars['String'];\n  type: Scalars['String'];\n};\n\nexport type DetailedAffectedRelationships = {\n  __typename?: 'DetailedAffectedRelationships';\n  displayName: Scalars['String'];\n  referenceName: Scalars['String'];\n};\n\nexport type DetailedChangeColumn = {\n  __typename?: 'DetailedChangeColumn';\n  displayName: Scalars['String'];\n  sourceColumnName: Scalars['String'];\n  type: Scalars['String'];\n};\n\nexport type DetailedChangeTable = {\n  __typename?: 'DetailedChangeTable';\n  calculatedFields: Array<DetailedAffectedCalculatedFields>;\n  columns: Array<DetailedChangeColumn>;\n  displayName: Scalars['String'];\n  relationships: Array<DetailedAffectedRelationships>;\n  sourceTableName: Scalars['String'];\n};\n\nexport type DetailedColumn = {\n  __typename?: 'DetailedColumn';\n  displayName: Scalars['String'];\n  isCalculated: Scalars['Boolean'];\n  nestedColumns?: Maybe<Array<DetailedNestedColumn>>;\n  notNull: Scalars['Boolean'];\n  properties: Scalars['JSON'];\n  referenceName: Scalars['String'];\n  sourceColumnName: Scalars['String'];\n  type?: Maybe<Scalars['String']>;\n};\n\nexport type DetailedDashboard = {\n  __typename?: 'DetailedDashboard';\n  cacheEnabled: Scalars['Boolean'];\n  description?: Maybe<Scalars['String']>;\n  id: Scalars['Int'];\n  items: Array<DashboardItem>;\n  name: Scalars['String'];\n  nextScheduledAt?: Maybe<Scalars['String']>;\n  schedule?: Maybe<DashboardSchedule>;\n};\n\nexport type DetailedModel = {\n  __typename?: 'DetailedModel';\n  cached: Scalars['Boolean'];\n  calculatedFields?: Maybe<Array<Maybe<DetailedColumn>>>;\n  description?: Maybe<Scalars['String']>;\n  displayName: Scalars['String'];\n  fields?: Maybe<Array<Maybe<DetailedColumn>>>;\n  primaryKey?: Maybe<Scalars['String']>;\n  properties: Scalars['JSON'];\n  refSql: Scalars['String'];\n  referenceName: Scalars['String'];\n  refreshTime?: Maybe<Scalars['String']>;\n  relations?: Maybe<Array<Maybe<DetailedRelation>>>;\n  sourceTableName: Scalars['String'];\n};\n\nexport type DetailedNestedColumn = {\n  __typename?: 'DetailedNestedColumn';\n  columnPath: Array<Scalars['String']>;\n  displayName: Scalars['String'];\n  id: Scalars['Int'];\n  properties?: Maybe<Scalars['JSON']>;\n  referenceName: Scalars['String'];\n  sourceColumnName: Scalars['String'];\n  type?: Maybe<Scalars['String']>;\n};\n\nexport type DetailedRelation = {\n  __typename?: 'DetailedRelation';\n  fromColumnId: Scalars['Int'];\n  fromModelId: Scalars['Int'];\n  name: Scalars['String'];\n  properties: Scalars['JSON'];\n  toColumnId: Scalars['Int'];\n  toModelId: Scalars['Int'];\n  type: RelationType;\n};\n\nexport type DetailedThread = {\n  __typename?: 'DetailedThread';\n  id: Scalars['Int'];\n  responses: Array<ThreadResponse>;\n};\n\nexport type Diagram = {\n  __typename?: 'Diagram';\n  models: Array<Maybe<DiagramModel>>;\n  views: Array<Maybe<DiagramView>>;\n};\n\nexport type DiagramModel = {\n  __typename?: 'DiagramModel';\n  cached: Scalars['Boolean'];\n  calculatedFields: Array<Maybe<DiagramModelField>>;\n  description?: Maybe<Scalars['String']>;\n  displayName: Scalars['String'];\n  fields: Array<Maybe<DiagramModelField>>;\n  id: Scalars['String'];\n  modelId: Scalars['Int'];\n  nodeType: NodeType;\n  refSql?: Maybe<Scalars['String']>;\n  referenceName: Scalars['String'];\n  refreshTime?: Maybe<Scalars['String']>;\n  relationFields: Array<Maybe<DiagramModelRelationField>>;\n  sourceTableName: Scalars['String'];\n};\n\nexport type DiagramModelField = {\n  __typename?: 'DiagramModelField';\n  aggregation?: Maybe<Scalars['String']>;\n  columnId: Scalars['Int'];\n  description?: Maybe<Scalars['String']>;\n  displayName: Scalars['String'];\n  expression?: Maybe<Scalars['String']>;\n  id: Scalars['String'];\n  isPrimaryKey: Scalars['Boolean'];\n  lineage?: Maybe<Array<Scalars['Int']>>;\n  nestedFields?: Maybe<Array<DiagramModelNestedField>>;\n  nodeType: NodeType;\n  referenceName: Scalars['String'];\n  type: Scalars['String'];\n};\n\nexport type DiagramModelNestedField = {\n  __typename?: 'DiagramModelNestedField';\n  columnPath: Array<Scalars['String']>;\n  description?: Maybe<Scalars['String']>;\n  displayName: Scalars['String'];\n  id: Scalars['String'];\n  nestedColumnId: Scalars['Int'];\n  referenceName: Scalars['String'];\n  type: Scalars['String'];\n};\n\nexport type DiagramModelRelationField = {\n  __typename?: 'DiagramModelRelationField';\n  description?: Maybe<Scalars['String']>;\n  displayName: Scalars['String'];\n  fromColumnDisplayName: Scalars['String'];\n  fromColumnId: Scalars['Int'];\n  fromColumnName: Scalars['String'];\n  fromModelDisplayName: Scalars['String'];\n  fromModelId: Scalars['Int'];\n  fromModelName: Scalars['String'];\n  id: Scalars['String'];\n  nodeType: NodeType;\n  referenceName: Scalars['String'];\n  relationId: Scalars['Int'];\n  toColumnDisplayName: Scalars['String'];\n  toColumnId: Scalars['Int'];\n  toColumnName: Scalars['String'];\n  toModelDisplayName: Scalars['String'];\n  toModelId: Scalars['Int'];\n  toModelName: Scalars['String'];\n  type: RelationType;\n};\n\nexport type DiagramView = {\n  __typename?: 'DiagramView';\n  description?: Maybe<Scalars['String']>;\n  displayName: Scalars['String'];\n  fields: Array<Maybe<DiagramViewField>>;\n  id: Scalars['String'];\n  nodeType: NodeType;\n  referenceName: Scalars['String'];\n  statement: Scalars['String'];\n  viewId: Scalars['Int'];\n};\n\nexport type DiagramViewField = {\n  __typename?: 'DiagramViewField';\n  description?: Maybe<Scalars['String']>;\n  displayName: Scalars['String'];\n  id: Scalars['String'];\n  nodeType: NodeType;\n  referenceName: Scalars['String'];\n  type: Scalars['String'];\n};\n\nexport type DimensionInput = {\n  isCalculated: Scalars['Boolean'];\n  name: Scalars['String'];\n  notNull: Scalars['Boolean'];\n  properties: Scalars['JSON'];\n  type: Scalars['String'];\n};\n\nexport type Error = {\n  __typename?: 'Error';\n  code?: Maybe<Scalars['String']>;\n  message?: Maybe<Scalars['String']>;\n  shortMessage?: Maybe<Scalars['String']>;\n  stacktrace?: Maybe<Array<Maybe<Scalars['String']>>>;\n};\n\nexport enum ExpressionName {\n  ABS = 'ABS',\n  AVG = 'AVG',\n  CBRT = 'CBRT',\n  CEIL = 'CEIL',\n  CEILING = 'CEILING',\n  COUNT = 'COUNT',\n  COUNT_IF = 'COUNT_IF',\n  EXP = 'EXP',\n  FLOOR = 'FLOOR',\n  LENGTH = 'LENGTH',\n  LN = 'LN',\n  LOG10 = 'LOG10',\n  MAX = 'MAX',\n  MIN = 'MIN',\n  REVERSE = 'REVERSE',\n  ROUND = 'ROUND',\n  SIGN = 'SIGN',\n  SUM = 'SUM'\n}\n\nexport type FieldInfo = {\n  __typename?: 'FieldInfo';\n  displayName: Scalars['String'];\n  expression?: Maybe<Scalars['String']>;\n  id: Scalars['Int'];\n  isCalculated: Scalars['Boolean'];\n  nestedColumns?: Maybe<Array<NestedFieldInfo>>;\n  notNull: Scalars['Boolean'];\n  properties?: Maybe<Scalars['JSON']>;\n  referenceName: Scalars['String'];\n  sourceColumnName: Scalars['String'];\n  type?: Maybe<Scalars['String']>;\n};\n\nexport type GenerateQuestionInput = {\n  sql: Scalars['String'];\n};\n\nexport type GetMdlResult = {\n  __typename?: 'GetMDLResult';\n  hash: Scalars['String'];\n  mdl?: Maybe<Scalars['String']>;\n};\n\nexport type InstantRecommendedQuestionsInput = {\n  previousQuestions?: InputMaybe<Array<Scalars['String']>>;\n};\n\nexport type Instruction = {\n  __typename?: 'Instruction';\n  createdAt: Scalars['String'];\n  id: Scalars['Int'];\n  instruction: Scalars['String'];\n  isDefault: Scalars['Boolean'];\n  projectId: Scalars['Int'];\n  questions: Array<Scalars['String']>;\n  updatedAt: Scalars['String'];\n};\n\nexport type InstructionWhereInput = {\n  id: Scalars['Int'];\n};\n\nexport type ItemLayoutInput = {\n  h: Scalars['Int'];\n  itemId: Scalars['Int'];\n  w: Scalars['Int'];\n  x: Scalars['Int'];\n  y: Scalars['Int'];\n};\n\nexport type LearningRecord = {\n  __typename?: 'LearningRecord';\n  paths: Array<Scalars['String']>;\n};\n\nexport type MdlModelSubmitInput = {\n  columns: Array<Scalars['String']>;\n  name: Scalars['String'];\n};\n\nexport type ModelInfo = {\n  __typename?: 'ModelInfo';\n  cached: Scalars['Boolean'];\n  calculatedFields: Array<Maybe<FieldInfo>>;\n  description?: Maybe<Scalars['String']>;\n  displayName: Scalars['String'];\n  fields: Array<Maybe<FieldInfo>>;\n  id: Scalars['Int'];\n  primaryKey?: Maybe<Scalars['String']>;\n  properties?: Maybe<Scalars['JSON']>;\n  refSql?: Maybe<Scalars['String']>;\n  referenceName: Scalars['String'];\n  refreshTime?: Maybe<Scalars['String']>;\n  sourceTableName: Scalars['String'];\n};\n\nexport type ModelSubstituteInput = {\n  sql: Scalars['DialectSQL'];\n};\n\nexport type ModelSyncResponse = {\n  __typename?: 'ModelSyncResponse';\n  status: SyncStatus;\n};\n\nexport type ModelWhereInput = {\n  id: Scalars['Int'];\n};\n\nexport type Mutation = {\n  __typename?: 'Mutation';\n  adjustThreadResponse: ThreadResponse;\n  adjustThreadResponseChart: ThreadResponse;\n  cancelAdjustmentTask: Scalars['Boolean'];\n  cancelAskingTask: Scalars['Boolean'];\n  createAskingTask: Task;\n  createCalculatedField: Scalars['JSON'];\n  createDashboardItem: DashboardItem;\n  createInstantRecommendedQuestions: Task;\n  createInstruction: Instruction;\n  createModel: Scalars['JSON'];\n  createRelation: Scalars['JSON'];\n  createSqlPair: SqlPair;\n  createThread: Thread;\n  createThreadResponse: ThreadResponse;\n  createView: ViewInfo;\n  deleteCalculatedField: Scalars['Boolean'];\n  deleteDashboardItem: Scalars['Boolean'];\n  deleteInstruction: Scalars['Boolean'];\n  deleteModel: Scalars['Boolean'];\n  deleteRelation: Scalars['Boolean'];\n  deleteSqlPair: Scalars['Boolean'];\n  deleteThread: Scalars['Boolean'];\n  deleteView: Scalars['Boolean'];\n  deploy: Scalars['JSON'];\n  generateProjectRecommendationQuestions: Scalars['Boolean'];\n  generateQuestion: Scalars['String'];\n  generateThreadRecommendationQuestions: Scalars['Boolean'];\n  generateThreadResponseAnswer: ThreadResponse;\n  generateThreadResponseBreakdown: ThreadResponse;\n  generateThreadResponseChart: ThreadResponse;\n  modelSubstitute: Scalars['String'];\n  previewBreakdownData: Scalars['JSON'];\n  previewData: Scalars['JSON'];\n  previewItemSQL: PreviewItemResponse;\n  previewModelData: Scalars['JSON'];\n  previewSql: Scalars['JSON'];\n  previewViewData: Scalars['JSON'];\n  rerunAdjustmentTask: Scalars['Boolean'];\n  rerunAskingTask: Task;\n  resetCurrentProject: Scalars['Boolean'];\n  resolveSchemaChange: Scalars['Boolean'];\n  saveDataSource: DataSource;\n  saveLearningRecord: LearningRecord;\n  saveRelations: Scalars['JSON'];\n  saveTables: Scalars['JSON'];\n  setDashboardSchedule: Dashboard;\n  startSampleDataset: Scalars['JSON'];\n  triggerDataSourceDetection: Scalars['Boolean'];\n  updateCalculatedField: Scalars['JSON'];\n  updateCurrentProject: Scalars['Boolean'];\n  updateDashboardItem: DashboardItem;\n  updateDashboardItemLayouts: Array<DashboardItem>;\n  updateDataSource: DataSource;\n  updateInstruction: Instruction;\n  updateModel: Scalars['JSON'];\n  updateModelMetadata: Scalars['Boolean'];\n  updateRelation: Scalars['JSON'];\n  updateSqlPair: SqlPair;\n  updateThread: Thread;\n  updateThreadResponse: ThreadResponse;\n  updateViewMetadata: Scalars['Boolean'];\n  validateCalculatedField: CalculatedFieldValidationResponse;\n  validateView: ViewValidationResponse;\n};\n\n\nexport type MutationAdjustThreadResponseArgs = {\n  data: AdjustThreadResponseInput;\n  responseId: Scalars['Int'];\n};\n\n\nexport type MutationAdjustThreadResponseChartArgs = {\n  data: AdjustThreadResponseChartInput;\n  responseId: Scalars['Int'];\n};\n\n\nexport type MutationCancelAdjustmentTaskArgs = {\n  taskId: Scalars['String'];\n};\n\n\nexport type MutationCancelAskingTaskArgs = {\n  taskId: Scalars['String'];\n};\n\n\nexport type MutationCreateAskingTaskArgs = {\n  data: AskingTaskInput;\n};\n\n\nexport type MutationCreateCalculatedFieldArgs = {\n  data: CreateCalculatedFieldInput;\n};\n\n\nexport type MutationCreateDashboardItemArgs = {\n  data: CreateDashboardItemInput;\n};\n\n\nexport type MutationCreateInstantRecommendedQuestionsArgs = {\n  data: InstantRecommendedQuestionsInput;\n};\n\n\nexport type MutationCreateInstructionArgs = {\n  data: CreateInstructionInput;\n};\n\n\nexport type MutationCreateModelArgs = {\n  data: CreateModelInput;\n};\n\n\nexport type MutationCreateRelationArgs = {\n  data: RelationInput;\n};\n\n\nexport type MutationCreateSqlPairArgs = {\n  data: CreateSqlPairInput;\n};\n\n\nexport type MutationCreateThreadArgs = {\n  data: CreateThreadInput;\n};\n\n\nexport type MutationCreateThreadResponseArgs = {\n  data: CreateThreadResponseInput;\n  threadId: Scalars['Int'];\n};\n\n\nexport type MutationCreateViewArgs = {\n  data: CreateViewInput;\n};\n\n\nexport type MutationDeleteCalculatedFieldArgs = {\n  where?: InputMaybe<UpdateCalculatedFieldWhere>;\n};\n\n\nexport type MutationDeleteDashboardItemArgs = {\n  where: DashboardItemWhereInput;\n};\n\n\nexport type MutationDeleteInstructionArgs = {\n  where: InstructionWhereInput;\n};\n\n\nexport type MutationDeleteModelArgs = {\n  where: ModelWhereInput;\n};\n\n\nexport type MutationDeleteRelationArgs = {\n  where: WhereIdInput;\n};\n\n\nexport type MutationDeleteSqlPairArgs = {\n  where: SqlPairWhereUniqueInput;\n};\n\n\nexport type MutationDeleteThreadArgs = {\n  where: ThreadUniqueWhereInput;\n};\n\n\nexport type MutationDeleteViewArgs = {\n  where: ViewWhereUniqueInput;\n};\n\n\nexport type MutationDeployArgs = {\n  force?: InputMaybe<Scalars['Boolean']>;\n};\n\n\nexport type MutationGenerateQuestionArgs = {\n  data: GenerateQuestionInput;\n};\n\n\nexport type MutationGenerateThreadRecommendationQuestionsArgs = {\n  threadId: Scalars['Int'];\n};\n\n\nexport type MutationGenerateThreadResponseAnswerArgs = {\n  responseId: Scalars['Int'];\n};\n\n\nexport type MutationGenerateThreadResponseBreakdownArgs = {\n  responseId: Scalars['Int'];\n};\n\n\nexport type MutationGenerateThreadResponseChartArgs = {\n  responseId: Scalars['Int'];\n};\n\n\nexport type MutationModelSubstituteArgs = {\n  data: ModelSubstituteInput;\n};\n\n\nexport type MutationPreviewBreakdownDataArgs = {\n  where: PreviewDataInput;\n};\n\n\nexport type MutationPreviewDataArgs = {\n  where: PreviewDataInput;\n};\n\n\nexport type MutationPreviewItemSqlArgs = {\n  data: PreviewItemSqlInput;\n};\n\n\nexport type MutationPreviewModelDataArgs = {\n  where: WhereIdInput;\n};\n\n\nexport type MutationPreviewSqlArgs = {\n  data?: InputMaybe<PreviewSqlDataInput>;\n};\n\n\nexport type MutationPreviewViewDataArgs = {\n  where: PreviewViewDataInput;\n};\n\n\nexport type MutationRerunAdjustmentTaskArgs = {\n  responseId: Scalars['Int'];\n};\n\n\nexport type MutationRerunAskingTaskArgs = {\n  responseId: Scalars['Int'];\n};\n\n\nexport type MutationResolveSchemaChangeArgs = {\n  where: ResolveSchemaChangeWhereInput;\n};\n\n\nexport type MutationSaveDataSourceArgs = {\n  data: DataSourceInput;\n};\n\n\nexport type MutationSaveLearningRecordArgs = {\n  data: SaveLearningRecordInput;\n};\n\n\nexport type MutationSaveRelationsArgs = {\n  data: SaveRelationInput;\n};\n\n\nexport type MutationSaveTablesArgs = {\n  data: SaveTablesInput;\n};\n\n\nexport type MutationSetDashboardScheduleArgs = {\n  data: SetDashboardScheduleInput;\n};\n\n\nexport type MutationStartSampleDatasetArgs = {\n  data: SampleDatasetInput;\n};\n\n\nexport type MutationUpdateCalculatedFieldArgs = {\n  data: UpdateCalculatedFieldInput;\n  where: UpdateCalculatedFieldWhere;\n};\n\n\nexport type MutationUpdateCurrentProjectArgs = {\n  data: UpdateCurrentProjectInput;\n};\n\n\nexport type MutationUpdateDashboardItemArgs = {\n  data: UpdateDashboardItemInput;\n  where: DashboardItemWhereInput;\n};\n\n\nexport type MutationUpdateDashboardItemLayoutsArgs = {\n  data: UpdateDashboardItemLayoutsInput;\n};\n\n\nexport type MutationUpdateDataSourceArgs = {\n  data: UpdateDataSourceInput;\n};\n\n\nexport type MutationUpdateInstructionArgs = {\n  data: UpdateInstructionInput;\n  where: InstructionWhereInput;\n};\n\n\nexport type MutationUpdateModelArgs = {\n  data: UpdateModelInput;\n  where: ModelWhereInput;\n};\n\n\nexport type MutationUpdateModelMetadataArgs = {\n  data: UpdateModelMetadataInput;\n  where: ModelWhereInput;\n};\n\n\nexport type MutationUpdateRelationArgs = {\n  data: UpdateRelationInput;\n  where: WhereIdInput;\n};\n\n\nexport type MutationUpdateSqlPairArgs = {\n  data: UpdateSqlPairInput;\n  where: SqlPairWhereUniqueInput;\n};\n\n\nexport type MutationUpdateThreadArgs = {\n  data: UpdateThreadInput;\n  where: ThreadUniqueWhereInput;\n};\n\n\nexport type MutationUpdateThreadResponseArgs = {\n  data: UpdateThreadResponseInput;\n  where: ThreadResponseUniqueWhereInput;\n};\n\n\nexport type MutationUpdateViewMetadataArgs = {\n  data: UpdateViewMetadataInput;\n  where: ViewWhereUniqueInput;\n};\n\n\nexport type MutationValidateCalculatedFieldArgs = {\n  data: ValidateCalculatedFieldInput;\n};\n\n\nexport type MutationValidateViewArgs = {\n  data: ValidateViewInput;\n};\n\nexport type NestedFieldInfo = {\n  __typename?: 'NestedFieldInfo';\n  columnPath: Array<Scalars['String']>;\n  displayName: Scalars['String'];\n  id: Scalars['Int'];\n  properties: Scalars['JSON'];\n  referenceName: Scalars['String'];\n  sourceColumnName: Scalars['String'];\n  type: Scalars['String'];\n};\n\nexport enum NodeType {\n  CALCULATED_FIELD = 'CALCULATED_FIELD',\n  FIELD = 'FIELD',\n  METRIC = 'METRIC',\n  MODEL = 'MODEL',\n  RELATION = 'RELATION',\n  VIEW = 'VIEW'\n}\n\nexport enum OnboardingStatus {\n  DATASOURCE_SAVED = 'DATASOURCE_SAVED',\n  NOT_STARTED = 'NOT_STARTED',\n  ONBOARDING_FINISHED = 'ONBOARDING_FINISHED',\n  WITH_SAMPLE_DATASET = 'WITH_SAMPLE_DATASET'\n}\n\nexport type OnboardingStatusResponse = {\n  __typename?: 'OnboardingStatusResponse';\n  status?: Maybe<OnboardingStatus>;\n};\n\nexport type PreviewDataInput = {\n  limit?: InputMaybe<Scalars['Int']>;\n  responseId: Scalars['Int'];\n  stepIndex?: InputMaybe<Scalars['Int']>;\n};\n\nexport type PreviewItemResponse = {\n  __typename?: 'PreviewItemResponse';\n  cacheCreatedAt?: Maybe<Scalars['String']>;\n  cacheHit: Scalars['Boolean'];\n  cacheOverrodeAt?: Maybe<Scalars['String']>;\n  data: Scalars['JSON'];\n  override: Scalars['Boolean'];\n};\n\nexport type PreviewItemSqlInput = {\n  itemId: Scalars['Int'];\n  limit?: InputMaybe<Scalars['Int']>;\n  refresh?: InputMaybe<Scalars['Boolean']>;\n};\n\nexport type PreviewSqlDataInput = {\n  dryRun?: InputMaybe<Scalars['Boolean']>;\n  limit?: InputMaybe<Scalars['Int']>;\n  projectId?: InputMaybe<Scalars['String']>;\n  sql: Scalars['String'];\n};\n\nexport type PreviewViewDataInput = {\n  id: Scalars['Int'];\n  limit?: InputMaybe<Scalars['Int']>;\n};\n\nexport enum ProjectLanguage {\n  AR = 'AR',\n  AZ_AZ = 'AZ_AZ',\n  DE = 'DE',\n  EN = 'EN',\n  ES = 'ES',\n  FA_IR = 'FA_IR',\n  FR = 'FR',\n  IT = 'IT',\n  JA = 'JA',\n  KO = 'KO',\n  NL = 'NL',\n  PT = 'PT',\n  RU = 'RU',\n  TR = 'TR',\n  ZH_CN = 'ZH_CN',\n  ZH_TW = 'ZH_TW'\n}\n\nexport type Query = {\n  __typename?: 'Query';\n  adjustmentTask?: Maybe<AdjustmentTask>;\n  apiHistory: ApiHistoryPaginatedResponse;\n  askingTask?: Maybe<AskingTask>;\n  autoGenerateRelation: Array<RecommendRelations>;\n  dashboard: DetailedDashboard;\n  dashboardItems: Array<DashboardItem>;\n  diagram: Diagram;\n  getMDL: GetMdlResult;\n  getProjectRecommendationQuestions: RecommendedQuestionsTask;\n  getThreadRecommendationQuestions: RecommendedQuestionsTask;\n  instantRecommendedQuestions: RecommendedQuestionsTask;\n  instructions: Array<Maybe<Instruction>>;\n  learningRecord: LearningRecord;\n  listDataSourceTables: Array<CompactTable>;\n  listModels: Array<ModelInfo>;\n  listViews: Array<ViewInfo>;\n  model: DetailedModel;\n  modelSync: ModelSyncResponse;\n  nativeSql: Scalars['String'];\n  onboardingStatus: OnboardingStatusResponse;\n  schemaChange: SchemaChange;\n  settings: Settings;\n  sqlPairs: Array<Maybe<SqlPair>>;\n  suggestedQuestions: SuggestedQuestionResponse;\n  thread: DetailedThread;\n  threadResponse: ThreadResponse;\n  threads: Array<Thread>;\n  view: ViewInfo;\n};\n\n\nexport type QueryAdjustmentTaskArgs = {\n  taskId: Scalars['String'];\n};\n\n\nexport type QueryApiHistoryArgs = {\n  filter?: InputMaybe<ApiHistoryFilterInput>;\n  pagination: ApiHistoryPaginationInput;\n};\n\n\nexport type QueryAskingTaskArgs = {\n  taskId: Scalars['String'];\n};\n\n\nexport type QueryGetMdlArgs = {\n  hash: Scalars['String'];\n};\n\n\nexport type QueryGetThreadRecommendationQuestionsArgs = {\n  threadId: Scalars['Int'];\n};\n\n\nexport type QueryInstantRecommendedQuestionsArgs = {\n  taskId: Scalars['String'];\n};\n\n\nexport type QueryModelArgs = {\n  where: ModelWhereInput;\n};\n\n\nexport type QueryNativeSqlArgs = {\n  responseId: Scalars['Int'];\n};\n\n\nexport type QueryThreadArgs = {\n  threadId: Scalars['Int'];\n};\n\n\nexport type QueryThreadResponseArgs = {\n  responseId: Scalars['Int'];\n};\n\n\nexport type QueryViewArgs = {\n  where: ViewWhereUniqueInput;\n};\n\nexport type RecommendRelations = {\n  __typename?: 'RecommendRelations';\n  displayName: Scalars['String'];\n  id: Scalars['Int'];\n  referenceName: Scalars['String'];\n  relations: Array<Maybe<Relation>>;\n};\n\nexport type RecommendedQuestionsTask = {\n  __typename?: 'RecommendedQuestionsTask';\n  error?: Maybe<Error>;\n  questions: Array<ResultQuestion>;\n  status: RecommendedQuestionsTaskStatus;\n};\n\nexport enum RecommendedQuestionsTaskStatus {\n  FAILED = 'FAILED',\n  FINISHED = 'FINISHED',\n  GENERATING = 'GENERATING',\n  NOT_STARTED = 'NOT_STARTED'\n}\n\nexport enum RedshiftConnectionType {\n  redshift = 'redshift',\n  redshift_iam = 'redshift_iam'\n}\n\nexport type Relation = {\n  __typename?: 'Relation';\n  fromColumnId: Scalars['Int'];\n  fromColumnReferenceName: Scalars['String'];\n  fromModelId: Scalars['Int'];\n  fromModelReferenceName: Scalars['String'];\n  name: Scalars['String'];\n  toColumnId: Scalars['Int'];\n  toColumnReferenceName: Scalars['String'];\n  toModelId: Scalars['Int'];\n  toModelReferenceName: Scalars['String'];\n  type: RelationType;\n};\n\nexport type RelationInput = {\n  fromColumnId: Scalars['Int'];\n  fromModelId: Scalars['Int'];\n  toColumnId: Scalars['Int'];\n  toModelId: Scalars['Int'];\n  type: RelationType;\n};\n\nexport enum RelationType {\n  MANY_TO_ONE = 'MANY_TO_ONE',\n  ONE_TO_MANY = 'ONE_TO_MANY',\n  ONE_TO_ONE = 'ONE_TO_ONE'\n}\n\nexport type ResolveSchemaChangeWhereInput = {\n  type: SchemaChangeType;\n};\n\nexport type ResultCandidate = {\n  __typename?: 'ResultCandidate';\n  sql: Scalars['String'];\n  sqlPair?: Maybe<SqlPair>;\n  type: ResultCandidateType;\n  view?: Maybe<ViewInfo>;\n};\n\nexport enum ResultCandidateType {\n  LLM = 'LLM',\n  SQL_PAIR = 'SQL_PAIR',\n  VIEW = 'VIEW'\n}\n\nexport type ResultQuestion = {\n  __typename?: 'ResultQuestion';\n  category: Scalars['String'];\n  question: Scalars['String'];\n  sql: Scalars['String'];\n};\n\nexport type SampleDatasetInput = {\n  name: SampleDatasetName;\n};\n\nexport enum SampleDatasetName {\n  ECOMMERCE = 'ECOMMERCE',\n  HR = 'HR',\n  MUSIC = 'MUSIC',\n  NBA = 'NBA'\n}\n\nexport type SaveLearningRecordInput = {\n  path: Scalars['String'];\n};\n\nexport type SaveRelationInput = {\n  relations: Array<InputMaybe<RelationInput>>;\n};\n\nexport type SaveTablesInput = {\n  tables: Array<Scalars['String']>;\n};\n\nexport enum ScheduleFrequencyEnum {\n  CUSTOM = 'CUSTOM',\n  DAILY = 'DAILY',\n  NEVER = 'NEVER',\n  WEEKLY = 'WEEKLY'\n}\n\nexport type SchemaChange = {\n  __typename?: 'SchemaChange';\n  deletedColumns?: Maybe<Array<DetailedChangeTable>>;\n  deletedTables?: Maybe<Array<DetailedChangeTable>>;\n  lastSchemaChangeTime?: Maybe<Scalars['String']>;\n  modifiedColumns?: Maybe<Array<DetailedChangeTable>>;\n};\n\nexport enum SchemaChangeType {\n  DELETED_COLUMNS = 'DELETED_COLUMNS',\n  DELETED_TABLES = 'DELETED_TABLES',\n  MODIFIED_COLUMNS = 'MODIFIED_COLUMNS'\n}\n\nexport type SetDashboardScheduleData = {\n  cron?: InputMaybe<Scalars['String']>;\n  day?: InputMaybe<CacheScheduleDayEnum>;\n  frequency: ScheduleFrequencyEnum;\n  hour?: InputMaybe<Scalars['Int']>;\n  minute?: InputMaybe<Scalars['Int']>;\n  timezone?: InputMaybe<Scalars['String']>;\n};\n\nexport type SetDashboardScheduleInput = {\n  cacheEnabled: Scalars['Boolean'];\n  schedule?: InputMaybe<SetDashboardScheduleData>;\n};\n\nexport type Settings = {\n  __typename?: 'Settings';\n  dataSource: DataSource;\n  language: ProjectLanguage;\n  productVersion: Scalars['String'];\n};\n\nexport type SimpleMeasureInput = {\n  isCalculated: Scalars['Boolean'];\n  name: Scalars['String'];\n  notNull: Scalars['Boolean'];\n  properties: Scalars['JSON'];\n  type: Scalars['String'];\n};\n\nexport type SqlPair = {\n  __typename?: 'SqlPair';\n  createdAt?: Maybe<Scalars['String']>;\n  id: Scalars['Int'];\n  projectId: Scalars['Int'];\n  question: Scalars['String'];\n  sql: Scalars['String'];\n  updatedAt?: Maybe<Scalars['String']>;\n};\n\nexport type SqlPairWhereUniqueInput = {\n  id: Scalars['Int'];\n};\n\nexport type SuggestedQuestion = {\n  __typename?: 'SuggestedQuestion';\n  label: Scalars['String'];\n  question: Scalars['String'];\n};\n\nexport type SuggestedQuestionResponse = {\n  __typename?: 'SuggestedQuestionResponse';\n  questions: Array<Maybe<SuggestedQuestion>>;\n};\n\nexport enum SyncStatus {\n  IN_PROGRESS = 'IN_PROGRESS',\n  SYNCRONIZED = 'SYNCRONIZED',\n  UNSYNCRONIZED = 'UNSYNCRONIZED'\n}\n\nexport type Task = {\n  __typename?: 'Task';\n  id: Scalars['String'];\n};\n\nexport type Thread = {\n  __typename?: 'Thread';\n  id: Scalars['Int'];\n  summary: Scalars['String'];\n};\n\nexport type ThreadResponse = {\n  __typename?: 'ThreadResponse';\n  adjustment?: Maybe<ThreadResponseAdjustment>;\n  adjustmentTask?: Maybe<AdjustmentTask>;\n  answerDetail?: Maybe<ThreadResponseAnswerDetail>;\n  askingTask?: Maybe<AskingTask>;\n  breakdownDetail?: Maybe<ThreadResponseBreakdownDetail>;\n  chartDetail?: Maybe<ThreadResponseChartDetail>;\n  id: Scalars['Int'];\n  question: Scalars['String'];\n  sql?: Maybe<Scalars['String']>;\n  threadId: Scalars['Int'];\n  view?: Maybe<ViewInfo>;\n};\n\nexport type ThreadResponseAdjustment = {\n  __typename?: 'ThreadResponseAdjustment';\n  payload?: Maybe<Scalars['JSON']>;\n  type: ThreadResponseAdjustmentType;\n};\n\nexport enum ThreadResponseAdjustmentType {\n  APPLY_SQL = 'APPLY_SQL',\n  REASONING = 'REASONING'\n}\n\nexport type ThreadResponseAnswerDetail = {\n  __typename?: 'ThreadResponseAnswerDetail';\n  content?: Maybe<Scalars['String']>;\n  error?: Maybe<Error>;\n  numRowsUsedInLLM?: Maybe<Scalars['Int']>;\n  queryId?: Maybe<Scalars['String']>;\n  status?: Maybe<ThreadResponseAnswerStatus>;\n};\n\nexport enum ThreadResponseAnswerStatus {\n  FAILED = 'FAILED',\n  FETCHING_DATA = 'FETCHING_DATA',\n  FINISHED = 'FINISHED',\n  INTERRUPTED = 'INTERRUPTED',\n  NOT_STARTED = 'NOT_STARTED',\n  PREPROCESSING = 'PREPROCESSING',\n  STREAMING = 'STREAMING'\n}\n\nexport type ThreadResponseBreakdownDetail = {\n  __typename?: 'ThreadResponseBreakdownDetail';\n  description?: Maybe<Scalars['String']>;\n  error?: Maybe<Error>;\n  queryId?: Maybe<Scalars['String']>;\n  status: AskingTaskStatus;\n  steps?: Maybe<Array<DetailStep>>;\n};\n\nexport type ThreadResponseChartDetail = {\n  __typename?: 'ThreadResponseChartDetail';\n  adjustment?: Maybe<Scalars['Boolean']>;\n  chartSchema?: Maybe<Scalars['JSON']>;\n  chartType?: Maybe<ChartType>;\n  description?: Maybe<Scalars['String']>;\n  error?: Maybe<Error>;\n  queryId?: Maybe<Scalars['String']>;\n  status: ChartTaskStatus;\n};\n\nexport type ThreadResponseUniqueWhereInput = {\n  id: Scalars['Int'];\n};\n\nexport type ThreadUniqueWhereInput = {\n  id: Scalars['Int'];\n};\n\nexport type TimeGrainInput = {\n  dateParts: Array<Scalars['String']>;\n  name: Scalars['String'];\n  refColumn: Scalars['String'];\n};\n\nexport type UpdateCalculatedFieldInput = {\n  expression: ExpressionName;\n  lineage: Array<Scalars['Int']>;\n  name: Scalars['String'];\n};\n\nexport type UpdateCalculatedFieldMetadataInput = {\n  description?: InputMaybe<Scalars['String']>;\n  id: Scalars['Int'];\n};\n\nexport type UpdateCalculatedFieldWhere = {\n  id: Scalars['Int'];\n};\n\nexport type UpdateColumnMetadataInput = {\n  description?: InputMaybe<Scalars['String']>;\n  displayName?: InputMaybe<Scalars['String']>;\n  id: Scalars['Int'];\n};\n\nexport type UpdateCurrentProjectInput = {\n  language: ProjectLanguage;\n};\n\nexport type UpdateDashboardItemInput = {\n  displayName: Scalars['String'];\n};\n\nexport type UpdateDashboardItemLayoutsInput = {\n  layouts: Array<ItemLayoutInput>;\n};\n\nexport type UpdateDataSourceInput = {\n  properties: Scalars['JSON'];\n};\n\nexport type UpdateInstructionInput = {\n  instruction?: InputMaybe<Scalars['String']>;\n  isDefault?: InputMaybe<Scalars['Boolean']>;\n  questions?: InputMaybe<Array<Scalars['String']>>;\n};\n\nexport type UpdateModelInput = {\n  fields: Array<Scalars['String']>;\n  primaryKey?: InputMaybe<Scalars['String']>;\n};\n\nexport type UpdateModelMetadataInput = {\n  calculatedFields?: InputMaybe<Array<UpdateCalculatedFieldMetadataInput>>;\n  columns?: InputMaybe<Array<UpdateColumnMetadataInput>>;\n  description?: InputMaybe<Scalars['String']>;\n  displayName?: InputMaybe<Scalars['String']>;\n  nestedColumns?: InputMaybe<Array<UpdateNestedColumnMetadataInput>>;\n  relationships?: InputMaybe<Array<UpdateRelationshipMetadataInput>>;\n};\n\nexport type UpdateNestedColumnMetadataInput = {\n  description?: InputMaybe<Scalars['String']>;\n  displayName?: InputMaybe<Scalars['String']>;\n  id: Scalars['Int'];\n};\n\nexport type UpdateRelationInput = {\n  type: RelationType;\n};\n\nexport type UpdateRelationshipMetadataInput = {\n  description?: InputMaybe<Scalars['String']>;\n  id: Scalars['Int'];\n};\n\nexport type UpdateSqlPairInput = {\n  question?: InputMaybe<Scalars['String']>;\n  sql?: InputMaybe<Scalars['String']>;\n};\n\nexport type UpdateThreadInput = {\n  summary?: InputMaybe<Scalars['String']>;\n};\n\nexport type UpdateThreadResponseInput = {\n  sql?: InputMaybe<Scalars['String']>;\n};\n\nexport type UpdateViewColumnMetadataInput = {\n  description?: InputMaybe<Scalars['String']>;\n  referenceName: Scalars['String'];\n};\n\nexport type UpdateViewMetadataInput = {\n  columns?: InputMaybe<Array<UpdateViewColumnMetadataInput>>;\n  description?: InputMaybe<Scalars['String']>;\n  displayName?: InputMaybe<Scalars['String']>;\n};\n\nexport type ValidateCalculatedFieldInput = {\n  columnId?: InputMaybe<Scalars['Int']>;\n  modelId: Scalars['Int'];\n  name: Scalars['String'];\n};\n\nexport type ValidateViewInput = {\n  name: Scalars['String'];\n};\n\nexport type ViewInfo = {\n  __typename?: 'ViewInfo';\n  displayName: Scalars['String'];\n  id: Scalars['Int'];\n  name: Scalars['String'];\n  statement: Scalars['String'];\n};\n\nexport type ViewValidationResponse = {\n  __typename?: 'ViewValidationResponse';\n  message?: Maybe<Scalars['String']>;\n  valid: Scalars['Boolean'];\n};\n\nexport type ViewWhereUniqueInput = {\n  id: Scalars['Int'];\n};\n\nexport type WhereIdInput = {\n  id: Scalars['Int'];\n};\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/apiManagement.generated.ts",
    "content": "import * as Types from './__types__';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nconst defaultOptions = {} as const;\nexport type ApiHistoryQueryVariables = Types.Exact<{\n  filter?: Types.InputMaybe<Types.ApiHistoryFilterInput>;\n  pagination: Types.ApiHistoryPaginationInput;\n}>;\n\n\nexport type ApiHistoryQuery = { __typename?: 'Query', apiHistory: { __typename?: 'ApiHistoryPaginatedResponse', total: number, hasMore: boolean, items: Array<{ __typename?: 'ApiHistoryResponse', id: string, projectId: number, apiType: Types.ApiType, threadId?: string | null, headers?: any | null, requestPayload?: any | null, responsePayload?: any | null, statusCode?: number | null, durationMs?: number | null, createdAt: string, updatedAt: string }> } };\n\n\nexport const ApiHistoryDocument = gql`\n    query ApiHistory($filter: ApiHistoryFilterInput, $pagination: ApiHistoryPaginationInput!) {\n  apiHistory(filter: $filter, pagination: $pagination) {\n    items {\n      id\n      projectId\n      apiType\n      threadId\n      headers\n      requestPayload\n      responsePayload\n      statusCode\n      durationMs\n      createdAt\n      updatedAt\n    }\n    total\n    hasMore\n  }\n}\n    `;\n\n/**\n * __useApiHistoryQuery__\n *\n * To run a query within a React component, call `useApiHistoryQuery` and pass it any options that fit your needs.\n * When your component renders, `useApiHistoryQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useApiHistoryQuery({\n *   variables: {\n *      filter: // value for 'filter'\n *      pagination: // value for 'pagination'\n *   },\n * });\n */\nexport function useApiHistoryQuery(baseOptions: Apollo.QueryHookOptions<ApiHistoryQuery, ApiHistoryQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<ApiHistoryQuery, ApiHistoryQueryVariables>(ApiHistoryDocument, options);\n      }\nexport function useApiHistoryLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ApiHistoryQuery, ApiHistoryQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<ApiHistoryQuery, ApiHistoryQueryVariables>(ApiHistoryDocument, options);\n        }\nexport type ApiHistoryQueryHookResult = ReturnType<typeof useApiHistoryQuery>;\nexport type ApiHistoryLazyQueryHookResult = ReturnType<typeof useApiHistoryLazyQuery>;\nexport type ApiHistoryQueryResult = Apollo.QueryResult<ApiHistoryQuery, ApiHistoryQueryVariables>;"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/apiManagement.ts",
    "content": "import { gql } from '@apollo/client';\n\nexport const API_HISTORY = gql`\n  query ApiHistory(\n    $filter: ApiHistoryFilterInput\n    $pagination: ApiHistoryPaginationInput!\n  ) {\n    apiHistory(filter: $filter, pagination: $pagination) {\n      items {\n        id\n        projectId\n        apiType\n        threadId\n        headers\n        requestPayload\n        responsePayload\n        statusCode\n        durationMs\n        createdAt\n        updatedAt\n      }\n      total\n      hasMore\n    }\n  }\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/calculatedField.generated.ts",
    "content": "import * as Types from './__types__';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nconst defaultOptions = {} as const;\nexport type ValidateCalculatedFieldMutationVariables = Types.Exact<{\n  data: Types.ValidateCalculatedFieldInput;\n}>;\n\n\nexport type ValidateCalculatedFieldMutation = { __typename?: 'Mutation', validateCalculatedField: { __typename?: 'CalculatedFieldValidationResponse', message?: string | null, valid: boolean } };\n\nexport type CreateCalculatedFieldMutationVariables = Types.Exact<{\n  data: Types.CreateCalculatedFieldInput;\n}>;\n\n\nexport type CreateCalculatedFieldMutation = { __typename?: 'Mutation', createCalculatedField: any };\n\nexport type UpdateCalculatedFieldMutationVariables = Types.Exact<{\n  where: Types.UpdateCalculatedFieldWhere;\n  data: Types.UpdateCalculatedFieldInput;\n}>;\n\n\nexport type UpdateCalculatedFieldMutation = { __typename?: 'Mutation', updateCalculatedField: any };\n\nexport type DeleteCalculatedFieldMutationVariables = Types.Exact<{\n  where: Types.UpdateCalculatedFieldWhere;\n}>;\n\n\nexport type DeleteCalculatedFieldMutation = { __typename?: 'Mutation', deleteCalculatedField: boolean };\n\n\nexport const ValidateCalculatedFieldDocument = gql`\n    mutation ValidateCalculatedField($data: ValidateCalculatedFieldInput!) {\n  validateCalculatedField(data: $data) {\n    message\n    valid\n  }\n}\n    `;\nexport type ValidateCalculatedFieldMutationFn = Apollo.MutationFunction<ValidateCalculatedFieldMutation, ValidateCalculatedFieldMutationVariables>;\n\n/**\n * __useValidateCalculatedFieldMutation__\n *\n * To run a mutation, you first call `useValidateCalculatedFieldMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useValidateCalculatedFieldMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [validateCalculatedFieldMutation, { data, loading, error }] = useValidateCalculatedFieldMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useValidateCalculatedFieldMutation(baseOptions?: Apollo.MutationHookOptions<ValidateCalculatedFieldMutation, ValidateCalculatedFieldMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<ValidateCalculatedFieldMutation, ValidateCalculatedFieldMutationVariables>(ValidateCalculatedFieldDocument, options);\n      }\nexport type ValidateCalculatedFieldMutationHookResult = ReturnType<typeof useValidateCalculatedFieldMutation>;\nexport type ValidateCalculatedFieldMutationResult = Apollo.MutationResult<ValidateCalculatedFieldMutation>;\nexport type ValidateCalculatedFieldMutationOptions = Apollo.BaseMutationOptions<ValidateCalculatedFieldMutation, ValidateCalculatedFieldMutationVariables>;\nexport const CreateCalculatedFieldDocument = gql`\n    mutation CreateCalculatedField($data: CreateCalculatedFieldInput!) {\n  createCalculatedField(data: $data)\n}\n    `;\nexport type CreateCalculatedFieldMutationFn = Apollo.MutationFunction<CreateCalculatedFieldMutation, CreateCalculatedFieldMutationVariables>;\n\n/**\n * __useCreateCalculatedFieldMutation__\n *\n * To run a mutation, you first call `useCreateCalculatedFieldMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateCalculatedFieldMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createCalculatedFieldMutation, { data, loading, error }] = useCreateCalculatedFieldMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useCreateCalculatedFieldMutation(baseOptions?: Apollo.MutationHookOptions<CreateCalculatedFieldMutation, CreateCalculatedFieldMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<CreateCalculatedFieldMutation, CreateCalculatedFieldMutationVariables>(CreateCalculatedFieldDocument, options);\n      }\nexport type CreateCalculatedFieldMutationHookResult = ReturnType<typeof useCreateCalculatedFieldMutation>;\nexport type CreateCalculatedFieldMutationResult = Apollo.MutationResult<CreateCalculatedFieldMutation>;\nexport type CreateCalculatedFieldMutationOptions = Apollo.BaseMutationOptions<CreateCalculatedFieldMutation, CreateCalculatedFieldMutationVariables>;\nexport const UpdateCalculatedFieldDocument = gql`\n    mutation UpdateCalculatedField($where: UpdateCalculatedFieldWhere!, $data: UpdateCalculatedFieldInput!) {\n  updateCalculatedField(where: $where, data: $data)\n}\n    `;\nexport type UpdateCalculatedFieldMutationFn = Apollo.MutationFunction<UpdateCalculatedFieldMutation, UpdateCalculatedFieldMutationVariables>;\n\n/**\n * __useUpdateCalculatedFieldMutation__\n *\n * To run a mutation, you first call `useUpdateCalculatedFieldMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateCalculatedFieldMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateCalculatedFieldMutation, { data, loading, error }] = useUpdateCalculatedFieldMutation({\n *   variables: {\n *      where: // value for 'where'\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useUpdateCalculatedFieldMutation(baseOptions?: Apollo.MutationHookOptions<UpdateCalculatedFieldMutation, UpdateCalculatedFieldMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<UpdateCalculatedFieldMutation, UpdateCalculatedFieldMutationVariables>(UpdateCalculatedFieldDocument, options);\n      }\nexport type UpdateCalculatedFieldMutationHookResult = ReturnType<typeof useUpdateCalculatedFieldMutation>;\nexport type UpdateCalculatedFieldMutationResult = Apollo.MutationResult<UpdateCalculatedFieldMutation>;\nexport type UpdateCalculatedFieldMutationOptions = Apollo.BaseMutationOptions<UpdateCalculatedFieldMutation, UpdateCalculatedFieldMutationVariables>;\nexport const DeleteCalculatedFieldDocument = gql`\n    mutation DeleteCalculatedField($where: UpdateCalculatedFieldWhere!) {\n  deleteCalculatedField(where: $where)\n}\n    `;\nexport type DeleteCalculatedFieldMutationFn = Apollo.MutationFunction<DeleteCalculatedFieldMutation, DeleteCalculatedFieldMutationVariables>;\n\n/**\n * __useDeleteCalculatedFieldMutation__\n *\n * To run a mutation, you first call `useDeleteCalculatedFieldMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDeleteCalculatedFieldMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [deleteCalculatedFieldMutation, { data, loading, error }] = useDeleteCalculatedFieldMutation({\n *   variables: {\n *      where: // value for 'where'\n *   },\n * });\n */\nexport function useDeleteCalculatedFieldMutation(baseOptions?: Apollo.MutationHookOptions<DeleteCalculatedFieldMutation, DeleteCalculatedFieldMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<DeleteCalculatedFieldMutation, DeleteCalculatedFieldMutationVariables>(DeleteCalculatedFieldDocument, options);\n      }\nexport type DeleteCalculatedFieldMutationHookResult = ReturnType<typeof useDeleteCalculatedFieldMutation>;\nexport type DeleteCalculatedFieldMutationResult = Apollo.MutationResult<DeleteCalculatedFieldMutation>;\nexport type DeleteCalculatedFieldMutationOptions = Apollo.BaseMutationOptions<DeleteCalculatedFieldMutation, DeleteCalculatedFieldMutationVariables>;"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/calculatedField.ts",
    "content": "import { gql } from '@apollo/client';\n\nexport const VALIDATE_CALCULATED_FIELD = gql`\n  mutation ValidateCalculatedField($data: ValidateCalculatedFieldInput!) {\n    validateCalculatedField(data: $data) {\n      message\n      valid\n    }\n  }\n`;\n\nexport const CREATE_CALCULATED_FIELD = gql`\n  mutation CreateCalculatedField($data: CreateCalculatedFieldInput!) {\n    createCalculatedField(data: $data)\n  }\n`;\n\nexport const UPDATE_CALCULATED_FIELD = gql`\n  mutation UpdateCalculatedField(\n    $where: UpdateCalculatedFieldWhere!\n    $data: UpdateCalculatedFieldInput!\n  ) {\n    updateCalculatedField(where: $where, data: $data)\n  }\n`;\n\nexport const DELETE_CALCULATED_FIELD = gql`\n  mutation DeleteCalculatedField($where: UpdateCalculatedFieldWhere!) {\n    deleteCalculatedField(where: $where)\n  }\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/dashboard.generated.ts",
    "content": "import * as Types from './__types__';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nconst defaultOptions = {} as const;\nexport type CommonDashboardItemFragment = { __typename?: 'DashboardItem', id: number, dashboardId: number, type: Types.DashboardItemType, displayName?: string | null, layout: { __typename?: 'DashboardItemLayout', x: number, y: number, w: number, h: number }, detail: { __typename?: 'DashboardItemDetail', sql: string, chartSchema?: any | null } };\n\nexport type DashboardItemsQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type DashboardItemsQuery = { __typename?: 'Query', dashboardItems: Array<{ __typename?: 'DashboardItem', id: number, dashboardId: number, type: Types.DashboardItemType, displayName?: string | null, layout: { __typename?: 'DashboardItemLayout', x: number, y: number, w: number, h: number }, detail: { __typename?: 'DashboardItemDetail', sql: string, chartSchema?: any | null } }> };\n\nexport type CreateDashboardItemMutationVariables = Types.Exact<{\n  data: Types.CreateDashboardItemInput;\n}>;\n\n\nexport type CreateDashboardItemMutation = { __typename?: 'Mutation', createDashboardItem: { __typename?: 'DashboardItem', id: number, dashboardId: number, type: Types.DashboardItemType, displayName?: string | null, layout: { __typename?: 'DashboardItemLayout', x: number, y: number, w: number, h: number }, detail: { __typename?: 'DashboardItemDetail', sql: string, chartSchema?: any | null } } };\n\nexport type UpdateDashboardItemMutationVariables = Types.Exact<{\n  where: Types.DashboardItemWhereInput;\n  data: Types.UpdateDashboardItemInput;\n}>;\n\n\nexport type UpdateDashboardItemMutation = { __typename?: 'Mutation', updateDashboardItem: { __typename?: 'DashboardItem', id: number, dashboardId: number, type: Types.DashboardItemType, displayName?: string | null, layout: { __typename?: 'DashboardItemLayout', x: number, y: number, w: number, h: number }, detail: { __typename?: 'DashboardItemDetail', sql: string, chartSchema?: any | null } } };\n\nexport type UpdateDashboardItemLayoutsMutationVariables = Types.Exact<{\n  data: Types.UpdateDashboardItemLayoutsInput;\n}>;\n\n\nexport type UpdateDashboardItemLayoutsMutation = { __typename?: 'Mutation', updateDashboardItemLayouts: Array<{ __typename?: 'DashboardItem', id: number, dashboardId: number, type: Types.DashboardItemType, displayName?: string | null, layout: { __typename?: 'DashboardItemLayout', x: number, y: number, w: number, h: number }, detail: { __typename?: 'DashboardItemDetail', sql: string, chartSchema?: any | null } }> };\n\nexport type DeleteDashboardItemMutationVariables = Types.Exact<{\n  where: Types.DashboardItemWhereInput;\n}>;\n\n\nexport type DeleteDashboardItemMutation = { __typename?: 'Mutation', deleteDashboardItem: boolean };\n\nexport type PreviewItemSqlMutationVariables = Types.Exact<{\n  data: Types.PreviewItemSqlInput;\n}>;\n\n\nexport type PreviewItemSqlMutation = { __typename?: 'Mutation', previewItemSQL: { __typename?: 'PreviewItemResponse', data: any, cacheHit: boolean, cacheCreatedAt?: string | null, cacheOverrodeAt?: string | null, override: boolean } };\n\nexport type SetDashboardScheduleMutationVariables = Types.Exact<{\n  data: Types.SetDashboardScheduleInput;\n}>;\n\n\nexport type SetDashboardScheduleMutation = { __typename?: 'Mutation', setDashboardSchedule: { __typename?: 'Dashboard', id: number, projectId: number, name: string, cacheEnabled: boolean, scheduleFrequency?: Types.ScheduleFrequencyEnum | null, scheduleTimezone?: string | null, scheduleCron?: string | null, nextScheduledAt?: string | null } };\n\nexport type DashboardQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type DashboardQuery = { __typename?: 'Query', dashboard: { __typename?: 'DetailedDashboard', id: number, name: string, description?: string | null, cacheEnabled: boolean, nextScheduledAt?: string | null, schedule?: { __typename?: 'DashboardSchedule', frequency?: Types.ScheduleFrequencyEnum | null, hour?: number | null, minute?: number | null, day?: Types.CacheScheduleDayEnum | null, timezone?: string | null, cron?: string | null } | null, items: Array<{ __typename?: 'DashboardItem', id: number, dashboardId: number, type: Types.DashboardItemType, displayName?: string | null, layout: { __typename?: 'DashboardItemLayout', x: number, y: number, w: number, h: number }, detail: { __typename?: 'DashboardItemDetail', sql: string, chartSchema?: any | null } }> } };\n\nexport const CommonDashboardItemFragmentDoc = gql`\n    fragment CommonDashboardItem on DashboardItem {\n  id\n  dashboardId\n  type\n  layout {\n    x\n    y\n    w\n    h\n  }\n  detail {\n    sql\n    chartSchema\n  }\n  displayName\n}\n    `;\nexport const DashboardItemsDocument = gql`\n    query DashboardItems {\n  dashboardItems {\n    ...CommonDashboardItem\n  }\n}\n    ${CommonDashboardItemFragmentDoc}`;\n\n/**\n * __useDashboardItemsQuery__\n *\n * To run a query within a React component, call `useDashboardItemsQuery` and pass it any options that fit your needs.\n * When your component renders, `useDashboardItemsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useDashboardItemsQuery({\n *   variables: {\n *   },\n * });\n */\nexport function useDashboardItemsQuery(baseOptions?: Apollo.QueryHookOptions<DashboardItemsQuery, DashboardItemsQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<DashboardItemsQuery, DashboardItemsQueryVariables>(DashboardItemsDocument, options);\n      }\nexport function useDashboardItemsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<DashboardItemsQuery, DashboardItemsQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<DashboardItemsQuery, DashboardItemsQueryVariables>(DashboardItemsDocument, options);\n        }\nexport type DashboardItemsQueryHookResult = ReturnType<typeof useDashboardItemsQuery>;\nexport type DashboardItemsLazyQueryHookResult = ReturnType<typeof useDashboardItemsLazyQuery>;\nexport type DashboardItemsQueryResult = Apollo.QueryResult<DashboardItemsQuery, DashboardItemsQueryVariables>;\nexport const CreateDashboardItemDocument = gql`\n    mutation CreateDashboardItem($data: CreateDashboardItemInput!) {\n  createDashboardItem(data: $data) {\n    ...CommonDashboardItem\n  }\n}\n    ${CommonDashboardItemFragmentDoc}`;\nexport type CreateDashboardItemMutationFn = Apollo.MutationFunction<CreateDashboardItemMutation, CreateDashboardItemMutationVariables>;\n\n/**\n * __useCreateDashboardItemMutation__\n *\n * To run a mutation, you first call `useCreateDashboardItemMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateDashboardItemMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createDashboardItemMutation, { data, loading, error }] = useCreateDashboardItemMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useCreateDashboardItemMutation(baseOptions?: Apollo.MutationHookOptions<CreateDashboardItemMutation, CreateDashboardItemMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<CreateDashboardItemMutation, CreateDashboardItemMutationVariables>(CreateDashboardItemDocument, options);\n      }\nexport type CreateDashboardItemMutationHookResult = ReturnType<typeof useCreateDashboardItemMutation>;\nexport type CreateDashboardItemMutationResult = Apollo.MutationResult<CreateDashboardItemMutation>;\nexport type CreateDashboardItemMutationOptions = Apollo.BaseMutationOptions<CreateDashboardItemMutation, CreateDashboardItemMutationVariables>;\nexport const UpdateDashboardItemDocument = gql`\n    mutation UpdateDashboardItem($where: DashboardItemWhereInput!, $data: UpdateDashboardItemInput!) {\n  updateDashboardItem(where: $where, data: $data) {\n    ...CommonDashboardItem\n  }\n}\n    ${CommonDashboardItemFragmentDoc}`;\nexport type UpdateDashboardItemMutationFn = Apollo.MutationFunction<UpdateDashboardItemMutation, UpdateDashboardItemMutationVariables>;\n\n/**\n * __useUpdateDashboardItemMutation__\n *\n * To run a mutation, you first call `useUpdateDashboardItemMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateDashboardItemMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateDashboardItemMutation, { data, loading, error }] = useUpdateDashboardItemMutation({\n *   variables: {\n *      where: // value for 'where'\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useUpdateDashboardItemMutation(baseOptions?: Apollo.MutationHookOptions<UpdateDashboardItemMutation, UpdateDashboardItemMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<UpdateDashboardItemMutation, UpdateDashboardItemMutationVariables>(UpdateDashboardItemDocument, options);\n      }\nexport type UpdateDashboardItemMutationHookResult = ReturnType<typeof useUpdateDashboardItemMutation>;\nexport type UpdateDashboardItemMutationResult = Apollo.MutationResult<UpdateDashboardItemMutation>;\nexport type UpdateDashboardItemMutationOptions = Apollo.BaseMutationOptions<UpdateDashboardItemMutation, UpdateDashboardItemMutationVariables>;\nexport const UpdateDashboardItemLayoutsDocument = gql`\n    mutation UpdateDashboardItemLayouts($data: UpdateDashboardItemLayoutsInput!) {\n  updateDashboardItemLayouts(data: $data) {\n    ...CommonDashboardItem\n  }\n}\n    ${CommonDashboardItemFragmentDoc}`;\nexport type UpdateDashboardItemLayoutsMutationFn = Apollo.MutationFunction<UpdateDashboardItemLayoutsMutation, UpdateDashboardItemLayoutsMutationVariables>;\n\n/**\n * __useUpdateDashboardItemLayoutsMutation__\n *\n * To run a mutation, you first call `useUpdateDashboardItemLayoutsMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateDashboardItemLayoutsMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateDashboardItemLayoutsMutation, { data, loading, error }] = useUpdateDashboardItemLayoutsMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useUpdateDashboardItemLayoutsMutation(baseOptions?: Apollo.MutationHookOptions<UpdateDashboardItemLayoutsMutation, UpdateDashboardItemLayoutsMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<UpdateDashboardItemLayoutsMutation, UpdateDashboardItemLayoutsMutationVariables>(UpdateDashboardItemLayoutsDocument, options);\n      }\nexport type UpdateDashboardItemLayoutsMutationHookResult = ReturnType<typeof useUpdateDashboardItemLayoutsMutation>;\nexport type UpdateDashboardItemLayoutsMutationResult = Apollo.MutationResult<UpdateDashboardItemLayoutsMutation>;\nexport type UpdateDashboardItemLayoutsMutationOptions = Apollo.BaseMutationOptions<UpdateDashboardItemLayoutsMutation, UpdateDashboardItemLayoutsMutationVariables>;\nexport const DeleteDashboardItemDocument = gql`\n    mutation DeleteDashboardItem($where: DashboardItemWhereInput!) {\n  deleteDashboardItem(where: $where)\n}\n    `;\nexport type DeleteDashboardItemMutationFn = Apollo.MutationFunction<DeleteDashboardItemMutation, DeleteDashboardItemMutationVariables>;\n\n/**\n * __useDeleteDashboardItemMutation__\n *\n * To run a mutation, you first call `useDeleteDashboardItemMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDeleteDashboardItemMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [deleteDashboardItemMutation, { data, loading, error }] = useDeleteDashboardItemMutation({\n *   variables: {\n *      where: // value for 'where'\n *   },\n * });\n */\nexport function useDeleteDashboardItemMutation(baseOptions?: Apollo.MutationHookOptions<DeleteDashboardItemMutation, DeleteDashboardItemMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<DeleteDashboardItemMutation, DeleteDashboardItemMutationVariables>(DeleteDashboardItemDocument, options);\n      }\nexport type DeleteDashboardItemMutationHookResult = ReturnType<typeof useDeleteDashboardItemMutation>;\nexport type DeleteDashboardItemMutationResult = Apollo.MutationResult<DeleteDashboardItemMutation>;\nexport type DeleteDashboardItemMutationOptions = Apollo.BaseMutationOptions<DeleteDashboardItemMutation, DeleteDashboardItemMutationVariables>;\nexport const PreviewItemSqlDocument = gql`\n    mutation PreviewItemSQL($data: PreviewItemSQLInput!) {\n  previewItemSQL(data: $data) {\n    data\n    cacheHit\n    cacheCreatedAt\n    cacheOverrodeAt\n    override\n  }\n}\n    `;\nexport type PreviewItemSqlMutationFn = Apollo.MutationFunction<PreviewItemSqlMutation, PreviewItemSqlMutationVariables>;\n\n/**\n * __usePreviewItemSqlMutation__\n *\n * To run a mutation, you first call `usePreviewItemSqlMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `usePreviewItemSqlMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [previewItemSqlMutation, { data, loading, error }] = usePreviewItemSqlMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function usePreviewItemSqlMutation(baseOptions?: Apollo.MutationHookOptions<PreviewItemSqlMutation, PreviewItemSqlMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<PreviewItemSqlMutation, PreviewItemSqlMutationVariables>(PreviewItemSqlDocument, options);\n      }\nexport type PreviewItemSqlMutationHookResult = ReturnType<typeof usePreviewItemSqlMutation>;\nexport type PreviewItemSqlMutationResult = Apollo.MutationResult<PreviewItemSqlMutation>;\nexport type PreviewItemSqlMutationOptions = Apollo.BaseMutationOptions<PreviewItemSqlMutation, PreviewItemSqlMutationVariables>;\nexport const SetDashboardScheduleDocument = gql`\n    mutation SetDashboardSchedule($data: SetDashboardScheduleInput!) {\n  setDashboardSchedule(data: $data) {\n    id\n    projectId\n    name\n    cacheEnabled\n    scheduleFrequency\n    scheduleTimezone\n    scheduleCron\n    nextScheduledAt\n  }\n}\n    `;\nexport type SetDashboardScheduleMutationFn = Apollo.MutationFunction<SetDashboardScheduleMutation, SetDashboardScheduleMutationVariables>;\n\n/**\n * __useSetDashboardScheduleMutation__\n *\n * To run a mutation, you first call `useSetDashboardScheduleMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useSetDashboardScheduleMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [setDashboardScheduleMutation, { data, loading, error }] = useSetDashboardScheduleMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useSetDashboardScheduleMutation(baseOptions?: Apollo.MutationHookOptions<SetDashboardScheduleMutation, SetDashboardScheduleMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<SetDashboardScheduleMutation, SetDashboardScheduleMutationVariables>(SetDashboardScheduleDocument, options);\n      }\nexport type SetDashboardScheduleMutationHookResult = ReturnType<typeof useSetDashboardScheduleMutation>;\nexport type SetDashboardScheduleMutationResult = Apollo.MutationResult<SetDashboardScheduleMutation>;\nexport type SetDashboardScheduleMutationOptions = Apollo.BaseMutationOptions<SetDashboardScheduleMutation, SetDashboardScheduleMutationVariables>;\nexport const DashboardDocument = gql`\n    query Dashboard {\n  dashboard {\n    id\n    name\n    description\n    cacheEnabled\n    nextScheduledAt\n    schedule {\n      frequency\n      hour\n      minute\n      day\n      timezone\n      cron\n    }\n    items {\n      ...CommonDashboardItem\n    }\n  }\n}\n    ${CommonDashboardItemFragmentDoc}`;\n\n/**\n * __useDashboardQuery__\n *\n * To run a query within a React component, call `useDashboardQuery` and pass it any options that fit your needs.\n * When your component renders, `useDashboardQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useDashboardQuery({\n *   variables: {\n *   },\n * });\n */\nexport function useDashboardQuery(baseOptions?: Apollo.QueryHookOptions<DashboardQuery, DashboardQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<DashboardQuery, DashboardQueryVariables>(DashboardDocument, options);\n      }\nexport function useDashboardLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<DashboardQuery, DashboardQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<DashboardQuery, DashboardQueryVariables>(DashboardDocument, options);\n        }\nexport type DashboardQueryHookResult = ReturnType<typeof useDashboardQuery>;\nexport type DashboardLazyQueryHookResult = ReturnType<typeof useDashboardLazyQuery>;\nexport type DashboardQueryResult = Apollo.QueryResult<DashboardQuery, DashboardQueryVariables>;"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/dashboard.ts",
    "content": "import { gql } from '@apollo/client';\n\nexport const COMMON_DASHBOARD_ITEM = gql`\n  fragment CommonDashboardItem on DashboardItem {\n    id\n    dashboardId\n    type\n    layout {\n      x\n      y\n      w\n      h\n    }\n    detail {\n      sql\n      chartSchema\n    }\n    displayName\n  }\n`;\n\nexport const DASHBOARD_ITEMS = gql`\n  query DashboardItems {\n    dashboardItems {\n      ...CommonDashboardItem\n    }\n  }\n  ${COMMON_DASHBOARD_ITEM}\n`;\n\nexport const CREATE_DASHBOARD_ITEM = gql`\n  mutation CreateDashboardItem($data: CreateDashboardItemInput!) {\n    createDashboardItem(data: $data) {\n      ...CommonDashboardItem\n    }\n  }\n  ${COMMON_DASHBOARD_ITEM}\n`;\n\nexport const UPDATE_DASHBOARD_ITEM = gql`\n  mutation UpdateDashboardItem(\n    $where: DashboardItemWhereInput!\n    $data: UpdateDashboardItemInput!\n  ) {\n    updateDashboardItem(where: $where, data: $data) {\n      ...CommonDashboardItem\n    }\n  }\n  ${COMMON_DASHBOARD_ITEM}\n`;\n\nexport const UPDATE_DASHBOARD_ITEM_LAYOUTS = gql`\n  mutation UpdateDashboardItemLayouts($data: UpdateDashboardItemLayoutsInput!) {\n    updateDashboardItemLayouts(data: $data) {\n      ...CommonDashboardItem\n    }\n  }\n  ${COMMON_DASHBOARD_ITEM}\n`;\n\nexport const DELETE_DASHBOARD_ITEM = gql`\n  mutation DeleteDashboardItem($where: DashboardItemWhereInput!) {\n    deleteDashboardItem(where: $where)\n  }\n`;\n\nexport const PREVIEW_ITEM_SQL = gql`\n  mutation PreviewItemSQL($data: PreviewItemSQLInput!) {\n    previewItemSQL(data: $data) {\n      data\n      cacheHit\n      cacheCreatedAt\n      cacheOverrodeAt\n      override\n    }\n  }\n`;\n\nexport const SET_DASHBOARD_SCHEDULE = gql`\n  mutation SetDashboardSchedule($data: SetDashboardScheduleInput!) {\n    setDashboardSchedule(data: $data) {\n      id\n      projectId\n      name\n      cacheEnabled\n      scheduleFrequency\n      scheduleTimezone\n      scheduleCron\n      nextScheduledAt\n    }\n  }\n`;\n\nexport const DASHBOARD = gql`\n  query Dashboard {\n    dashboard {\n      id\n      name\n      description\n      cacheEnabled\n      nextScheduledAt\n      schedule {\n        frequency\n        hour\n        minute\n        day\n        timezone\n        cron\n      }\n      items {\n        ...CommonDashboardItem\n      }\n    }\n  }\n  ${COMMON_DASHBOARD_ITEM}\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/dataSource.generated.ts",
    "content": "import * as Types from './__types__';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nconst defaultOptions = {} as const;\nexport type StartSampleDatasetMutationVariables = Types.Exact<{\n  data: Types.SampleDatasetInput;\n}>;\n\n\nexport type StartSampleDatasetMutation = { __typename?: 'Mutation', startSampleDataset: any };\n\nexport type ListDataSourceTablesQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type ListDataSourceTablesQuery = { __typename?: 'Query', listDataSourceTables: Array<{ __typename?: 'CompactTable', name: string, columns: Array<{ __typename?: 'CompactColumn', name: string, type: string }> }> };\n\nexport type AutoGeneratedRelationsQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type AutoGeneratedRelationsQuery = { __typename?: 'Query', autoGenerateRelation: Array<{ __typename?: 'RecommendRelations', id: number, displayName: string, referenceName: string, relations: Array<{ __typename?: 'Relation', fromModelId: number, fromModelReferenceName: string, fromColumnId: number, fromColumnReferenceName: string, toModelId: number, toModelReferenceName: string, toColumnId: number, toColumnReferenceName: string, type: Types.RelationType, name: string } | null> }> };\n\nexport type SaveDataSourceMutationVariables = Types.Exact<{\n  data: Types.DataSourceInput;\n}>;\n\n\nexport type SaveDataSourceMutation = { __typename?: 'Mutation', saveDataSource: { __typename?: 'DataSource', type: Types.DataSourceName, properties: any } };\n\nexport type UpdateDataSourceMutationVariables = Types.Exact<{\n  data: Types.UpdateDataSourceInput;\n}>;\n\n\nexport type UpdateDataSourceMutation = { __typename?: 'Mutation', updateDataSource: { __typename?: 'DataSource', type: Types.DataSourceName, properties: any } };\n\nexport type SaveTablesMutationVariables = Types.Exact<{\n  data: Types.SaveTablesInput;\n}>;\n\n\nexport type SaveTablesMutation = { __typename?: 'Mutation', saveTables: any };\n\nexport type SaveRelationsMutationVariables = Types.Exact<{\n  data: Types.SaveRelationInput;\n}>;\n\n\nexport type SaveRelationsMutation = { __typename?: 'Mutation', saveRelations: any };\n\nexport type SchemaChangeQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type SchemaChangeQuery = { __typename?: 'Query', schemaChange: { __typename?: 'SchemaChange', lastSchemaChangeTime?: string | null, deletedTables?: Array<{ __typename?: 'DetailedChangeTable', sourceTableName: string, displayName: string, columns: Array<{ __typename?: 'DetailedChangeColumn', sourceColumnName: string, displayName: string, type: string }>, relationships: Array<{ __typename?: 'DetailedAffectedRelationships', displayName: string, referenceName: string }>, calculatedFields: Array<{ __typename?: 'DetailedAffectedCalculatedFields', displayName: string, referenceName: string, type: string }> }> | null, deletedColumns?: Array<{ __typename?: 'DetailedChangeTable', sourceTableName: string, displayName: string, columns: Array<{ __typename?: 'DetailedChangeColumn', sourceColumnName: string, displayName: string, type: string }>, relationships: Array<{ __typename?: 'DetailedAffectedRelationships', displayName: string, referenceName: string }>, calculatedFields: Array<{ __typename?: 'DetailedAffectedCalculatedFields', displayName: string, referenceName: string, type: string }> }> | null, modifiedColumns?: Array<{ __typename?: 'DetailedChangeTable', sourceTableName: string, displayName: string, columns: Array<{ __typename?: 'DetailedChangeColumn', sourceColumnName: string, displayName: string, type: string }>, relationships: Array<{ __typename?: 'DetailedAffectedRelationships', displayName: string, referenceName: string }>, calculatedFields: Array<{ __typename?: 'DetailedAffectedCalculatedFields', displayName: string, referenceName: string, type: string }> }> | null } };\n\nexport type TriggerDataSourceDetectionMutationVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type TriggerDataSourceDetectionMutation = { __typename?: 'Mutation', triggerDataSourceDetection: boolean };\n\nexport type ResolveSchemaChangeMutationVariables = Types.Exact<{\n  where: Types.ResolveSchemaChangeWhereInput;\n}>;\n\n\nexport type ResolveSchemaChangeMutation = { __typename?: 'Mutation', resolveSchemaChange: boolean };\n\n\nexport const StartSampleDatasetDocument = gql`\n    mutation StartSampleDataset($data: SampleDatasetInput!) {\n  startSampleDataset(data: $data)\n}\n    `;\nexport type StartSampleDatasetMutationFn = Apollo.MutationFunction<StartSampleDatasetMutation, StartSampleDatasetMutationVariables>;\n\n/**\n * __useStartSampleDatasetMutation__\n *\n * To run a mutation, you first call `useStartSampleDatasetMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useStartSampleDatasetMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [startSampleDatasetMutation, { data, loading, error }] = useStartSampleDatasetMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useStartSampleDatasetMutation(baseOptions?: Apollo.MutationHookOptions<StartSampleDatasetMutation, StartSampleDatasetMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<StartSampleDatasetMutation, StartSampleDatasetMutationVariables>(StartSampleDatasetDocument, options);\n      }\nexport type StartSampleDatasetMutationHookResult = ReturnType<typeof useStartSampleDatasetMutation>;\nexport type StartSampleDatasetMutationResult = Apollo.MutationResult<StartSampleDatasetMutation>;\nexport type StartSampleDatasetMutationOptions = Apollo.BaseMutationOptions<StartSampleDatasetMutation, StartSampleDatasetMutationVariables>;\nexport const ListDataSourceTablesDocument = gql`\n    query ListDataSourceTables {\n  listDataSourceTables {\n    name\n    columns {\n      name\n      type\n    }\n  }\n}\n    `;\n\n/**\n * __useListDataSourceTablesQuery__\n *\n * To run a query within a React component, call `useListDataSourceTablesQuery` and pass it any options that fit your needs.\n * When your component renders, `useListDataSourceTablesQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useListDataSourceTablesQuery({\n *   variables: {\n *   },\n * });\n */\nexport function useListDataSourceTablesQuery(baseOptions?: Apollo.QueryHookOptions<ListDataSourceTablesQuery, ListDataSourceTablesQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<ListDataSourceTablesQuery, ListDataSourceTablesQueryVariables>(ListDataSourceTablesDocument, options);\n      }\nexport function useListDataSourceTablesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ListDataSourceTablesQuery, ListDataSourceTablesQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<ListDataSourceTablesQuery, ListDataSourceTablesQueryVariables>(ListDataSourceTablesDocument, options);\n        }\nexport type ListDataSourceTablesQueryHookResult = ReturnType<typeof useListDataSourceTablesQuery>;\nexport type ListDataSourceTablesLazyQueryHookResult = ReturnType<typeof useListDataSourceTablesLazyQuery>;\nexport type ListDataSourceTablesQueryResult = Apollo.QueryResult<ListDataSourceTablesQuery, ListDataSourceTablesQueryVariables>;\nexport const AutoGeneratedRelationsDocument = gql`\n    query AutoGeneratedRelations {\n  autoGenerateRelation {\n    id\n    displayName\n    referenceName\n    relations {\n      fromModelId\n      fromModelReferenceName\n      fromColumnId\n      fromColumnReferenceName\n      toModelId\n      toModelReferenceName\n      toColumnId\n      toColumnReferenceName\n      type\n      name\n    }\n  }\n}\n    `;\n\n/**\n * __useAutoGeneratedRelationsQuery__\n *\n * To run a query within a React component, call `useAutoGeneratedRelationsQuery` and pass it any options that fit your needs.\n * When your component renders, `useAutoGeneratedRelationsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useAutoGeneratedRelationsQuery({\n *   variables: {\n *   },\n * });\n */\nexport function useAutoGeneratedRelationsQuery(baseOptions?: Apollo.QueryHookOptions<AutoGeneratedRelationsQuery, AutoGeneratedRelationsQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<AutoGeneratedRelationsQuery, AutoGeneratedRelationsQueryVariables>(AutoGeneratedRelationsDocument, options);\n      }\nexport function useAutoGeneratedRelationsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<AutoGeneratedRelationsQuery, AutoGeneratedRelationsQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<AutoGeneratedRelationsQuery, AutoGeneratedRelationsQueryVariables>(AutoGeneratedRelationsDocument, options);\n        }\nexport type AutoGeneratedRelationsQueryHookResult = ReturnType<typeof useAutoGeneratedRelationsQuery>;\nexport type AutoGeneratedRelationsLazyQueryHookResult = ReturnType<typeof useAutoGeneratedRelationsLazyQuery>;\nexport type AutoGeneratedRelationsQueryResult = Apollo.QueryResult<AutoGeneratedRelationsQuery, AutoGeneratedRelationsQueryVariables>;\nexport const SaveDataSourceDocument = gql`\n    mutation SaveDataSource($data: DataSourceInput!) {\n  saveDataSource(data: $data) {\n    type\n    properties\n  }\n}\n    `;\nexport type SaveDataSourceMutationFn = Apollo.MutationFunction<SaveDataSourceMutation, SaveDataSourceMutationVariables>;\n\n/**\n * __useSaveDataSourceMutation__\n *\n * To run a mutation, you first call `useSaveDataSourceMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useSaveDataSourceMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [saveDataSourceMutation, { data, loading, error }] = useSaveDataSourceMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useSaveDataSourceMutation(baseOptions?: Apollo.MutationHookOptions<SaveDataSourceMutation, SaveDataSourceMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<SaveDataSourceMutation, SaveDataSourceMutationVariables>(SaveDataSourceDocument, options);\n      }\nexport type SaveDataSourceMutationHookResult = ReturnType<typeof useSaveDataSourceMutation>;\nexport type SaveDataSourceMutationResult = Apollo.MutationResult<SaveDataSourceMutation>;\nexport type SaveDataSourceMutationOptions = Apollo.BaseMutationOptions<SaveDataSourceMutation, SaveDataSourceMutationVariables>;\nexport const UpdateDataSourceDocument = gql`\n    mutation UpdateDataSource($data: UpdateDataSourceInput!) {\n  updateDataSource(data: $data) {\n    type\n    properties\n  }\n}\n    `;\nexport type UpdateDataSourceMutationFn = Apollo.MutationFunction<UpdateDataSourceMutation, UpdateDataSourceMutationVariables>;\n\n/**\n * __useUpdateDataSourceMutation__\n *\n * To run a mutation, you first call `useUpdateDataSourceMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateDataSourceMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateDataSourceMutation, { data, loading, error }] = useUpdateDataSourceMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useUpdateDataSourceMutation(baseOptions?: Apollo.MutationHookOptions<UpdateDataSourceMutation, UpdateDataSourceMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<UpdateDataSourceMutation, UpdateDataSourceMutationVariables>(UpdateDataSourceDocument, options);\n      }\nexport type UpdateDataSourceMutationHookResult = ReturnType<typeof useUpdateDataSourceMutation>;\nexport type UpdateDataSourceMutationResult = Apollo.MutationResult<UpdateDataSourceMutation>;\nexport type UpdateDataSourceMutationOptions = Apollo.BaseMutationOptions<UpdateDataSourceMutation, UpdateDataSourceMutationVariables>;\nexport const SaveTablesDocument = gql`\n    mutation SaveTables($data: SaveTablesInput!) {\n  saveTables(data: $data)\n}\n    `;\nexport type SaveTablesMutationFn = Apollo.MutationFunction<SaveTablesMutation, SaveTablesMutationVariables>;\n\n/**\n * __useSaveTablesMutation__\n *\n * To run a mutation, you first call `useSaveTablesMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useSaveTablesMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [saveTablesMutation, { data, loading, error }] = useSaveTablesMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useSaveTablesMutation(baseOptions?: Apollo.MutationHookOptions<SaveTablesMutation, SaveTablesMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<SaveTablesMutation, SaveTablesMutationVariables>(SaveTablesDocument, options);\n      }\nexport type SaveTablesMutationHookResult = ReturnType<typeof useSaveTablesMutation>;\nexport type SaveTablesMutationResult = Apollo.MutationResult<SaveTablesMutation>;\nexport type SaveTablesMutationOptions = Apollo.BaseMutationOptions<SaveTablesMutation, SaveTablesMutationVariables>;\nexport const SaveRelationsDocument = gql`\n    mutation SaveRelations($data: SaveRelationInput!) {\n  saveRelations(data: $data)\n}\n    `;\nexport type SaveRelationsMutationFn = Apollo.MutationFunction<SaveRelationsMutation, SaveRelationsMutationVariables>;\n\n/**\n * __useSaveRelationsMutation__\n *\n * To run a mutation, you first call `useSaveRelationsMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useSaveRelationsMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [saveRelationsMutation, { data, loading, error }] = useSaveRelationsMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useSaveRelationsMutation(baseOptions?: Apollo.MutationHookOptions<SaveRelationsMutation, SaveRelationsMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<SaveRelationsMutation, SaveRelationsMutationVariables>(SaveRelationsDocument, options);\n      }\nexport type SaveRelationsMutationHookResult = ReturnType<typeof useSaveRelationsMutation>;\nexport type SaveRelationsMutationResult = Apollo.MutationResult<SaveRelationsMutation>;\nexport type SaveRelationsMutationOptions = Apollo.BaseMutationOptions<SaveRelationsMutation, SaveRelationsMutationVariables>;\nexport const SchemaChangeDocument = gql`\n    query SchemaChange {\n  schemaChange {\n    deletedTables {\n      sourceTableName\n      displayName\n      columns {\n        sourceColumnName\n        displayName\n        type\n      }\n      relationships {\n        displayName\n        referenceName\n      }\n      calculatedFields {\n        displayName\n        referenceName\n        type\n      }\n    }\n    deletedColumns {\n      sourceTableName\n      displayName\n      columns {\n        sourceColumnName\n        displayName\n        type\n      }\n      relationships {\n        displayName\n        referenceName\n      }\n      calculatedFields {\n        displayName\n        referenceName\n        type\n      }\n    }\n    modifiedColumns {\n      sourceTableName\n      displayName\n      columns {\n        sourceColumnName\n        displayName\n        type\n      }\n      relationships {\n        displayName\n        referenceName\n      }\n      calculatedFields {\n        displayName\n        referenceName\n        type\n      }\n    }\n    lastSchemaChangeTime\n  }\n}\n    `;\n\n/**\n * __useSchemaChangeQuery__\n *\n * To run a query within a React component, call `useSchemaChangeQuery` and pass it any options that fit your needs.\n * When your component renders, `useSchemaChangeQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useSchemaChangeQuery({\n *   variables: {\n *   },\n * });\n */\nexport function useSchemaChangeQuery(baseOptions?: Apollo.QueryHookOptions<SchemaChangeQuery, SchemaChangeQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<SchemaChangeQuery, SchemaChangeQueryVariables>(SchemaChangeDocument, options);\n      }\nexport function useSchemaChangeLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<SchemaChangeQuery, SchemaChangeQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<SchemaChangeQuery, SchemaChangeQueryVariables>(SchemaChangeDocument, options);\n        }\nexport type SchemaChangeQueryHookResult = ReturnType<typeof useSchemaChangeQuery>;\nexport type SchemaChangeLazyQueryHookResult = ReturnType<typeof useSchemaChangeLazyQuery>;\nexport type SchemaChangeQueryResult = Apollo.QueryResult<SchemaChangeQuery, SchemaChangeQueryVariables>;\nexport const TriggerDataSourceDetectionDocument = gql`\n    mutation TriggerDataSourceDetection {\n  triggerDataSourceDetection\n}\n    `;\nexport type TriggerDataSourceDetectionMutationFn = Apollo.MutationFunction<TriggerDataSourceDetectionMutation, TriggerDataSourceDetectionMutationVariables>;\n\n/**\n * __useTriggerDataSourceDetectionMutation__\n *\n * To run a mutation, you first call `useTriggerDataSourceDetectionMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useTriggerDataSourceDetectionMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [triggerDataSourceDetectionMutation, { data, loading, error }] = useTriggerDataSourceDetectionMutation({\n *   variables: {\n *   },\n * });\n */\nexport function useTriggerDataSourceDetectionMutation(baseOptions?: Apollo.MutationHookOptions<TriggerDataSourceDetectionMutation, TriggerDataSourceDetectionMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<TriggerDataSourceDetectionMutation, TriggerDataSourceDetectionMutationVariables>(TriggerDataSourceDetectionDocument, options);\n      }\nexport type TriggerDataSourceDetectionMutationHookResult = ReturnType<typeof useTriggerDataSourceDetectionMutation>;\nexport type TriggerDataSourceDetectionMutationResult = Apollo.MutationResult<TriggerDataSourceDetectionMutation>;\nexport type TriggerDataSourceDetectionMutationOptions = Apollo.BaseMutationOptions<TriggerDataSourceDetectionMutation, TriggerDataSourceDetectionMutationVariables>;\nexport const ResolveSchemaChangeDocument = gql`\n    mutation ResolveSchemaChange($where: ResolveSchemaChangeWhereInput!) {\n  resolveSchemaChange(where: $where)\n}\n    `;\nexport type ResolveSchemaChangeMutationFn = Apollo.MutationFunction<ResolveSchemaChangeMutation, ResolveSchemaChangeMutationVariables>;\n\n/**\n * __useResolveSchemaChangeMutation__\n *\n * To run a mutation, you first call `useResolveSchemaChangeMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useResolveSchemaChangeMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [resolveSchemaChangeMutation, { data, loading, error }] = useResolveSchemaChangeMutation({\n *   variables: {\n *      where: // value for 'where'\n *   },\n * });\n */\nexport function useResolveSchemaChangeMutation(baseOptions?: Apollo.MutationHookOptions<ResolveSchemaChangeMutation, ResolveSchemaChangeMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<ResolveSchemaChangeMutation, ResolveSchemaChangeMutationVariables>(ResolveSchemaChangeDocument, options);\n      }\nexport type ResolveSchemaChangeMutationHookResult = ReturnType<typeof useResolveSchemaChangeMutation>;\nexport type ResolveSchemaChangeMutationResult = Apollo.MutationResult<ResolveSchemaChangeMutation>;\nexport type ResolveSchemaChangeMutationOptions = Apollo.BaseMutationOptions<ResolveSchemaChangeMutation, ResolveSchemaChangeMutationVariables>;"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/dataSource.ts",
    "content": "import { gql } from '@apollo/client';\n\nexport const SET_SAMPLE_DATASETS = gql`\n  mutation StartSampleDataset($data: SampleDatasetInput!) {\n    startSampleDataset(data: $data)\n  }\n`;\n\nexport const LIST_DATA_SOURCE_TABLES = gql`\n  query ListDataSourceTables {\n    listDataSourceTables {\n      name\n      columns {\n        name\n        type\n      }\n    }\n  }\n`;\n\nexport const AUTO_GENERATED_RELATIONS = gql`\n  query AutoGeneratedRelations {\n    autoGenerateRelation {\n      id\n      displayName\n      referenceName\n      relations {\n        fromModelId\n        fromModelReferenceName\n        fromColumnId\n        fromColumnReferenceName\n        toModelId\n        toModelReferenceName\n        toColumnId\n        toColumnReferenceName\n        type\n        name\n      }\n    }\n  }\n`;\n\nexport const SAVE_DATA_SOURCE = gql`\n  mutation SaveDataSource($data: DataSourceInput!) {\n    saveDataSource(data: $data) {\n      type\n      properties\n    }\n  }\n`;\n\nexport const UPDATE_DATA_SOURCE = gql`\n  mutation UpdateDataSource($data: UpdateDataSourceInput!) {\n    updateDataSource(data: $data) {\n      type\n      properties\n    }\n  }\n`;\n\nexport const SAVE_TABLES = gql`\n  mutation SaveTables($data: SaveTablesInput!) {\n    saveTables(data: $data)\n  }\n`;\n\nexport const SAVE_RELATIONS = gql`\n  mutation SaveRelations($data: SaveRelationInput!) {\n    saveRelations(data: $data)\n  }\n`;\n\nexport const GET_SCHEMA_CHANGE = gql`\n  query SchemaChange {\n    schemaChange {\n      deletedTables {\n        sourceTableName\n        displayName\n        columns {\n          sourceColumnName\n          displayName\n          type\n        }\n        relationships {\n          displayName\n          referenceName\n        }\n        calculatedFields {\n          displayName\n          referenceName\n          type\n        }\n      }\n      deletedColumns {\n        sourceTableName\n        displayName\n        columns {\n          sourceColumnName\n          displayName\n          type\n        }\n        relationships {\n          displayName\n          referenceName\n        }\n        calculatedFields {\n          displayName\n          referenceName\n          type\n        }\n      }\n      modifiedColumns {\n        sourceTableName\n        displayName\n        columns {\n          sourceColumnName\n          displayName\n          type\n        }\n        relationships {\n          displayName\n          referenceName\n        }\n        calculatedFields {\n          displayName\n          referenceName\n          type\n        }\n      }\n      lastSchemaChangeTime\n    }\n  }\n`;\n\nexport const TRIGGER_DATA_SOURCE_DETECTION = gql`\n  mutation TriggerDataSourceDetection {\n    triggerDataSourceDetection\n  }\n`;\n\nexport const RESOLVE_SCHEMA_CHANGE = gql`\n  mutation ResolveSchemaChange($where: ResolveSchemaChangeWhereInput!) {\n    resolveSchemaChange(where: $where)\n  }\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/deploy.generated.ts",
    "content": "import * as Types from './__types__';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nconst defaultOptions = {} as const;\nexport type DeployMutationVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type DeployMutation = { __typename?: 'Mutation', deploy: any };\n\nexport type DeployStatusQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type DeployStatusQuery = { __typename?: 'Query', modelSync: { __typename?: 'ModelSyncResponse', status: Types.SyncStatus } };\n\n\nexport const DeployDocument = gql`\n    mutation Deploy {\n  deploy\n}\n    `;\nexport type DeployMutationFn = Apollo.MutationFunction<DeployMutation, DeployMutationVariables>;\n\n/**\n * __useDeployMutation__\n *\n * To run a mutation, you first call `useDeployMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDeployMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [deployMutation, { data, loading, error }] = useDeployMutation({\n *   variables: {\n *   },\n * });\n */\nexport function useDeployMutation(baseOptions?: Apollo.MutationHookOptions<DeployMutation, DeployMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<DeployMutation, DeployMutationVariables>(DeployDocument, options);\n      }\nexport type DeployMutationHookResult = ReturnType<typeof useDeployMutation>;\nexport type DeployMutationResult = Apollo.MutationResult<DeployMutation>;\nexport type DeployMutationOptions = Apollo.BaseMutationOptions<DeployMutation, DeployMutationVariables>;\nexport const DeployStatusDocument = gql`\n    query DeployStatus {\n  modelSync {\n    status\n  }\n}\n    `;\n\n/**\n * __useDeployStatusQuery__\n *\n * To run a query within a React component, call `useDeployStatusQuery` and pass it any options that fit your needs.\n * When your component renders, `useDeployStatusQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useDeployStatusQuery({\n *   variables: {\n *   },\n * });\n */\nexport function useDeployStatusQuery(baseOptions?: Apollo.QueryHookOptions<DeployStatusQuery, DeployStatusQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<DeployStatusQuery, DeployStatusQueryVariables>(DeployStatusDocument, options);\n      }\nexport function useDeployStatusLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<DeployStatusQuery, DeployStatusQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<DeployStatusQuery, DeployStatusQueryVariables>(DeployStatusDocument, options);\n        }\nexport type DeployStatusQueryHookResult = ReturnType<typeof useDeployStatusQuery>;\nexport type DeployStatusLazyQueryHookResult = ReturnType<typeof useDeployStatusLazyQuery>;\nexport type DeployStatusQueryResult = Apollo.QueryResult<DeployStatusQuery, DeployStatusQueryVariables>;"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/deploy.ts",
    "content": "import { gql } from '@apollo/client';\n\nexport const DEPLOY = gql`\n  mutation Deploy {\n    deploy\n  }\n`;\n\nexport const GET_DEPLOY_STATUS = gql`\n  query DeployStatus {\n    modelSync {\n      status\n    }\n  }\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/diagram.generated.ts",
    "content": "import * as Types from './__types__';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nconst defaultOptions = {} as const;\nexport type ViewFieldFragment = { __typename?: 'DiagramViewField', id: string, displayName: string, referenceName: string, type: string, nodeType: Types.NodeType, description?: string | null };\n\nexport type RelationFieldFragment = { __typename?: 'DiagramModelRelationField', id: string, relationId: number, type: Types.RelationType, nodeType: Types.NodeType, displayName: string, referenceName: string, fromModelId: number, fromModelName: string, fromModelDisplayName: string, fromColumnId: number, fromColumnName: string, fromColumnDisplayName: string, toModelId: number, toModelName: string, toModelDisplayName: string, toColumnId: number, toColumnName: string, toColumnDisplayName: string, description?: string | null };\n\nexport type NestedFieldFragment = { __typename?: 'DiagramModelNestedField', id: string, nestedColumnId: number, columnPath: Array<string>, type: string, displayName: string, referenceName: string, description?: string | null };\n\nexport type FieldFragment = { __typename?: 'DiagramModelField', id: string, columnId: number, type: string, nodeType: Types.NodeType, displayName: string, referenceName: string, description?: string | null, isPrimaryKey: boolean, expression?: string | null, aggregation?: string | null, lineage?: Array<number> | null, nestedFields?: Array<{ __typename?: 'DiagramModelNestedField', id: string, nestedColumnId: number, columnPath: Array<string>, type: string, displayName: string, referenceName: string, description?: string | null }> | null };\n\nexport type DiagramQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type DiagramQuery = { __typename?: 'Query', diagram: { __typename?: 'Diagram', models: Array<{ __typename?: 'DiagramModel', id: string, modelId: number, nodeType: Types.NodeType, displayName: string, referenceName: string, sourceTableName: string, refSql?: string | null, cached: boolean, refreshTime?: string | null, description?: string | null, fields: Array<{ __typename?: 'DiagramModelField', id: string, columnId: number, type: string, nodeType: Types.NodeType, displayName: string, referenceName: string, description?: string | null, isPrimaryKey: boolean, expression?: string | null, aggregation?: string | null, lineage?: Array<number> | null, nestedFields?: Array<{ __typename?: 'DiagramModelNestedField', id: string, nestedColumnId: number, columnPath: Array<string>, type: string, displayName: string, referenceName: string, description?: string | null }> | null } | null>, calculatedFields: Array<{ __typename?: 'DiagramModelField', id: string, columnId: number, type: string, nodeType: Types.NodeType, displayName: string, referenceName: string, description?: string | null, isPrimaryKey: boolean, expression?: string | null, aggregation?: string | null, lineage?: Array<number> | null, nestedFields?: Array<{ __typename?: 'DiagramModelNestedField', id: string, nestedColumnId: number, columnPath: Array<string>, type: string, displayName: string, referenceName: string, description?: string | null }> | null } | null>, relationFields: Array<{ __typename?: 'DiagramModelRelationField', id: string, relationId: number, type: Types.RelationType, nodeType: Types.NodeType, displayName: string, referenceName: string, fromModelId: number, fromModelName: string, fromModelDisplayName: string, fromColumnId: number, fromColumnName: string, fromColumnDisplayName: string, toModelId: number, toModelName: string, toModelDisplayName: string, toColumnId: number, toColumnName: string, toColumnDisplayName: string, description?: string | null } | null> } | null>, views: Array<{ __typename?: 'DiagramView', id: string, viewId: number, nodeType: Types.NodeType, displayName: string, description?: string | null, referenceName: string, statement: string, fields: Array<{ __typename?: 'DiagramViewField', id: string, displayName: string, referenceName: string, type: string, nodeType: Types.NodeType, description?: string | null } | null> } | null> } };\n\nexport const ViewFieldFragmentDoc = gql`\n    fragment ViewField on DiagramViewField {\n  id\n  displayName\n  referenceName\n  type\n  nodeType\n  description\n}\n    `;\nexport const RelationFieldFragmentDoc = gql`\n    fragment RelationField on DiagramModelRelationField {\n  id\n  relationId\n  type\n  nodeType\n  displayName\n  referenceName\n  fromModelId\n  fromModelName\n  fromModelDisplayName\n  fromColumnId\n  fromColumnName\n  fromColumnDisplayName\n  toModelId\n  toModelName\n  toModelDisplayName\n  toColumnId\n  toColumnName\n  toColumnDisplayName\n  description\n}\n    `;\nexport const NestedFieldFragmentDoc = gql`\n    fragment NestedField on DiagramModelNestedField {\n  id\n  nestedColumnId\n  columnPath\n  type\n  displayName\n  referenceName\n  description\n}\n    `;\nexport const FieldFragmentDoc = gql`\n    fragment Field on DiagramModelField {\n  id\n  columnId\n  type\n  nodeType\n  displayName\n  referenceName\n  description\n  isPrimaryKey\n  expression\n  aggregation\n  lineage\n  nestedFields {\n    ...NestedField\n  }\n}\n    ${NestedFieldFragmentDoc}`;\nexport const DiagramDocument = gql`\n    query Diagram {\n  diagram {\n    models {\n      id\n      modelId\n      nodeType\n      displayName\n      referenceName\n      sourceTableName\n      refSql\n      cached\n      refreshTime\n      description\n      fields {\n        ...Field\n      }\n      calculatedFields {\n        ...Field\n      }\n      relationFields {\n        ...RelationField\n      }\n    }\n    views {\n      id\n      viewId\n      nodeType\n      displayName\n      description\n      referenceName\n      statement\n      fields {\n        ...ViewField\n      }\n    }\n  }\n}\n    ${FieldFragmentDoc}\n${RelationFieldFragmentDoc}\n${ViewFieldFragmentDoc}`;\n\n/**\n * __useDiagramQuery__\n *\n * To run a query within a React component, call `useDiagramQuery` and pass it any options that fit your needs.\n * When your component renders, `useDiagramQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useDiagramQuery({\n *   variables: {\n *   },\n * });\n */\nexport function useDiagramQuery(baseOptions?: Apollo.QueryHookOptions<DiagramQuery, DiagramQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<DiagramQuery, DiagramQueryVariables>(DiagramDocument, options);\n      }\nexport function useDiagramLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<DiagramQuery, DiagramQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<DiagramQuery, DiagramQueryVariables>(DiagramDocument, options);\n        }\nexport type DiagramQueryHookResult = ReturnType<typeof useDiagramQuery>;\nexport type DiagramLazyQueryHookResult = ReturnType<typeof useDiagramLazyQuery>;\nexport type DiagramQueryResult = Apollo.QueryResult<DiagramQuery, DiagramQueryVariables>;"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/diagram.ts",
    "content": "import { gql } from '@apollo/client';\n\nconst VIEW_FIELD = gql`\n  fragment ViewField on DiagramViewField {\n    id\n    displayName\n    referenceName\n    type\n    nodeType\n    description\n  }\n`;\n\nconst RELATION_FIELD = gql`\n  fragment RelationField on DiagramModelRelationField {\n    id\n    relationId\n    type\n    nodeType\n    displayName\n    referenceName\n    fromModelId\n    fromModelName\n    fromModelDisplayName\n    fromColumnId\n    fromColumnName\n    fromColumnDisplayName\n    toModelId\n    toModelName\n    toModelDisplayName\n    toColumnId\n    toColumnName\n    toColumnDisplayName\n    description\n  }\n`;\n\nconst NESTED_FIELD = gql`\n  fragment NestedField on DiagramModelNestedField {\n    id\n    nestedColumnId\n    columnPath\n    type\n    displayName\n    referenceName\n    description\n  }\n`;\n\nconst FIELD = gql`\n  fragment Field on DiagramModelField {\n    id\n    columnId\n    type\n    nodeType\n    displayName\n    referenceName\n    description\n    isPrimaryKey\n    expression\n    aggregation\n    lineage\n    nestedFields {\n      ...NestedField\n    }\n  }\n  ${NESTED_FIELD}\n`;\n\nexport const DIAGRAM = gql`\n  query Diagram {\n    diagram {\n      models {\n        id\n        modelId\n        nodeType\n        displayName\n        referenceName\n        sourceTableName\n        refSql\n        cached\n        refreshTime\n        description\n        fields {\n          ...Field\n        }\n        calculatedFields {\n          ...Field\n        }\n        relationFields {\n          ...RelationField\n        }\n      }\n      views {\n        id\n        viewId\n        nodeType\n        displayName\n        description\n        referenceName\n        statement\n        fields {\n          ...ViewField\n        }\n      }\n    }\n  }\n  ${FIELD}\n  ${RELATION_FIELD}\n  ${VIEW_FIELD}\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/home.generated.ts",
    "content": "import * as Types from './__types__';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nconst defaultOptions = {} as const;\nexport type CommonErrorFragment = { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null };\n\nexport type CommonBreakdownDetailFragment = { __typename?: 'ThreadResponseBreakdownDetail', queryId?: string | null, status: Types.AskingTaskStatus, description?: string | null, steps?: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }> | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null };\n\nexport type CommonAnswerDetailFragment = { __typename?: 'ThreadResponseAnswerDetail', queryId?: string | null, status?: Types.ThreadResponseAnswerStatus | null, content?: string | null, numRowsUsedInLLM?: number | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null };\n\nexport type CommonChartDetailFragment = { __typename?: 'ThreadResponseChartDetail', queryId?: string | null, status: Types.ChartTaskStatus, description?: string | null, chartType?: Types.ChartType | null, chartSchema?: any | null, adjustment?: boolean | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null };\n\nexport type CommonAskingTaskFragment = { __typename?: 'AskingTask', status: Types.AskingTaskStatus, type?: Types.AskingTaskType | null, rephrasedQuestion?: string | null, intentReasoning?: string | null, sqlGenerationReasoning?: string | null, retrievedTables?: Array<string> | null, invalidSql?: string | null, traceId?: string | null, queryId?: string | null, candidates: Array<{ __typename?: 'ResultCandidate', sql: string, type: Types.ResultCandidateType, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, sqlPair?: { __typename?: 'SqlPair', id: number, question: string, sql: string, projectId: number } | null }>, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null };\n\nexport type CommonResponseFragment = { __typename?: 'ThreadResponse', id: number, threadId: number, question: string, sql?: string | null, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, breakdownDetail?: { __typename?: 'ThreadResponseBreakdownDetail', queryId?: string | null, status: Types.AskingTaskStatus, description?: string | null, steps?: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }> | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, answerDetail?: { __typename?: 'ThreadResponseAnswerDetail', queryId?: string | null, status?: Types.ThreadResponseAnswerStatus | null, content?: string | null, numRowsUsedInLLM?: number | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, chartDetail?: { __typename?: 'ThreadResponseChartDetail', queryId?: string | null, status: Types.ChartTaskStatus, description?: string | null, chartType?: Types.ChartType | null, chartSchema?: any | null, adjustment?: boolean | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, askingTask?: { __typename?: 'AskingTask', status: Types.AskingTaskStatus, type?: Types.AskingTaskType | null, rephrasedQuestion?: string | null, intentReasoning?: string | null, sqlGenerationReasoning?: string | null, retrievedTables?: Array<string> | null, invalidSql?: string | null, traceId?: string | null, queryId?: string | null, candidates: Array<{ __typename?: 'ResultCandidate', sql: string, type: Types.ResultCandidateType, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, sqlPair?: { __typename?: 'SqlPair', id: number, question: string, sql: string, projectId: number } | null }>, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, adjustment?: { __typename?: 'ThreadResponseAdjustment', type: Types.ThreadResponseAdjustmentType, payload?: any | null } | null, adjustmentTask?: { __typename?: 'AdjustmentTask', queryId?: string | null, status?: Types.AskingTaskStatus | null, sql?: string | null, traceId?: string | null, invalidSql?: string | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null };\n\nexport type CommonRecommendedQuestionsTaskFragment = { __typename?: 'RecommendedQuestionsTask', status: Types.RecommendedQuestionsTaskStatus, questions: Array<{ __typename?: 'ResultQuestion', question: string, category: string, sql: string }>, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null };\n\nexport type SuggestedQuestionsQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type SuggestedQuestionsQuery = { __typename?: 'Query', suggestedQuestions: { __typename?: 'SuggestedQuestionResponse', questions: Array<{ __typename?: 'SuggestedQuestion', label: string, question: string } | null> } };\n\nexport type AskingTaskQueryVariables = Types.Exact<{\n  taskId: Types.Scalars['String'];\n}>;\n\n\nexport type AskingTaskQuery = { __typename?: 'Query', askingTask?: { __typename?: 'AskingTask', status: Types.AskingTaskStatus, type?: Types.AskingTaskType | null, rephrasedQuestion?: string | null, intentReasoning?: string | null, sqlGenerationReasoning?: string | null, retrievedTables?: Array<string> | null, invalidSql?: string | null, traceId?: string | null, queryId?: string | null, candidates: Array<{ __typename?: 'ResultCandidate', sql: string, type: Types.ResultCandidateType, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, sqlPair?: { __typename?: 'SqlPair', id: number, question: string, sql: string, projectId: number } | null }>, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null };\n\nexport type ThreadsQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type ThreadsQuery = { __typename?: 'Query', threads: Array<{ __typename?: 'Thread', id: number, summary: string }> };\n\nexport type ThreadQueryVariables = Types.Exact<{\n  threadId: Types.Scalars['Int'];\n}>;\n\n\nexport type ThreadQuery = { __typename?: 'Query', thread: { __typename?: 'DetailedThread', id: number, responses: Array<{ __typename?: 'ThreadResponse', id: number, threadId: number, question: string, sql?: string | null, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, breakdownDetail?: { __typename?: 'ThreadResponseBreakdownDetail', queryId?: string | null, status: Types.AskingTaskStatus, description?: string | null, steps?: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }> | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, answerDetail?: { __typename?: 'ThreadResponseAnswerDetail', queryId?: string | null, status?: Types.ThreadResponseAnswerStatus | null, content?: string | null, numRowsUsedInLLM?: number | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, chartDetail?: { __typename?: 'ThreadResponseChartDetail', queryId?: string | null, status: Types.ChartTaskStatus, description?: string | null, chartType?: Types.ChartType | null, chartSchema?: any | null, adjustment?: boolean | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, askingTask?: { __typename?: 'AskingTask', status: Types.AskingTaskStatus, type?: Types.AskingTaskType | null, rephrasedQuestion?: string | null, intentReasoning?: string | null, sqlGenerationReasoning?: string | null, retrievedTables?: Array<string> | null, invalidSql?: string | null, traceId?: string | null, queryId?: string | null, candidates: Array<{ __typename?: 'ResultCandidate', sql: string, type: Types.ResultCandidateType, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, sqlPair?: { __typename?: 'SqlPair', id: number, question: string, sql: string, projectId: number } | null }>, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, adjustment?: { __typename?: 'ThreadResponseAdjustment', type: Types.ThreadResponseAdjustmentType, payload?: any | null } | null, adjustmentTask?: { __typename?: 'AdjustmentTask', queryId?: string | null, status?: Types.AskingTaskStatus | null, sql?: string | null, traceId?: string | null, invalidSql?: string | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null }> } };\n\nexport type ThreadResponseQueryVariables = Types.Exact<{\n  responseId: Types.Scalars['Int'];\n}>;\n\n\nexport type ThreadResponseQuery = { __typename?: 'Query', threadResponse: { __typename?: 'ThreadResponse', id: number, threadId: number, question: string, sql?: string | null, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, breakdownDetail?: { __typename?: 'ThreadResponseBreakdownDetail', queryId?: string | null, status: Types.AskingTaskStatus, description?: string | null, steps?: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }> | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, answerDetail?: { __typename?: 'ThreadResponseAnswerDetail', queryId?: string | null, status?: Types.ThreadResponseAnswerStatus | null, content?: string | null, numRowsUsedInLLM?: number | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, chartDetail?: { __typename?: 'ThreadResponseChartDetail', queryId?: string | null, status: Types.ChartTaskStatus, description?: string | null, chartType?: Types.ChartType | null, chartSchema?: any | null, adjustment?: boolean | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, askingTask?: { __typename?: 'AskingTask', status: Types.AskingTaskStatus, type?: Types.AskingTaskType | null, rephrasedQuestion?: string | null, intentReasoning?: string | null, sqlGenerationReasoning?: string | null, retrievedTables?: Array<string> | null, invalidSql?: string | null, traceId?: string | null, queryId?: string | null, candidates: Array<{ __typename?: 'ResultCandidate', sql: string, type: Types.ResultCandidateType, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, sqlPair?: { __typename?: 'SqlPair', id: number, question: string, sql: string, projectId: number } | null }>, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, adjustment?: { __typename?: 'ThreadResponseAdjustment', type: Types.ThreadResponseAdjustmentType, payload?: any | null } | null, adjustmentTask?: { __typename?: 'AdjustmentTask', queryId?: string | null, status?: Types.AskingTaskStatus | null, sql?: string | null, traceId?: string | null, invalidSql?: string | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null } };\n\nexport type CreateAskingTaskMutationVariables = Types.Exact<{\n  data: Types.AskingTaskInput;\n}>;\n\n\nexport type CreateAskingTaskMutation = { __typename?: 'Mutation', createAskingTask: { __typename?: 'Task', id: string } };\n\nexport type CancelAskingTaskMutationVariables = Types.Exact<{\n  taskId: Types.Scalars['String'];\n}>;\n\n\nexport type CancelAskingTaskMutation = { __typename?: 'Mutation', cancelAskingTask: boolean };\n\nexport type RerunAskingTaskMutationVariables = Types.Exact<{\n  responseId: Types.Scalars['Int'];\n}>;\n\n\nexport type RerunAskingTaskMutation = { __typename?: 'Mutation', rerunAskingTask: { __typename?: 'Task', id: string } };\n\nexport type CreateThreadMutationVariables = Types.Exact<{\n  data: Types.CreateThreadInput;\n}>;\n\n\nexport type CreateThreadMutation = { __typename?: 'Mutation', createThread: { __typename?: 'Thread', id: number } };\n\nexport type CreateThreadResponseMutationVariables = Types.Exact<{\n  threadId: Types.Scalars['Int'];\n  data: Types.CreateThreadResponseInput;\n}>;\n\n\nexport type CreateThreadResponseMutation = { __typename?: 'Mutation', createThreadResponse: { __typename?: 'ThreadResponse', id: number, threadId: number, question: string, sql?: string | null, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, breakdownDetail?: { __typename?: 'ThreadResponseBreakdownDetail', queryId?: string | null, status: Types.AskingTaskStatus, description?: string | null, steps?: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }> | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, answerDetail?: { __typename?: 'ThreadResponseAnswerDetail', queryId?: string | null, status?: Types.ThreadResponseAnswerStatus | null, content?: string | null, numRowsUsedInLLM?: number | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, chartDetail?: { __typename?: 'ThreadResponseChartDetail', queryId?: string | null, status: Types.ChartTaskStatus, description?: string | null, chartType?: Types.ChartType | null, chartSchema?: any | null, adjustment?: boolean | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, askingTask?: { __typename?: 'AskingTask', status: Types.AskingTaskStatus, type?: Types.AskingTaskType | null, rephrasedQuestion?: string | null, intentReasoning?: string | null, sqlGenerationReasoning?: string | null, retrievedTables?: Array<string> | null, invalidSql?: string | null, traceId?: string | null, queryId?: string | null, candidates: Array<{ __typename?: 'ResultCandidate', sql: string, type: Types.ResultCandidateType, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, sqlPair?: { __typename?: 'SqlPair', id: number, question: string, sql: string, projectId: number } | null }>, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, adjustment?: { __typename?: 'ThreadResponseAdjustment', type: Types.ThreadResponseAdjustmentType, payload?: any | null } | null, adjustmentTask?: { __typename?: 'AdjustmentTask', queryId?: string | null, status?: Types.AskingTaskStatus | null, sql?: string | null, traceId?: string | null, invalidSql?: string | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null } };\n\nexport type UpdateThreadMutationVariables = Types.Exact<{\n  where: Types.ThreadUniqueWhereInput;\n  data: Types.UpdateThreadInput;\n}>;\n\n\nexport type UpdateThreadMutation = { __typename?: 'Mutation', updateThread: { __typename?: 'Thread', id: number, summary: string } };\n\nexport type UpdateThreadResponseMutationVariables = Types.Exact<{\n  where: Types.ThreadResponseUniqueWhereInput;\n  data: Types.UpdateThreadResponseInput;\n}>;\n\n\nexport type UpdateThreadResponseMutation = { __typename?: 'Mutation', updateThreadResponse: { __typename?: 'ThreadResponse', id: number, threadId: number, question: string, sql?: string | null, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, breakdownDetail?: { __typename?: 'ThreadResponseBreakdownDetail', queryId?: string | null, status: Types.AskingTaskStatus, description?: string | null, steps?: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }> | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, answerDetail?: { __typename?: 'ThreadResponseAnswerDetail', queryId?: string | null, status?: Types.ThreadResponseAnswerStatus | null, content?: string | null, numRowsUsedInLLM?: number | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, chartDetail?: { __typename?: 'ThreadResponseChartDetail', queryId?: string | null, status: Types.ChartTaskStatus, description?: string | null, chartType?: Types.ChartType | null, chartSchema?: any | null, adjustment?: boolean | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, askingTask?: { __typename?: 'AskingTask', status: Types.AskingTaskStatus, type?: Types.AskingTaskType | null, rephrasedQuestion?: string | null, intentReasoning?: string | null, sqlGenerationReasoning?: string | null, retrievedTables?: Array<string> | null, invalidSql?: string | null, traceId?: string | null, queryId?: string | null, candidates: Array<{ __typename?: 'ResultCandidate', sql: string, type: Types.ResultCandidateType, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, sqlPair?: { __typename?: 'SqlPair', id: number, question: string, sql: string, projectId: number } | null }>, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, adjustment?: { __typename?: 'ThreadResponseAdjustment', type: Types.ThreadResponseAdjustmentType, payload?: any | null } | null, adjustmentTask?: { __typename?: 'AdjustmentTask', queryId?: string | null, status?: Types.AskingTaskStatus | null, sql?: string | null, traceId?: string | null, invalidSql?: string | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null } };\n\nexport type AdjustThreadResponseMutationVariables = Types.Exact<{\n  responseId: Types.Scalars['Int'];\n  data: Types.AdjustThreadResponseInput;\n}>;\n\n\nexport type AdjustThreadResponseMutation = { __typename?: 'Mutation', adjustThreadResponse: { __typename?: 'ThreadResponse', id: number, threadId: number, question: string, sql?: string | null, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, breakdownDetail?: { __typename?: 'ThreadResponseBreakdownDetail', queryId?: string | null, status: Types.AskingTaskStatus, description?: string | null, steps?: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }> | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, answerDetail?: { __typename?: 'ThreadResponseAnswerDetail', queryId?: string | null, status?: Types.ThreadResponseAnswerStatus | null, content?: string | null, numRowsUsedInLLM?: number | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, chartDetail?: { __typename?: 'ThreadResponseChartDetail', queryId?: string | null, status: Types.ChartTaskStatus, description?: string | null, chartType?: Types.ChartType | null, chartSchema?: any | null, adjustment?: boolean | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, askingTask?: { __typename?: 'AskingTask', status: Types.AskingTaskStatus, type?: Types.AskingTaskType | null, rephrasedQuestion?: string | null, intentReasoning?: string | null, sqlGenerationReasoning?: string | null, retrievedTables?: Array<string> | null, invalidSql?: string | null, traceId?: string | null, queryId?: string | null, candidates: Array<{ __typename?: 'ResultCandidate', sql: string, type: Types.ResultCandidateType, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, sqlPair?: { __typename?: 'SqlPair', id: number, question: string, sql: string, projectId: number } | null }>, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, adjustment?: { __typename?: 'ThreadResponseAdjustment', type: Types.ThreadResponseAdjustmentType, payload?: any | null } | null, adjustmentTask?: { __typename?: 'AdjustmentTask', queryId?: string | null, status?: Types.AskingTaskStatus | null, sql?: string | null, traceId?: string | null, invalidSql?: string | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null } };\n\nexport type DeleteThreadMutationVariables = Types.Exact<{\n  where: Types.ThreadUniqueWhereInput;\n}>;\n\n\nexport type DeleteThreadMutation = { __typename?: 'Mutation', deleteThread: boolean };\n\nexport type PreviewDataMutationVariables = Types.Exact<{\n  where: Types.PreviewDataInput;\n}>;\n\n\nexport type PreviewDataMutation = { __typename?: 'Mutation', previewData: any };\n\nexport type PreviewBreakdownDataMutationVariables = Types.Exact<{\n  where: Types.PreviewDataInput;\n}>;\n\n\nexport type PreviewBreakdownDataMutation = { __typename?: 'Mutation', previewBreakdownData: any };\n\nexport type GetNativeSqlQueryVariables = Types.Exact<{\n  responseId: Types.Scalars['Int'];\n}>;\n\n\nexport type GetNativeSqlQuery = { __typename?: 'Query', nativeSql: string };\n\nexport type CreateInstantRecommendedQuestionsMutationVariables = Types.Exact<{\n  data: Types.InstantRecommendedQuestionsInput;\n}>;\n\n\nexport type CreateInstantRecommendedQuestionsMutation = { __typename?: 'Mutation', createInstantRecommendedQuestions: { __typename?: 'Task', id: string } };\n\nexport type InstantRecommendedQuestionsQueryVariables = Types.Exact<{\n  taskId: Types.Scalars['String'];\n}>;\n\n\nexport type InstantRecommendedQuestionsQuery = { __typename?: 'Query', instantRecommendedQuestions: { __typename?: 'RecommendedQuestionsTask', status: Types.RecommendedQuestionsTaskStatus, questions: Array<{ __typename?: 'ResultQuestion', question: string, category: string, sql: string }>, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } };\n\nexport type GetThreadRecommendationQuestionsQueryVariables = Types.Exact<{\n  threadId: Types.Scalars['Int'];\n}>;\n\n\nexport type GetThreadRecommendationQuestionsQuery = { __typename?: 'Query', getThreadRecommendationQuestions: { __typename?: 'RecommendedQuestionsTask', status: Types.RecommendedQuestionsTaskStatus, questions: Array<{ __typename?: 'ResultQuestion', question: string, category: string, sql: string }>, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } };\n\nexport type GetProjectRecommendationQuestionsQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type GetProjectRecommendationQuestionsQuery = { __typename?: 'Query', getProjectRecommendationQuestions: { __typename?: 'RecommendedQuestionsTask', status: Types.RecommendedQuestionsTaskStatus, questions: Array<{ __typename?: 'ResultQuestion', question: string, category: string, sql: string }>, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } };\n\nexport type GenerateProjectRecommendationQuestionsMutationVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type GenerateProjectRecommendationQuestionsMutation = { __typename?: 'Mutation', generateProjectRecommendationQuestions: boolean };\n\nexport type GenerateThreadRecommendationQuestionsMutationVariables = Types.Exact<{\n  threadId: Types.Scalars['Int'];\n}>;\n\n\nexport type GenerateThreadRecommendationQuestionsMutation = { __typename?: 'Mutation', generateThreadRecommendationQuestions: boolean };\n\nexport type GenerateThreadResponseAnswerMutationVariables = Types.Exact<{\n  responseId: Types.Scalars['Int'];\n}>;\n\n\nexport type GenerateThreadResponseAnswerMutation = { __typename?: 'Mutation', generateThreadResponseAnswer: { __typename?: 'ThreadResponse', id: number, threadId: number, question: string, sql?: string | null, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, breakdownDetail?: { __typename?: 'ThreadResponseBreakdownDetail', queryId?: string | null, status: Types.AskingTaskStatus, description?: string | null, steps?: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }> | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, answerDetail?: { __typename?: 'ThreadResponseAnswerDetail', queryId?: string | null, status?: Types.ThreadResponseAnswerStatus | null, content?: string | null, numRowsUsedInLLM?: number | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, chartDetail?: { __typename?: 'ThreadResponseChartDetail', queryId?: string | null, status: Types.ChartTaskStatus, description?: string | null, chartType?: Types.ChartType | null, chartSchema?: any | null, adjustment?: boolean | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, askingTask?: { __typename?: 'AskingTask', status: Types.AskingTaskStatus, type?: Types.AskingTaskType | null, rephrasedQuestion?: string | null, intentReasoning?: string | null, sqlGenerationReasoning?: string | null, retrievedTables?: Array<string> | null, invalidSql?: string | null, traceId?: string | null, queryId?: string | null, candidates: Array<{ __typename?: 'ResultCandidate', sql: string, type: Types.ResultCandidateType, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, sqlPair?: { __typename?: 'SqlPair', id: number, question: string, sql: string, projectId: number } | null }>, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, adjustment?: { __typename?: 'ThreadResponseAdjustment', type: Types.ThreadResponseAdjustmentType, payload?: any | null } | null, adjustmentTask?: { __typename?: 'AdjustmentTask', queryId?: string | null, status?: Types.AskingTaskStatus | null, sql?: string | null, traceId?: string | null, invalidSql?: string | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null } };\n\nexport type GenerateThreadResponseChartMutationVariables = Types.Exact<{\n  responseId: Types.Scalars['Int'];\n}>;\n\n\nexport type GenerateThreadResponseChartMutation = { __typename?: 'Mutation', generateThreadResponseChart: { __typename?: 'ThreadResponse', id: number, threadId: number, question: string, sql?: string | null, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, breakdownDetail?: { __typename?: 'ThreadResponseBreakdownDetail', queryId?: string | null, status: Types.AskingTaskStatus, description?: string | null, steps?: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }> | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, answerDetail?: { __typename?: 'ThreadResponseAnswerDetail', queryId?: string | null, status?: Types.ThreadResponseAnswerStatus | null, content?: string | null, numRowsUsedInLLM?: number | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, chartDetail?: { __typename?: 'ThreadResponseChartDetail', queryId?: string | null, status: Types.ChartTaskStatus, description?: string | null, chartType?: Types.ChartType | null, chartSchema?: any | null, adjustment?: boolean | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, askingTask?: { __typename?: 'AskingTask', status: Types.AskingTaskStatus, type?: Types.AskingTaskType | null, rephrasedQuestion?: string | null, intentReasoning?: string | null, sqlGenerationReasoning?: string | null, retrievedTables?: Array<string> | null, invalidSql?: string | null, traceId?: string | null, queryId?: string | null, candidates: Array<{ __typename?: 'ResultCandidate', sql: string, type: Types.ResultCandidateType, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, sqlPair?: { __typename?: 'SqlPair', id: number, question: string, sql: string, projectId: number } | null }>, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, adjustment?: { __typename?: 'ThreadResponseAdjustment', type: Types.ThreadResponseAdjustmentType, payload?: any | null } | null, adjustmentTask?: { __typename?: 'AdjustmentTask', queryId?: string | null, status?: Types.AskingTaskStatus | null, sql?: string | null, traceId?: string | null, invalidSql?: string | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null } };\n\nexport type AdjustThreadResponseChartMutationVariables = Types.Exact<{\n  responseId: Types.Scalars['Int'];\n  data: Types.AdjustThreadResponseChartInput;\n}>;\n\n\nexport type AdjustThreadResponseChartMutation = { __typename?: 'Mutation', adjustThreadResponseChart: { __typename?: 'ThreadResponse', id: number, threadId: number, question: string, sql?: string | null, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, breakdownDetail?: { __typename?: 'ThreadResponseBreakdownDetail', queryId?: string | null, status: Types.AskingTaskStatus, description?: string | null, steps?: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }> | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, answerDetail?: { __typename?: 'ThreadResponseAnswerDetail', queryId?: string | null, status?: Types.ThreadResponseAnswerStatus | null, content?: string | null, numRowsUsedInLLM?: number | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, chartDetail?: { __typename?: 'ThreadResponseChartDetail', queryId?: string | null, status: Types.ChartTaskStatus, description?: string | null, chartType?: Types.ChartType | null, chartSchema?: any | null, adjustment?: boolean | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, askingTask?: { __typename?: 'AskingTask', status: Types.AskingTaskStatus, type?: Types.AskingTaskType | null, rephrasedQuestion?: string | null, intentReasoning?: string | null, sqlGenerationReasoning?: string | null, retrievedTables?: Array<string> | null, invalidSql?: string | null, traceId?: string | null, queryId?: string | null, candidates: Array<{ __typename?: 'ResultCandidate', sql: string, type: Types.ResultCandidateType, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null, sqlPair?: { __typename?: 'SqlPair', id: number, question: string, sql: string, projectId: number } | null }>, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null, adjustment?: { __typename?: 'ThreadResponseAdjustment', type: Types.ThreadResponseAdjustmentType, payload?: any | null } | null, adjustmentTask?: { __typename?: 'AdjustmentTask', queryId?: string | null, status?: Types.AskingTaskStatus | null, sql?: string | null, traceId?: string | null, invalidSql?: string | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null } };\n\nexport type AdjustmentTaskQueryVariables = Types.Exact<{\n  taskId: Types.Scalars['String'];\n}>;\n\n\nexport type AdjustmentTaskQuery = { __typename?: 'Query', adjustmentTask?: { __typename?: 'AdjustmentTask', queryId?: string | null, status?: Types.AskingTaskStatus | null, sql?: string | null, traceId?: string | null, invalidSql?: string | null, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null } | null };\n\nexport type CancelAdjustmentTaskMutationVariables = Types.Exact<{\n  taskId: Types.Scalars['String'];\n}>;\n\n\nexport type CancelAdjustmentTaskMutation = { __typename?: 'Mutation', cancelAdjustmentTask: boolean };\n\nexport type RerunAdjustmentTaskMutationVariables = Types.Exact<{\n  responseId: Types.Scalars['Int'];\n}>;\n\n\nexport type RerunAdjustmentTaskMutation = { __typename?: 'Mutation', rerunAdjustmentTask: boolean };\n\nexport const CommonErrorFragmentDoc = gql`\n    fragment CommonError on Error {\n  code\n  shortMessage\n  message\n  stacktrace\n}\n    `;\nexport const CommonBreakdownDetailFragmentDoc = gql`\n    fragment CommonBreakdownDetail on ThreadResponseBreakdownDetail {\n  queryId\n  status\n  description\n  steps {\n    summary\n    sql\n    cteName\n  }\n  error {\n    ...CommonError\n  }\n}\n    ${CommonErrorFragmentDoc}`;\nexport const CommonAnswerDetailFragmentDoc = gql`\n    fragment CommonAnswerDetail on ThreadResponseAnswerDetail {\n  queryId\n  status\n  content\n  numRowsUsedInLLM\n  error {\n    ...CommonError\n  }\n}\n    ${CommonErrorFragmentDoc}`;\nexport const CommonChartDetailFragmentDoc = gql`\n    fragment CommonChartDetail on ThreadResponseChartDetail {\n  queryId\n  status\n  description\n  chartType\n  chartSchema\n  error {\n    ...CommonError\n  }\n  adjustment\n}\n    ${CommonErrorFragmentDoc}`;\nexport const CommonAskingTaskFragmentDoc = gql`\n    fragment CommonAskingTask on AskingTask {\n  status\n  type\n  candidates {\n    sql\n    type\n    view {\n      id\n      name\n      statement\n      displayName\n    }\n    sqlPair {\n      id\n      question\n      sql\n      projectId\n    }\n  }\n  error {\n    ...CommonError\n  }\n  rephrasedQuestion\n  intentReasoning\n  sqlGenerationReasoning\n  retrievedTables\n  invalidSql\n  traceId\n  queryId\n}\n    ${CommonErrorFragmentDoc}`;\nexport const CommonResponseFragmentDoc = gql`\n    fragment CommonResponse on ThreadResponse {\n  id\n  threadId\n  question\n  sql\n  view {\n    id\n    name\n    statement\n    displayName\n  }\n  breakdownDetail {\n    ...CommonBreakdownDetail\n  }\n  answerDetail {\n    ...CommonAnswerDetail\n  }\n  chartDetail {\n    ...CommonChartDetail\n  }\n  askingTask {\n    ...CommonAskingTask\n  }\n  adjustment {\n    type\n    payload\n  }\n  adjustmentTask {\n    queryId\n    status\n    error {\n      ...CommonError\n    }\n    sql\n    traceId\n    invalidSql\n  }\n}\n    ${CommonBreakdownDetailFragmentDoc}\n${CommonAnswerDetailFragmentDoc}\n${CommonChartDetailFragmentDoc}\n${CommonAskingTaskFragmentDoc}\n${CommonErrorFragmentDoc}`;\nexport const CommonRecommendedQuestionsTaskFragmentDoc = gql`\n    fragment CommonRecommendedQuestionsTask on RecommendedQuestionsTask {\n  status\n  questions {\n    question\n    category\n    sql\n  }\n  error {\n    ...CommonError\n  }\n}\n    ${CommonErrorFragmentDoc}`;\nexport const SuggestedQuestionsDocument = gql`\n    query SuggestedQuestions {\n  suggestedQuestions {\n    questions {\n      label\n      question\n    }\n  }\n}\n    `;\n\n/**\n * __useSuggestedQuestionsQuery__\n *\n * To run a query within a React component, call `useSuggestedQuestionsQuery` and pass it any options that fit your needs.\n * When your component renders, `useSuggestedQuestionsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useSuggestedQuestionsQuery({\n *   variables: {\n *   },\n * });\n */\nexport function useSuggestedQuestionsQuery(baseOptions?: Apollo.QueryHookOptions<SuggestedQuestionsQuery, SuggestedQuestionsQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<SuggestedQuestionsQuery, SuggestedQuestionsQueryVariables>(SuggestedQuestionsDocument, options);\n      }\nexport function useSuggestedQuestionsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<SuggestedQuestionsQuery, SuggestedQuestionsQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<SuggestedQuestionsQuery, SuggestedQuestionsQueryVariables>(SuggestedQuestionsDocument, options);\n        }\nexport type SuggestedQuestionsQueryHookResult = ReturnType<typeof useSuggestedQuestionsQuery>;\nexport type SuggestedQuestionsLazyQueryHookResult = ReturnType<typeof useSuggestedQuestionsLazyQuery>;\nexport type SuggestedQuestionsQueryResult = Apollo.QueryResult<SuggestedQuestionsQuery, SuggestedQuestionsQueryVariables>;\nexport const AskingTaskDocument = gql`\n    query AskingTask($taskId: String!) {\n  askingTask(taskId: $taskId) {\n    ...CommonAskingTask\n  }\n}\n    ${CommonAskingTaskFragmentDoc}`;\n\n/**\n * __useAskingTaskQuery__\n *\n * To run a query within a React component, call `useAskingTaskQuery` and pass it any options that fit your needs.\n * When your component renders, `useAskingTaskQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useAskingTaskQuery({\n *   variables: {\n *      taskId: // value for 'taskId'\n *   },\n * });\n */\nexport function useAskingTaskQuery(baseOptions: Apollo.QueryHookOptions<AskingTaskQuery, AskingTaskQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<AskingTaskQuery, AskingTaskQueryVariables>(AskingTaskDocument, options);\n      }\nexport function useAskingTaskLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<AskingTaskQuery, AskingTaskQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<AskingTaskQuery, AskingTaskQueryVariables>(AskingTaskDocument, options);\n        }\nexport type AskingTaskQueryHookResult = ReturnType<typeof useAskingTaskQuery>;\nexport type AskingTaskLazyQueryHookResult = ReturnType<typeof useAskingTaskLazyQuery>;\nexport type AskingTaskQueryResult = Apollo.QueryResult<AskingTaskQuery, AskingTaskQueryVariables>;\nexport const ThreadsDocument = gql`\n    query Threads {\n  threads {\n    id\n    summary\n  }\n}\n    `;\n\n/**\n * __useThreadsQuery__\n *\n * To run a query within a React component, call `useThreadsQuery` and pass it any options that fit your needs.\n * When your component renders, `useThreadsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useThreadsQuery({\n *   variables: {\n *   },\n * });\n */\nexport function useThreadsQuery(baseOptions?: Apollo.QueryHookOptions<ThreadsQuery, ThreadsQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<ThreadsQuery, ThreadsQueryVariables>(ThreadsDocument, options);\n      }\nexport function useThreadsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ThreadsQuery, ThreadsQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<ThreadsQuery, ThreadsQueryVariables>(ThreadsDocument, options);\n        }\nexport type ThreadsQueryHookResult = ReturnType<typeof useThreadsQuery>;\nexport type ThreadsLazyQueryHookResult = ReturnType<typeof useThreadsLazyQuery>;\nexport type ThreadsQueryResult = Apollo.QueryResult<ThreadsQuery, ThreadsQueryVariables>;\nexport const ThreadDocument = gql`\n    query Thread($threadId: Int!) {\n  thread(threadId: $threadId) {\n    id\n    responses {\n      ...CommonResponse\n    }\n  }\n}\n    ${CommonResponseFragmentDoc}`;\n\n/**\n * __useThreadQuery__\n *\n * To run a query within a React component, call `useThreadQuery` and pass it any options that fit your needs.\n * When your component renders, `useThreadQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useThreadQuery({\n *   variables: {\n *      threadId: // value for 'threadId'\n *   },\n * });\n */\nexport function useThreadQuery(baseOptions: Apollo.QueryHookOptions<ThreadQuery, ThreadQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<ThreadQuery, ThreadQueryVariables>(ThreadDocument, options);\n      }\nexport function useThreadLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ThreadQuery, ThreadQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<ThreadQuery, ThreadQueryVariables>(ThreadDocument, options);\n        }\nexport type ThreadQueryHookResult = ReturnType<typeof useThreadQuery>;\nexport type ThreadLazyQueryHookResult = ReturnType<typeof useThreadLazyQuery>;\nexport type ThreadQueryResult = Apollo.QueryResult<ThreadQuery, ThreadQueryVariables>;\nexport const ThreadResponseDocument = gql`\n    query ThreadResponse($responseId: Int!) {\n  threadResponse(responseId: $responseId) {\n    ...CommonResponse\n  }\n}\n    ${CommonResponseFragmentDoc}`;\n\n/**\n * __useThreadResponseQuery__\n *\n * To run a query within a React component, call `useThreadResponseQuery` and pass it any options that fit your needs.\n * When your component renders, `useThreadResponseQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useThreadResponseQuery({\n *   variables: {\n *      responseId: // value for 'responseId'\n *   },\n * });\n */\nexport function useThreadResponseQuery(baseOptions: Apollo.QueryHookOptions<ThreadResponseQuery, ThreadResponseQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<ThreadResponseQuery, ThreadResponseQueryVariables>(ThreadResponseDocument, options);\n      }\nexport function useThreadResponseLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ThreadResponseQuery, ThreadResponseQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<ThreadResponseQuery, ThreadResponseQueryVariables>(ThreadResponseDocument, options);\n        }\nexport type ThreadResponseQueryHookResult = ReturnType<typeof useThreadResponseQuery>;\nexport type ThreadResponseLazyQueryHookResult = ReturnType<typeof useThreadResponseLazyQuery>;\nexport type ThreadResponseQueryResult = Apollo.QueryResult<ThreadResponseQuery, ThreadResponseQueryVariables>;\nexport const CreateAskingTaskDocument = gql`\n    mutation CreateAskingTask($data: AskingTaskInput!) {\n  createAskingTask(data: $data) {\n    id\n  }\n}\n    `;\nexport type CreateAskingTaskMutationFn = Apollo.MutationFunction<CreateAskingTaskMutation, CreateAskingTaskMutationVariables>;\n\n/**\n * __useCreateAskingTaskMutation__\n *\n * To run a mutation, you first call `useCreateAskingTaskMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateAskingTaskMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createAskingTaskMutation, { data, loading, error }] = useCreateAskingTaskMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useCreateAskingTaskMutation(baseOptions?: Apollo.MutationHookOptions<CreateAskingTaskMutation, CreateAskingTaskMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<CreateAskingTaskMutation, CreateAskingTaskMutationVariables>(CreateAskingTaskDocument, options);\n      }\nexport type CreateAskingTaskMutationHookResult = ReturnType<typeof useCreateAskingTaskMutation>;\nexport type CreateAskingTaskMutationResult = Apollo.MutationResult<CreateAskingTaskMutation>;\nexport type CreateAskingTaskMutationOptions = Apollo.BaseMutationOptions<CreateAskingTaskMutation, CreateAskingTaskMutationVariables>;\nexport const CancelAskingTaskDocument = gql`\n    mutation CancelAskingTask($taskId: String!) {\n  cancelAskingTask(taskId: $taskId)\n}\n    `;\nexport type CancelAskingTaskMutationFn = Apollo.MutationFunction<CancelAskingTaskMutation, CancelAskingTaskMutationVariables>;\n\n/**\n * __useCancelAskingTaskMutation__\n *\n * To run a mutation, you first call `useCancelAskingTaskMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCancelAskingTaskMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [cancelAskingTaskMutation, { data, loading, error }] = useCancelAskingTaskMutation({\n *   variables: {\n *      taskId: // value for 'taskId'\n *   },\n * });\n */\nexport function useCancelAskingTaskMutation(baseOptions?: Apollo.MutationHookOptions<CancelAskingTaskMutation, CancelAskingTaskMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<CancelAskingTaskMutation, CancelAskingTaskMutationVariables>(CancelAskingTaskDocument, options);\n      }\nexport type CancelAskingTaskMutationHookResult = ReturnType<typeof useCancelAskingTaskMutation>;\nexport type CancelAskingTaskMutationResult = Apollo.MutationResult<CancelAskingTaskMutation>;\nexport type CancelAskingTaskMutationOptions = Apollo.BaseMutationOptions<CancelAskingTaskMutation, CancelAskingTaskMutationVariables>;\nexport const RerunAskingTaskDocument = gql`\n    mutation RerunAskingTask($responseId: Int!) {\n  rerunAskingTask(responseId: $responseId) {\n    id\n  }\n}\n    `;\nexport type RerunAskingTaskMutationFn = Apollo.MutationFunction<RerunAskingTaskMutation, RerunAskingTaskMutationVariables>;\n\n/**\n * __useRerunAskingTaskMutation__\n *\n * To run a mutation, you first call `useRerunAskingTaskMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useRerunAskingTaskMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [rerunAskingTaskMutation, { data, loading, error }] = useRerunAskingTaskMutation({\n *   variables: {\n *      responseId: // value for 'responseId'\n *   },\n * });\n */\nexport function useRerunAskingTaskMutation(baseOptions?: Apollo.MutationHookOptions<RerunAskingTaskMutation, RerunAskingTaskMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<RerunAskingTaskMutation, RerunAskingTaskMutationVariables>(RerunAskingTaskDocument, options);\n      }\nexport type RerunAskingTaskMutationHookResult = ReturnType<typeof useRerunAskingTaskMutation>;\nexport type RerunAskingTaskMutationResult = Apollo.MutationResult<RerunAskingTaskMutation>;\nexport type RerunAskingTaskMutationOptions = Apollo.BaseMutationOptions<RerunAskingTaskMutation, RerunAskingTaskMutationVariables>;\nexport const CreateThreadDocument = gql`\n    mutation CreateThread($data: CreateThreadInput!) {\n  createThread(data: $data) {\n    id\n  }\n}\n    `;\nexport type CreateThreadMutationFn = Apollo.MutationFunction<CreateThreadMutation, CreateThreadMutationVariables>;\n\n/**\n * __useCreateThreadMutation__\n *\n * To run a mutation, you first call `useCreateThreadMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateThreadMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createThreadMutation, { data, loading, error }] = useCreateThreadMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useCreateThreadMutation(baseOptions?: Apollo.MutationHookOptions<CreateThreadMutation, CreateThreadMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<CreateThreadMutation, CreateThreadMutationVariables>(CreateThreadDocument, options);\n      }\nexport type CreateThreadMutationHookResult = ReturnType<typeof useCreateThreadMutation>;\nexport type CreateThreadMutationResult = Apollo.MutationResult<CreateThreadMutation>;\nexport type CreateThreadMutationOptions = Apollo.BaseMutationOptions<CreateThreadMutation, CreateThreadMutationVariables>;\nexport const CreateThreadResponseDocument = gql`\n    mutation CreateThreadResponse($threadId: Int!, $data: CreateThreadResponseInput!) {\n  createThreadResponse(threadId: $threadId, data: $data) {\n    ...CommonResponse\n  }\n}\n    ${CommonResponseFragmentDoc}`;\nexport type CreateThreadResponseMutationFn = Apollo.MutationFunction<CreateThreadResponseMutation, CreateThreadResponseMutationVariables>;\n\n/**\n * __useCreateThreadResponseMutation__\n *\n * To run a mutation, you first call `useCreateThreadResponseMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateThreadResponseMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createThreadResponseMutation, { data, loading, error }] = useCreateThreadResponseMutation({\n *   variables: {\n *      threadId: // value for 'threadId'\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useCreateThreadResponseMutation(baseOptions?: Apollo.MutationHookOptions<CreateThreadResponseMutation, CreateThreadResponseMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<CreateThreadResponseMutation, CreateThreadResponseMutationVariables>(CreateThreadResponseDocument, options);\n      }\nexport type CreateThreadResponseMutationHookResult = ReturnType<typeof useCreateThreadResponseMutation>;\nexport type CreateThreadResponseMutationResult = Apollo.MutationResult<CreateThreadResponseMutation>;\nexport type CreateThreadResponseMutationOptions = Apollo.BaseMutationOptions<CreateThreadResponseMutation, CreateThreadResponseMutationVariables>;\nexport const UpdateThreadDocument = gql`\n    mutation UpdateThread($where: ThreadUniqueWhereInput!, $data: UpdateThreadInput!) {\n  updateThread(where: $where, data: $data) {\n    id\n    summary\n  }\n}\n    `;\nexport type UpdateThreadMutationFn = Apollo.MutationFunction<UpdateThreadMutation, UpdateThreadMutationVariables>;\n\n/**\n * __useUpdateThreadMutation__\n *\n * To run a mutation, you first call `useUpdateThreadMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateThreadMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateThreadMutation, { data, loading, error }] = useUpdateThreadMutation({\n *   variables: {\n *      where: // value for 'where'\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useUpdateThreadMutation(baseOptions?: Apollo.MutationHookOptions<UpdateThreadMutation, UpdateThreadMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<UpdateThreadMutation, UpdateThreadMutationVariables>(UpdateThreadDocument, options);\n      }\nexport type UpdateThreadMutationHookResult = ReturnType<typeof useUpdateThreadMutation>;\nexport type UpdateThreadMutationResult = Apollo.MutationResult<UpdateThreadMutation>;\nexport type UpdateThreadMutationOptions = Apollo.BaseMutationOptions<UpdateThreadMutation, UpdateThreadMutationVariables>;\nexport const UpdateThreadResponseDocument = gql`\n    mutation UpdateThreadResponse($where: ThreadResponseUniqueWhereInput!, $data: UpdateThreadResponseInput!) {\n  updateThreadResponse(where: $where, data: $data) {\n    ...CommonResponse\n  }\n}\n    ${CommonResponseFragmentDoc}`;\nexport type UpdateThreadResponseMutationFn = Apollo.MutationFunction<UpdateThreadResponseMutation, UpdateThreadResponseMutationVariables>;\n\n/**\n * __useUpdateThreadResponseMutation__\n *\n * To run a mutation, you first call `useUpdateThreadResponseMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateThreadResponseMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateThreadResponseMutation, { data, loading, error }] = useUpdateThreadResponseMutation({\n *   variables: {\n *      where: // value for 'where'\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useUpdateThreadResponseMutation(baseOptions?: Apollo.MutationHookOptions<UpdateThreadResponseMutation, UpdateThreadResponseMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<UpdateThreadResponseMutation, UpdateThreadResponseMutationVariables>(UpdateThreadResponseDocument, options);\n      }\nexport type UpdateThreadResponseMutationHookResult = ReturnType<typeof useUpdateThreadResponseMutation>;\nexport type UpdateThreadResponseMutationResult = Apollo.MutationResult<UpdateThreadResponseMutation>;\nexport type UpdateThreadResponseMutationOptions = Apollo.BaseMutationOptions<UpdateThreadResponseMutation, UpdateThreadResponseMutationVariables>;\nexport const AdjustThreadResponseDocument = gql`\n    mutation AdjustThreadResponse($responseId: Int!, $data: AdjustThreadResponseInput!) {\n  adjustThreadResponse(responseId: $responseId, data: $data) {\n    ...CommonResponse\n  }\n}\n    ${CommonResponseFragmentDoc}`;\nexport type AdjustThreadResponseMutationFn = Apollo.MutationFunction<AdjustThreadResponseMutation, AdjustThreadResponseMutationVariables>;\n\n/**\n * __useAdjustThreadResponseMutation__\n *\n * To run a mutation, you first call `useAdjustThreadResponseMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useAdjustThreadResponseMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [adjustThreadResponseMutation, { data, loading, error }] = useAdjustThreadResponseMutation({\n *   variables: {\n *      responseId: // value for 'responseId'\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useAdjustThreadResponseMutation(baseOptions?: Apollo.MutationHookOptions<AdjustThreadResponseMutation, AdjustThreadResponseMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<AdjustThreadResponseMutation, AdjustThreadResponseMutationVariables>(AdjustThreadResponseDocument, options);\n      }\nexport type AdjustThreadResponseMutationHookResult = ReturnType<typeof useAdjustThreadResponseMutation>;\nexport type AdjustThreadResponseMutationResult = Apollo.MutationResult<AdjustThreadResponseMutation>;\nexport type AdjustThreadResponseMutationOptions = Apollo.BaseMutationOptions<AdjustThreadResponseMutation, AdjustThreadResponseMutationVariables>;\nexport const DeleteThreadDocument = gql`\n    mutation DeleteThread($where: ThreadUniqueWhereInput!) {\n  deleteThread(where: $where)\n}\n    `;\nexport type DeleteThreadMutationFn = Apollo.MutationFunction<DeleteThreadMutation, DeleteThreadMutationVariables>;\n\n/**\n * __useDeleteThreadMutation__\n *\n * To run a mutation, you first call `useDeleteThreadMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDeleteThreadMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [deleteThreadMutation, { data, loading, error }] = useDeleteThreadMutation({\n *   variables: {\n *      where: // value for 'where'\n *   },\n * });\n */\nexport function useDeleteThreadMutation(baseOptions?: Apollo.MutationHookOptions<DeleteThreadMutation, DeleteThreadMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<DeleteThreadMutation, DeleteThreadMutationVariables>(DeleteThreadDocument, options);\n      }\nexport type DeleteThreadMutationHookResult = ReturnType<typeof useDeleteThreadMutation>;\nexport type DeleteThreadMutationResult = Apollo.MutationResult<DeleteThreadMutation>;\nexport type DeleteThreadMutationOptions = Apollo.BaseMutationOptions<DeleteThreadMutation, DeleteThreadMutationVariables>;\nexport const PreviewDataDocument = gql`\n    mutation PreviewData($where: PreviewDataInput!) {\n  previewData(where: $where)\n}\n    `;\nexport type PreviewDataMutationFn = Apollo.MutationFunction<PreviewDataMutation, PreviewDataMutationVariables>;\n\n/**\n * __usePreviewDataMutation__\n *\n * To run a mutation, you first call `usePreviewDataMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `usePreviewDataMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [previewDataMutation, { data, loading, error }] = usePreviewDataMutation({\n *   variables: {\n *      where: // value for 'where'\n *   },\n * });\n */\nexport function usePreviewDataMutation(baseOptions?: Apollo.MutationHookOptions<PreviewDataMutation, PreviewDataMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<PreviewDataMutation, PreviewDataMutationVariables>(PreviewDataDocument, options);\n      }\nexport type PreviewDataMutationHookResult = ReturnType<typeof usePreviewDataMutation>;\nexport type PreviewDataMutationResult = Apollo.MutationResult<PreviewDataMutation>;\nexport type PreviewDataMutationOptions = Apollo.BaseMutationOptions<PreviewDataMutation, PreviewDataMutationVariables>;\nexport const PreviewBreakdownDataDocument = gql`\n    mutation PreviewBreakdownData($where: PreviewDataInput!) {\n  previewBreakdownData(where: $where)\n}\n    `;\nexport type PreviewBreakdownDataMutationFn = Apollo.MutationFunction<PreviewBreakdownDataMutation, PreviewBreakdownDataMutationVariables>;\n\n/**\n * __usePreviewBreakdownDataMutation__\n *\n * To run a mutation, you first call `usePreviewBreakdownDataMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `usePreviewBreakdownDataMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [previewBreakdownDataMutation, { data, loading, error }] = usePreviewBreakdownDataMutation({\n *   variables: {\n *      where: // value for 'where'\n *   },\n * });\n */\nexport function usePreviewBreakdownDataMutation(baseOptions?: Apollo.MutationHookOptions<PreviewBreakdownDataMutation, PreviewBreakdownDataMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<PreviewBreakdownDataMutation, PreviewBreakdownDataMutationVariables>(PreviewBreakdownDataDocument, options);\n      }\nexport type PreviewBreakdownDataMutationHookResult = ReturnType<typeof usePreviewBreakdownDataMutation>;\nexport type PreviewBreakdownDataMutationResult = Apollo.MutationResult<PreviewBreakdownDataMutation>;\nexport type PreviewBreakdownDataMutationOptions = Apollo.BaseMutationOptions<PreviewBreakdownDataMutation, PreviewBreakdownDataMutationVariables>;\nexport const GetNativeSqlDocument = gql`\n    query GetNativeSQL($responseId: Int!) {\n  nativeSql(responseId: $responseId)\n}\n    `;\n\n/**\n * __useGetNativeSqlQuery__\n *\n * To run a query within a React component, call `useGetNativeSqlQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetNativeSqlQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetNativeSqlQuery({\n *   variables: {\n *      responseId: // value for 'responseId'\n *   },\n * });\n */\nexport function useGetNativeSqlQuery(baseOptions: Apollo.QueryHookOptions<GetNativeSqlQuery, GetNativeSqlQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<GetNativeSqlQuery, GetNativeSqlQueryVariables>(GetNativeSqlDocument, options);\n      }\nexport function useGetNativeSqlLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetNativeSqlQuery, GetNativeSqlQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<GetNativeSqlQuery, GetNativeSqlQueryVariables>(GetNativeSqlDocument, options);\n        }\nexport type GetNativeSqlQueryHookResult = ReturnType<typeof useGetNativeSqlQuery>;\nexport type GetNativeSqlLazyQueryHookResult = ReturnType<typeof useGetNativeSqlLazyQuery>;\nexport type GetNativeSqlQueryResult = Apollo.QueryResult<GetNativeSqlQuery, GetNativeSqlQueryVariables>;\nexport const CreateInstantRecommendedQuestionsDocument = gql`\n    mutation CreateInstantRecommendedQuestions($data: InstantRecommendedQuestionsInput!) {\n  createInstantRecommendedQuestions(data: $data) {\n    id\n  }\n}\n    `;\nexport type CreateInstantRecommendedQuestionsMutationFn = Apollo.MutationFunction<CreateInstantRecommendedQuestionsMutation, CreateInstantRecommendedQuestionsMutationVariables>;\n\n/**\n * __useCreateInstantRecommendedQuestionsMutation__\n *\n * To run a mutation, you first call `useCreateInstantRecommendedQuestionsMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateInstantRecommendedQuestionsMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createInstantRecommendedQuestionsMutation, { data, loading, error }] = useCreateInstantRecommendedQuestionsMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useCreateInstantRecommendedQuestionsMutation(baseOptions?: Apollo.MutationHookOptions<CreateInstantRecommendedQuestionsMutation, CreateInstantRecommendedQuestionsMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<CreateInstantRecommendedQuestionsMutation, CreateInstantRecommendedQuestionsMutationVariables>(CreateInstantRecommendedQuestionsDocument, options);\n      }\nexport type CreateInstantRecommendedQuestionsMutationHookResult = ReturnType<typeof useCreateInstantRecommendedQuestionsMutation>;\nexport type CreateInstantRecommendedQuestionsMutationResult = Apollo.MutationResult<CreateInstantRecommendedQuestionsMutation>;\nexport type CreateInstantRecommendedQuestionsMutationOptions = Apollo.BaseMutationOptions<CreateInstantRecommendedQuestionsMutation, CreateInstantRecommendedQuestionsMutationVariables>;\nexport const InstantRecommendedQuestionsDocument = gql`\n    query InstantRecommendedQuestions($taskId: String!) {\n  instantRecommendedQuestions(taskId: $taskId) {\n    ...CommonRecommendedQuestionsTask\n  }\n}\n    ${CommonRecommendedQuestionsTaskFragmentDoc}`;\n\n/**\n * __useInstantRecommendedQuestionsQuery__\n *\n * To run a query within a React component, call `useInstantRecommendedQuestionsQuery` and pass it any options that fit your needs.\n * When your component renders, `useInstantRecommendedQuestionsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useInstantRecommendedQuestionsQuery({\n *   variables: {\n *      taskId: // value for 'taskId'\n *   },\n * });\n */\nexport function useInstantRecommendedQuestionsQuery(baseOptions: Apollo.QueryHookOptions<InstantRecommendedQuestionsQuery, InstantRecommendedQuestionsQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<InstantRecommendedQuestionsQuery, InstantRecommendedQuestionsQueryVariables>(InstantRecommendedQuestionsDocument, options);\n      }\nexport function useInstantRecommendedQuestionsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<InstantRecommendedQuestionsQuery, InstantRecommendedQuestionsQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<InstantRecommendedQuestionsQuery, InstantRecommendedQuestionsQueryVariables>(InstantRecommendedQuestionsDocument, options);\n        }\nexport type InstantRecommendedQuestionsQueryHookResult = ReturnType<typeof useInstantRecommendedQuestionsQuery>;\nexport type InstantRecommendedQuestionsLazyQueryHookResult = ReturnType<typeof useInstantRecommendedQuestionsLazyQuery>;\nexport type InstantRecommendedQuestionsQueryResult = Apollo.QueryResult<InstantRecommendedQuestionsQuery, InstantRecommendedQuestionsQueryVariables>;\nexport const GetThreadRecommendationQuestionsDocument = gql`\n    query GetThreadRecommendationQuestions($threadId: Int!) {\n  getThreadRecommendationQuestions(threadId: $threadId) {\n    ...CommonRecommendedQuestionsTask\n  }\n}\n    ${CommonRecommendedQuestionsTaskFragmentDoc}`;\n\n/**\n * __useGetThreadRecommendationQuestionsQuery__\n *\n * To run a query within a React component, call `useGetThreadRecommendationQuestionsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetThreadRecommendationQuestionsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetThreadRecommendationQuestionsQuery({\n *   variables: {\n *      threadId: // value for 'threadId'\n *   },\n * });\n */\nexport function useGetThreadRecommendationQuestionsQuery(baseOptions: Apollo.QueryHookOptions<GetThreadRecommendationQuestionsQuery, GetThreadRecommendationQuestionsQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<GetThreadRecommendationQuestionsQuery, GetThreadRecommendationQuestionsQueryVariables>(GetThreadRecommendationQuestionsDocument, options);\n      }\nexport function useGetThreadRecommendationQuestionsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetThreadRecommendationQuestionsQuery, GetThreadRecommendationQuestionsQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<GetThreadRecommendationQuestionsQuery, GetThreadRecommendationQuestionsQueryVariables>(GetThreadRecommendationQuestionsDocument, options);\n        }\nexport type GetThreadRecommendationQuestionsQueryHookResult = ReturnType<typeof useGetThreadRecommendationQuestionsQuery>;\nexport type GetThreadRecommendationQuestionsLazyQueryHookResult = ReturnType<typeof useGetThreadRecommendationQuestionsLazyQuery>;\nexport type GetThreadRecommendationQuestionsQueryResult = Apollo.QueryResult<GetThreadRecommendationQuestionsQuery, GetThreadRecommendationQuestionsQueryVariables>;\nexport const GetProjectRecommendationQuestionsDocument = gql`\n    query GetProjectRecommendationQuestions {\n  getProjectRecommendationQuestions {\n    ...CommonRecommendedQuestionsTask\n  }\n}\n    ${CommonRecommendedQuestionsTaskFragmentDoc}`;\n\n/**\n * __useGetProjectRecommendationQuestionsQuery__\n *\n * To run a query within a React component, call `useGetProjectRecommendationQuestionsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetProjectRecommendationQuestionsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetProjectRecommendationQuestionsQuery({\n *   variables: {\n *   },\n * });\n */\nexport function useGetProjectRecommendationQuestionsQuery(baseOptions?: Apollo.QueryHookOptions<GetProjectRecommendationQuestionsQuery, GetProjectRecommendationQuestionsQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<GetProjectRecommendationQuestionsQuery, GetProjectRecommendationQuestionsQueryVariables>(GetProjectRecommendationQuestionsDocument, options);\n      }\nexport function useGetProjectRecommendationQuestionsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetProjectRecommendationQuestionsQuery, GetProjectRecommendationQuestionsQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<GetProjectRecommendationQuestionsQuery, GetProjectRecommendationQuestionsQueryVariables>(GetProjectRecommendationQuestionsDocument, options);\n        }\nexport type GetProjectRecommendationQuestionsQueryHookResult = ReturnType<typeof useGetProjectRecommendationQuestionsQuery>;\nexport type GetProjectRecommendationQuestionsLazyQueryHookResult = ReturnType<typeof useGetProjectRecommendationQuestionsLazyQuery>;\nexport type GetProjectRecommendationQuestionsQueryResult = Apollo.QueryResult<GetProjectRecommendationQuestionsQuery, GetProjectRecommendationQuestionsQueryVariables>;\nexport const GenerateProjectRecommendationQuestionsDocument = gql`\n    mutation GenerateProjectRecommendationQuestions {\n  generateProjectRecommendationQuestions\n}\n    `;\nexport type GenerateProjectRecommendationQuestionsMutationFn = Apollo.MutationFunction<GenerateProjectRecommendationQuestionsMutation, GenerateProjectRecommendationQuestionsMutationVariables>;\n\n/**\n * __useGenerateProjectRecommendationQuestionsMutation__\n *\n * To run a mutation, you first call `useGenerateProjectRecommendationQuestionsMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useGenerateProjectRecommendationQuestionsMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [generateProjectRecommendationQuestionsMutation, { data, loading, error }] = useGenerateProjectRecommendationQuestionsMutation({\n *   variables: {\n *   },\n * });\n */\nexport function useGenerateProjectRecommendationQuestionsMutation(baseOptions?: Apollo.MutationHookOptions<GenerateProjectRecommendationQuestionsMutation, GenerateProjectRecommendationQuestionsMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<GenerateProjectRecommendationQuestionsMutation, GenerateProjectRecommendationQuestionsMutationVariables>(GenerateProjectRecommendationQuestionsDocument, options);\n      }\nexport type GenerateProjectRecommendationQuestionsMutationHookResult = ReturnType<typeof useGenerateProjectRecommendationQuestionsMutation>;\nexport type GenerateProjectRecommendationQuestionsMutationResult = Apollo.MutationResult<GenerateProjectRecommendationQuestionsMutation>;\nexport type GenerateProjectRecommendationQuestionsMutationOptions = Apollo.BaseMutationOptions<GenerateProjectRecommendationQuestionsMutation, GenerateProjectRecommendationQuestionsMutationVariables>;\nexport const GenerateThreadRecommendationQuestionsDocument = gql`\n    mutation GenerateThreadRecommendationQuestions($threadId: Int!) {\n  generateThreadRecommendationQuestions(threadId: $threadId)\n}\n    `;\nexport type GenerateThreadRecommendationQuestionsMutationFn = Apollo.MutationFunction<GenerateThreadRecommendationQuestionsMutation, GenerateThreadRecommendationQuestionsMutationVariables>;\n\n/**\n * __useGenerateThreadRecommendationQuestionsMutation__\n *\n * To run a mutation, you first call `useGenerateThreadRecommendationQuestionsMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useGenerateThreadRecommendationQuestionsMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [generateThreadRecommendationQuestionsMutation, { data, loading, error }] = useGenerateThreadRecommendationQuestionsMutation({\n *   variables: {\n *      threadId: // value for 'threadId'\n *   },\n * });\n */\nexport function useGenerateThreadRecommendationQuestionsMutation(baseOptions?: Apollo.MutationHookOptions<GenerateThreadRecommendationQuestionsMutation, GenerateThreadRecommendationQuestionsMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<GenerateThreadRecommendationQuestionsMutation, GenerateThreadRecommendationQuestionsMutationVariables>(GenerateThreadRecommendationQuestionsDocument, options);\n      }\nexport type GenerateThreadRecommendationQuestionsMutationHookResult = ReturnType<typeof useGenerateThreadRecommendationQuestionsMutation>;\nexport type GenerateThreadRecommendationQuestionsMutationResult = Apollo.MutationResult<GenerateThreadRecommendationQuestionsMutation>;\nexport type GenerateThreadRecommendationQuestionsMutationOptions = Apollo.BaseMutationOptions<GenerateThreadRecommendationQuestionsMutation, GenerateThreadRecommendationQuestionsMutationVariables>;\nexport const GenerateThreadResponseAnswerDocument = gql`\n    mutation GenerateThreadResponseAnswer($responseId: Int!) {\n  generateThreadResponseAnswer(responseId: $responseId) {\n    ...CommonResponse\n  }\n}\n    ${CommonResponseFragmentDoc}`;\nexport type GenerateThreadResponseAnswerMutationFn = Apollo.MutationFunction<GenerateThreadResponseAnswerMutation, GenerateThreadResponseAnswerMutationVariables>;\n\n/**\n * __useGenerateThreadResponseAnswerMutation__\n *\n * To run a mutation, you first call `useGenerateThreadResponseAnswerMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useGenerateThreadResponseAnswerMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [generateThreadResponseAnswerMutation, { data, loading, error }] = useGenerateThreadResponseAnswerMutation({\n *   variables: {\n *      responseId: // value for 'responseId'\n *   },\n * });\n */\nexport function useGenerateThreadResponseAnswerMutation(baseOptions?: Apollo.MutationHookOptions<GenerateThreadResponseAnswerMutation, GenerateThreadResponseAnswerMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<GenerateThreadResponseAnswerMutation, GenerateThreadResponseAnswerMutationVariables>(GenerateThreadResponseAnswerDocument, options);\n      }\nexport type GenerateThreadResponseAnswerMutationHookResult = ReturnType<typeof useGenerateThreadResponseAnswerMutation>;\nexport type GenerateThreadResponseAnswerMutationResult = Apollo.MutationResult<GenerateThreadResponseAnswerMutation>;\nexport type GenerateThreadResponseAnswerMutationOptions = Apollo.BaseMutationOptions<GenerateThreadResponseAnswerMutation, GenerateThreadResponseAnswerMutationVariables>;\nexport const GenerateThreadResponseChartDocument = gql`\n    mutation GenerateThreadResponseChart($responseId: Int!) {\n  generateThreadResponseChart(responseId: $responseId) {\n    ...CommonResponse\n  }\n}\n    ${CommonResponseFragmentDoc}`;\nexport type GenerateThreadResponseChartMutationFn = Apollo.MutationFunction<GenerateThreadResponseChartMutation, GenerateThreadResponseChartMutationVariables>;\n\n/**\n * __useGenerateThreadResponseChartMutation__\n *\n * To run a mutation, you first call `useGenerateThreadResponseChartMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useGenerateThreadResponseChartMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [generateThreadResponseChartMutation, { data, loading, error }] = useGenerateThreadResponseChartMutation({\n *   variables: {\n *      responseId: // value for 'responseId'\n *   },\n * });\n */\nexport function useGenerateThreadResponseChartMutation(baseOptions?: Apollo.MutationHookOptions<GenerateThreadResponseChartMutation, GenerateThreadResponseChartMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<GenerateThreadResponseChartMutation, GenerateThreadResponseChartMutationVariables>(GenerateThreadResponseChartDocument, options);\n      }\nexport type GenerateThreadResponseChartMutationHookResult = ReturnType<typeof useGenerateThreadResponseChartMutation>;\nexport type GenerateThreadResponseChartMutationResult = Apollo.MutationResult<GenerateThreadResponseChartMutation>;\nexport type GenerateThreadResponseChartMutationOptions = Apollo.BaseMutationOptions<GenerateThreadResponseChartMutation, GenerateThreadResponseChartMutationVariables>;\nexport const AdjustThreadResponseChartDocument = gql`\n    mutation AdjustThreadResponseChart($responseId: Int!, $data: AdjustThreadResponseChartInput!) {\n  adjustThreadResponseChart(responseId: $responseId, data: $data) {\n    ...CommonResponse\n  }\n}\n    ${CommonResponseFragmentDoc}`;\nexport type AdjustThreadResponseChartMutationFn = Apollo.MutationFunction<AdjustThreadResponseChartMutation, AdjustThreadResponseChartMutationVariables>;\n\n/**\n * __useAdjustThreadResponseChartMutation__\n *\n * To run a mutation, you first call `useAdjustThreadResponseChartMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useAdjustThreadResponseChartMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [adjustThreadResponseChartMutation, { data, loading, error }] = useAdjustThreadResponseChartMutation({\n *   variables: {\n *      responseId: // value for 'responseId'\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useAdjustThreadResponseChartMutation(baseOptions?: Apollo.MutationHookOptions<AdjustThreadResponseChartMutation, AdjustThreadResponseChartMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<AdjustThreadResponseChartMutation, AdjustThreadResponseChartMutationVariables>(AdjustThreadResponseChartDocument, options);\n      }\nexport type AdjustThreadResponseChartMutationHookResult = ReturnType<typeof useAdjustThreadResponseChartMutation>;\nexport type AdjustThreadResponseChartMutationResult = Apollo.MutationResult<AdjustThreadResponseChartMutation>;\nexport type AdjustThreadResponseChartMutationOptions = Apollo.BaseMutationOptions<AdjustThreadResponseChartMutation, AdjustThreadResponseChartMutationVariables>;\nexport const AdjustmentTaskDocument = gql`\n    query AdjustmentTask($taskId: String!) {\n  adjustmentTask(taskId: $taskId) {\n    queryId\n    status\n    error {\n      code\n      shortMessage\n      message\n      stacktrace\n    }\n    sql\n    traceId\n    invalidSql\n  }\n}\n    `;\n\n/**\n * __useAdjustmentTaskQuery__\n *\n * To run a query within a React component, call `useAdjustmentTaskQuery` and pass it any options that fit your needs.\n * When your component renders, `useAdjustmentTaskQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useAdjustmentTaskQuery({\n *   variables: {\n *      taskId: // value for 'taskId'\n *   },\n * });\n */\nexport function useAdjustmentTaskQuery(baseOptions: Apollo.QueryHookOptions<AdjustmentTaskQuery, AdjustmentTaskQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<AdjustmentTaskQuery, AdjustmentTaskQueryVariables>(AdjustmentTaskDocument, options);\n      }\nexport function useAdjustmentTaskLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<AdjustmentTaskQuery, AdjustmentTaskQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<AdjustmentTaskQuery, AdjustmentTaskQueryVariables>(AdjustmentTaskDocument, options);\n        }\nexport type AdjustmentTaskQueryHookResult = ReturnType<typeof useAdjustmentTaskQuery>;\nexport type AdjustmentTaskLazyQueryHookResult = ReturnType<typeof useAdjustmentTaskLazyQuery>;\nexport type AdjustmentTaskQueryResult = Apollo.QueryResult<AdjustmentTaskQuery, AdjustmentTaskQueryVariables>;\nexport const CancelAdjustmentTaskDocument = gql`\n    mutation CancelAdjustmentTask($taskId: String!) {\n  cancelAdjustmentTask(taskId: $taskId)\n}\n    `;\nexport type CancelAdjustmentTaskMutationFn = Apollo.MutationFunction<CancelAdjustmentTaskMutation, CancelAdjustmentTaskMutationVariables>;\n\n/**\n * __useCancelAdjustmentTaskMutation__\n *\n * To run a mutation, you first call `useCancelAdjustmentTaskMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCancelAdjustmentTaskMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [cancelAdjustmentTaskMutation, { data, loading, error }] = useCancelAdjustmentTaskMutation({\n *   variables: {\n *      taskId: // value for 'taskId'\n *   },\n * });\n */\nexport function useCancelAdjustmentTaskMutation(baseOptions?: Apollo.MutationHookOptions<CancelAdjustmentTaskMutation, CancelAdjustmentTaskMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<CancelAdjustmentTaskMutation, CancelAdjustmentTaskMutationVariables>(CancelAdjustmentTaskDocument, options);\n      }\nexport type CancelAdjustmentTaskMutationHookResult = ReturnType<typeof useCancelAdjustmentTaskMutation>;\nexport type CancelAdjustmentTaskMutationResult = Apollo.MutationResult<CancelAdjustmentTaskMutation>;\nexport type CancelAdjustmentTaskMutationOptions = Apollo.BaseMutationOptions<CancelAdjustmentTaskMutation, CancelAdjustmentTaskMutationVariables>;\nexport const RerunAdjustmentTaskDocument = gql`\n    mutation RerunAdjustmentTask($responseId: Int!) {\n  rerunAdjustmentTask(responseId: $responseId)\n}\n    `;\nexport type RerunAdjustmentTaskMutationFn = Apollo.MutationFunction<RerunAdjustmentTaskMutation, RerunAdjustmentTaskMutationVariables>;\n\n/**\n * __useRerunAdjustmentTaskMutation__\n *\n * To run a mutation, you first call `useRerunAdjustmentTaskMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useRerunAdjustmentTaskMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [rerunAdjustmentTaskMutation, { data, loading, error }] = useRerunAdjustmentTaskMutation({\n *   variables: {\n *      responseId: // value for 'responseId'\n *   },\n * });\n */\nexport function useRerunAdjustmentTaskMutation(baseOptions?: Apollo.MutationHookOptions<RerunAdjustmentTaskMutation, RerunAdjustmentTaskMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<RerunAdjustmentTaskMutation, RerunAdjustmentTaskMutationVariables>(RerunAdjustmentTaskDocument, options);\n      }\nexport type RerunAdjustmentTaskMutationHookResult = ReturnType<typeof useRerunAdjustmentTaskMutation>;\nexport type RerunAdjustmentTaskMutationResult = Apollo.MutationResult<RerunAdjustmentTaskMutation>;\nexport type RerunAdjustmentTaskMutationOptions = Apollo.BaseMutationOptions<RerunAdjustmentTaskMutation, RerunAdjustmentTaskMutationVariables>;"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/home.ts",
    "content": "import { gql } from '@apollo/client';\n\nconst COMMON_ERROR = gql`\n  fragment CommonError on Error {\n    code\n    shortMessage\n    message\n    stacktrace\n  }\n`;\n\nconst COMMON_BREAKDOWN_DETAIL = gql`\n  fragment CommonBreakdownDetail on ThreadResponseBreakdownDetail {\n    queryId\n    status\n    description\n    steps {\n      summary\n      sql\n      cteName\n    }\n    error {\n      ...CommonError\n    }\n  }\n\n  ${COMMON_ERROR}\n`;\n\nconst COMMON_ANSWER_DETAIL = gql`\n  fragment CommonAnswerDetail on ThreadResponseAnswerDetail {\n    queryId\n    status\n    content\n    numRowsUsedInLLM\n    error {\n      ...CommonError\n    }\n  }\n\n  ${COMMON_ERROR}\n`;\n\nconst COMMON_CHART_DETAIL = gql`\n  fragment CommonChartDetail on ThreadResponseChartDetail {\n    queryId\n    status\n    description\n    chartType\n    chartSchema\n    error {\n      ...CommonError\n    }\n    adjustment\n  }\n`;\n\nconst COMMON_ASKING_TASK = gql`\n  fragment CommonAskingTask on AskingTask {\n    status\n    type\n    candidates {\n      sql\n      type\n      view {\n        id\n        name\n        statement\n        displayName\n      }\n      sqlPair {\n        id\n        question\n        sql\n        projectId\n      }\n    }\n    error {\n      ...CommonError\n    }\n    rephrasedQuestion\n    intentReasoning\n    sqlGenerationReasoning\n    retrievedTables\n    invalidSql\n    traceId\n    queryId\n  }\n  ${COMMON_ERROR}\n`;\n\nconst COMMON_RESPONSE = gql`\n  fragment CommonResponse on ThreadResponse {\n    id\n    threadId\n    question\n    sql\n    view {\n      id\n      name\n      statement\n      displayName\n    }\n    breakdownDetail {\n      ...CommonBreakdownDetail\n    }\n    answerDetail {\n      ...CommonAnswerDetail\n    }\n    chartDetail {\n      ...CommonChartDetail\n    }\n    askingTask {\n      ...CommonAskingTask\n    }\n    adjustment {\n      type\n      payload\n    }\n    adjustmentTask {\n      queryId\n      status\n      error {\n        ...CommonError\n      }\n      sql\n      traceId\n      invalidSql\n    }\n  }\n\n  ${COMMON_BREAKDOWN_DETAIL}\n  ${COMMON_ANSWER_DETAIL}\n  ${COMMON_CHART_DETAIL}\n  ${COMMON_ASKING_TASK}\n  ${COMMON_ERROR}\n`;\n\nconst COMMON_RECOMMENDED_QUESTIONS_TASK = gql`\n  fragment CommonRecommendedQuestionsTask on RecommendedQuestionsTask {\n    status\n    questions {\n      question\n      category\n      sql\n    }\n    error {\n      ...CommonError\n    }\n  }\n\n  ${COMMON_ERROR}\n`;\n\nexport const SUGGESTED_QUESTIONS = gql`\n  query SuggestedQuestions {\n    suggestedQuestions {\n      questions {\n        label\n        question\n      }\n    }\n  }\n`;\n\nexport const ASKING_TASK = gql`\n  query AskingTask($taskId: String!) {\n    askingTask(taskId: $taskId) {\n      ...CommonAskingTask\n    }\n  }\n  ${COMMON_ASKING_TASK}\n`;\n\nexport const THREADS = gql`\n  query Threads {\n    threads {\n      id\n      summary\n    }\n  }\n`;\n\nexport const THREAD = gql`\n  query Thread($threadId: Int!) {\n    thread(threadId: $threadId) {\n      id\n      responses {\n        ...CommonResponse\n      }\n    }\n  }\n  ${COMMON_RESPONSE}\n`;\n\nexport const THREAD_RESPONSE = gql`\n  query ThreadResponse($responseId: Int!) {\n    threadResponse(responseId: $responseId) {\n      ...CommonResponse\n    }\n  }\n  ${COMMON_RESPONSE}\n`;\n\nexport const CREATE_ASKING_TASK = gql`\n  mutation CreateAskingTask($data: AskingTaskInput!) {\n    createAskingTask(data: $data) {\n      id\n    }\n  }\n`;\n\nexport const CANCEL_ASKING_TASK = gql`\n  mutation CancelAskingTask($taskId: String!) {\n    cancelAskingTask(taskId: $taskId)\n  }\n`;\n\nexport const RERUN_ASKING_TASK = gql`\n  mutation RerunAskingTask($responseId: Int!) {\n    rerunAskingTask(responseId: $responseId) {\n      id\n    }\n  }\n`;\n\nexport const CREATE_THREAD = gql`\n  mutation CreateThread($data: CreateThreadInput!) {\n    createThread(data: $data) {\n      id\n    }\n  }\n`;\n\nexport const CREATE_THREAD_RESPONSE = gql`\n  mutation CreateThreadResponse(\n    $threadId: Int!\n    $data: CreateThreadResponseInput!\n  ) {\n    createThreadResponse(threadId: $threadId, data: $data) {\n      ...CommonResponse\n    }\n  }\n  ${COMMON_RESPONSE}\n`;\n\nexport const UPDATE_THREAD = gql`\n  mutation UpdateThread(\n    $where: ThreadUniqueWhereInput!\n    $data: UpdateThreadInput!\n  ) {\n    updateThread(where: $where, data: $data) {\n      id\n      summary\n    }\n  }\n`;\n\nexport const UPDATE_THREAD_RESPONSE = gql`\n  mutation UpdateThreadResponse(\n    $where: ThreadResponseUniqueWhereInput!\n    $data: UpdateThreadResponseInput!\n  ) {\n    updateThreadResponse(where: $where, data: $data) {\n      ...CommonResponse\n    }\n  }\n  ${COMMON_RESPONSE}\n`;\n\n// For adjust reasoning steps or SQL\nexport const ADJUST_THREAD_RESPONSE = gql`\n  mutation AdjustThreadResponse(\n    $responseId: Int!\n    $data: AdjustThreadResponseInput!\n  ) {\n    adjustThreadResponse(responseId: $responseId, data: $data) {\n      ...CommonResponse\n    }\n  }\n  ${COMMON_RESPONSE}\n`;\n\nexport const DELETE_THREAD = gql`\n  mutation DeleteThread($where: ThreadUniqueWhereInput!) {\n    deleteThread(where: $where)\n  }\n`;\n\n// For text-based answer & chart-based answer\nexport const PREVIEW_DATA = gql`\n  mutation PreviewData($where: PreviewDataInput!) {\n    previewData(where: $where)\n  }\n`;\n\nexport const PREVIEW_BREAKDOWN_DATA = gql`\n  mutation PreviewBreakdownData($where: PreviewDataInput!) {\n    previewBreakdownData(where: $where)\n  }\n`;\n\nexport const GET_NATIVE_SQL = gql`\n  query GetNativeSQL($responseId: Int!) {\n    nativeSql(responseId: $responseId)\n  }\n`;\n\nexport const CREATE_INSTANT_RECOMMENDED_QUESTIONS = gql`\n  mutation CreateInstantRecommendedQuestions(\n    $data: InstantRecommendedQuestionsInput!\n  ) {\n    createInstantRecommendedQuestions(data: $data) {\n      id\n    }\n  }\n`;\n\nexport const INSTANT_RECOMMENDED_QUESTIONS = gql`\n  query InstantRecommendedQuestions($taskId: String!) {\n    instantRecommendedQuestions(taskId: $taskId) {\n      ...CommonRecommendedQuestionsTask\n    }\n  }\n  ${COMMON_RECOMMENDED_QUESTIONS_TASK}\n`;\n\nexport const GET_THREAD_RECOMMENDATION_QUESTIONS = gql`\n  query GetThreadRecommendationQuestions($threadId: Int!) {\n    getThreadRecommendationQuestions(threadId: $threadId) {\n      ...CommonRecommendedQuestionsTask\n    }\n  }\n\n  ${COMMON_RECOMMENDED_QUESTIONS_TASK}\n`;\n\nexport const GET_PROJECT_RECOMMENDATION_QUESTIONS = gql`\n  query GetProjectRecommendationQuestions {\n    getProjectRecommendationQuestions {\n      ...CommonRecommendedQuestionsTask\n    }\n  }\n\n  ${COMMON_RECOMMENDED_QUESTIONS_TASK}\n`;\n\nexport const GENERATE_PROJECT_RECOMMENDATION_QUESTIONS = gql`\n  mutation GenerateProjectRecommendationQuestions {\n    generateProjectRecommendationQuestions\n  }\n`;\n\nexport const GENERATE_THREAD_RECOMMENDATION_QUESTIONS = gql`\n  mutation GenerateThreadRecommendationQuestions($threadId: Int!) {\n    generateThreadRecommendationQuestions(threadId: $threadId)\n  }\n`;\n\nexport const GENERATE_THREAD_RESPONSE_ANSWER = gql`\n  mutation GenerateThreadResponseAnswer($responseId: Int!) {\n    generateThreadResponseAnswer(responseId: $responseId) {\n      ...CommonResponse\n    }\n  }\n\n  ${COMMON_RESPONSE}\n`;\n\nexport const GENERATE_THREAD_RESPONSE_CHART = gql`\n  mutation GenerateThreadResponseChart($responseId: Int!) {\n    generateThreadResponseChart(responseId: $responseId) {\n      ...CommonResponse\n    }\n  }\n  ${COMMON_RESPONSE}\n`;\n\nexport const ADJUST_THREAD_RESPONSE_CHART = gql`\n  mutation AdjustThreadResponseChart(\n    $responseId: Int!\n    $data: AdjustThreadResponseChartInput!\n  ) {\n    adjustThreadResponseChart(responseId: $responseId, data: $data) {\n      ...CommonResponse\n    }\n  }\n  ${COMMON_RESPONSE}\n`;\n\nexport const ADJUSTMENT_TASK = gql`\n  query AdjustmentTask($taskId: String!) {\n    adjustmentTask(taskId: $taskId) {\n      queryId\n      status\n      error {\n        code\n        shortMessage\n        message\n        stacktrace\n      }\n      sql\n      traceId\n      invalidSql\n    }\n  }\n`;\n\nexport const CANCEL_ADJUSTMENT_TASK = gql`\n  mutation CancelAdjustmentTask($taskId: String!) {\n    cancelAdjustmentTask(taskId: $taskId)\n  }\n`;\n\nexport const RERUN_ADJUSTMENT_TASK = gql`\n  mutation RerunAdjustmentTask($responseId: Int!) {\n    rerunAdjustmentTask(responseId: $responseId)\n  }\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/instructions.generated.ts",
    "content": "import * as Types from './__types__';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nconst defaultOptions = {} as const;\nexport type InstructionFragment = { __typename?: 'Instruction', id: number, projectId: number, instruction: string, questions: Array<string>, isDefault: boolean, createdAt: string, updatedAt: string };\n\nexport type InstructionsQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type InstructionsQuery = { __typename?: 'Query', instructions: Array<{ __typename?: 'Instruction', id: number, projectId: number, instruction: string, questions: Array<string>, isDefault: boolean, createdAt: string, updatedAt: string } | null> };\n\nexport type CreateInstructionMutationVariables = Types.Exact<{\n  data: Types.CreateInstructionInput;\n}>;\n\n\nexport type CreateInstructionMutation = { __typename?: 'Mutation', createInstruction: { __typename?: 'Instruction', id: number, projectId: number, instruction: string, questions: Array<string>, isDefault: boolean, createdAt: string, updatedAt: string } };\n\nexport type UpdateInstructionMutationVariables = Types.Exact<{\n  where: Types.InstructionWhereInput;\n  data: Types.UpdateInstructionInput;\n}>;\n\n\nexport type UpdateInstructionMutation = { __typename?: 'Mutation', updateInstruction: { __typename?: 'Instruction', id: number, projectId: number, instruction: string, questions: Array<string>, isDefault: boolean, createdAt: string, updatedAt: string } };\n\nexport type DeleteInstructionMutationVariables = Types.Exact<{\n  where: Types.InstructionWhereInput;\n}>;\n\n\nexport type DeleteInstructionMutation = { __typename?: 'Mutation', deleteInstruction: boolean };\n\nexport const InstructionFragmentDoc = gql`\n    fragment Instruction on Instruction {\n  id\n  projectId\n  instruction\n  questions\n  isDefault\n  createdAt\n  updatedAt\n}\n    `;\nexport const InstructionsDocument = gql`\n    query Instructions {\n  instructions {\n    ...Instruction\n  }\n}\n    ${InstructionFragmentDoc}`;\n\n/**\n * __useInstructionsQuery__\n *\n * To run a query within a React component, call `useInstructionsQuery` and pass it any options that fit your needs.\n * When your component renders, `useInstructionsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useInstructionsQuery({\n *   variables: {\n *   },\n * });\n */\nexport function useInstructionsQuery(baseOptions?: Apollo.QueryHookOptions<InstructionsQuery, InstructionsQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<InstructionsQuery, InstructionsQueryVariables>(InstructionsDocument, options);\n      }\nexport function useInstructionsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<InstructionsQuery, InstructionsQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<InstructionsQuery, InstructionsQueryVariables>(InstructionsDocument, options);\n        }\nexport type InstructionsQueryHookResult = ReturnType<typeof useInstructionsQuery>;\nexport type InstructionsLazyQueryHookResult = ReturnType<typeof useInstructionsLazyQuery>;\nexport type InstructionsQueryResult = Apollo.QueryResult<InstructionsQuery, InstructionsQueryVariables>;\nexport const CreateInstructionDocument = gql`\n    mutation CreateInstruction($data: CreateInstructionInput!) {\n  createInstruction(data: $data) {\n    ...Instruction\n  }\n}\n    ${InstructionFragmentDoc}`;\nexport type CreateInstructionMutationFn = Apollo.MutationFunction<CreateInstructionMutation, CreateInstructionMutationVariables>;\n\n/**\n * __useCreateInstructionMutation__\n *\n * To run a mutation, you first call `useCreateInstructionMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateInstructionMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createInstructionMutation, { data, loading, error }] = useCreateInstructionMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useCreateInstructionMutation(baseOptions?: Apollo.MutationHookOptions<CreateInstructionMutation, CreateInstructionMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<CreateInstructionMutation, CreateInstructionMutationVariables>(CreateInstructionDocument, options);\n      }\nexport type CreateInstructionMutationHookResult = ReturnType<typeof useCreateInstructionMutation>;\nexport type CreateInstructionMutationResult = Apollo.MutationResult<CreateInstructionMutation>;\nexport type CreateInstructionMutationOptions = Apollo.BaseMutationOptions<CreateInstructionMutation, CreateInstructionMutationVariables>;\nexport const UpdateInstructionDocument = gql`\n    mutation UpdateInstruction($where: InstructionWhereInput!, $data: UpdateInstructionInput!) {\n  updateInstruction(where: $where, data: $data) {\n    ...Instruction\n  }\n}\n    ${InstructionFragmentDoc}`;\nexport type UpdateInstructionMutationFn = Apollo.MutationFunction<UpdateInstructionMutation, UpdateInstructionMutationVariables>;\n\n/**\n * __useUpdateInstructionMutation__\n *\n * To run a mutation, you first call `useUpdateInstructionMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateInstructionMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateInstructionMutation, { data, loading, error }] = useUpdateInstructionMutation({\n *   variables: {\n *      where: // value for 'where'\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useUpdateInstructionMutation(baseOptions?: Apollo.MutationHookOptions<UpdateInstructionMutation, UpdateInstructionMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<UpdateInstructionMutation, UpdateInstructionMutationVariables>(UpdateInstructionDocument, options);\n      }\nexport type UpdateInstructionMutationHookResult = ReturnType<typeof useUpdateInstructionMutation>;\nexport type UpdateInstructionMutationResult = Apollo.MutationResult<UpdateInstructionMutation>;\nexport type UpdateInstructionMutationOptions = Apollo.BaseMutationOptions<UpdateInstructionMutation, UpdateInstructionMutationVariables>;\nexport const DeleteInstructionDocument = gql`\n    mutation DeleteInstruction($where: InstructionWhereInput!) {\n  deleteInstruction(where: $where)\n}\n    `;\nexport type DeleteInstructionMutationFn = Apollo.MutationFunction<DeleteInstructionMutation, DeleteInstructionMutationVariables>;\n\n/**\n * __useDeleteInstructionMutation__\n *\n * To run a mutation, you first call `useDeleteInstructionMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDeleteInstructionMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [deleteInstructionMutation, { data, loading, error }] = useDeleteInstructionMutation({\n *   variables: {\n *      where: // value for 'where'\n *   },\n * });\n */\nexport function useDeleteInstructionMutation(baseOptions?: Apollo.MutationHookOptions<DeleteInstructionMutation, DeleteInstructionMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<DeleteInstructionMutation, DeleteInstructionMutationVariables>(DeleteInstructionDocument, options);\n      }\nexport type DeleteInstructionMutationHookResult = ReturnType<typeof useDeleteInstructionMutation>;\nexport type DeleteInstructionMutationResult = Apollo.MutationResult<DeleteInstructionMutation>;\nexport type DeleteInstructionMutationOptions = Apollo.BaseMutationOptions<DeleteInstructionMutation, DeleteInstructionMutationVariables>;"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/instructions.ts",
    "content": "import { gql } from '@apollo/client';\n\nconst INSTRUCTION = gql`\n  fragment Instruction on Instruction {\n    id\n    projectId\n    instruction\n    questions\n    isDefault\n    createdAt\n    updatedAt\n  }\n`;\n\nexport const LIST_INSTRUCTIONS = gql`\n  query Instructions {\n    instructions {\n      ...Instruction\n    }\n  }\n\n  ${INSTRUCTION}\n`;\n\nexport const CREATE_INSTRUCTION = gql`\n  mutation CreateInstruction($data: CreateInstructionInput!) {\n    createInstruction(data: $data) {\n      ...Instruction\n    }\n  }\n\n  ${INSTRUCTION}\n`;\n\nexport const UPDATE_INSTRUCTION = gql`\n  mutation UpdateInstruction(\n    $where: InstructionWhereInput!\n    $data: UpdateInstructionInput!\n  ) {\n    updateInstruction(where: $where, data: $data) {\n      ...Instruction\n    }\n  }\n\n  ${INSTRUCTION}\n`;\n\nexport const DELETE_INSTRUCTION = gql`\n  mutation DeleteInstruction($where: InstructionWhereInput!) {\n    deleteInstruction(where: $where)\n  }\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/learning.generated.ts",
    "content": "import * as Types from './__types__';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nconst defaultOptions = {} as const;\nexport type LearningRecordQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type LearningRecordQuery = { __typename?: 'Query', learningRecord: { __typename?: 'LearningRecord', paths: Array<string> } };\n\nexport type SaveLearningRecordMutationVariables = Types.Exact<{\n  data: Types.SaveLearningRecordInput;\n}>;\n\n\nexport type SaveLearningRecordMutation = { __typename?: 'Mutation', saveLearningRecord: { __typename?: 'LearningRecord', paths: Array<string> } };\n\n\nexport const LearningRecordDocument = gql`\n    query LearningRecord {\n  learningRecord {\n    paths\n  }\n}\n    `;\n\n/**\n * __useLearningRecordQuery__\n *\n * To run a query within a React component, call `useLearningRecordQuery` and pass it any options that fit your needs.\n * When your component renders, `useLearningRecordQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useLearningRecordQuery({\n *   variables: {\n *   },\n * });\n */\nexport function useLearningRecordQuery(baseOptions?: Apollo.QueryHookOptions<LearningRecordQuery, LearningRecordQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<LearningRecordQuery, LearningRecordQueryVariables>(LearningRecordDocument, options);\n      }\nexport function useLearningRecordLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<LearningRecordQuery, LearningRecordQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<LearningRecordQuery, LearningRecordQueryVariables>(LearningRecordDocument, options);\n        }\nexport type LearningRecordQueryHookResult = ReturnType<typeof useLearningRecordQuery>;\nexport type LearningRecordLazyQueryHookResult = ReturnType<typeof useLearningRecordLazyQuery>;\nexport type LearningRecordQueryResult = Apollo.QueryResult<LearningRecordQuery, LearningRecordQueryVariables>;\nexport const SaveLearningRecordDocument = gql`\n    mutation SaveLearningRecord($data: SaveLearningRecordInput!) {\n  saveLearningRecord(data: $data) {\n    paths\n  }\n}\n    `;\nexport type SaveLearningRecordMutationFn = Apollo.MutationFunction<SaveLearningRecordMutation, SaveLearningRecordMutationVariables>;\n\n/**\n * __useSaveLearningRecordMutation__\n *\n * To run a mutation, you first call `useSaveLearningRecordMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useSaveLearningRecordMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [saveLearningRecordMutation, { data, loading, error }] = useSaveLearningRecordMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useSaveLearningRecordMutation(baseOptions?: Apollo.MutationHookOptions<SaveLearningRecordMutation, SaveLearningRecordMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<SaveLearningRecordMutation, SaveLearningRecordMutationVariables>(SaveLearningRecordDocument, options);\n      }\nexport type SaveLearningRecordMutationHookResult = ReturnType<typeof useSaveLearningRecordMutation>;\nexport type SaveLearningRecordMutationResult = Apollo.MutationResult<SaveLearningRecordMutation>;\nexport type SaveLearningRecordMutationOptions = Apollo.BaseMutationOptions<SaveLearningRecordMutation, SaveLearningRecordMutationVariables>;"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/learning.ts",
    "content": "import { gql } from '@apollo/client';\n\nexport const LEARNING_RECORD = gql`\n  query LearningRecord {\n    learningRecord {\n      paths\n    }\n  }\n`;\n\nexport const SAVE_LEARNING_RECORD = gql`\n  mutation SaveLearningRecord($data: SaveLearningRecordInput!) {\n    saveLearningRecord(data: $data) {\n      paths\n    }\n  }\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/metadata.generated.ts",
    "content": "import * as Types from './__types__';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nconst defaultOptions = {} as const;\nexport type UpdateModelMetadataMutationVariables = Types.Exact<{\n  where: Types.ModelWhereInput;\n  data: Types.UpdateModelMetadataInput;\n}>;\n\n\nexport type UpdateModelMetadataMutation = { __typename?: 'Mutation', updateModelMetadata: boolean };\n\nexport type UpdateViewMetadataMutationVariables = Types.Exact<{\n  where: Types.ViewWhereUniqueInput;\n  data: Types.UpdateViewMetadataInput;\n}>;\n\n\nexport type UpdateViewMetadataMutation = { __typename?: 'Mutation', updateViewMetadata: boolean };\n\n\nexport const UpdateModelMetadataDocument = gql`\n    mutation UpdateModelMetadata($where: ModelWhereInput!, $data: UpdateModelMetadataInput!) {\n  updateModelMetadata(where: $where, data: $data)\n}\n    `;\nexport type UpdateModelMetadataMutationFn = Apollo.MutationFunction<UpdateModelMetadataMutation, UpdateModelMetadataMutationVariables>;\n\n/**\n * __useUpdateModelMetadataMutation__\n *\n * To run a mutation, you first call `useUpdateModelMetadataMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateModelMetadataMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateModelMetadataMutation, { data, loading, error }] = useUpdateModelMetadataMutation({\n *   variables: {\n *      where: // value for 'where'\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useUpdateModelMetadataMutation(baseOptions?: Apollo.MutationHookOptions<UpdateModelMetadataMutation, UpdateModelMetadataMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<UpdateModelMetadataMutation, UpdateModelMetadataMutationVariables>(UpdateModelMetadataDocument, options);\n      }\nexport type UpdateModelMetadataMutationHookResult = ReturnType<typeof useUpdateModelMetadataMutation>;\nexport type UpdateModelMetadataMutationResult = Apollo.MutationResult<UpdateModelMetadataMutation>;\nexport type UpdateModelMetadataMutationOptions = Apollo.BaseMutationOptions<UpdateModelMetadataMutation, UpdateModelMetadataMutationVariables>;\nexport const UpdateViewMetadataDocument = gql`\n    mutation UpdateViewMetadata($where: ViewWhereUniqueInput!, $data: UpdateViewMetadataInput!) {\n  updateViewMetadata(where: $where, data: $data)\n}\n    `;\nexport type UpdateViewMetadataMutationFn = Apollo.MutationFunction<UpdateViewMetadataMutation, UpdateViewMetadataMutationVariables>;\n\n/**\n * __useUpdateViewMetadataMutation__\n *\n * To run a mutation, you first call `useUpdateViewMetadataMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateViewMetadataMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateViewMetadataMutation, { data, loading, error }] = useUpdateViewMetadataMutation({\n *   variables: {\n *      where: // value for 'where'\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useUpdateViewMetadataMutation(baseOptions?: Apollo.MutationHookOptions<UpdateViewMetadataMutation, UpdateViewMetadataMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<UpdateViewMetadataMutation, UpdateViewMetadataMutationVariables>(UpdateViewMetadataDocument, options);\n      }\nexport type UpdateViewMetadataMutationHookResult = ReturnType<typeof useUpdateViewMetadataMutation>;\nexport type UpdateViewMetadataMutationResult = Apollo.MutationResult<UpdateViewMetadataMutation>;\nexport type UpdateViewMetadataMutationOptions = Apollo.BaseMutationOptions<UpdateViewMetadataMutation, UpdateViewMetadataMutationVariables>;"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/metadata.ts",
    "content": "import { gql } from '@apollo/client';\n\nexport const UPDATE_MODEL_METADATA = gql`\n  mutation UpdateModelMetadata(\n    $where: ModelWhereInput!\n    $data: UpdateModelMetadataInput!\n  ) {\n    updateModelMetadata(where: $where, data: $data)\n  }\n`;\n\nexport const UPDATE_VIEW_METADATA = gql`\n  mutation UpdateViewMetadata(\n    $where: ViewWhereUniqueInput!\n    $data: UpdateViewMetadataInput!\n  ) {\n    updateViewMetadata(where: $where, data: $data)\n  }\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/model.generated.ts",
    "content": "import * as Types from './__types__';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nconst defaultOptions = {} as const;\nexport type CommonColumnFragment = { __typename?: 'DetailedColumn', displayName: string, referenceName: string, sourceColumnName: string, type?: string | null, isCalculated: boolean, notNull: boolean, properties: any };\n\nexport type CommonFieldFragment = { __typename?: 'FieldInfo', id: number, displayName: string, referenceName: string, sourceColumnName: string, type?: string | null, isCalculated: boolean, notNull: boolean, expression?: string | null, properties?: any | null };\n\nexport type CommonRelationFragment = { __typename?: 'DetailedRelation', fromModelId: number, fromColumnId: number, toModelId: number, toColumnId: number, type: Types.RelationType, name: string };\n\nexport type ListModelsQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type ListModelsQuery = { __typename?: 'Query', listModels: Array<{ __typename?: 'ModelInfo', id: number, displayName: string, referenceName: string, sourceTableName: string, refSql?: string | null, primaryKey?: string | null, cached: boolean, refreshTime?: string | null, description?: string | null, fields: Array<{ __typename?: 'FieldInfo', id: number, displayName: string, referenceName: string, sourceColumnName: string, type?: string | null, isCalculated: boolean, notNull: boolean, expression?: string | null, properties?: any | null } | null>, calculatedFields: Array<{ __typename?: 'FieldInfo', id: number, displayName: string, referenceName: string, sourceColumnName: string, type?: string | null, isCalculated: boolean, notNull: boolean, expression?: string | null, properties?: any | null } | null> }> };\n\nexport type GetModelQueryVariables = Types.Exact<{\n  where: Types.ModelWhereInput;\n}>;\n\n\nexport type GetModelQuery = { __typename?: 'Query', model: { __typename?: 'DetailedModel', displayName: string, referenceName: string, sourceTableName: string, refSql: string, primaryKey?: string | null, cached: boolean, refreshTime?: string | null, description?: string | null, properties: any, fields?: Array<{ __typename?: 'DetailedColumn', displayName: string, referenceName: string, sourceColumnName: string, type?: string | null, isCalculated: boolean, notNull: boolean, properties: any } | null> | null, calculatedFields?: Array<{ __typename?: 'DetailedColumn', displayName: string, referenceName: string, sourceColumnName: string, type?: string | null, isCalculated: boolean, notNull: boolean, properties: any } | null> | null, relations?: Array<{ __typename?: 'DetailedRelation', fromModelId: number, fromColumnId: number, toModelId: number, toColumnId: number, type: Types.RelationType, name: string } | null> | null } };\n\nexport type CreateModelMutationVariables = Types.Exact<{\n  data: Types.CreateModelInput;\n}>;\n\n\nexport type CreateModelMutation = { __typename?: 'Mutation', createModel: any };\n\nexport type UpdateModelMutationVariables = Types.Exact<{\n  where: Types.ModelWhereInput;\n  data: Types.UpdateModelInput;\n}>;\n\n\nexport type UpdateModelMutation = { __typename?: 'Mutation', updateModel: any };\n\nexport type DeleteModelMutationVariables = Types.Exact<{\n  where: Types.ModelWhereInput;\n}>;\n\n\nexport type DeleteModelMutation = { __typename?: 'Mutation', deleteModel: boolean };\n\nexport type PreviewModelDataMutationVariables = Types.Exact<{\n  where: Types.WhereIdInput;\n}>;\n\n\nexport type PreviewModelDataMutation = { __typename?: 'Mutation', previewModelData: any };\n\nexport const CommonColumnFragmentDoc = gql`\n    fragment CommonColumn on DetailedColumn {\n  displayName\n  referenceName\n  sourceColumnName\n  type\n  isCalculated\n  notNull\n  properties\n}\n    `;\nexport const CommonFieldFragmentDoc = gql`\n    fragment CommonField on FieldInfo {\n  id\n  displayName\n  referenceName\n  sourceColumnName\n  type\n  isCalculated\n  notNull\n  expression\n  properties\n}\n    `;\nexport const CommonRelationFragmentDoc = gql`\n    fragment CommonRelation on DetailedRelation {\n  fromModelId\n  fromColumnId\n  toModelId\n  toColumnId\n  type\n  name\n}\n    `;\nexport const ListModelsDocument = gql`\n    query ListModels {\n  listModels {\n    id\n    displayName\n    referenceName\n    sourceTableName\n    refSql\n    primaryKey\n    cached\n    refreshTime\n    description\n    fields {\n      ...CommonField\n    }\n    calculatedFields {\n      ...CommonField\n    }\n  }\n}\n    ${CommonFieldFragmentDoc}`;\n\n/**\n * __useListModelsQuery__\n *\n * To run a query within a React component, call `useListModelsQuery` and pass it any options that fit your needs.\n * When your component renders, `useListModelsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useListModelsQuery({\n *   variables: {\n *   },\n * });\n */\nexport function useListModelsQuery(baseOptions?: Apollo.QueryHookOptions<ListModelsQuery, ListModelsQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<ListModelsQuery, ListModelsQueryVariables>(ListModelsDocument, options);\n      }\nexport function useListModelsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ListModelsQuery, ListModelsQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<ListModelsQuery, ListModelsQueryVariables>(ListModelsDocument, options);\n        }\nexport type ListModelsQueryHookResult = ReturnType<typeof useListModelsQuery>;\nexport type ListModelsLazyQueryHookResult = ReturnType<typeof useListModelsLazyQuery>;\nexport type ListModelsQueryResult = Apollo.QueryResult<ListModelsQuery, ListModelsQueryVariables>;\nexport const GetModelDocument = gql`\n    query GetModel($where: ModelWhereInput!) {\n  model(where: $where) {\n    displayName\n    referenceName\n    sourceTableName\n    refSql\n    primaryKey\n    cached\n    refreshTime\n    description\n    fields {\n      ...CommonColumn\n    }\n    calculatedFields {\n      ...CommonColumn\n    }\n    relations {\n      ...CommonRelation\n    }\n    properties\n  }\n}\n    ${CommonColumnFragmentDoc}\n${CommonRelationFragmentDoc}`;\n\n/**\n * __useGetModelQuery__\n *\n * To run a query within a React component, call `useGetModelQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetModelQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetModelQuery({\n *   variables: {\n *      where: // value for 'where'\n *   },\n * });\n */\nexport function useGetModelQuery(baseOptions: Apollo.QueryHookOptions<GetModelQuery, GetModelQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<GetModelQuery, GetModelQueryVariables>(GetModelDocument, options);\n      }\nexport function useGetModelLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetModelQuery, GetModelQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<GetModelQuery, GetModelQueryVariables>(GetModelDocument, options);\n        }\nexport type GetModelQueryHookResult = ReturnType<typeof useGetModelQuery>;\nexport type GetModelLazyQueryHookResult = ReturnType<typeof useGetModelLazyQuery>;\nexport type GetModelQueryResult = Apollo.QueryResult<GetModelQuery, GetModelQueryVariables>;\nexport const CreateModelDocument = gql`\n    mutation CreateModel($data: CreateModelInput!) {\n  createModel(data: $data)\n}\n    `;\nexport type CreateModelMutationFn = Apollo.MutationFunction<CreateModelMutation, CreateModelMutationVariables>;\n\n/**\n * __useCreateModelMutation__\n *\n * To run a mutation, you first call `useCreateModelMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateModelMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createModelMutation, { data, loading, error }] = useCreateModelMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useCreateModelMutation(baseOptions?: Apollo.MutationHookOptions<CreateModelMutation, CreateModelMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<CreateModelMutation, CreateModelMutationVariables>(CreateModelDocument, options);\n      }\nexport type CreateModelMutationHookResult = ReturnType<typeof useCreateModelMutation>;\nexport type CreateModelMutationResult = Apollo.MutationResult<CreateModelMutation>;\nexport type CreateModelMutationOptions = Apollo.BaseMutationOptions<CreateModelMutation, CreateModelMutationVariables>;\nexport const UpdateModelDocument = gql`\n    mutation UpdateModel($where: ModelWhereInput!, $data: UpdateModelInput!) {\n  updateModel(where: $where, data: $data)\n}\n    `;\nexport type UpdateModelMutationFn = Apollo.MutationFunction<UpdateModelMutation, UpdateModelMutationVariables>;\n\n/**\n * __useUpdateModelMutation__\n *\n * To run a mutation, you first call `useUpdateModelMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateModelMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateModelMutation, { data, loading, error }] = useUpdateModelMutation({\n *   variables: {\n *      where: // value for 'where'\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useUpdateModelMutation(baseOptions?: Apollo.MutationHookOptions<UpdateModelMutation, UpdateModelMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<UpdateModelMutation, UpdateModelMutationVariables>(UpdateModelDocument, options);\n      }\nexport type UpdateModelMutationHookResult = ReturnType<typeof useUpdateModelMutation>;\nexport type UpdateModelMutationResult = Apollo.MutationResult<UpdateModelMutation>;\nexport type UpdateModelMutationOptions = Apollo.BaseMutationOptions<UpdateModelMutation, UpdateModelMutationVariables>;\nexport const DeleteModelDocument = gql`\n    mutation DeleteModel($where: ModelWhereInput!) {\n  deleteModel(where: $where)\n}\n    `;\nexport type DeleteModelMutationFn = Apollo.MutationFunction<DeleteModelMutation, DeleteModelMutationVariables>;\n\n/**\n * __useDeleteModelMutation__\n *\n * To run a mutation, you first call `useDeleteModelMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDeleteModelMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [deleteModelMutation, { data, loading, error }] = useDeleteModelMutation({\n *   variables: {\n *      where: // value for 'where'\n *   },\n * });\n */\nexport function useDeleteModelMutation(baseOptions?: Apollo.MutationHookOptions<DeleteModelMutation, DeleteModelMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<DeleteModelMutation, DeleteModelMutationVariables>(DeleteModelDocument, options);\n      }\nexport type DeleteModelMutationHookResult = ReturnType<typeof useDeleteModelMutation>;\nexport type DeleteModelMutationResult = Apollo.MutationResult<DeleteModelMutation>;\nexport type DeleteModelMutationOptions = Apollo.BaseMutationOptions<DeleteModelMutation, DeleteModelMutationVariables>;\nexport const PreviewModelDataDocument = gql`\n    mutation PreviewModelData($where: WhereIdInput!) {\n  previewModelData(where: $where)\n}\n    `;\nexport type PreviewModelDataMutationFn = Apollo.MutationFunction<PreviewModelDataMutation, PreviewModelDataMutationVariables>;\n\n/**\n * __usePreviewModelDataMutation__\n *\n * To run a mutation, you first call `usePreviewModelDataMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `usePreviewModelDataMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [previewModelDataMutation, { data, loading, error }] = usePreviewModelDataMutation({\n *   variables: {\n *      where: // value for 'where'\n *   },\n * });\n */\nexport function usePreviewModelDataMutation(baseOptions?: Apollo.MutationHookOptions<PreviewModelDataMutation, PreviewModelDataMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<PreviewModelDataMutation, PreviewModelDataMutationVariables>(PreviewModelDataDocument, options);\n      }\nexport type PreviewModelDataMutationHookResult = ReturnType<typeof usePreviewModelDataMutation>;\nexport type PreviewModelDataMutationResult = Apollo.MutationResult<PreviewModelDataMutation>;\nexport type PreviewModelDataMutationOptions = Apollo.BaseMutationOptions<PreviewModelDataMutation, PreviewModelDataMutationVariables>;"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/model.ts",
    "content": "import { gql } from '@apollo/client';\n\nconst COMMON_COLUMN = gql`\n  fragment CommonColumn on DetailedColumn {\n    displayName\n    referenceName\n    sourceColumnName\n    type\n    isCalculated\n    notNull\n    properties\n  }\n`;\n\nconst COMMON_FIELD = gql`\n  fragment CommonField on FieldInfo {\n    id\n    displayName\n    referenceName\n    sourceColumnName\n    type\n    isCalculated\n    notNull\n    expression\n    properties\n  }\n`;\n\nconst COMMON_RELATION = gql`\n  fragment CommonRelation on DetailedRelation {\n    fromModelId\n    fromColumnId\n    toModelId\n    toColumnId\n    type\n    name\n  }\n`;\n\nexport const LIST_MODELS = gql`\n  query ListModels {\n    listModels {\n      id\n      displayName\n      referenceName\n      sourceTableName\n      refSql\n      primaryKey\n      cached\n      refreshTime\n      description\n      fields {\n        ...CommonField\n      }\n      calculatedFields {\n        ...CommonField\n      }\n    }\n  }\n  ${COMMON_FIELD}\n`;\n\nexport const GET_MODEL = gql`\n  query GetModel($where: ModelWhereInput!) {\n    model(where: $where) {\n      displayName\n      referenceName\n      sourceTableName\n      refSql\n      primaryKey\n      cached\n      refreshTime\n      description\n      fields {\n        ...CommonColumn\n      }\n      calculatedFields {\n        ...CommonColumn\n      }\n      relations {\n        ...CommonRelation\n      }\n      properties\n    }\n  }\n  ${COMMON_COLUMN}\n  ${COMMON_RELATION}\n`;\n\nexport const CREATE_MODEL = gql`\n  mutation CreateModel($data: CreateModelInput!) {\n    createModel(data: $data)\n  }\n`;\n\nexport const UPDATE_MODEL = gql`\n  mutation UpdateModel($where: ModelWhereInput!, $data: UpdateModelInput!) {\n    updateModel(where: $where, data: $data)\n  }\n`;\n\nexport const DELETE_MODEL = gql`\n  mutation DeleteModel($where: ModelWhereInput!) {\n    deleteModel(where: $where)\n  }\n`;\n\nexport const PREVIEW_MODEL_DATA = gql`\n  mutation PreviewModelData($where: WhereIdInput!) {\n    previewModelData(where: $where)\n  }\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/onboarding.generated.ts",
    "content": "import * as Types from './__types__';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nconst defaultOptions = {} as const;\nexport type OnboardingStatusQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type OnboardingStatusQuery = { __typename?: 'Query', onboardingStatus: { __typename?: 'OnboardingStatusResponse', status?: Types.OnboardingStatus | null } };\n\n\nexport const OnboardingStatusDocument = gql`\n    query OnboardingStatus {\n  onboardingStatus {\n    status\n  }\n}\n    `;\n\n/**\n * __useOnboardingStatusQuery__\n *\n * To run a query within a React component, call `useOnboardingStatusQuery` and pass it any options that fit your needs.\n * When your component renders, `useOnboardingStatusQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useOnboardingStatusQuery({\n *   variables: {\n *   },\n * });\n */\nexport function useOnboardingStatusQuery(baseOptions?: Apollo.QueryHookOptions<OnboardingStatusQuery, OnboardingStatusQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<OnboardingStatusQuery, OnboardingStatusQueryVariables>(OnboardingStatusDocument, options);\n      }\nexport function useOnboardingStatusLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<OnboardingStatusQuery, OnboardingStatusQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<OnboardingStatusQuery, OnboardingStatusQueryVariables>(OnboardingStatusDocument, options);\n        }\nexport type OnboardingStatusQueryHookResult = ReturnType<typeof useOnboardingStatusQuery>;\nexport type OnboardingStatusLazyQueryHookResult = ReturnType<typeof useOnboardingStatusLazyQuery>;\nexport type OnboardingStatusQueryResult = Apollo.QueryResult<OnboardingStatusQuery, OnboardingStatusQueryVariables>;"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/onboarding.ts",
    "content": "import { gql } from '@apollo/client';\n\nexport const ONBOARDING_STATUS = gql`\n  query OnboardingStatus {\n    onboardingStatus {\n      status\n    }\n  }\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/relationship.generated.ts",
    "content": "import * as Types from './__types__';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nconst defaultOptions = {} as const;\nexport type CreateRelationshipMutationVariables = Types.Exact<{\n  data: Types.RelationInput;\n}>;\n\n\nexport type CreateRelationshipMutation = { __typename?: 'Mutation', createRelation: any };\n\nexport type UpdateRelationshipMutationVariables = Types.Exact<{\n  where: Types.WhereIdInput;\n  data: Types.UpdateRelationInput;\n}>;\n\n\nexport type UpdateRelationshipMutation = { __typename?: 'Mutation', updateRelation: any };\n\nexport type DeleteRelationshipMutationVariables = Types.Exact<{\n  where: Types.WhereIdInput;\n}>;\n\n\nexport type DeleteRelationshipMutation = { __typename?: 'Mutation', deleteRelation: boolean };\n\n\nexport const CreateRelationshipDocument = gql`\n    mutation CreateRelationship($data: RelationInput!) {\n  createRelation(data: $data)\n}\n    `;\nexport type CreateRelationshipMutationFn = Apollo.MutationFunction<CreateRelationshipMutation, CreateRelationshipMutationVariables>;\n\n/**\n * __useCreateRelationshipMutation__\n *\n * To run a mutation, you first call `useCreateRelationshipMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateRelationshipMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createRelationshipMutation, { data, loading, error }] = useCreateRelationshipMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useCreateRelationshipMutation(baseOptions?: Apollo.MutationHookOptions<CreateRelationshipMutation, CreateRelationshipMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<CreateRelationshipMutation, CreateRelationshipMutationVariables>(CreateRelationshipDocument, options);\n      }\nexport type CreateRelationshipMutationHookResult = ReturnType<typeof useCreateRelationshipMutation>;\nexport type CreateRelationshipMutationResult = Apollo.MutationResult<CreateRelationshipMutation>;\nexport type CreateRelationshipMutationOptions = Apollo.BaseMutationOptions<CreateRelationshipMutation, CreateRelationshipMutationVariables>;\nexport const UpdateRelationshipDocument = gql`\n    mutation UpdateRelationship($where: WhereIdInput!, $data: UpdateRelationInput!) {\n  updateRelation(where: $where, data: $data)\n}\n    `;\nexport type UpdateRelationshipMutationFn = Apollo.MutationFunction<UpdateRelationshipMutation, UpdateRelationshipMutationVariables>;\n\n/**\n * __useUpdateRelationshipMutation__\n *\n * To run a mutation, you first call `useUpdateRelationshipMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateRelationshipMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateRelationshipMutation, { data, loading, error }] = useUpdateRelationshipMutation({\n *   variables: {\n *      where: // value for 'where'\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useUpdateRelationshipMutation(baseOptions?: Apollo.MutationHookOptions<UpdateRelationshipMutation, UpdateRelationshipMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<UpdateRelationshipMutation, UpdateRelationshipMutationVariables>(UpdateRelationshipDocument, options);\n      }\nexport type UpdateRelationshipMutationHookResult = ReturnType<typeof useUpdateRelationshipMutation>;\nexport type UpdateRelationshipMutationResult = Apollo.MutationResult<UpdateRelationshipMutation>;\nexport type UpdateRelationshipMutationOptions = Apollo.BaseMutationOptions<UpdateRelationshipMutation, UpdateRelationshipMutationVariables>;\nexport const DeleteRelationshipDocument = gql`\n    mutation DeleteRelationship($where: WhereIdInput!) {\n  deleteRelation(where: $where)\n}\n    `;\nexport type DeleteRelationshipMutationFn = Apollo.MutationFunction<DeleteRelationshipMutation, DeleteRelationshipMutationVariables>;\n\n/**\n * __useDeleteRelationshipMutation__\n *\n * To run a mutation, you first call `useDeleteRelationshipMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDeleteRelationshipMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [deleteRelationshipMutation, { data, loading, error }] = useDeleteRelationshipMutation({\n *   variables: {\n *      where: // value for 'where'\n *   },\n * });\n */\nexport function useDeleteRelationshipMutation(baseOptions?: Apollo.MutationHookOptions<DeleteRelationshipMutation, DeleteRelationshipMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<DeleteRelationshipMutation, DeleteRelationshipMutationVariables>(DeleteRelationshipDocument, options);\n      }\nexport type DeleteRelationshipMutationHookResult = ReturnType<typeof useDeleteRelationshipMutation>;\nexport type DeleteRelationshipMutationResult = Apollo.MutationResult<DeleteRelationshipMutation>;\nexport type DeleteRelationshipMutationOptions = Apollo.BaseMutationOptions<DeleteRelationshipMutation, DeleteRelationshipMutationVariables>;"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/relationship.ts",
    "content": "import { gql } from '@apollo/client';\n\nexport const CREATE_RELATIONSHIP = gql`\n  mutation CreateRelationship($data: RelationInput!) {\n    createRelation(data: $data)\n  }\n`;\n\nexport const UPDATE_RELATIONSHIP = gql`\n  mutation UpdateRelationship(\n    $where: WhereIdInput!\n    $data: UpdateRelationInput!\n  ) {\n    updateRelation(where: $where, data: $data)\n  }\n`;\n\nexport const DELETE_RELATIONSHIP = gql`\n  mutation DeleteRelationship($where: WhereIdInput!) {\n    deleteRelation(where: $where)\n  }\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/settings.generated.ts",
    "content": "import * as Types from './__types__';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nconst defaultOptions = {} as const;\nexport type GetSettingsQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type GetSettingsQuery = { __typename?: 'Query', settings: { __typename?: 'Settings', productVersion: string, language: Types.ProjectLanguage, dataSource: { __typename?: 'DataSource', type: Types.DataSourceName, properties: any, sampleDataset?: Types.SampleDatasetName | null } } };\n\nexport type ResetCurrentProjectMutationVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type ResetCurrentProjectMutation = { __typename?: 'Mutation', resetCurrentProject: boolean };\n\nexport type UpdateCurrentProjectMutationVariables = Types.Exact<{\n  data: Types.UpdateCurrentProjectInput;\n}>;\n\n\nexport type UpdateCurrentProjectMutation = { __typename?: 'Mutation', updateCurrentProject: boolean };\n\n\nexport const GetSettingsDocument = gql`\n    query GetSettings {\n  settings {\n    productVersion\n    dataSource {\n      type\n      properties\n      sampleDataset\n    }\n    language\n  }\n}\n    `;\n\n/**\n * __useGetSettingsQuery__\n *\n * To run a query within a React component, call `useGetSettingsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetSettingsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetSettingsQuery({\n *   variables: {\n *   },\n * });\n */\nexport function useGetSettingsQuery(baseOptions?: Apollo.QueryHookOptions<GetSettingsQuery, GetSettingsQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<GetSettingsQuery, GetSettingsQueryVariables>(GetSettingsDocument, options);\n      }\nexport function useGetSettingsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetSettingsQuery, GetSettingsQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<GetSettingsQuery, GetSettingsQueryVariables>(GetSettingsDocument, options);\n        }\nexport type GetSettingsQueryHookResult = ReturnType<typeof useGetSettingsQuery>;\nexport type GetSettingsLazyQueryHookResult = ReturnType<typeof useGetSettingsLazyQuery>;\nexport type GetSettingsQueryResult = Apollo.QueryResult<GetSettingsQuery, GetSettingsQueryVariables>;\nexport const ResetCurrentProjectDocument = gql`\n    mutation ResetCurrentProject {\n  resetCurrentProject\n}\n    `;\nexport type ResetCurrentProjectMutationFn = Apollo.MutationFunction<ResetCurrentProjectMutation, ResetCurrentProjectMutationVariables>;\n\n/**\n * __useResetCurrentProjectMutation__\n *\n * To run a mutation, you first call `useResetCurrentProjectMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useResetCurrentProjectMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [resetCurrentProjectMutation, { data, loading, error }] = useResetCurrentProjectMutation({\n *   variables: {\n *   },\n * });\n */\nexport function useResetCurrentProjectMutation(baseOptions?: Apollo.MutationHookOptions<ResetCurrentProjectMutation, ResetCurrentProjectMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<ResetCurrentProjectMutation, ResetCurrentProjectMutationVariables>(ResetCurrentProjectDocument, options);\n      }\nexport type ResetCurrentProjectMutationHookResult = ReturnType<typeof useResetCurrentProjectMutation>;\nexport type ResetCurrentProjectMutationResult = Apollo.MutationResult<ResetCurrentProjectMutation>;\nexport type ResetCurrentProjectMutationOptions = Apollo.BaseMutationOptions<ResetCurrentProjectMutation, ResetCurrentProjectMutationVariables>;\nexport const UpdateCurrentProjectDocument = gql`\n    mutation UpdateCurrentProject($data: UpdateCurrentProjectInput!) {\n  updateCurrentProject(data: $data)\n}\n    `;\nexport type UpdateCurrentProjectMutationFn = Apollo.MutationFunction<UpdateCurrentProjectMutation, UpdateCurrentProjectMutationVariables>;\n\n/**\n * __useUpdateCurrentProjectMutation__\n *\n * To run a mutation, you first call `useUpdateCurrentProjectMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateCurrentProjectMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateCurrentProjectMutation, { data, loading, error }] = useUpdateCurrentProjectMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useUpdateCurrentProjectMutation(baseOptions?: Apollo.MutationHookOptions<UpdateCurrentProjectMutation, UpdateCurrentProjectMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<UpdateCurrentProjectMutation, UpdateCurrentProjectMutationVariables>(UpdateCurrentProjectDocument, options);\n      }\nexport type UpdateCurrentProjectMutationHookResult = ReturnType<typeof useUpdateCurrentProjectMutation>;\nexport type UpdateCurrentProjectMutationResult = Apollo.MutationResult<UpdateCurrentProjectMutation>;\nexport type UpdateCurrentProjectMutationOptions = Apollo.BaseMutationOptions<UpdateCurrentProjectMutation, UpdateCurrentProjectMutationVariables>;"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/settings.ts",
    "content": "import { gql } from '@apollo/client';\n\nexport const GET_SETTINGS = gql`\n  query GetSettings {\n    settings {\n      productVersion\n      dataSource {\n        type\n        properties\n        sampleDataset\n      }\n      language\n    }\n  }\n`;\n\nexport const RESET_CURRENT_PROJECT = gql`\n  mutation ResetCurrentProject {\n    resetCurrentProject\n  }\n`;\n\nexport const UPDATE_CURRENT_PROJECT = gql`\n  mutation UpdateCurrentProject($data: UpdateCurrentProjectInput!) {\n    updateCurrentProject(data: $data)\n  }\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/sql.generated.ts",
    "content": "import * as Types from './__types__';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nconst defaultOptions = {} as const;\nexport type PreviewSqlMutationVariables = Types.Exact<{\n  data: Types.PreviewSqlDataInput;\n}>;\n\n\nexport type PreviewSqlMutation = { __typename?: 'Mutation', previewSql: any };\n\nexport type GenerateQuestionMutationVariables = Types.Exact<{\n  data: Types.GenerateQuestionInput;\n}>;\n\n\nexport type GenerateQuestionMutation = { __typename?: 'Mutation', generateQuestion: string };\n\nexport type ModelSubstituteMutationVariables = Types.Exact<{\n  data: Types.ModelSubstituteInput;\n}>;\n\n\nexport type ModelSubstituteMutation = { __typename?: 'Mutation', modelSubstitute: string };\n\n\nexport const PreviewSqlDocument = gql`\n    mutation PreviewSQL($data: PreviewSQLDataInput!) {\n  previewSql(data: $data)\n}\n    `;\nexport type PreviewSqlMutationFn = Apollo.MutationFunction<PreviewSqlMutation, PreviewSqlMutationVariables>;\n\n/**\n * __usePreviewSqlMutation__\n *\n * To run a mutation, you first call `usePreviewSqlMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `usePreviewSqlMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [previewSqlMutation, { data, loading, error }] = usePreviewSqlMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function usePreviewSqlMutation(baseOptions?: Apollo.MutationHookOptions<PreviewSqlMutation, PreviewSqlMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<PreviewSqlMutation, PreviewSqlMutationVariables>(PreviewSqlDocument, options);\n      }\nexport type PreviewSqlMutationHookResult = ReturnType<typeof usePreviewSqlMutation>;\nexport type PreviewSqlMutationResult = Apollo.MutationResult<PreviewSqlMutation>;\nexport type PreviewSqlMutationOptions = Apollo.BaseMutationOptions<PreviewSqlMutation, PreviewSqlMutationVariables>;\nexport const GenerateQuestionDocument = gql`\n    mutation GenerateQuestion($data: GenerateQuestionInput!) {\n  generateQuestion(data: $data)\n}\n    `;\nexport type GenerateQuestionMutationFn = Apollo.MutationFunction<GenerateQuestionMutation, GenerateQuestionMutationVariables>;\n\n/**\n * __useGenerateQuestionMutation__\n *\n * To run a mutation, you first call `useGenerateQuestionMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useGenerateQuestionMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [generateQuestionMutation, { data, loading, error }] = useGenerateQuestionMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useGenerateQuestionMutation(baseOptions?: Apollo.MutationHookOptions<GenerateQuestionMutation, GenerateQuestionMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<GenerateQuestionMutation, GenerateQuestionMutationVariables>(GenerateQuestionDocument, options);\n      }\nexport type GenerateQuestionMutationHookResult = ReturnType<typeof useGenerateQuestionMutation>;\nexport type GenerateQuestionMutationResult = Apollo.MutationResult<GenerateQuestionMutation>;\nexport type GenerateQuestionMutationOptions = Apollo.BaseMutationOptions<GenerateQuestionMutation, GenerateQuestionMutationVariables>;\nexport const ModelSubstituteDocument = gql`\n    mutation ModelSubstitute($data: ModelSubstituteInput!) {\n  modelSubstitute(data: $data)\n}\n    `;\nexport type ModelSubstituteMutationFn = Apollo.MutationFunction<ModelSubstituteMutation, ModelSubstituteMutationVariables>;\n\n/**\n * __useModelSubstituteMutation__\n *\n * To run a mutation, you first call `useModelSubstituteMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useModelSubstituteMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [modelSubstituteMutation, { data, loading, error }] = useModelSubstituteMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useModelSubstituteMutation(baseOptions?: Apollo.MutationHookOptions<ModelSubstituteMutation, ModelSubstituteMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<ModelSubstituteMutation, ModelSubstituteMutationVariables>(ModelSubstituteDocument, options);\n      }\nexport type ModelSubstituteMutationHookResult = ReturnType<typeof useModelSubstituteMutation>;\nexport type ModelSubstituteMutationResult = Apollo.MutationResult<ModelSubstituteMutation>;\nexport type ModelSubstituteMutationOptions = Apollo.BaseMutationOptions<ModelSubstituteMutation, ModelSubstituteMutationVariables>;"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/sql.ts",
    "content": "import { gql } from '@apollo/client';\n\nexport const PREVIEW_SQL_STATEMENT = gql`\n  mutation PreviewSQL($data: PreviewSQLDataInput!) {\n    previewSql(data: $data)\n  }\n`;\n\nexport const GENERATE_QUESTION = gql`\n  mutation GenerateQuestion($data: GenerateQuestionInput!) {\n    generateQuestion(data: $data)\n  }\n`;\n\nexport const MODEL_SUBSTITUDE = gql`\n  mutation ModelSubstitute($data: ModelSubstituteInput!) {\n    modelSubstitute(data: $data)\n  }\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/sqlPairs.generated.ts",
    "content": "import * as Types from './__types__';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nconst defaultOptions = {} as const;\nexport type SqlPairFragment = { __typename?: 'SqlPair', id: number, projectId: number, sql: string, question: string, createdAt?: string | null, updatedAt?: string | null };\n\nexport type SqlPairsQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type SqlPairsQuery = { __typename?: 'Query', sqlPairs: Array<{ __typename?: 'SqlPair', id: number, projectId: number, sql: string, question: string, createdAt?: string | null, updatedAt?: string | null } | null> };\n\nexport type CreateSqlPairMutationVariables = Types.Exact<{\n  data: Types.CreateSqlPairInput;\n}>;\n\n\nexport type CreateSqlPairMutation = { __typename?: 'Mutation', createSqlPair: { __typename?: 'SqlPair', id: number, projectId: number, sql: string, question: string, createdAt?: string | null, updatedAt?: string | null } };\n\nexport type UpdateSqlPairMutationVariables = Types.Exact<{\n  where: Types.SqlPairWhereUniqueInput;\n  data: Types.UpdateSqlPairInput;\n}>;\n\n\nexport type UpdateSqlPairMutation = { __typename?: 'Mutation', updateSqlPair: { __typename?: 'SqlPair', id: number, projectId: number, sql: string, question: string, createdAt?: string | null, updatedAt?: string | null } };\n\nexport type DeleteSqlPairMutationVariables = Types.Exact<{\n  where: Types.SqlPairWhereUniqueInput;\n}>;\n\n\nexport type DeleteSqlPairMutation = { __typename?: 'Mutation', deleteSqlPair: boolean };\n\nexport const SqlPairFragmentDoc = gql`\n    fragment SqlPair on SqlPair {\n  id\n  projectId\n  sql\n  question\n  createdAt\n  updatedAt\n}\n    `;\nexport const SqlPairsDocument = gql`\n    query SqlPairs {\n  sqlPairs {\n    ...SqlPair\n  }\n}\n    ${SqlPairFragmentDoc}`;\n\n/**\n * __useSqlPairsQuery__\n *\n * To run a query within a React component, call `useSqlPairsQuery` and pass it any options that fit your needs.\n * When your component renders, `useSqlPairsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useSqlPairsQuery({\n *   variables: {\n *   },\n * });\n */\nexport function useSqlPairsQuery(baseOptions?: Apollo.QueryHookOptions<SqlPairsQuery, SqlPairsQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<SqlPairsQuery, SqlPairsQueryVariables>(SqlPairsDocument, options);\n      }\nexport function useSqlPairsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<SqlPairsQuery, SqlPairsQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<SqlPairsQuery, SqlPairsQueryVariables>(SqlPairsDocument, options);\n        }\nexport type SqlPairsQueryHookResult = ReturnType<typeof useSqlPairsQuery>;\nexport type SqlPairsLazyQueryHookResult = ReturnType<typeof useSqlPairsLazyQuery>;\nexport type SqlPairsQueryResult = Apollo.QueryResult<SqlPairsQuery, SqlPairsQueryVariables>;\nexport const CreateSqlPairDocument = gql`\n    mutation CreateSqlPair($data: CreateSqlPairInput!) {\n  createSqlPair(data: $data) {\n    ...SqlPair\n  }\n}\n    ${SqlPairFragmentDoc}`;\nexport type CreateSqlPairMutationFn = Apollo.MutationFunction<CreateSqlPairMutation, CreateSqlPairMutationVariables>;\n\n/**\n * __useCreateSqlPairMutation__\n *\n * To run a mutation, you first call `useCreateSqlPairMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateSqlPairMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createSqlPairMutation, { data, loading, error }] = useCreateSqlPairMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useCreateSqlPairMutation(baseOptions?: Apollo.MutationHookOptions<CreateSqlPairMutation, CreateSqlPairMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<CreateSqlPairMutation, CreateSqlPairMutationVariables>(CreateSqlPairDocument, options);\n      }\nexport type CreateSqlPairMutationHookResult = ReturnType<typeof useCreateSqlPairMutation>;\nexport type CreateSqlPairMutationResult = Apollo.MutationResult<CreateSqlPairMutation>;\nexport type CreateSqlPairMutationOptions = Apollo.BaseMutationOptions<CreateSqlPairMutation, CreateSqlPairMutationVariables>;\nexport const UpdateSqlPairDocument = gql`\n    mutation UpdateSqlPair($where: SqlPairWhereUniqueInput!, $data: UpdateSqlPairInput!) {\n  updateSqlPair(where: $where, data: $data) {\n    ...SqlPair\n  }\n}\n    ${SqlPairFragmentDoc}`;\nexport type UpdateSqlPairMutationFn = Apollo.MutationFunction<UpdateSqlPairMutation, UpdateSqlPairMutationVariables>;\n\n/**\n * __useUpdateSqlPairMutation__\n *\n * To run a mutation, you first call `useUpdateSqlPairMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useUpdateSqlPairMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [updateSqlPairMutation, { data, loading, error }] = useUpdateSqlPairMutation({\n *   variables: {\n *      where: // value for 'where'\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useUpdateSqlPairMutation(baseOptions?: Apollo.MutationHookOptions<UpdateSqlPairMutation, UpdateSqlPairMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<UpdateSqlPairMutation, UpdateSqlPairMutationVariables>(UpdateSqlPairDocument, options);\n      }\nexport type UpdateSqlPairMutationHookResult = ReturnType<typeof useUpdateSqlPairMutation>;\nexport type UpdateSqlPairMutationResult = Apollo.MutationResult<UpdateSqlPairMutation>;\nexport type UpdateSqlPairMutationOptions = Apollo.BaseMutationOptions<UpdateSqlPairMutation, UpdateSqlPairMutationVariables>;\nexport const DeleteSqlPairDocument = gql`\n    mutation DeleteSqlPair($where: SqlPairWhereUniqueInput!) {\n  deleteSqlPair(where: $where)\n}\n    `;\nexport type DeleteSqlPairMutationFn = Apollo.MutationFunction<DeleteSqlPairMutation, DeleteSqlPairMutationVariables>;\n\n/**\n * __useDeleteSqlPairMutation__\n *\n * To run a mutation, you first call `useDeleteSqlPairMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDeleteSqlPairMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [deleteSqlPairMutation, { data, loading, error }] = useDeleteSqlPairMutation({\n *   variables: {\n *      where: // value for 'where'\n *   },\n * });\n */\nexport function useDeleteSqlPairMutation(baseOptions?: Apollo.MutationHookOptions<DeleteSqlPairMutation, DeleteSqlPairMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<DeleteSqlPairMutation, DeleteSqlPairMutationVariables>(DeleteSqlPairDocument, options);\n      }\nexport type DeleteSqlPairMutationHookResult = ReturnType<typeof useDeleteSqlPairMutation>;\nexport type DeleteSqlPairMutationResult = Apollo.MutationResult<DeleteSqlPairMutation>;\nexport type DeleteSqlPairMutationOptions = Apollo.BaseMutationOptions<DeleteSqlPairMutation, DeleteSqlPairMutationVariables>;"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/sqlPairs.ts",
    "content": "import { gql } from '@apollo/client';\n\nconst SQL_PAIR = gql`\n  fragment SqlPair on SqlPair {\n    id\n    projectId\n    sql\n    question\n    createdAt\n    updatedAt\n  }\n`;\n\nexport const LIST_SQL_PAIRS = gql`\n  query SqlPairs {\n    sqlPairs {\n      ...SqlPair\n    }\n  }\n\n  ${SQL_PAIR}\n`;\n\nexport const CREATE_SQL_PAIR = gql`\n  mutation CreateSqlPair($data: CreateSqlPairInput!) {\n    createSqlPair(data: $data) {\n      ...SqlPair\n    }\n  }\n\n  ${SQL_PAIR}\n`;\n\nexport const UPDATE_SQL_PAIR = gql`\n  mutation UpdateSqlPair(\n    $where: SqlPairWhereUniqueInput!\n    $data: UpdateSqlPairInput!\n  ) {\n    updateSqlPair(where: $where, data: $data) {\n      ...SqlPair\n    }\n  }\n\n  ${SQL_PAIR}\n`;\n\nexport const DELETE_SQL_PAIR = gql`\n  mutation DeleteSqlPair($where: SqlPairWhereUniqueInput!) {\n    deleteSqlPair(where: $where)\n  }\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/view.generated.ts",
    "content": "import * as Types from './__types__';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nconst defaultOptions = {} as const;\nexport type CreateViewMutationVariables = Types.Exact<{\n  data: Types.CreateViewInput;\n}>;\n\n\nexport type CreateViewMutation = { __typename?: 'Mutation', createView: { __typename?: 'ViewInfo', id: number, name: string, statement: string } };\n\nexport type DeleteViewMutationVariables = Types.Exact<{\n  where: Types.ViewWhereUniqueInput;\n}>;\n\n\nexport type DeleteViewMutation = { __typename?: 'Mutation', deleteView: boolean };\n\nexport type GetViewQueryVariables = Types.Exact<{\n  where: Types.ViewWhereUniqueInput;\n}>;\n\n\nexport type GetViewQuery = { __typename?: 'Query', view: { __typename?: 'ViewInfo', id: number, name: string, statement: string } };\n\nexport type ListViewsQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type ListViewsQuery = { __typename?: 'Query', listViews: Array<{ __typename?: 'ViewInfo', id: number, name: string, displayName: string, statement: string }> };\n\nexport type PreviewViewDataMutationVariables = Types.Exact<{\n  where: Types.PreviewViewDataInput;\n}>;\n\n\nexport type PreviewViewDataMutation = { __typename?: 'Mutation', previewViewData: any };\n\nexport type ValidateViewMutationVariables = Types.Exact<{\n  data: Types.ValidateViewInput;\n}>;\n\n\nexport type ValidateViewMutation = { __typename?: 'Mutation', validateView: { __typename?: 'ViewValidationResponse', valid: boolean, message?: string | null } };\n\n\nexport const CreateViewDocument = gql`\n    mutation CreateView($data: CreateViewInput!) {\n  createView(data: $data) {\n    id\n    name\n    statement\n  }\n}\n    `;\nexport type CreateViewMutationFn = Apollo.MutationFunction<CreateViewMutation, CreateViewMutationVariables>;\n\n/**\n * __useCreateViewMutation__\n *\n * To run a mutation, you first call `useCreateViewMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useCreateViewMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [createViewMutation, { data, loading, error }] = useCreateViewMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useCreateViewMutation(baseOptions?: Apollo.MutationHookOptions<CreateViewMutation, CreateViewMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<CreateViewMutation, CreateViewMutationVariables>(CreateViewDocument, options);\n      }\nexport type CreateViewMutationHookResult = ReturnType<typeof useCreateViewMutation>;\nexport type CreateViewMutationResult = Apollo.MutationResult<CreateViewMutation>;\nexport type CreateViewMutationOptions = Apollo.BaseMutationOptions<CreateViewMutation, CreateViewMutationVariables>;\nexport const DeleteViewDocument = gql`\n    mutation DeleteView($where: ViewWhereUniqueInput!) {\n  deleteView(where: $where)\n}\n    `;\nexport type DeleteViewMutationFn = Apollo.MutationFunction<DeleteViewMutation, DeleteViewMutationVariables>;\n\n/**\n * __useDeleteViewMutation__\n *\n * To run a mutation, you first call `useDeleteViewMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useDeleteViewMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [deleteViewMutation, { data, loading, error }] = useDeleteViewMutation({\n *   variables: {\n *      where: // value for 'where'\n *   },\n * });\n */\nexport function useDeleteViewMutation(baseOptions?: Apollo.MutationHookOptions<DeleteViewMutation, DeleteViewMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<DeleteViewMutation, DeleteViewMutationVariables>(DeleteViewDocument, options);\n      }\nexport type DeleteViewMutationHookResult = ReturnType<typeof useDeleteViewMutation>;\nexport type DeleteViewMutationResult = Apollo.MutationResult<DeleteViewMutation>;\nexport type DeleteViewMutationOptions = Apollo.BaseMutationOptions<DeleteViewMutation, DeleteViewMutationVariables>;\nexport const GetViewDocument = gql`\n    query GetView($where: ViewWhereUniqueInput!) {\n  view(where: $ViewWhereUniqueInput) {\n    id\n    name\n    statement\n  }\n}\n    `;\n\n/**\n * __useGetViewQuery__\n *\n * To run a query within a React component, call `useGetViewQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetViewQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetViewQuery({\n *   variables: {\n *      where: // value for 'where'\n *   },\n * });\n */\nexport function useGetViewQuery(baseOptions: Apollo.QueryHookOptions<GetViewQuery, GetViewQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<GetViewQuery, GetViewQueryVariables>(GetViewDocument, options);\n      }\nexport function useGetViewLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetViewQuery, GetViewQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<GetViewQuery, GetViewQueryVariables>(GetViewDocument, options);\n        }\nexport type GetViewQueryHookResult = ReturnType<typeof useGetViewQuery>;\nexport type GetViewLazyQueryHookResult = ReturnType<typeof useGetViewLazyQuery>;\nexport type GetViewQueryResult = Apollo.QueryResult<GetViewQuery, GetViewQueryVariables>;\nexport const ListViewsDocument = gql`\n    query ListViews {\n  listViews {\n    id\n    name\n    displayName\n    statement\n  }\n}\n    `;\n\n/**\n * __useListViewsQuery__\n *\n * To run a query within a React component, call `useListViewsQuery` and pass it any options that fit your needs.\n * When your component renders, `useListViewsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useListViewsQuery({\n *   variables: {\n *   },\n * });\n */\nexport function useListViewsQuery(baseOptions?: Apollo.QueryHookOptions<ListViewsQuery, ListViewsQueryVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useQuery<ListViewsQuery, ListViewsQueryVariables>(ListViewsDocument, options);\n      }\nexport function useListViewsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ListViewsQuery, ListViewsQueryVariables>) {\n          const options = {...defaultOptions, ...baseOptions}\n          return Apollo.useLazyQuery<ListViewsQuery, ListViewsQueryVariables>(ListViewsDocument, options);\n        }\nexport type ListViewsQueryHookResult = ReturnType<typeof useListViewsQuery>;\nexport type ListViewsLazyQueryHookResult = ReturnType<typeof useListViewsLazyQuery>;\nexport type ListViewsQueryResult = Apollo.QueryResult<ListViewsQuery, ListViewsQueryVariables>;\nexport const PreviewViewDataDocument = gql`\n    mutation PreviewViewData($where: PreviewViewDataInput!) {\n  previewViewData(where: $where)\n}\n    `;\nexport type PreviewViewDataMutationFn = Apollo.MutationFunction<PreviewViewDataMutation, PreviewViewDataMutationVariables>;\n\n/**\n * __usePreviewViewDataMutation__\n *\n * To run a mutation, you first call `usePreviewViewDataMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `usePreviewViewDataMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [previewViewDataMutation, { data, loading, error }] = usePreviewViewDataMutation({\n *   variables: {\n *      where: // value for 'where'\n *   },\n * });\n */\nexport function usePreviewViewDataMutation(baseOptions?: Apollo.MutationHookOptions<PreviewViewDataMutation, PreviewViewDataMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<PreviewViewDataMutation, PreviewViewDataMutationVariables>(PreviewViewDataDocument, options);\n      }\nexport type PreviewViewDataMutationHookResult = ReturnType<typeof usePreviewViewDataMutation>;\nexport type PreviewViewDataMutationResult = Apollo.MutationResult<PreviewViewDataMutation>;\nexport type PreviewViewDataMutationOptions = Apollo.BaseMutationOptions<PreviewViewDataMutation, PreviewViewDataMutationVariables>;\nexport const ValidateViewDocument = gql`\n    mutation ValidateView($data: ValidateViewInput!) {\n  validateView(data: $data) {\n    valid\n    message\n  }\n}\n    `;\nexport type ValidateViewMutationFn = Apollo.MutationFunction<ValidateViewMutation, ValidateViewMutationVariables>;\n\n/**\n * __useValidateViewMutation__\n *\n * To run a mutation, you first call `useValidateViewMutation` within a React component and pass it any options that fit your needs.\n * When your component renders, `useValidateViewMutation` returns a tuple that includes:\n * - A mutate function that you can call at any time to execute the mutation\n * - An object with fields that represent the current status of the mutation's execution\n *\n * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;\n *\n * @example\n * const [validateViewMutation, { data, loading, error }] = useValidateViewMutation({\n *   variables: {\n *      data: // value for 'data'\n *   },\n * });\n */\nexport function useValidateViewMutation(baseOptions?: Apollo.MutationHookOptions<ValidateViewMutation, ValidateViewMutationVariables>) {\n        const options = {...defaultOptions, ...baseOptions}\n        return Apollo.useMutation<ValidateViewMutation, ValidateViewMutationVariables>(ValidateViewDocument, options);\n      }\nexport type ValidateViewMutationHookResult = ReturnType<typeof useValidateViewMutation>;\nexport type ValidateViewMutationResult = Apollo.MutationResult<ValidateViewMutation>;\nexport type ValidateViewMutationOptions = Apollo.BaseMutationOptions<ValidateViewMutation, ValidateViewMutationVariables>;"
  },
  {
    "path": "wren-ui/src/apollo/client/graphql/view.ts",
    "content": "import { gql } from '@apollo/client';\n\nexport const CREATE_VIEW = gql`\n  mutation CreateView($data: CreateViewInput!) {\n    createView(data: $data) {\n      id\n      name\n      statement\n    }\n  }\n`;\n\nexport const DELETE_VIEW = gql`\n  mutation DeleteView($where: ViewWhereUniqueInput!) {\n    deleteView(where: $where)\n  }\n`;\n\nexport const GET_VIEW = gql`\n  query GetView($where: ViewWhereUniqueInput!) {\n    view(where: $ViewWhereUniqueInput) {\n      id\n      name\n      statement\n    }\n  }\n`;\n\nexport const LIST_VIEWS = gql`\n  query ListViews {\n    listViews {\n      id\n      name\n      displayName\n      statement\n    }\n  }\n`;\n\nexport const PREVIEW_VIEW_DATA = gql`\n  mutation PreviewViewData($where: PreviewViewDataInput!) {\n    previewViewData(where: $where)\n  }\n`;\n\nexport const VALIDATE_CREATE_VIEW = gql`\n  mutation ValidateView($data: ValidateViewInput!) {\n    validateView(data: $data) {\n      valid\n      message\n    }\n  }\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/client/index.ts",
    "content": "import { ApolloClient, HttpLink, InMemoryCache, from } from '@apollo/client';\nimport { onError } from '@apollo/client/link/error';\nimport errorHandler from '@/utils/errorHandler';\n\nconst apolloErrorLink = onError((error) => errorHandler(error));\n\nconst httpLink = new HttpLink({\n  uri: '/api/graphql',\n});\n\nconst client = new ApolloClient({\n  link: from([apolloErrorLink, httpLink]),\n  cache: new InMemoryCache(),\n});\n\nexport default client;\n"
  },
  {
    "path": "wren-ui/src/apollo/server/adaptors/ibisAdaptor.ts",
    "content": "import axios, { AxiosResponse } from 'axios';\n\nimport { getLogger } from '@server/utils/logger';\nimport { DataSourceName } from '@server/types';\nimport { Manifest } from '@server/mdl/type';\nimport * as Errors from '@server/utils/error';\nimport { getConfig } from '@server/config';\nimport { toDockerHost } from '@server/utils';\nimport {\n  CompactColumn,\n  CompactTable,\n  DEFAULT_PREVIEW_LIMIT,\n  RecommendConstraint,\n} from '@server/services';\nimport { snakeCase } from 'lodash';\nimport { WREN_AI_CONNECTION_INFO } from '../repositories';\nimport {\n  toIbisConnectionInfo,\n  toMultipleIbisConnectionInfos,\n} from '../dataSource';\nimport { DialectSQL, WrenSQL } from '../models/adaptor';\n\nexport type { WrenSQL };\n\nconst logger = getLogger('IbisAdaptor');\nlogger.level = 'debug';\n\nconst config = getConfig();\n\nexport interface HostBasedConnectionInfo {\n  host: string;\n  port: number;\n  database: string;\n  user: string;\n  password: string;\n}\n\nexport interface UrlBasedConnectionInfo {\n  connectionUrl: string;\n}\n\nexport type IbisPostgresConnectionInfo =\n  | UrlBasedConnectionInfo\n  | HostBasedConnectionInfo;\n\nexport interface IbisBigQueryConnectionInfo {\n  project_id: string;\n  dataset_id: string;\n  credentials: string; // base64 encoded\n}\n\nexport interface IbisTrinoConnectionInfo {\n  host: string;\n  port: number;\n  catalog: string;\n  schema: string;\n  user: string;\n  password: string;\n}\n\nexport interface IbisSnowflakeConnectionInfo {\n  user: string;\n  account: string;\n  database: string;\n  schema: string;\n  password?: string;\n  privateKey?: string;\n  warehouse?: string;\n}\n\nexport interface IbisAthenaConnectionInfo {\n  // AWS access key auth (optional if using OIDC)\n  aws_access_key_id?: string;\n  aws_secret_access_key?: string;\n\n  // OIDC auth (optional if using access keys)\n  web_identity_token?: string;\n  role_arn?: string;\n  role_session_name?: string;\n\n  region_name: string;\n  s3_staging_dir: string;\n  schema_name: string;\n}\n\nexport enum IbisRedshiftConnectionType {\n  REDSHIFT = 'redshift',\n  REDSHIFT_IAM = 'redshift_iam',\n}\n\ninterface IbisRedshiftPasswordAuth {\n  host: string;\n  port: number;\n  database: string;\n  user: string;\n  password: string;\n  redshift_type: IbisRedshiftConnectionType;\n}\n\ninterface IbisRedshiftIAMAuth {\n  cluster_identifier: string;\n  user: string;\n  database: string;\n  region: string;\n  access_key_id: string;\n  access_key_secret: string;\n  redshift_type: IbisRedshiftConnectionType;\n}\n\nexport enum IbisDatabricksConnectionType {\n  TOKEN = 'token',\n  SERVICE_PRINCIPAL = 'service_principal',\n}\n\ninterface IbisDatabricksPersonalAccessTokenAuth {\n  databricks_type: IbisDatabricksConnectionType;\n  serverHostname: string;\n  httpPath: string;\n  accessToken: string;\n}\n\ninterface IbisDatabricksServicePrincipalAuth {\n  databricks_type: IbisDatabricksConnectionType;\n  serverHostname: string;\n  httpPath: string;\n  clientId: string;\n  clientSecret: string;\n  azureTenantId?: string;\n}\n\nexport type IbisRedshiftConnectionInfo =\n  | IbisRedshiftPasswordAuth\n  | IbisRedshiftIAMAuth;\n\nexport type IbisDatabricksConnectionInfo =\n  | IbisDatabricksPersonalAccessTokenAuth\n  | IbisDatabricksServicePrincipalAuth;\n\nexport enum SupportedDataSource {\n  POSTGRES = 'POSTGRES',\n  BIG_QUERY = 'BIG_QUERY',\n  SNOWFLAKE = 'SNOWFLAKE',\n  MYSQL = 'MYSQL',\n  ORACLE = 'ORACLE',\n  MSSQL = 'MSSQL',\n  CLICK_HOUSE = 'CLICK_HOUSE',\n  TRINO = 'TRINO',\n  ATHENA = 'ATHENA',\n  REDSHIFT = 'REDSHIFT',\n  DATABRICKS = 'DATABRICKS',\n}\n\nconst dataSourceUrlMap: Record<SupportedDataSource, string> = {\n  [SupportedDataSource.POSTGRES]: 'postgres',\n  [SupportedDataSource.BIG_QUERY]: 'bigquery',\n  [SupportedDataSource.SNOWFLAKE]: 'snowflake',\n  [SupportedDataSource.MYSQL]: 'mysql',\n  [SupportedDataSource.ORACLE]: 'oracle',\n  [SupportedDataSource.MSSQL]: 'mssql',\n  [SupportedDataSource.CLICK_HOUSE]: 'clickhouse',\n  [SupportedDataSource.TRINO]: 'trino',\n  [SupportedDataSource.ATHENA]: 'athena',\n  [SupportedDataSource.REDSHIFT]: 'redshift',\n  [SupportedDataSource.DATABRICKS]: 'databricks',\n};\n\nexport interface TableResponse {\n  tables: CompactTable[];\n}\n\nexport enum ValidationRules {\n  COLUMN_IS_VALID = 'COLUMN_IS_VALID',\n}\n\nexport interface ValidationResponse {\n  valid: boolean;\n  message: string | null;\n}\n\nexport interface IbisBaseOptions {\n  dataSource: DataSourceName;\n  connectionInfo: WREN_AI_CONNECTION_INFO;\n  mdl: Manifest;\n}\nexport interface IbisQueryOptions extends IbisBaseOptions {\n  limit?: number;\n  refresh?: boolean;\n  cacheEnabled?: boolean;\n}\nexport interface IbisDryPlanOptions {\n  dataSource: DataSourceName;\n  mdl: Manifest;\n  // TODO: replace sql type with WrenSQL\n  sql: string;\n}\n\nexport interface IIbisAdaptor {\n  query: (\n    // TODO: replace query type with WrenSQL\n    query: string,\n    options: IbisQueryOptions,\n  ) => Promise<IbisQueryResponse>;\n  dryRun: (query: string, options: IbisBaseOptions) => Promise<DryRunResponse>;\n  getTables: (\n    dataSource: DataSourceName,\n    connectionInfo: WREN_AI_CONNECTION_INFO,\n  ) => Promise<CompactTable[]>;\n  getConstraints: (\n    dataSource: DataSourceName,\n    connectionInfo: WREN_AI_CONNECTION_INFO,\n  ) => Promise<RecommendConstraint[]>;\n\n  getNativeSql: (options: IbisDryPlanOptions) => Promise<string>;\n  validate: (\n    dataSource: DataSourceName,\n    rule: ValidationRules,\n    connectionInfo: WREN_AI_CONNECTION_INFO,\n    mdl: Manifest,\n    parameters: Record<string, any>,\n  ) => Promise<ValidationResponse>;\n  modelSubstitute: (\n    sql: DialectSQL,\n    options: {\n      dataSource: DataSourceName;\n      connectionInfo: WREN_AI_CONNECTION_INFO;\n      mdl: Manifest;\n      catalog?: string;\n      schema?: string;\n    },\n  ) => Promise<WrenSQL>;\n  getVersion: (\n    dataSource: DataSourceName,\n    connectionInfo: WREN_AI_CONNECTION_INFO,\n  ) => Promise<string>;\n}\n\nexport interface IbisResponse {\n  correlationId?: string;\n  processTime?: string;\n}\n\nexport interface IbisQueryResponse extends IbisResponse {\n  columns: string[];\n  data: any[];\n  dtypes: Record<string, string>;\n  cacheHit?: boolean;\n  cacheCreatedAt?: string;\n  cacheOverrodeAt?: string;\n  override?: boolean;\n}\n\nexport interface DryRunResponse extends IbisResponse {}\n\nenum IBIS_API_TYPE {\n  QUERY = 'QUERY',\n  DRY_RUN = 'DRY_RUN',\n  DRY_PLAN = 'DRY_PLAN',\n  METADATA = 'METADATA',\n  VALIDATION = 'VALIDATION',\n  ANALYSIS = 'ANALYSIS',\n  MODEL_SUBSTITUTE = 'MODEL_SUBSTITUTE',\n}\n\nexport class IbisAdaptor implements IIbisAdaptor {\n  private ibisServerEndpoint: string;\n\n  constructor({ ibisServerEndpoint }: { ibisServerEndpoint: string }) {\n    this.ibisServerEndpoint = ibisServerEndpoint;\n  }\n  public async getNativeSql(options: IbisDryPlanOptions): Promise<string> {\n    const { dataSource, mdl, sql } = options;\n    const body = {\n      sql,\n      manifestStr: Buffer.from(JSON.stringify(mdl)).toString('base64'),\n    };\n    try {\n      const res = await axios.post(\n        `${this.ibisServerEndpoint}/${this.getIbisApiVersion(IBIS_API_TYPE.DRY_PLAN)}/connector/${dataSourceUrlMap[dataSource]}/dry-plan`,\n        body,\n      );\n      return res.data;\n    } catch (e) {\n      logger.debug(`Dry plan error: ${e.response?.data || e.message}`);\n      this.throwError(e, 'Error during dry plan execution');\n    }\n  }\n\n  public async query(\n    query: string,\n    options: IbisQueryOptions,\n  ): Promise<IbisQueryResponse> {\n    const { dataSource, mdl } = options;\n    const connectionInfo = this.updateConnectionInfo(options.connectionInfo);\n    const ibisConnectionInfo = toIbisConnectionInfo(dataSource, connectionInfo);\n    const queryString = this.buildQueryString(options);\n    const body = {\n      sql: query,\n      connectionInfo: ibisConnectionInfo,\n      manifestStr: Buffer.from(JSON.stringify(mdl)).toString('base64'),\n    };\n    try {\n      const res = await axios.post(\n        `${this.ibisServerEndpoint}/${this.getIbisApiVersion(IBIS_API_TYPE.QUERY)}/connector/${dataSourceUrlMap[dataSource]}/query${queryString}`,\n        body,\n        {\n          params: {\n            limit: options.limit || DEFAULT_PREVIEW_LIMIT,\n          },\n        },\n      );\n      return {\n        ...res.data,\n        correlationId: res.headers['x-correlation-id'],\n        processTime: res.headers['x-process-time'],\n        cacheHit: res.headers['x-cache-hit'] === 'true',\n        cacheCreatedAt:\n          res.headers['x-cache-create-at'] &&\n          new Date(parseInt(res.headers['x-cache-create-at'])).toISOString(),\n        cacheOverrodeAt:\n          res.headers['x-cache-override-at'] &&\n          new Date(parseInt(res.headers['x-cache-override-at'])).toISOString(),\n        override: res.headers['x-cache-override'] === 'true',\n      };\n    } catch (e) {\n      logger.debug(`Query error: ${e.response?.data || e.message}`);\n      this.throwError(e, 'Error querying ibis server');\n    }\n  }\n\n  public async dryRun(\n    query: string,\n    options: IbisQueryOptions,\n  ): Promise<DryRunResponse> {\n    const { dataSource, mdl } = options;\n    const connectionInfo = this.updateConnectionInfo(options.connectionInfo);\n    const ibisConnectionInfo = toIbisConnectionInfo(dataSource, connectionInfo);\n    const body = {\n      sql: query,\n      connectionInfo: ibisConnectionInfo,\n      manifestStr: Buffer.from(JSON.stringify(mdl)).toString('base64'),\n    };\n    logger.debug(`Dry run sql from ibis with body:`);\n    try {\n      const response = await axios.post(\n        `${this.ibisServerEndpoint}/${this.getIbisApiVersion(IBIS_API_TYPE.DRY_RUN)}/connector/${dataSourceUrlMap[dataSource]}/query?dryRun=true`,\n        body,\n      );\n      logger.debug(`Ibis server Dry run success`);\n      return {\n        correlationId: response.headers['x-correlation-id'],\n        processTime: response.headers['x-process-time'],\n      };\n    } catch (err) {\n      logger.debug(`Dry run error: ${err.response?.data || err.message}`);\n      this.throwError(err, 'Error during dry run execution');\n    }\n  }\n\n  public async getTables(\n    dataSource: DataSourceName,\n    connectionInfo: WREN_AI_CONNECTION_INFO,\n  ): Promise<CompactTable[]> {\n    try {\n      const getTablesByConnectionInfo = async (ibisConnectionInfo) => {\n        const body = {\n          connectionInfo: ibisConnectionInfo,\n        };\n        logger.debug(`Getting tables from ibis`);\n        const res: AxiosResponse<CompactTable[]> = await axios.post(\n          `${this.ibisServerEndpoint}/${this.getIbisApiVersion(IBIS_API_TYPE.METADATA)}/connector/${dataSourceUrlMap[dataSource]}/metadata/tables`,\n          body,\n        );\n\n        return this.transformDescriptionToProperties(res.data);\n      };\n\n      connectionInfo = this.updateConnectionInfo(connectionInfo);\n\n      // If the dataSource supports multiple connection info, we need to get tables from each connection info\n      const multipleIbisConnectionInfos = toMultipleIbisConnectionInfos(\n        dataSource,\n        connectionInfo,\n      );\n      if (multipleIbisConnectionInfos) {\n        const results = await Promise.all(\n          multipleIbisConnectionInfos.map(getTablesByConnectionInfo),\n        );\n        return results.flat();\n      }\n\n      // If the dataSource does not support multiple connection info, we only need to get tables from one connection info\n      const ibisConnectionInfo = toIbisConnectionInfo(\n        dataSource,\n        connectionInfo,\n      );\n      return await getTablesByConnectionInfo(ibisConnectionInfo);\n    } catch (e) {\n      logger.debug(`Get tables error: ${e.response?.data || e.message}`);\n      this.throwError(e, 'Error getting table from ibis server');\n    }\n  }\n\n  public async getConstraints(\n    dataSource: DataSourceName,\n    connectionInfo: WREN_AI_CONNECTION_INFO,\n  ): Promise<RecommendConstraint[]> {\n    connectionInfo = this.updateConnectionInfo(connectionInfo);\n    const ibisConnectionInfo = toIbisConnectionInfo(dataSource, connectionInfo);\n    const body = {\n      connectionInfo: ibisConnectionInfo,\n    };\n    try {\n      logger.debug(`Getting constraint from ibis`);\n      const res: AxiosResponse<RecommendConstraint[]> = await axios.post(\n        `${this.ibisServerEndpoint}/${this.getIbisApiVersion(IBIS_API_TYPE.METADATA)}/connector/${dataSourceUrlMap[dataSource]}/metadata/constraints`,\n        body,\n      );\n      return res.data;\n    } catch (e) {\n      logger.debug(`Get constraints error: ${e.response?.data || e.message}`);\n      this.throwError(e, 'Error getting constraint from ibis server');\n    }\n  }\n\n  public async validate(\n    dataSource: DataSourceName,\n    validationRule: ValidationRules,\n    connectionInfo: WREN_AI_CONNECTION_INFO,\n    mdl: Manifest,\n    parameters: Record<string, any>,\n  ): Promise<ValidationResponse> {\n    connectionInfo = this.updateConnectionInfo(connectionInfo);\n    const ibisConnectionInfo = toIbisConnectionInfo(dataSource, connectionInfo);\n    const body = {\n      connectionInfo: ibisConnectionInfo,\n      manifestStr: Buffer.from(JSON.stringify(mdl)).toString('base64'),\n      parameters,\n    };\n    try {\n      logger.debug(`Run validation rule \"${validationRule}\" with ibis`);\n      await axios.post(\n        `${this.ibisServerEndpoint}/${this.getIbisApiVersion(IBIS_API_TYPE.VALIDATION)}/connector/${dataSourceUrlMap[dataSource]}/validate/${snakeCase(validationRule)}`,\n        body,\n      );\n      return { valid: true, message: null };\n    } catch (e) {\n      logger.debug(`Validation error: ${e.response?.data || e.message}`);\n      return { valid: false, message: e.response?.data || e.message };\n    }\n  }\n\n  public async modelSubstitute(\n    sql: DialectSQL,\n    options: {\n      dataSource: DataSourceName;\n      connectionInfo: WREN_AI_CONNECTION_INFO;\n      mdl: Manifest;\n      catalog?: string;\n      schema?: string;\n    },\n  ): Promise<WrenSQL> {\n    const { dataSource, mdl, catalog, schema } = options;\n    let connectionInfo = options.connectionInfo;\n    connectionInfo = this.updateConnectionInfo(connectionInfo);\n    const headers = {\n      'X-User-CATALOG': catalog,\n      'X-User-SCHEMA': schema,\n    };\n    const ibisConnectionInfo = toIbisConnectionInfo(dataSource, connectionInfo);\n    const body = {\n      sql,\n      connectionInfo: ibisConnectionInfo,\n      manifestStr: Buffer.from(JSON.stringify(mdl)).toString('base64'),\n    };\n    try {\n      logger.debug(`Running model substitution with ibis`);\n      const res = await axios.post(\n        `${this.ibisServerEndpoint}/${this.getIbisApiVersion(IBIS_API_TYPE.MODEL_SUBSTITUTE)}/connector/${dataSourceUrlMap[dataSource]}/model-substitute`,\n        body,\n        {\n          headers,\n        },\n      );\n      return res.data as WrenSQL;\n    } catch (e) {\n      logger.debug(\n        `Model substitution error: ${e.response?.data || e.message}`,\n      );\n      this.throwError(\n        e,\n        'Error running model substitution with ibis server',\n        this.modelSubstituteErrorMessageBuilder,\n      );\n    }\n  }\n\n  public async getVersion(\n    dataSource: DataSourceName,\n    connectionInfo: WREN_AI_CONNECTION_INFO,\n  ): Promise<string> {\n    connectionInfo = this.updateConnectionInfo(connectionInfo);\n    const ibisConnectionInfo = toIbisConnectionInfo(dataSource, connectionInfo);\n    const body = {\n      connectionInfo: ibisConnectionInfo,\n    };\n    try {\n      logger.debug(`Getting version from ibis`);\n      const res: AxiosResponse<string> = await axios.post(\n        `${this.ibisServerEndpoint}/${this.getIbisApiVersion(IBIS_API_TYPE.METADATA)}/connector/${dataSourceUrlMap[dataSource]}/metadata/version`,\n        body,\n      );\n      return res.data;\n    } catch (e) {\n      logger.debug(`Get version error: ${e.response?.data || e.message}`);\n      this.throwError(e, 'Error getting version from ibis server');\n    }\n  }\n\n  private updateConnectionInfo(connectionInfo: any) {\n    if (\n      config.otherServiceUsingDocker &&\n      Object.hasOwnProperty.call(connectionInfo, 'host')\n    ) {\n      connectionInfo.host = toDockerHost(connectionInfo.host);\n      logger.debug(`Host replaced with docker host`);\n    }\n    return connectionInfo;\n  }\n\n  private transformDescriptionToProperties(\n    tables: CompactTable[],\n  ): CompactTable[] {\n    const handleColumnProperties = (column: CompactColumn): CompactColumn => {\n      const properties = column?.properties || {};\n      if (column.description) {\n        properties.description = column.description;\n      }\n      const nestedColumns = column.nestedColumns?.map((nc) => {\n        return handleColumnProperties(nc);\n      });\n      return { ...column, properties, nestedColumns };\n    };\n\n    return tables.map((table) => {\n      try {\n        const properties = table?.properties || {};\n        if (table.description) {\n          properties.description = table.description;\n        }\n        if (table.columns) {\n          const transformedColumns = table.columns.map((column) =>\n            handleColumnProperties(column),\n          );\n          table.columns = transformedColumns;\n        }\n        return { ...table, properties };\n      } catch (e) {\n        console.log('e', e);\n      }\n    });\n  }\n\n  private getIbisApiVersion(apiType: IBIS_API_TYPE) {\n    if (!config.experimentalEngineRustVersion) {\n      return 'v2';\n    }\n    const useV3 = [\n      IBIS_API_TYPE.QUERY,\n      IBIS_API_TYPE.DRY_RUN,\n      IBIS_API_TYPE.DRY_PLAN,\n      IBIS_API_TYPE.VALIDATION,\n      IBIS_API_TYPE.MODEL_SUBSTITUTE,\n    ].includes(apiType);\n    if (useV3) logger.debug('Using ibis v3 api');\n    return useV3 ? 'v3' : 'v2';\n  }\n\n  private throwError(\n    e: any,\n    defaultMessage: string,\n    errorMessageBuilder?: CallableFunction,\n  ) {\n    const customMessage =\n      e.response?.data?.message ||\n      e.response?.data ||\n      e.message ||\n      defaultMessage;\n\n    const errorData = e.response?.data;\n    throw Errors.create(Errors.GeneralErrorCodes.IBIS_SERVER_ERROR, {\n      customMessage: errorMessageBuilder\n        ? errorMessageBuilder(customMessage)\n        : customMessage,\n      originalError: e,\n      other: {\n        correlationId: e.response?.headers['x-correlation-id'],\n        processTime: e.response?.headers['x-process-time'],\n        ...errorData,\n      },\n    });\n  }\n\n  private modelSubstituteErrorMessageBuilder(message: string) {\n    const ModelSubstituteErrorEnum = {\n      MODEL_NOT_FOUND: () => {\n        return message.includes('Model not found');\n      },\n      PARSING_EXCEPTION: () => {\n        return message.includes('sql.parser.ParsingException');\n      },\n    };\n    if (ModelSubstituteErrorEnum.MODEL_NOT_FOUND()) {\n      const modelName = message.split(': ')[1];\n      const dotCount = modelName.split('.').length - 1;\n      switch (dotCount) {\n        case 0:\n          return (\n            message +\n            `. Try adding both catalog and schema before your table name. e.g. my_database.public.${modelName}`\n          );\n        case 1:\n          return (\n            message +\n            `. Try adding the catalog before the schema in your table name. e.g. my_database.${modelName}`\n          );\n        case 2:\n          return (\n            message +\n            `. It may be missing from models, misnamed, or have a case mismatch.`\n          );\n        default:\n          return (\n            message +\n            `. It may be missing from models, misnamed, or have a case mismatch.`\n          );\n      }\n    } else if (ModelSubstituteErrorEnum.PARSING_EXCEPTION()) {\n      return (\n        message +\n        '. Please check your selected column and make sure its quoted for columns with non-alphanumeric characters.'\n      );\n    }\n    return message;\n  }\n\n  private buildQueryString(options: IbisQueryOptions) {\n    if (!options.cacheEnabled) {\n      return '';\n    }\n    const queryString = [];\n    queryString.push('cacheEnable=true');\n    if (options.refresh) {\n      queryString.push('overrideCache=true');\n    }\n    return `?${queryString.join('&')}`;\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/adaptors/index.ts",
    "content": "export * from './ibisAdaptor';\nexport * from './wrenAIAdaptor';\nexport * from './wrenEngineAdaptor';\n"
  },
  {
    "path": "wren-ui/src/apollo/server/adaptors/tests/ibisAdaptor.test.ts",
    "content": "import axios from 'axios';\nimport {\n  DryRunResponse,\n  IbisAdaptor,\n  IbisQueryOptions,\n  IbisQueryResponse,\n  ValidationRules,\n} from '../ibisAdaptor';\nimport { DataSourceName } from '../../types';\nimport { Manifest } from '../../mdl/type';\nimport { DialectSQL } from '../../models/adaptor';\nimport {\n  BIG_QUERY_CONNECTION_INFO,\n  CLICK_HOUSE_CONNECTION_INFO,\n  MS_SQL_CONNECTION_INFO,\n  MYSQL_CONNECTION_INFO,\n  POSTGRES_CONNECTION_INFO,\n  TRINO_CONNECTION_INFO,\n  SNOWFLAKE_CONNECTION_INFO,\n} from '../../repositories';\nimport { snakeCase } from 'lodash';\nimport { Encryptor } from '../../utils';\nimport { DEFAULT_PREVIEW_LIMIT } from '../../services';\n\njest.mock('axios');\njest.mock('@server/utils/encryptor');\nconst mockedAxios = axios as jest.Mocked<typeof axios>;\n// mock encryptor\nconst mockedEncryptor = Encryptor as jest.MockedClass<typeof Encryptor>;\n\ndescribe('IbisAdaptor', () => {\n  let ibisAdaptor: IbisAdaptor;\n  const ibisServerEndpoint = 'http://localhost:8080';\n\n  const mockMSSQLConnectionInfo: MS_SQL_CONNECTION_INFO = {\n    host: 'localhost',\n    port: 1433,\n    database: 'my-database',\n    user: 'my-user',\n    password: 'my-password',\n    trustServerCertificate: false,\n  };\n\n  const mockMySQLConnectionInfo: MYSQL_CONNECTION_INFO = {\n    host: 'localhost',\n    port: 3306,\n    database: 'my-database',\n    user: 'my-user',\n    password: 'my-password',\n    ssl: false,\n  };\n\n  const mockPostgresConnectionInfo: POSTGRES_CONNECTION_INFO = {\n    host: 'localhost',\n    port: 5432,\n    database: 'my-database',\n    user: 'my-user',\n    password: 'my-password',\n    ssl: true,\n  };\n\n  const mockClickHouseConnectionInfo: CLICK_HOUSE_CONNECTION_INFO = {\n    host: 'my-host',\n    port: 8443,\n    database: 'my-database',\n    user: 'my-user',\n    password: 'my-password',\n    ssl: true,\n  };\n  const { host, port, database, user, password } = mockPostgresConnectionInfo;\n  const postgresConnectionUrl = `postgresql://${user}:${password}@${host}:${port}/${database}?sslmode=require`;\n\n  const mockBigQueryConnectionInfo: BIG_QUERY_CONNECTION_INFO = {\n    projectId: 'my-bq-project-id',\n    datasetId: 'my-bq-dataset-id',\n    credentials: 'encrypted-credential-string',\n  };\n\n  const mockTrinoConnectionInfo: TRINO_CONNECTION_INFO = {\n    schemas: 'my-catalog.my-schema',\n    host: 'localhost',\n    port: 5450,\n    password: 'my-password',\n    ssl: true,\n    username: 'my-username',\n  };\n\n  const mockSnowflakeConnectionInfo: SNOWFLAKE_CONNECTION_INFO = {\n    user: 'my-user',\n    password: 'my-password',\n    account: 'my-account',\n    database: 'my-database',\n    schema: 'my-schema',\n  };\n\n  const mockManifest: Manifest = {\n    catalog: 'wrenai', // eg: \"test-catalog\"\n    schema: 'wrenai', // eg: \"test-schema\"\n    models: [\n      {\n        name: 'test_table',\n        tableReference: {\n          catalog: 'wrenai',\n          schema: 'wrenai',\n          table: 'test_table',\n        },\n        properties: {\n          description: 'test table',\n        },\n        columns: [\n          {\n            name: 'id',\n            type: 'integer',\n            properties: {},\n            isCalculated: false,\n          },\n          {\n            name: 'sumId',\n            type: 'float',\n            properties: {},\n            isCalculated: true,\n            expression: 'SUM(id)',\n          },\n        ],\n        cached: false,\n      },\n    ],\n    relationships: [],\n    views: [],\n  };\n\n  beforeEach(() => {\n    ibisAdaptor = new IbisAdaptor({\n      ibisServerEndpoint: ibisServerEndpoint,\n    });\n  });\n\n  afterEach(() => {\n    jest.resetAllMocks();\n  });\n\n  it('should get mssql constraints', async () => {\n    const mockResponse = { data: [] };\n    mockedAxios.post.mockResolvedValue(mockResponse);\n    // mock decrypt method in Encryptor to return the same password\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockMSSQLConnectionInfo.password }),\n    );\n\n    const result = await ibisAdaptor.getConstraints(\n      DataSourceName.MSSQL,\n      mockMSSQLConnectionInfo,\n    );\n    const expectConnectionInfo = Object.entries(mockMSSQLConnectionInfo).reduce(\n      (acc, [key, value]) => {\n        if (key === 'trustServerCertificate') {\n          if (value) {\n            acc['kwargs'] = { trustServerCertificate: 'YES' };\n            return acc;\n          }\n        } else {\n          acc[snakeCase(key)] = value;\n        }\n        return acc;\n      },\n      {},\n    );\n\n    expect(result).toEqual([]);\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      `${ibisServerEndpoint}/v2/connector/mssql/metadata/constraints`,\n      { connectionInfo: expectConnectionInfo },\n    );\n  });\n\n  it('should get mysql constraints', async () => {\n    const mockResponse = { data: [] };\n    mockedAxios.post.mockResolvedValue(mockResponse);\n    // mock decrypt method in Encryptor to return the same password\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockMySQLConnectionInfo.password }),\n    );\n\n    const result = await ibisAdaptor.getConstraints(\n      DataSourceName.MYSQL,\n      mockMySQLConnectionInfo,\n    );\n    const expectConnectionInfo = Object.entries(mockMySQLConnectionInfo).reduce(\n      (acc, [key, value]) => ((acc[snakeCase(key)] = value), acc),\n      {},\n    );\n\n    expect(result).toEqual([]);\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      `${ibisServerEndpoint}/v2/connector/mysql/metadata/constraints`,\n      { connectionInfo: expectConnectionInfo },\n    );\n  });\n\n  // check clickhouse connection info\n  it.each([\n    [\n      {\n        host: 'my-host',\n        port: 8443,\n        database: 'my-database',\n        user: 'my-user',\n        password: 'my-password',\n        ssl: true,\n      },\n      `clickhouse://my-user:my-password@my-host:8443/my-database?secure=1`,\n    ],\n    [\n      {\n        host: 'my-host',\n        port: 8443,\n        database: 'my-database',\n        user: 'my-user',\n        password: 'my-password',\n        ssl: false,\n      },\n      `clickhouse://my-user:my-password@my-host:8443/my-database?`,\n    ],\n  ])(\n    'should get correct clickhouse connection info',\n    async (connectionInfo, expectConnectionUrl) => {\n      const mockResponse = { data: [] };\n      mockedAxios.post.mockResolvedValue(mockResponse);\n      // mock decrypt method in Encryptor to return the same password\n      mockedEncryptor.prototype.decrypt.mockReturnValue(\n        JSON.stringify({ password: connectionInfo.password }),\n      );\n\n      const result = await ibisAdaptor.getConstraints(\n        DataSourceName.CLICK_HOUSE,\n        connectionInfo,\n      );\n      const expectConnectionInfo = {\n        connectionUrl: expectConnectionUrl,\n      };\n\n      expect(result).toEqual([]);\n      expect(mockedAxios.post).toHaveBeenCalledWith(\n        `${ibisServerEndpoint}/v2/connector/clickhouse/metadata/constraints`,\n        { connectionInfo: expectConnectionInfo },\n      );\n    },\n  );\n\n  it('should get trino constraints', async () => {\n    const mockResponse = { data: [] };\n    mockedAxios.post.mockResolvedValue(mockResponse);\n\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockTrinoConnectionInfo.password }),\n    );\n\n    const result = await ibisAdaptor.getConstraints(\n      DataSourceName.TRINO,\n      mockTrinoConnectionInfo,\n    );\n\n    const { username, host, password, port, schemas } = mockTrinoConnectionInfo;\n    const schemasArray = schemas.split(',');\n    const [catalog, schema] = schemasArray[0].split('.');\n    const expectConnectionInfo = {\n      catalog,\n      host: `https://${host}`,\n      password,\n      port,\n      schema,\n      user: username,\n    };\n\n    expect(result).toEqual([]);\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      `${ibisServerEndpoint}/v2/connector/trino/metadata/constraints`,\n      { connectionInfo: expectConnectionInfo },\n    );\n  });\n\n  it('should get snowflake constraints', async () => {\n    const mockResponse = { data: [] };\n    mockedAxios.post.mockResolvedValue(mockResponse);\n    // mock decrypt method in Encryptor to return the same password\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockSnowflakeConnectionInfo.password }),\n    );\n\n    const result = await ibisAdaptor.getConstraints(\n      DataSourceName.SNOWFLAKE,\n      mockSnowflakeConnectionInfo,\n    );\n    const expectConnectionInfo = Object.entries(\n      mockSnowflakeConnectionInfo,\n    ).reduce((acc, [key, value]) => ((acc[snakeCase(key)] = value), acc), {});\n\n    expect(result).toEqual([]);\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      `${ibisServerEndpoint}/v2/connector/snowflake/metadata/constraints`,\n      { connectionInfo: expectConnectionInfo },\n    );\n  });\n\n  it('should get click house constraints', async () => {\n    const mockResponse = { data: [] };\n    mockedAxios.post.mockResolvedValue(mockResponse);\n    // mock decrypt method in Encryptor to return the same password\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockClickHouseConnectionInfo.password }),\n    );\n\n    const result = await ibisAdaptor.getConstraints(\n      DataSourceName.CLICK_HOUSE,\n      mockClickHouseConnectionInfo,\n    );\n    const { user, password, host, port, database, ssl } =\n      mockClickHouseConnectionInfo;\n    const expectConnectionInfo = {\n      connectionUrl: `clickhouse://${user}:${password}@${host}:${port}/${database}${ssl ? '?secure=1' : ''}`,\n    };\n\n    expect(result).toEqual([]);\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      `${ibisServerEndpoint}/v2/connector/clickhouse/metadata/constraints`,\n      { connectionInfo: expectConnectionInfo },\n    );\n  });\n\n  it('should get postgres constraints', async () => {\n    const mockResponse = { data: [] };\n    mockedAxios.post.mockResolvedValue(mockResponse);\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    const result = await ibisAdaptor.getConstraints(\n      DataSourceName.POSTGRES,\n      mockPostgresConnectionInfo,\n    );\n\n    expect(result).toEqual([]);\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      `${ibisServerEndpoint}/v2/connector/postgres/metadata/constraints`,\n      {\n        connectionInfo: {\n          connectionUrl: postgresConnectionUrl,\n        },\n      },\n    );\n  });\n\n  it('should get bigquery constraints', async () => {\n    const mockResponse = { data: [] };\n    mockedAxios.post.mockResolvedValue(mockResponse);\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ credentials: mockBigQueryConnectionInfo.credentials }),\n    );\n    const result = await ibisAdaptor.getConstraints(\n      DataSourceName.BIG_QUERY,\n      mockBigQueryConnectionInfo,\n    );\n    const expectConnectionInfo = Object.entries(\n      mockBigQueryConnectionInfo,\n    ).reduce((acc, [key, value]) => {\n      if (key === 'credentials') {\n        acc['credentials'] = Buffer.from(\n          JSON.stringify(mockBigQueryConnectionInfo.credentials),\n        ).toString('base64');\n      } else {\n        acc[snakeCase(key)] = value;\n      }\n      return acc;\n    }, {});\n\n    expect(result).toEqual([]);\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      `${ibisServerEndpoint}/v2/connector/bigquery/metadata/constraints`,\n      { connectionInfo: expectConnectionInfo },\n    );\n  });\n\n  it('should validate with rule COLUMN_IS_VALID', async () => {\n    mockedAxios.post.mockResolvedValue(true);\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    const parameters = {\n      modelName: 'test_table',\n      columnName: 'sumId',\n    };\n    const result = await ibisAdaptor.validate(\n      DataSourceName.POSTGRES,\n      ValidationRules.COLUMN_IS_VALID,\n      mockPostgresConnectionInfo,\n      mockManifest,\n      parameters,\n    );\n\n    expect(result).toEqual({ valid: true, message: null });\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      `${ibisServerEndpoint}/v3/connector/postgres/validate/column_is_valid`,\n      {\n        connectionInfo: { connectionUrl: postgresConnectionUrl },\n        manifestStr: Buffer.from(JSON.stringify(mockManifest)).toString(\n          'base64',\n        ),\n        parameters,\n      },\n    );\n  });\n\n  it('should handle error when validating', async () => {\n    const mockError = { response: { data: 'Error' } };\n    const parameters = {\n      modelName: 'test_table',\n      columnName: 'sumId',\n    };\n    mockedAxios.post.mockRejectedValue(mockError);\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    const result = await ibisAdaptor.validate(\n      DataSourceName.POSTGRES,\n      ValidationRules.COLUMN_IS_VALID,\n      mockPostgresConnectionInfo,\n      mockManifest,\n      parameters,\n    );\n\n    expect(result).toEqual({ valid: false, message: 'Error' });\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      `${ibisServerEndpoint}/v3/connector/postgres/validate/column_is_valid`,\n      {\n        connectionInfo: { connectionUrl: postgresConnectionUrl },\n        manifestStr: Buffer.from(JSON.stringify(mockManifest)).toString(\n          'base64',\n        ),\n        parameters,\n      },\n    );\n  });\n\n  it('should get data, correlationId and processTime', async () => {\n    mockedAxios.post.mockResolvedValue({\n      data: {\n        columns: [],\n        data: [],\n        dtypes: {},\n      },\n      headers: {\n        'x-correlation-id': '123',\n        'x-process-time': '1s',\n      },\n    });\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    const res: IbisQueryResponse = await ibisAdaptor.query(\n      'SELECT * FROM test_table',\n      {\n        dataSource: DataSourceName.POSTGRES,\n        connectionInfo: mockPostgresConnectionInfo,\n        mdl: mockManifest,\n        limit: 10,\n      } as IbisQueryOptions,\n    );\n\n    expect(res.data).toEqual([]);\n    expect(res.correlationId).toEqual('123');\n    expect(res.processTime).toEqual('1s');\n  });\n\n  it('should handle query with cache-related headers', async () => {\n    mockedAxios.post.mockResolvedValue({\n      data: {\n        columns: ['id'],\n        data: [[1]],\n        dtypes: { id: 'integer' },\n      },\n      headers: {\n        'x-correlation-id': '123',\n        'x-process-time': '1s',\n        'x-cache-hit': 'true',\n        'x-cache-create-at': '2024-01-01T00:00:00Z',\n        'x-cache-override': 'false',\n        'x-cache-override-at': '2024-01-01T00:00:00Z',\n      },\n    });\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    const res: IbisQueryResponse = await ibisAdaptor.query(\n      'SELECT * FROM test_table',\n      {\n        dataSource: DataSourceName.POSTGRES,\n        connectionInfo: mockPostgresConnectionInfo,\n        mdl: mockManifest,\n        cacheEnabled: true,\n      } as IbisQueryOptions,\n    );\n\n    expect(res.data).toEqual([[1]]);\n    expect(res.columns).toEqual(['id']);\n    expect(res.dtypes).toEqual({ id: 'integer' });\n    expect(res.cacheHit).toEqual(true);\n    expect(new Date(res.cacheCreatedAt).getTime()).toBeGreaterThan(0);\n    expect(res.override).toEqual(false);\n    expect(new Date(res.cacheOverrodeAt).getTime()).toBeGreaterThan(0);\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      `${ibisServerEndpoint}/v3/connector/postgres/query?cacheEnable=true`,\n      expect.any(Object),\n      expect.any(Object),\n    );\n  });\n\n  it('should handle query with cache refresh', async () => {\n    mockedAxios.post.mockResolvedValue({\n      data: {\n        columns: ['id'],\n        data: [[1]],\n        dtypes: { id: 'integer' },\n      },\n      headers: {\n        'x-correlation-id': '123',\n        'x-process-time': '1s',\n      },\n    });\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    const res: IbisQueryResponse = await ibisAdaptor.query(\n      'SELECT * FROM test_table',\n      {\n        dataSource: DataSourceName.POSTGRES,\n        connectionInfo: mockPostgresConnectionInfo,\n        mdl: mockManifest,\n        cacheEnabled: true,\n        refresh: true,\n      } as IbisQueryOptions,\n    );\n\n    expect(res.data).toEqual([[1]]);\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      `${ibisServerEndpoint}/v3/connector/postgres/query?cacheEnable=true&overrideCache=true`,\n      expect.any(Object),\n      expect.any(Object),\n    );\n  });\n\n  it('should use default limit when not specified', async () => {\n    mockedAxios.post.mockResolvedValue({\n      data: {\n        columns: ['id'],\n        data: [[1]],\n        dtypes: { id: 'integer' },\n      },\n      headers: {\n        'x-correlation-id': '123',\n        'x-process-time': '1s',\n      },\n    });\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    await ibisAdaptor.query('SELECT * FROM test_table', {\n      dataSource: DataSourceName.POSTGRES,\n      connectionInfo: mockPostgresConnectionInfo,\n      mdl: mockManifest,\n    } as IbisQueryOptions);\n\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      expect.any(String),\n      expect.any(Object),\n      {\n        params: {\n          limit: DEFAULT_PREVIEW_LIMIT,\n        },\n      },\n    );\n  });\n\n  it('should use custom limit when specified', async () => {\n    mockedAxios.post.mockResolvedValue({\n      data: {\n        columns: ['id'],\n        data: [[1]],\n        dtypes: { id: 'integer' },\n      },\n      headers: {\n        'x-correlation-id': '123',\n        'x-process-time': '1s',\n      },\n    });\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    const customLimit = 50;\n    await ibisAdaptor.query('SELECT * FROM test_table', {\n      dataSource: DataSourceName.POSTGRES,\n      connectionInfo: mockPostgresConnectionInfo,\n      mdl: mockManifest,\n      limit: customLimit,\n    } as IbisQueryOptions);\n\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      expect.any(String),\n      expect.any(Object),\n      {\n        params: {\n          limit: customLimit,\n        },\n      },\n    );\n  });\n\n  it('should throw an exception with correlationId and processTime when query fails', async () => {\n    const mockError = {\n      response: {\n        data: 'Error message',\n        headers: {\n          'x-correlation-id': '123',\n          'x-process-time': '1s',\n        },\n      },\n    };\n    mockedAxios.post.mockRejectedValue(mockError);\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    await expect(\n      ibisAdaptor.query('SELECT * FROM test_table', {\n        dataSource: DataSourceName.POSTGRES,\n        connectionInfo: mockPostgresConnectionInfo,\n        mdl: mockManifest,\n        limit: 10,\n      }),\n    ).rejects.toMatchObject({\n      message: 'Error message',\n      extensions: {\n        other: {\n          correlationId: '123',\n          processTime: '1s',\n        },\n      },\n    });\n  });\n\n  it('should get data, correlationId and processTime when dry run succeeds', async () => {\n    mockedAxios.post.mockResolvedValue({\n      headers: {\n        'x-correlation-id': '123',\n        'x-process-time': '1s',\n      },\n    });\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    const res: DryRunResponse = await ibisAdaptor.dryRun(\n      'SELECT * FROM test_table',\n      {\n        dataSource: DataSourceName.POSTGRES,\n        connectionInfo: mockPostgresConnectionInfo,\n        mdl: mockManifest,\n      } as IbisQueryOptions,\n    );\n\n    expect(res.correlationId).toEqual('123');\n    expect(res.processTime).toEqual('1s');\n  });\n\n  it('should throw an exception with correlationId and processTime when dry run fails', async () => {\n    const mockError = {\n      response: {\n        data: 'Error message',\n        headers: {\n          'x-correlation-id': '123',\n          'x-process-time': '1s',\n        },\n      },\n    };\n    mockedAxios.post.mockRejectedValue(mockError);\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    await expect(\n      ibisAdaptor.dryRun('SELECT * FROM test_table', {\n        dataSource: DataSourceName.POSTGRES,\n        connectionInfo: mockPostgresConnectionInfo,\n        mdl: mockManifest,\n      }),\n    ).rejects.toMatchObject({\n      message: 'Error message',\n      extensions: {\n        other: {\n          correlationId: '123',\n          processTime: '1s',\n        },\n      },\n    });\n  });\n\n  it('should successfully substitute SQL with model', async () => {\n    const mockResponse = { data: 'SELECT * FROM substituted_table' };\n    mockedAxios.post.mockResolvedValue(mockResponse);\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    const result = await ibisAdaptor.modelSubstitute(\n      'SELECT * FROM test_table' as DialectSQL,\n      {\n        dataSource: DataSourceName.POSTGRES,\n        connectionInfo: mockPostgresConnectionInfo,\n        mdl: mockManifest,\n      },\n    );\n\n    expect(result).toEqual('SELECT * FROM substituted_table');\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      `${ibisServerEndpoint}/v3/connector/postgres/model-substitute`,\n      {\n        sql: 'SELECT * FROM test_table',\n        connectionInfo: { connectionUrl: postgresConnectionUrl },\n        manifestStr: Buffer.from(JSON.stringify(mockManifest)).toString(\n          'base64',\n        ),\n      },\n      {\n        headers: {\n          'X-User-CATALOG': undefined,\n          'X-User-SCHEMA': undefined,\n        },\n      },\n    );\n  });\n\n  it('should handle error when model substitution fails with MODEL_NOT_FOUND', async () => {\n    const mockError = {\n      response: {\n        data: 'Model not found: test_table',\n        headers: {\n          'x-correlation-id': '123',\n          'x-process-time': '1s',\n        },\n      },\n    };\n    mockedAxios.post.mockRejectedValue(mockError);\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    await expect(\n      ibisAdaptor.modelSubstitute('SELECT * FROM test_table' as DialectSQL, {\n        dataSource: DataSourceName.POSTGRES,\n        connectionInfo: mockPostgresConnectionInfo,\n        mdl: mockManifest,\n      }),\n    ).rejects.toMatchObject({\n      message:\n        'Model not found: test_table. Try adding both catalog and schema before your table name. e.g. my_database.public.test_table',\n      extensions: {\n        other: {\n          correlationId: '123',\n          processTime: '1s',\n        },\n      },\n    });\n  });\n\n  it('should handle error when model substitution fails with MODEL_NOT_FOUND and one dot in model name', async () => {\n    const mockError = {\n      response: {\n        data: 'Model not found: public.test_table',\n        headers: {\n          'x-correlation-id': '123',\n          'x-process-time': '1s',\n        },\n      },\n    };\n    mockedAxios.post.mockRejectedValue(mockError);\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    await expect(\n      ibisAdaptor.modelSubstitute(\n        'SELECT * FROM public.test_table' as DialectSQL,\n        {\n          dataSource: DataSourceName.POSTGRES,\n          connectionInfo: mockPostgresConnectionInfo,\n          mdl: mockManifest,\n        },\n      ),\n    ).rejects.toMatchObject({\n      message:\n        'Model not found: public.test_table. Try adding the catalog before the schema in your table name. e.g. my_database.public.test_table',\n      extensions: {\n        other: {\n          correlationId: '123',\n          processTime: '1s',\n        },\n      },\n    });\n  });\n\n  it('should handle error when model substitution fails with MODEL_NOT_FOUND and two dots in model name', async () => {\n    const mockError = {\n      response: {\n        data: 'Model not found: my_database.public.test_table',\n        headers: {\n          'x-correlation-id': '123',\n          'x-process-time': '1s',\n        },\n      },\n    };\n    mockedAxios.post.mockRejectedValue(mockError);\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    await expect(\n      ibisAdaptor.modelSubstitute(\n        'SELECT * FROM my_database.public.test_table' as DialectSQL,\n        {\n          dataSource: DataSourceName.POSTGRES,\n          connectionInfo: mockPostgresConnectionInfo,\n          mdl: mockManifest,\n        },\n      ),\n    ).rejects.toMatchObject({\n      message:\n        'Model not found: my_database.public.test_table. It may be missing from models, misnamed, or have a case mismatch.',\n      extensions: {\n        other: {\n          correlationId: '123',\n          processTime: '1s',\n        },\n      },\n    });\n  });\n\n  it('should handle error when model substitution fails with MODEL_NOT_FOUND and more than two dots in model name', async () => {\n    const mockError = {\n      response: {\n        data: 'Model not found: my_database.public.schema.test_table',\n        headers: {\n          'x-correlation-id': '123',\n          'x-process-time': '1s',\n        },\n      },\n    };\n    mockedAxios.post.mockRejectedValue(mockError);\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    await expect(\n      ibisAdaptor.modelSubstitute(\n        'SELECT * FROM my_database.public.schema.test_table' as DialectSQL,\n        {\n          dataSource: DataSourceName.POSTGRES,\n          connectionInfo: mockPostgresConnectionInfo,\n          mdl: mockManifest,\n        },\n      ),\n    ).rejects.toMatchObject({\n      message:\n        'Model not found: my_database.public.schema.test_table. It may be missing from models, misnamed, or have a case mismatch.',\n      extensions: {\n        other: {\n          correlationId: '123',\n          processTime: '1s',\n        },\n      },\n    });\n  });\n\n  it('should handle error when model substitution fails with PARSING_EXCEPTION', async () => {\n    const mockError = {\n      response: {\n        data: 'sql.parser.ParsingException: Invalid SQL syntax',\n        headers: {\n          'x-correlation-id': '123',\n          'x-process-time': '1s',\n        },\n      },\n    };\n    mockedAxios.post.mockRejectedValue(mockError);\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    await expect(\n      ibisAdaptor.modelSubstitute('SELECT * FROM test_table' as DialectSQL, {\n        dataSource: DataSourceName.POSTGRES,\n        connectionInfo: mockPostgresConnectionInfo,\n        mdl: mockManifest,\n      }),\n    ).rejects.toMatchObject({\n      message:\n        'sql.parser.ParsingException: Invalid SQL syntax. Please check your selected column and make sure its quoted for columns with non-alphanumeric characters.',\n      extensions: {\n        other: {\n          correlationId: '123',\n          processTime: '1s',\n        },\n      },\n    });\n  });\n\n  it('should handle error when model substitution fails with generic error', async () => {\n    const mockError = {\n      response: {\n        data: 'Generic error occurred',\n        headers: {\n          'x-correlation-id': '123',\n          'x-process-time': '1s',\n        },\n      },\n    };\n    mockedAxios.post.mockRejectedValue(mockError);\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    await expect(\n      ibisAdaptor.modelSubstitute('SELECT * FROM test_table' as DialectSQL, {\n        dataSource: DataSourceName.POSTGRES,\n        connectionInfo: mockPostgresConnectionInfo,\n        mdl: mockManifest,\n      }),\n    ).rejects.toMatchObject({\n      message: 'Generic error occurred',\n      extensions: {\n        other: {\n          correlationId: '123',\n          processTime: '1s',\n        },\n      },\n    });\n  });\n\n  it('should include catalog and schema in headers when provided', async () => {\n    const mockResponse = { data: 'SELECT * FROM substituted_table' };\n    mockedAxios.post.mockResolvedValue(mockResponse);\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    const catalog = 'my_catalog';\n    const schema = 'my_schema';\n\n    const result = await ibisAdaptor.modelSubstitute(\n      'SELECT * FROM test_table' as DialectSQL,\n      {\n        dataSource: DataSourceName.POSTGRES,\n        connectionInfo: mockPostgresConnectionInfo,\n        mdl: mockManifest,\n        catalog,\n        schema,\n      },\n    );\n\n    expect(result).toEqual('SELECT * FROM substituted_table');\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      `${ibisServerEndpoint}/v3/connector/postgres/model-substitute`,\n      {\n        sql: 'SELECT * FROM test_table',\n        connectionInfo: { connectionUrl: postgresConnectionUrl },\n        manifestStr: Buffer.from(JSON.stringify(mockManifest)).toString(\n          'base64',\n        ),\n      },\n      {\n        headers: {\n          'X-User-CATALOG': catalog,\n          'X-User-SCHEMA': schema,\n        },\n      },\n    );\n  });\n\n  it('should get version successfully', async () => {\n    const mockVersion = '1.2.3';\n    mockedAxios.post.mockResolvedValue({ data: mockVersion });\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    const result = await ibisAdaptor.getVersion(\n      DataSourceName.POSTGRES,\n      mockPostgresConnectionInfo,\n    );\n\n    expect(result).toEqual(mockVersion);\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      `${ibisServerEndpoint}/v2/connector/postgres/metadata/version`,\n      {\n        connectionInfo: { connectionUrl: postgresConnectionUrl },\n      },\n    );\n  });\n\n  it('should throw an error when getting version fails', async () => {\n    const mockError = {\n      response: {\n        data: 'Failed to get version',\n        headers: {\n          'x-correlation-id': '123',\n          'x-process-time': '1s',\n        },\n      },\n    };\n    mockedAxios.post.mockRejectedValue(mockError);\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockPostgresConnectionInfo.password }),\n    );\n\n    await expect(\n      ibisAdaptor.getVersion(\n        DataSourceName.POSTGRES,\n        mockPostgresConnectionInfo,\n      ),\n    ).rejects.toMatchObject({\n      message: 'Failed to get version',\n      extensions: {\n        other: {\n          correlationId: '123',\n          processTime: '1s',\n        },\n      },\n    });\n  });\n\n  it('should get version for different data sources', async () => {\n    const mockVersion = '1.2.3';\n    mockedAxios.post.mockResolvedValue({ data: mockVersion });\n\n    // Test BigQuery\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ credentials: mockBigQueryConnectionInfo.credentials }),\n    );\n\n    const bigQueryResult = await ibisAdaptor.getVersion(\n      DataSourceName.BIG_QUERY,\n      mockBigQueryConnectionInfo,\n    );\n\n    expect(bigQueryResult).toEqual(mockVersion);\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      `${ibisServerEndpoint}/v2/connector/bigquery/metadata/version`,\n      {\n        connectionInfo: {\n          project_id: mockBigQueryConnectionInfo.projectId,\n          dataset_id: mockBigQueryConnectionInfo.datasetId,\n          credentials: Buffer.from(\n            JSON.stringify(mockBigQueryConnectionInfo.credentials),\n          ).toString('base64'),\n        },\n      },\n    );\n\n    // Test Snowflake\n    mockedEncryptor.prototype.decrypt.mockReturnValue(\n      JSON.stringify({ password: mockSnowflakeConnectionInfo.password }),\n    );\n\n    const snowflakeResult = await ibisAdaptor.getVersion(\n      DataSourceName.SNOWFLAKE,\n      mockSnowflakeConnectionInfo,\n    );\n\n    expect(snowflakeResult).toEqual(mockVersion);\n    expect(mockedAxios.post).toHaveBeenCalledWith(\n      `${ibisServerEndpoint}/v2/connector/snowflake/metadata/version`,\n      {\n        connectionInfo: {\n          user: mockSnowflakeConnectionInfo.user,\n          password: mockSnowflakeConnectionInfo.password,\n          account: mockSnowflakeConnectionInfo.account,\n          database: mockSnowflakeConnectionInfo.database,\n          schema: mockSnowflakeConnectionInfo.schema,\n        },\n      },\n    );\n  });\n});\n"
  },
  {
    "path": "wren-ui/src/apollo/server/adaptors/tests/wrenAIAdaptor.test.ts",
    "content": "import axios from 'axios';\nimport { WrenAIAdaptor } from '../wrenAIAdaptor';\nimport {\n  RecommendationQuestionsInput,\n  RecommendationQuestionStatus,\n} from '@server/models/adaptor';\nimport { Manifest } from '../../mdl/type';\n\njest.mock('axios');\nconst mockedAxios = axios as jest.Mocked<typeof axios>;\n\nconst sampleManifest: Manifest = {\n  models: [\n    {\n      name: 'model1',\n      columns: [\n        {\n          name: 'column1',\n          type: 'string',\n          isCalculated: false,\n        },\n      ],\n    },\n  ],\n};\n\ndescribe('WrenAIAdaptor', () => {\n  const baseEndpoint = 'http://test-endpoint';\n  let adaptor: WrenAIAdaptor;\n\n  beforeEach(() => {\n    adaptor = new WrenAIAdaptor({ wrenAIBaseEndpoint: baseEndpoint });\n    jest.clearAllMocks();\n  });\n\n  describe('generateRecommendationQuestions', () => {\n    const mockInput: RecommendationQuestionsInput = {\n      manifest: sampleManifest,\n      previousQuestions: ['What is sales by region?'],\n      projectId: 'project-123',\n      maxQuestions: 5,\n      maxCategories: 3,\n      configuration: {\n        language: 'English',\n      },\n    };\n\n    it('should successfully generate recommendation questions', async () => {\n      const mockQueryId = 'query-123';\n      mockedAxios.post.mockResolvedValueOnce({ data: { id: mockQueryId } });\n\n      const result = await adaptor.generateRecommendationQuestions(mockInput);\n\n      expect(result).toEqual({ queryId: mockQueryId });\n      expect(mockedAxios.post).toHaveBeenCalledWith(\n        `${baseEndpoint}/v1/question-recommendations`,\n        {\n          mdl: JSON.stringify(mockInput.manifest),\n          previous_questions: mockInput.previousQuestions,\n          project_id: mockInput.projectId,\n          max_questions: mockInput.maxQuestions,\n          max_categories: mockInput.maxCategories,\n          configuration: mockInput.configuration,\n        },\n      );\n    });\n\n    it('should handle errors when generating recommendation questions', async () => {\n      const errorMessage = 'Network error';\n      mockedAxios.post.mockRejectedValueOnce(new Error(errorMessage));\n\n      await expect(\n        adaptor.generateRecommendationQuestions(mockInput),\n      ).rejects.toThrow(errorMessage);\n    });\n  });\n\n  describe('getRecommendationQuestionsResult', () => {\n    const queryId = 'query-123';\n\n    it('should successfully get recommendation questions result', async () => {\n      const mockResponse = {\n        status: 'FINISHED',\n        response: {\n          questions: [\n            {\n              question: 'What is the total revenue?',\n              explanation: 'This shows overall business performance',\n              category: 'Revenue',\n            },\n          ],\n        },\n      };\n\n      mockedAxios.get.mockResolvedValueOnce({ data: mockResponse });\n\n      const result = await adaptor.getRecommendationQuestionsResult(queryId);\n\n      expect(result).toEqual({\n        status: RecommendationQuestionStatus.FINISHED,\n        error: null,\n        ...mockResponse,\n      });\n      expect(mockedAxios.get).toHaveBeenCalledWith(\n        `${baseEndpoint}/v1/question-recommendations/${queryId}/result`,\n      );\n    });\n\n    it('should handle errors when getting recommendation questions result', async () => {\n      const errorMessage = 'Network error';\n      mockedAxios.get.mockRejectedValueOnce(new Error(errorMessage));\n\n      await expect(\n        adaptor.getRecommendationQuestionsResult(queryId),\n      ).rejects.toThrow(errorMessage);\n    });\n  });\n});\n"
  },
  {
    "path": "wren-ui/src/apollo/server/adaptors/wrenAIAdaptor.ts",
    "content": "import axios from 'axios';\nimport { Readable } from 'stream';\nimport {\n  AskCandidateType,\n  AskDetailInput,\n  AskDetailResult,\n  AskHistory,\n  AskResult,\n  AskResultStatus,\n  AsyncQueryResponse,\n  RecommendationQuestionsInput,\n  RecommendationQuestionsResult,\n  WrenAIDeployStatusEnum,\n  WrenAISystemStatus,\n  WrenAIDeployResponse,\n  DeployData,\n  AskInput,\n  TextBasedAnswerInput,\n  TextBasedAnswerResult,\n  ChartInput,\n  ChartAdjustmentInput,\n  ChartResult,\n  ChartStatus,\n  TextBasedAnswerStatus,\n  SqlPairResult,\n  SqlPairStatus,\n  QuestionInput,\n  QuestionsResult,\n  QuestionsStatus,\n  GenerateInstructionInput,\n  InstructionStatus,\n  InstructionResult,\n  AskFeedbackInput,\n  AskFeedbackResult,\n  AskFeedbackStatus,\n} from '@server/models/adaptor';\nimport { getLogger } from '@server/utils';\nimport * as Errors from '@server/utils/error';\nimport { SqlPair } from '../repositories';\nimport { ThreadResponse } from '@server/repositories';\n\nconst logger = getLogger('WrenAIAdaptor');\nlogger.level = 'debug';\n\nconst getAIServiceError = (error: any) => {\n  const { data } = error.response || {};\n  return data?.detail\n    ? `${error.message}, detail: ${data.detail}`\n    : error.message;\n};\n\nexport interface IWrenAIAdaptor {\n  deploy(deployData: DeployData): Promise<WrenAIDeployResponse>;\n  delete(projectId: number): Promise<void>;\n\n  /**\n   * Ask AI service a question.\n   * AI service will return anwser candidates containing sql.\n   * 1. use ask() to ask a question, AI service will return a queryId\n   * 2. use getAskResult() to get the result of the queryId\n   * 3. use cancelAsk() to cancel the query\n   **/\n  ask(input: AskInput): Promise<AsyncQueryResponse>;\n  cancelAsk(queryId: string): Promise<void>;\n  getAskResult(queryId: string): Promise<AskResult>;\n  getAskStreamingResult(queryId: string): Promise<Readable>;\n\n  /**\n   * After you choose a candidate, you can request AI service to generate the detail.\n   * 1. use generateAskDetail() to generate the detail. AI service will return a queryId\n   * 2. use getAskDetailResult() to get the result of the queryId\n   */\n  generateAskDetail(input: AskDetailInput): Promise<AsyncQueryResponse>;\n  getAskDetailResult(queryId: string): Promise<AskDetailResult>;\n\n  /**\n   * Generate recommendation questions\n   */\n  generateRecommendationQuestions(\n    input: RecommendationQuestionsInput,\n  ): Promise<AsyncQueryResponse>;\n  getRecommendationQuestionsResult(\n    queryId: string,\n  ): Promise<RecommendationQuestionsResult>;\n\n  /**\n   * Get text-based answer from SQL\n   */\n  createTextBasedAnswer(\n    input: TextBasedAnswerInput,\n  ): Promise<AsyncQueryResponse>;\n  getTextBasedAnswerResult(queryId: string): Promise<TextBasedAnswerResult>;\n  streamTextBasedAnswer(queryId: string): Promise<Readable>;\n\n  /**\n   * Chart related APIs\n   */\n  generateChart(input: ChartInput): Promise<AsyncQueryResponse>;\n  getChartResult(queryId: string): Promise<ChartResult>;\n  cancelChart(queryId: string): Promise<void>;\n  adjustChart(input: ChartAdjustmentInput): Promise<AsyncQueryResponse>;\n  getChartAdjustmentResult(queryId: string): Promise<ChartResult>;\n  cancelChartAdjustment(queryId: string): Promise<void>;\n\n  /**\n   * Sql Pair APIs\n   */\n  deploySqlPair(\n    projectId: number,\n    sqlPair: { question: string; sql: string },\n  ): Promise<AsyncQueryResponse>;\n  getSqlPairResult(queryId: string): Promise<SqlPairResult>;\n  deleteSqlPairs(projectId: number, sqlPairIds: number[]): Promise<void>;\n  generateQuestions(input: QuestionInput): Promise<AsyncQueryResponse>;\n  getQuestionsResult(queryId: string): Promise<Partial<QuestionsResult>>;\n\n  /**\n   * instruction related APIs\n   */\n  generateInstruction(\n    input: GenerateInstructionInput[],\n  ): Promise<AsyncQueryResponse>;\n  getInstructionResult(queryId: string): Promise<InstructionResult>;\n  deleteInstructions(ids: number[], projectId: number): Promise<void>;\n\n  /**\n   * Ask feedback APIs\n   */\n  createAskFeedback(input: AskFeedbackInput): Promise<AsyncQueryResponse>;\n  getAskFeedbackResult(queryId: string): Promise<AskFeedbackResult>;\n  cancelAskFeedback(queryId: string): Promise<void>;\n}\n\nexport class WrenAIAdaptor implements IWrenAIAdaptor {\n  private readonly wrenAIBaseEndpoint: string;\n\n  constructor({ wrenAIBaseEndpoint }: { wrenAIBaseEndpoint: string }) {\n    this.wrenAIBaseEndpoint = wrenAIBaseEndpoint;\n  }\n\n  public async delete(projectId: number): Promise<void> {\n    try {\n      if (!projectId) {\n        throw new Error('Project ID is required');\n      }\n      const url = `${this.wrenAIBaseEndpoint}/v1/semantics`;\n      const response = await axios.delete(url, {\n        params: {\n          project_id: projectId.toString(),\n        },\n      });\n\n      if (response.status === 200) {\n        logger.info(`Wren AI: Deleted semantics for project ${projectId}`);\n      } else {\n        throw new Error(`Failed to delete semantics. ${response.data?.error}`);\n      }\n    } catch (error: any) {\n      throw new Error(\n        `Wren AI: Failed to delete semantics: ${getAIServiceError(error)}`,\n      );\n    }\n  }\n\n  public async deploySqlPair(\n    projectId: number,\n    sqlPair: Partial<SqlPair>,\n  ): Promise<AsyncQueryResponse> {\n    try {\n      const body = {\n        sql_pairs: [\n          {\n            id: `${sqlPair.id}`,\n            sql: sqlPair.sql,\n            question: sqlPair.question,\n          },\n        ],\n        project_id: projectId.toString(),\n      };\n\n      return axios\n        .post(`${this.wrenAIBaseEndpoint}/v1/sql-pairs`, body)\n        .then((res) => {\n          return { queryId: res.data.event_id };\n        });\n    } catch (err: any) {\n      logger.debug(\n        `Got error when deploying SQL pair: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n  public async getSqlPairResult(queryId: string): Promise<SqlPairResult> {\n    try {\n      const res = await axios.get(\n        `${this.wrenAIBaseEndpoint}/v1/sql-pairs/${queryId}`,\n      );\n      const { status, error } = this.transformStatusAndError(res.data);\n      return {\n        status: status as SqlPairStatus,\n        error,\n      };\n    } catch (err: any) {\n      logger.debug(\n        `Got error when getting SQL pair result: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n  public async deleteSqlPairs(\n    projectId: number,\n    sqlPairIds: number[],\n  ): Promise<void> {\n    try {\n      await axios.delete(`${this.wrenAIBaseEndpoint}/v1/sql-pairs`, {\n        data: {\n          sql_pair_ids: sqlPairIds.map((id) => id.toString()),\n          project_id: projectId.toString(),\n        },\n      });\n      return;\n    } catch (err: any) {\n      logger.debug(\n        `Got error when deleting SQL pair: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  /**\n   * Ask AI service a question.\n   * AI service will return anwser candidates containing sql.\n   */\n\n  public async ask(input: AskInput): Promise<AsyncQueryResponse> {\n    try {\n      const res = await axios.post(`${this.wrenAIBaseEndpoint}/v1/asks`, {\n        query: input.query,\n        id: input.deployId,\n        histories: this.transformHistoryInput(input.histories),\n        configurations: input.configurations,\n      });\n      return { queryId: res.data.query_id };\n    } catch (err: any) {\n      logger.debug(`Got error when asking wren AI: ${getAIServiceError(err)}`);\n      throw err;\n    }\n  }\n\n  public async cancelAsk(queryId: string): Promise<void> {\n    // make PATCH request /v1/asks/:query_id to cancel the query\n    try {\n      await axios.patch(`${this.wrenAIBaseEndpoint}/v1/asks/${queryId}`, {\n        status: 'stopped',\n      });\n    } catch (err: any) {\n      logger.debug(`Got error when canceling ask: ${getAIServiceError(err)}`);\n      throw err;\n    }\n  }\n\n  public async getAskResult(queryId: string): Promise<AskResult> {\n    // make GET request /v1/asks/:query_id/result to get the result\n    try {\n      const res = await axios.get(\n        `${this.wrenAIBaseEndpoint}/v1/asks/${queryId}/result`,\n      );\n      return this.transformAskResult(res.data);\n    } catch (err: any) {\n      logger.debug(\n        `Got error when getting ask result: ${getAIServiceError(err)}`,\n      );\n      // throw err;\n      throw Errors.create(Errors.GeneralErrorCodes.INTERNAL_SERVER_ERROR, {\n        originalError: err,\n      });\n    }\n  }\n\n  public async getAskStreamingResult(queryId: string): Promise<Readable> {\n    // make GET request /v1/asks/:query_id/streaming-result to get the streaming result\n    try {\n      const res = await axios.get(\n        `${this.wrenAIBaseEndpoint}/v1/asks/${queryId}/streaming-result`,\n        { responseType: 'stream' },\n      );\n      return res.data;\n    } catch (err: any) {\n      logger.debug(\n        `Got error when getting ask streaming result: ${getAIServiceError(err)}`,\n      );\n      // throw err;\n      throw Errors.create(Errors.GeneralErrorCodes.INTERNAL_SERVER_ERROR, {\n        originalError: err,\n      });\n    }\n  }\n\n  /**\n   * After you choose a candidate, you can request AI service to generate the detail.\n   */\n\n  public async generateAskDetail(\n    input: AskDetailInput,\n  ): Promise<AsyncQueryResponse> {\n    try {\n      const res = await axios.post(\n        `${this.wrenAIBaseEndpoint}/v1/ask-details`,\n        input,\n      );\n      return { queryId: res.data.query_id };\n    } catch (err: any) {\n      logger.debug(\n        `Got error when generating ask detail: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  public async getAskDetailResult(queryId: string): Promise<AskDetailResult> {\n    // make GET request /v1/ask-details/:query_id/result to get the result\n    try {\n      const res = await axios.get(\n        `${this.wrenAIBaseEndpoint}/v1/ask-details/${queryId}/result`,\n      );\n      return this.transformAskDetailResult(res.data);\n    } catch (err: any) {\n      logger.debug(\n        `Got error when getting ask detail result: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  public async deploy(deployData: DeployData): Promise<WrenAIDeployResponse> {\n    const { manifest, hash } = deployData;\n    try {\n      const res = await axios.post(\n        `${this.wrenAIBaseEndpoint}/v1/semantics-preparations`,\n        {\n          mdl: JSON.stringify(manifest),\n          id: hash,\n        },\n      );\n      const deployId = res.data.id;\n      logger.debug(\n        `Wren AI: Deploying wren AI, hash: ${hash}, deployId: ${deployId}`,\n      );\n      const deploySuccess = await this.waitDeployFinished(deployId);\n      if (deploySuccess) {\n        logger.debug(`Wren AI: Deploy wren AI success, hash: ${hash}`);\n        return { status: WrenAIDeployStatusEnum.SUCCESS };\n      } else {\n        return {\n          status: WrenAIDeployStatusEnum.FAILED,\n          error: `Wren AI: Deploy wren AI failed or timeout, hash: ${hash}`,\n        };\n      }\n    } catch (err: any) {\n      logger.debug(\n        `Got error when deploying to wren AI, hash: ${hash}. Error: ${err.message}`,\n      );\n      return {\n        status: WrenAIDeployStatusEnum.FAILED,\n        error: `Wren AI Error: deployment hash:${hash}, ${err.message}`,\n      };\n    }\n  }\n\n  public async generateRecommendationQuestions(\n    input: RecommendationQuestionsInput,\n  ): Promise<AsyncQueryResponse> {\n    const body = {\n      mdl: JSON.stringify(input.manifest),\n      previous_questions: input.previousQuestions,\n      max_questions: input.maxQuestions,\n      max_categories: input.maxCategories,\n      configuration: input.configuration,\n    };\n    logger.info(`Wren AI: Generating recommendation questions`);\n    try {\n      const res = await axios.post(\n        `${this.wrenAIBaseEndpoint}/v1/question-recommendations`,\n        body,\n      );\n      logger.info(\n        `Wren AI: Generating recommendation questions, queryId: ${res.data.id}`,\n      );\n      return { queryId: res.data.id };\n    } catch (err: any) {\n      logger.debug(\n        `Got error when generating recommendation questions: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  public async getRecommendationQuestionsResult(\n    queryId: string,\n  ): Promise<RecommendationQuestionsResult> {\n    try {\n      const res = await axios.get(\n        `${this.wrenAIBaseEndpoint}/v1/question-recommendations/${queryId}`,\n      );\n      return this.transformRecommendationQuestionsResult(res.data);\n    } catch (err: any) {\n      logger.debug(\n        `Got error when getting recommendation questions result: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  public async createTextBasedAnswer(\n    input: TextBasedAnswerInput,\n  ): Promise<AsyncQueryResponse> {\n    const body = {\n      query: input.query,\n      sql: input.sql,\n      sql_data: input.sqlData,\n      thread_id: input.threadId,\n      user_id: input.userId,\n      configurations: input.configurations,\n    };\n    // make POST request /v1/sql-answers to create text-based answer\n    try {\n      const res = await axios.post(\n        `${this.wrenAIBaseEndpoint}/v1/sql-answers`,\n        body,\n      );\n      return { queryId: res.data.query_id };\n    } catch (err: any) {\n      logger.debug(\n        `Got error when creating text-based answer: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  public async getTextBasedAnswerResult(\n    queryId: string,\n  ): Promise<TextBasedAnswerResult> {\n    // make GET request /v1/sql-answers/:query_id to get the result\n    try {\n      const res = await axios.get(\n        `${this.wrenAIBaseEndpoint}/v1/sql-answers/${queryId}`,\n      );\n      return this.transformTextBasedAnswerResult(res.data);\n    } catch (err: any) {\n      logger.debug(\n        `Got error when getting text-based answer result: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  public async streamTextBasedAnswer(queryId: string): Promise<Readable> {\n    // make GET request /v1/sql-answers/:query_id/streaming to get the streaming result\n    try {\n      const res = await axios.get(\n        `${this.wrenAIBaseEndpoint}/v1/sql-answers/${queryId}/streaming`,\n        { responseType: 'stream' },\n      );\n      return res.data;\n    } catch (err: any) {\n      logger.debug(\n        `Got error when getting text-based answer streaming result: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  public async generateChart(input: ChartInput): Promise<AsyncQueryResponse> {\n    try {\n      const res = await axios.post(\n        `${this.wrenAIBaseEndpoint}/v1/charts`,\n        input,\n      );\n      return { queryId: res.data.query_id };\n    } catch (err: any) {\n      logger.debug(`Got error when creating chart: ${getAIServiceError(err)}`);\n      throw err;\n    }\n  }\n\n  public async getChartResult(queryId: string): Promise<ChartResult> {\n    try {\n      const res = await axios.get(\n        `${this.wrenAIBaseEndpoint}/v1/charts/${queryId}`,\n      );\n      return this.transformChartResult(res.data);\n    } catch (err: any) {\n      logger.debug(\n        `Got error when getting chart result: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  public async cancelChart(queryId: string): Promise<void> {\n    try {\n      await axios.patch(`${this.wrenAIBaseEndpoint}/v1/charts/${queryId}`, {\n        status: 'stopped',\n      });\n    } catch (err: any) {\n      logger.debug(`Got error when canceling chart: ${getAIServiceError(err)}`);\n      throw err;\n    }\n  }\n\n  public async adjustChart(\n    input: ChartAdjustmentInput,\n  ): Promise<AsyncQueryResponse> {\n    try {\n      const res = await axios.post(\n        `${this.wrenAIBaseEndpoint}/v1/chart-adjustments`,\n        this.transformChartAdjustmentInput(input),\n      );\n      return { queryId: res.data.query_id };\n    } catch (err: any) {\n      logger.debug(`Got error when adjusting chart: ${getAIServiceError(err)}`);\n      throw err;\n    }\n  }\n\n  public async getChartAdjustmentResult(queryId: string): Promise<ChartResult> {\n    try {\n      const res = await axios.get(\n        `${this.wrenAIBaseEndpoint}/v1/chart-adjustments/${queryId}`,\n      );\n      return this.transformChartResult(res.data);\n    } catch (err: any) {\n      logger.debug(\n        `Got error when getting chart adjustment result: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  public async cancelChartAdjustment(queryId: string): Promise<void> {\n    try {\n      await axios.patch(\n        `${this.wrenAIBaseEndpoint}/v1/chart-adjustments/${queryId}`,\n        {\n          status: 'stopped',\n        },\n      );\n    } catch (err: any) {\n      logger.debug(\n        `Got error when canceling chart adjustment: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n  public async generateQuestions(\n    input: QuestionInput,\n  ): Promise<AsyncQueryResponse> {\n    try {\n      const body = {\n        sqls: input.sqls,\n        project_id: input.projectId.toString(),\n        configurations: input.configurations,\n      };\n\n      const res = await axios.post(\n        `${this.wrenAIBaseEndpoint}/v1/sql-questions`,\n        body,\n      );\n      return { queryId: res.data.query_id };\n    } catch (err: any) {\n      logger.debug(\n        `Got error when generating questions: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  public async generateInstruction(\n    input: GenerateInstructionInput[],\n  ): Promise<AsyncQueryResponse> {\n    const body = {\n      instructions: input.map((item) => ({\n        id: item.id.toString(),\n        instruction: item.instruction,\n        questions: item.questions,\n        is_default: item.isDefault,\n      })),\n      project_id: input[0]?.projectId.toString(),\n    };\n    try {\n      const res = await axios.post(\n        `${this.wrenAIBaseEndpoint}/v1/instructions`,\n        body,\n      );\n      return { queryId: res.data.event_id };\n    } catch (err: any) {\n      logger.debug(\n        `Got error when generating instruction: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  public async getQuestionsResult(\n    queryId: string,\n  ): Promise<Partial<QuestionsResult>> {\n    try {\n      const res = await axios.get(\n        `${this.wrenAIBaseEndpoint}/v1/sql-questions/${queryId}`,\n      );\n      const { status, error } = this.transformStatusAndError(res.data);\n      return {\n        status: status as QuestionsStatus,\n        error,\n        questions: res.data.questions || [],\n      };\n    } catch (err: any) {\n      logger.debug(\n        `Got error when getting questions result: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  public async getInstructionResult(\n    queryId: string,\n  ): Promise<InstructionResult> {\n    try {\n      const res = await axios.get(\n        `${this.wrenAIBaseEndpoint}/v1/instructions/${queryId}`,\n      );\n      return this.transformStatusAndError(res.data) as InstructionResult;\n    } catch (err: any) {\n      logger.debug(\n        `Got error when getting instruction result: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  public async deleteInstructions(\n    ids: number[],\n    projectId: number,\n  ): Promise<void> {\n    try {\n      await axios.delete(`${this.wrenAIBaseEndpoint}/v1/instructions`, {\n        data: {\n          instruction_ids: ids.map((id) => id.toString()),\n          project_id: projectId.toString(),\n        },\n      });\n    } catch (err: any) {\n      logger.debug(\n        `Got error when deleting instruction: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  public async createAskFeedback(\n    input: AskFeedbackInput,\n  ): Promise<AsyncQueryResponse> {\n    try {\n      const body = {\n        question: input.question,\n        tables: input.tables,\n        sql_generation_reasoning: input.sqlGenerationReasoning,\n        sql: input.sql,\n        project_id: input.projectId.toString(),\n        configurations: input.configurations,\n      };\n      const res = await axios.post(\n        `${this.wrenAIBaseEndpoint}/v1/ask-feedbacks`,\n        body,\n      );\n      return { queryId: res.data.query_id };\n    } catch (err: any) {\n      logger.debug(\n        `Got error when creating ask feedback: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  public async getAskFeedbackResult(\n    queryId: string,\n  ): Promise<AskFeedbackResult> {\n    try {\n      const res = await axios.get(\n        `${this.wrenAIBaseEndpoint}/v1/ask-feedbacks/${queryId}`,\n      );\n      return this.transformAskFeedbackResult(res.data);\n    } catch (err: any) {\n      logger.debug(\n        `Got error when getting ask feedback result: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  public async cancelAskFeedback(queryId: string): Promise<void> {\n    try {\n      await axios.patch(\n        `${this.wrenAIBaseEndpoint}/v1/ask-feedbacks/${queryId}`,\n        {\n          status: 'stopped',\n        },\n      );\n    } catch (err: any) {\n      logger.debug(\n        `Got error when canceling ask feedback: ${getAIServiceError(err)}`,\n      );\n      throw err;\n    }\n  }\n\n  private transformAskFeedbackResult(body: any): AskFeedbackResult {\n    const { status, error } = this.transformStatusAndError(body);\n    return {\n      status: status as AskFeedbackStatus,\n      error,\n      response:\n        body.response?.map((result: any) => ({\n          sql: result.sql,\n          type: result.type?.toUpperCase() as AskCandidateType,\n        })) || [],\n      traceId: body.trace_id,\n      invalidSql: body.invalid_sql,\n    };\n  }\n\n  private transformChartAdjustmentInput(input: ChartAdjustmentInput) {\n    const { query, sql, adjustmentOption, chartSchema, configurations } = input;\n    return {\n      query,\n      sql,\n      adjustment_option: {\n        chart_type: adjustmentOption.chartType.toLowerCase(),\n        x_axis: adjustmentOption.xAxis,\n        y_axis: adjustmentOption.yAxis,\n        x_offset: adjustmentOption.xOffset,\n        color: adjustmentOption.color,\n        theta: adjustmentOption.theta,\n      },\n      chart_schema: chartSchema,\n      configurations,\n    };\n  }\n\n  private transformChartResult(body: any): ChartResult {\n    const { status, error } = this.transformStatusAndError(body);\n    return {\n      status: status as ChartStatus,\n      error,\n      response: {\n        reasoning: body.response?.reasoning,\n        chartType: body.response?.chart_type,\n        chartSchema: body.response?.chart_schema,\n      },\n    };\n  }\n\n  private transformTextBasedAnswerResult(body: any): TextBasedAnswerResult {\n    const { status, error } = this.transformStatusAndError(body);\n    return {\n      status: status as TextBasedAnswerStatus,\n      numRowsUsedInLLM: body.num_rows_used_in_llm,\n      error,\n    };\n  }\n\n  private async waitDeployFinished(deployId: string): Promise<boolean> {\n    let deploySuccess = false;\n    // timeout after 30 seconds\n    for (let waitTime = 1; waitTime <= 7; waitTime++) {\n      try {\n        const status = await this.getDeployStatus(deployId);\n        logger.debug(`Wren AI: Deploy status: ${status}`);\n        if (status === WrenAISystemStatus.FINISHED) {\n          deploySuccess = true;\n          break;\n        } else if (status === WrenAISystemStatus.FAILED) {\n          break;\n        } else if (status === WrenAISystemStatus.INDEXING) {\n          // do nothing\n        } else {\n          logger.debug(`Wren AI: Unknown Wren AI deploy status: ${status}`);\n          return;\n        }\n      } catch (err: any) {\n        throw err;\n      }\n      await new Promise((resolve) => setTimeout(resolve, waitTime * 1000));\n    }\n    return deploySuccess;\n  }\n\n  private async getDeployStatus(deployId: string): Promise<WrenAISystemStatus> {\n    try {\n      const res = await axios.get(\n        `${this.wrenAIBaseEndpoint}/v1/semantics-preparations/${deployId}/status`,\n      );\n      if (res.data.error) {\n        // passing AI response error string to catch block\n        throw new Error(res.data.error);\n      }\n      return res.data?.status.toUpperCase() as WrenAISystemStatus;\n    } catch (err: any) {\n      logger.debug(\n        `Got error in API /v1/semantics-preparations/${deployId}/status: ${err.message}`,\n      );\n      throw err;\n    }\n  }\n\n  private transformAskResult(body: any): AskResult {\n    const { status, error } = this.transformStatusAndError(body);\n    const candidates = (body?.response || []).map((candidate: any) => ({\n      type: candidate?.type?.toUpperCase() as AskCandidateType,\n      sql: candidate.sql,\n      viewId: candidate?.viewId ? Number(candidate.viewId) : null,\n      sqlpairId: candidate?.sqlpairId ? Number(candidate.sqlpairId) : null,\n    }));\n\n    return {\n      type: body?.type,\n      status: status as AskResultStatus,\n      error,\n      response: candidates,\n      rephrasedQuestion: body?.rephrased_question,\n      intentReasoning: body?.intent_reasoning,\n      sqlGenerationReasoning: body?.sql_generation_reasoning,\n      retrievedTables: body?.retrieved_tables,\n      invalidSql: body?.invalid_sql,\n      traceId: body?.trace_id,\n    };\n  }\n\n  private transformRecommendationQuestionsResult(\n    body: any,\n  ): RecommendationQuestionsResult {\n    const { status, error } = this.transformStatusAndError(body);\n    return {\n      ...body,\n      status,\n      error,\n    };\n  }\n\n  private transformAskDetailResult(body: any): AskDetailResult {\n    const { type } = body;\n    const { status, error } = this.transformStatusAndError(body);\n\n    // snake_case to camelCase\n    const steps = (body?.response?.steps || []).map((step: any) => ({\n      summary: step.summary,\n      sql: step.sql,\n      cteName: step.cte_name,\n    }));\n\n    return {\n      type,\n      status: status as AskResultStatus,\n      error,\n      response: {\n        description: body?.response?.description,\n        steps,\n      },\n    };\n  }\n\n  private transformStatusAndError(body: any): {\n    status:\n      | AskResultStatus\n      | TextBasedAnswerStatus\n      | ChartStatus\n      | SqlPairStatus\n      | QuestionsStatus\n      | InstructionStatus\n      | AskFeedbackStatus;\n    error?: {\n      code: Errors.GeneralErrorCodes;\n      message: string;\n      shortMessage: string;\n    } | null;\n  } {\n    // transform status to enum\n    const status = body?.status?.toUpperCase();\n\n    if (!status) {\n      throw new Error(`Unknown ask status: ${body?.status}`);\n    }\n\n    // use custom error to transform error\n    const code = body?.error?.code;\n    const isShowAIServiceErrorMessage =\n      code === Errors.GeneralErrorCodes.NO_RELEVANT_SQL ||\n      code === Errors.GeneralErrorCodes.AI_SERVICE_UNDEFINED_ERROR;\n\n    const error = code\n      ? Errors.create(\n          code,\n          isShowAIServiceErrorMessage\n            ? {\n                customMessage: body?.error?.message,\n              }\n            : undefined,\n        )\n      : null;\n\n    // format custom error into WrenAIError that is used in graphql\n    const formattedError = error\n      ? {\n          code: error.extensions.code as Errors.GeneralErrorCodes,\n          message: error.message,\n          shortMessage: error.extensions.shortMessage as string,\n        }\n      : null;\n\n    return {\n      status,\n      error: formattedError,\n    };\n  }\n\n  private transformHistoryInput(histories: ThreadResponse[]): AskHistory[] {\n    if (!histories) {\n      return [];\n    }\n\n    // make it snake_case\n    return histories.map((history) => ({\n      sql: history.sql,\n      question: history.question,\n    }));\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/adaptors/wrenEngineAdaptor.ts",
    "content": "import axios, { AxiosResponse } from 'axios';\nimport { Manifest } from '../mdl/type';\nimport { getLogger } from '@server/utils';\nimport * as Errors from '@server/utils/error';\nimport { CompactTable, DEFAULT_PREVIEW_LIMIT } from '../services';\n\nconst logger = getLogger('WrenEngineAdaptor');\nlogger.level = 'debug';\n\nexport interface WrenEngineDeployStatusResponse {\n  systemStatus: string;\n  version: string;\n}\n\nexport interface ColumnMetadata {\n  name: string;\n  type: string;\n}\n\nexport interface EngineQueryResponse {\n  columns: ColumnMetadata[];\n  data: any[][];\n}\n\nexport interface DescribeStatementResponse {\n  columns: ColumnMetadata[];\n}\n\nexport enum WrenEngineValidateStatus {\n  PASS = 'PASS',\n  ERROR = 'ERROR',\n  FAIL = 'FAIL',\n  WARN = 'WARN',\n  SKIP = 'SKIP',\n}\n\nexport interface WrenEngineValidateResponse {\n  duration: string;\n  name: string;\n  status: WrenEngineValidateStatus;\n}\n\nexport interface WrenEngineValidationResponse {\n  valid: boolean;\n  message?: string;\n}\n\nexport interface DryPlanOption {\n  modelingOnly?: boolean;\n  manifest?: Manifest;\n}\n\nexport interface WrenEngineDryRunOption {\n  manifest?: Manifest;\n  limit?: number;\n}\n\nexport interface DuckDBPrepareOptions {\n  initSql: string;\n  sessionProps: Record<string, any>;\n}\n\n// The response consists of an array containing columns. Each column contains a name and a type.\nexport interface WrenEngineDryRunResponse {\n  name: string;\n  type: string;\n}\n\nexport interface IWrenEngineAdaptor {\n  // duckdb data source related\n  prepareDuckDB(options: DuckDBPrepareOptions): Promise<void>;\n  queryDuckdb(sql: string): Promise<EngineQueryResponse>;\n  putSessionProps(props: Record<string, any>): Promise<void>;\n\n  // metadata related, used to fetch metadata of duckdb\n  listTables(): Promise<CompactTable[]>;\n\n  // config wren engine\n  patchConfig(config: Record<string, any>): Promise<void>;\n\n  // query\n  previewData(\n    sql: string,\n    mdl: Manifest,\n    limit?: number,\n  ): Promise<EngineQueryResponse>;\n  getNativeSQL(sql: string, options?: DryPlanOption): Promise<string>;\n  validateColumnIsValid(\n    manifest: Manifest,\n    modelName: string,\n    columnName: string,\n  ): Promise<WrenEngineValidationResponse>;\n  dryRun(\n    sql: string,\n    options: WrenEngineDryRunOption,\n  ): Promise<WrenEngineDryRunResponse[]>;\n}\n\nexport class WrenEngineAdaptor implements IWrenEngineAdaptor {\n  private readonly wrenEngineBaseEndpoint: string;\n  private sessionPropsUrlPath = '/v1/data-source/duckdb/settings/session-sql';\n  private queryDuckdbUrlPath = '/v1/data-source/duckdb/query';\n  private initSqlUrlPath = '/v1/data-source/duckdb/settings/init-sql';\n  private previewUrlPath = '/v1/mdl/preview';\n  private dryPlanUrlPath = '/v1/mdl/dry-plan';\n  private dryRunUrlPath = '/v1/mdl/dry-run';\n  private validateUrlPath = '/v1/mdl/validate';\n\n  constructor({ wrenEngineEndpoint }: { wrenEngineEndpoint: string }) {\n    this.wrenEngineBaseEndpoint = wrenEngineEndpoint;\n  }\n\n  public async validateColumnIsValid(\n    manifest: Manifest,\n    modelName: string,\n    columnName: string,\n  ) {\n    const model = manifest.models.find((m) => m.name === modelName);\n    if (!model) {\n      return {\n        valid: false,\n        message: `Model ${modelName} not found in the manifest`,\n      };\n    }\n    const column = model.columns.find((c) => c.name === columnName);\n    if (!column) {\n      return {\n        valid: false,\n        message: `Column ${columnName} not found in model ${modelName} in the manifest`,\n      };\n    }\n    try {\n      const payload = {\n        manifest,\n        parameters: { modelName, columnName },\n      };\n      const res = await axios.post(\n        `${this.wrenEngineBaseEndpoint}${this.validateUrlPath}/column_is_valid`,\n        payload,\n      );\n      const result = res.data[0] as WrenEngineValidateResponse;\n      if (result.status === WrenEngineValidateStatus.PASS) {\n        return { valid: true };\n      } else {\n        return { valid: false, message: JSON.stringify(result) };\n      }\n    } catch (err: any) {\n      logger.debug(`Got error when validating column: ${err.message}`);\n      return { valid: false, message: err.message };\n    }\n  }\n\n  public async prepareDuckDB(options: DuckDBPrepareOptions): Promise<void> {\n    const { initSql, sessionProps } = options;\n    await this.initDatabase(initSql);\n    await this.putSessionProps(sessionProps);\n  }\n\n  public async listTables() {\n    const sql =\n      'SELECT \\\n      table_catalog, table_schema, table_name, column_name, ordinal_position, is_nullable, data_type\\\n      FROM INFORMATION_SCHEMA.COLUMNS;';\n    const response = await this.queryDuckdb(sql);\n    return this.formatToCompactTable(response);\n  }\n\n  public async putSessionProps(props: Record<string, any>) {\n    const setSessionStatements = Object.entries(props)\n      .map(([key, value]) => {\n        return `SET ${key} = '${value}';`;\n      })\n      .join('\\n');\n    try {\n      const url = new URL(\n        this.sessionPropsUrlPath,\n        this.wrenEngineBaseEndpoint,\n      );\n      const headers = {\n        'Content-Type': 'text/plain; charset=utf-8',\n      };\n      await axios.put(url.href, setSessionStatements, { headers });\n    } catch (err: any) {\n      logger.debug(`Got error when put session props: ${err.message}`);\n      throw Errors.create(Errors.GeneralErrorCodes.SESSION_PROPS_ERROR, {\n        customMessage:\n          Errors.errorMessages[Errors.GeneralErrorCodes.SESSION_PROPS_ERROR],\n        originalError: err,\n      });\n    }\n  }\n\n  public async queryDuckdb(sql: string): Promise<EngineQueryResponse> {\n    try {\n      const url = new URL(this.queryDuckdbUrlPath, this.wrenEngineBaseEndpoint);\n      const headers = {\n        'Content-Type': 'text/plain; charset=utf-8',\n      };\n      const res = await axios.post(url.href, sql, { headers });\n      return res.data as EngineQueryResponse;\n    } catch (err: any) {\n      logger.debug(`Got error when querying duckdb: ${err.message}`);\n      throw Errors.create(Errors.GeneralErrorCodes.WREN_ENGINE_ERROR, {\n        customMessage: err.response?.data?.message || err.message,\n        originalError: err,\n      });\n    }\n  }\n\n  public async patchConfig(config: Record<string, any>) {\n    try {\n      const configPayload = Object.entries(config).map(([key, value]) => {\n        return {\n          name: key,\n          value,\n        };\n      });\n      const url = new URL('/v1/config', this.wrenEngineBaseEndpoint);\n      const headers = {\n        'Content-Type': 'application/json',\n      };\n      await axios.patch(url.href, configPayload, { headers });\n    } catch (err: any) {\n      logger.debug(`Got error when patching config: ${err.message}`);\n      throw Errors.create(Errors.GeneralErrorCodes.WREN_ENGINE_ERROR, {\n        customMessage: err.response?.data?.message || err.message,\n        originalError: err,\n      });\n    }\n  }\n\n  public async previewData(\n    sql: string,\n    manifest: Manifest,\n    limit: number = DEFAULT_PREVIEW_LIMIT,\n  ): Promise<EngineQueryResponse> {\n    try {\n      const url = new URL(this.previewUrlPath, this.wrenEngineBaseEndpoint);\n      const headers = {\n        'Content-Type': 'application/json',\n      };\n\n      const res: AxiosResponse<EngineQueryResponse> = await axios({\n        method: 'get',\n        url: url.href,\n        headers,\n        data: {\n          sql,\n          limit,\n          manifest,\n        },\n      });\n\n      return res.data;\n    } catch (err: any) {\n      logger.debug(`Got error when previewing data: ${err.message}`);\n      throw Errors.create(Errors.GeneralErrorCodes.WREN_ENGINE_ERROR, {\n        customMessage: err.response?.data?.message || err.message,\n        originalError: err,\n      });\n    }\n  }\n\n  public async getNativeSQL(\n    sql: string,\n    options: DryPlanOption,\n  ): Promise<string> {\n    try {\n      const props = {\n        modelingOnly: options?.modelingOnly ? true : false,\n        manifest: options?.manifest,\n      };\n\n      const url = new URL(this.dryPlanUrlPath, this.wrenEngineBaseEndpoint);\n      const headers = { 'Content-Type': 'application/json' };\n\n      const res: AxiosResponse<string> = await axios({\n        method: 'get',\n        url: url.href,\n        headers,\n        data: {\n          sql,\n          ...props,\n        },\n      });\n\n      return res.data;\n    } catch (err: any) {\n      logger.debug(`Got error when getting native SQL: ${err.message}`);\n      Errors.create(Errors.GeneralErrorCodes.DRY_PLAN_ERROR, {\n        customMessage: err.message,\n        originalError: err,\n      });\n    }\n  }\n\n  public async dryRun(\n    sql: string,\n    options: WrenEngineDryRunOption,\n  ): Promise<WrenEngineDryRunResponse[]> {\n    try {\n      const { manifest } = options;\n      const body = {\n        sql,\n        manifest,\n      };\n      logger.debug(\n        `Dry run wren engine with body: ${JSON.stringify(sql, null, 2)}`,\n      );\n      const url = new URL(this.dryRunUrlPath, this.wrenEngineBaseEndpoint);\n      const res: AxiosResponse<WrenEngineDryRunResponse[]> = await axios({\n        method: 'get',\n        url: url.href,\n        data: body,\n      });\n      logger.debug(`Wren Engine Dry run success`);\n      return res.data;\n    } catch (err: any) {\n      logger.info(`Got error when dry running`);\n      throw Errors.create(Errors.GeneralErrorCodes.DRY_RUN_ERROR, {\n        customMessage: err.response.data.message,\n        originalError: err,\n      });\n    }\n  }\n\n  private async getDeployStatus(): Promise<WrenEngineDeployStatusResponse> {\n    try {\n      const res = await axios.get(\n        `${this.wrenEngineBaseEndpoint}/v1/mdl/status`,\n      );\n      return res.data as WrenEngineDeployStatusResponse;\n    } catch (err: any) {\n      logger.debug(\n        `WrenEngine: Got error when getting deploy status: ${err.message}`,\n      );\n      throw err;\n    }\n  }\n\n  private async initDatabase(sql) {\n    try {\n      const url = new URL(this.initSqlUrlPath, this.wrenEngineBaseEndpoint);\n      const headers = {\n        'Content-Type': 'text/plain; charset=utf-8',\n      };\n      await axios.put(url.href, sql, { headers });\n    } catch (err: any) {\n      logger.debug(`Got error when init database: ${err}`);\n      throw Errors.create(Errors.GeneralErrorCodes.INIT_SQL_ERROR, {\n        customMessage:\n          Errors.errorMessages[Errors.GeneralErrorCodes.INIT_SQL_ERROR],\n        originalError: err,\n      });\n    }\n  }\n\n  private formatToCompactTable(columns: EngineQueryResponse): CompactTable[] {\n    return columns.data.reduce((acc: CompactTable[], row: any) => {\n      const [\n        table_catalog,\n        table_schema,\n        table_name,\n        column_name,\n        _ordinal_position,\n        is_nullable,\n        data_type,\n      ] = row;\n      let table = acc.find(\n        (t) => t.name === table_name && t.properties.schema === table_schema,\n      );\n      if (!table) {\n        table = {\n          name: table_name,\n          description: '',\n          columns: [],\n          properties: {\n            schema: table_schema,\n            catalog: table_catalog,\n            table: table_name,\n          },\n          primaryKey: null,\n        };\n        acc.push(table);\n      }\n      table.columns.push({\n        name: column_name,\n        type: data_type,\n        notNull: is_nullable.toLocaleLowerCase() !== 'yes',\n        description: '',\n        properties: {},\n      });\n      return acc;\n    }, []);\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/backgrounds/adjustmentBackgroundTracker.ts",
    "content": "import { getLogger } from '@server/utils';\nimport {\n  AskFeedbackInput,\n  AskFeedbackResult,\n  AskFeedbackStatus,\n} from '@server/models/adaptor';\nimport {\n  AskingTask,\n  IAskingTaskRepository,\n  IThreadResponseRepository,\n  ThreadResponse,\n  ThreadResponseAdjustmentType,\n} from '@server/repositories';\nimport { IWrenAIAdaptor } from '../adaptors';\nimport { TelemetryEvent, WrenService } from '../telemetry/telemetry';\nimport { PostHogTelemetry } from '../telemetry/telemetry';\n\nconst logger = getLogger('AdjustmentTaskTracker');\nlogger.level = 'debug';\n\ninterface TrackedTask {\n  queryId: string;\n  taskId?: number;\n  lastPolled: number;\n  result?: AskFeedbackResult;\n  isFinalized: boolean;\n  threadResponseId: number;\n  question: string;\n  originalThreadResponseId: number;\n  rerun?: boolean;\n  adjustmentPayload?: {\n    originalThreadResponseId: number;\n    retrievedTables: string[];\n    sqlGenerationReasoning: string;\n  };\n}\n\nexport type TrackedAdjustmentResult = AskFeedbackResult & {\n  taskId?: number;\n  queryId: string;\n};\n\nexport type CreateAdjustmentTaskInput = AskFeedbackInput & {\n  threadId: number;\n  question: string;\n  originalThreadResponseId: number;\n  configurations: { language: string };\n};\n\nexport type RerunAdjustmentTaskInput = {\n  threadResponseId: number;\n  threadId: number;\n  projectId: number;\n  configurations: { language: string };\n};\n\nexport interface IAdjustmentBackgroundTaskTracker {\n  createAdjustmentTask(\n    input: CreateAdjustmentTaskInput,\n  ): Promise<{ queryId: string }>;\n  getAdjustmentResult(queryId: string): Promise<TrackedAdjustmentResult | null>;\n  getAdjustmentResultById(id: number): Promise<TrackedAdjustmentResult | null>;\n  cancelAdjustmentTask(queryId: string): Promise<void>;\n  rerunAdjustmentTask(\n    input: RerunAdjustmentTaskInput,\n  ): Promise<{ queryId: string }>;\n}\n\nexport class AdjustmentBackgroundTaskTracker\n  implements IAdjustmentBackgroundTaskTracker\n{\n  private wrenAIAdaptor: IWrenAIAdaptor;\n  private askingTaskRepository: IAskingTaskRepository;\n  private trackedTasks: Map<string, TrackedTask> = new Map();\n  private trackedTasksById: Map<number, TrackedTask> = new Map();\n  private pollingInterval: number;\n  private memoryRetentionTime: number;\n  private pollingIntervalId: NodeJS.Timeout;\n  private runningJobs = new Set<string>();\n  private threadResponseRepository: IThreadResponseRepository;\n  private telemetry: PostHogTelemetry;\n\n  constructor({\n    telemetry,\n    wrenAIAdaptor,\n    askingTaskRepository,\n    threadResponseRepository,\n    pollingInterval = 1000, // 1 second\n    memoryRetentionTime = 5 * 60 * 1000, // 5 minutes\n  }: {\n    telemetry: PostHogTelemetry;\n    wrenAIAdaptor: IWrenAIAdaptor;\n    askingTaskRepository: IAskingTaskRepository;\n    threadResponseRepository: IThreadResponseRepository;\n    pollingInterval?: number;\n    memoryRetentionTime?: number;\n  }) {\n    this.telemetry = telemetry;\n    this.wrenAIAdaptor = wrenAIAdaptor;\n    this.askingTaskRepository = askingTaskRepository;\n    this.threadResponseRepository = threadResponseRepository;\n    this.pollingInterval = pollingInterval;\n    this.memoryRetentionTime = memoryRetentionTime;\n    this.startPolling();\n  }\n\n  public async createAdjustmentTask(\n    input: CreateAdjustmentTaskInput,\n  ): Promise<{ queryId: string; createdThreadResponse: ThreadResponse }> {\n    try {\n      // Call the AI service to create a task\n      const response = await this.wrenAIAdaptor.createAskFeedback(input);\n      const queryId = response.queryId;\n\n      // create a new asking task\n      const createdAskingTask = await this.askingTaskRepository.createOne({\n        queryId,\n        question: input.question,\n        threadId: input.threadId,\n        detail: {\n          adjustment: true,\n          status: AskFeedbackStatus.UNDERSTANDING,\n          response: [],\n          error: null,\n        },\n      });\n\n      // create a new thread response with adjustment payload\n      const createdThreadResponse =\n        await this.threadResponseRepository.createOne({\n          question: input.question,\n          threadId: input.threadId,\n          askingTaskId: createdAskingTask.id,\n          adjustment: {\n            type: ThreadResponseAdjustmentType.REASONING,\n            payload: {\n              originalThreadResponseId: input.originalThreadResponseId,\n              retrievedTables: input.tables,\n              sqlGenerationReasoning: input.sqlGenerationReasoning,\n            },\n          },\n        });\n\n      // bind the thread response to the asking task\n      // todo: it's weird that we need to update the asking task again\n      // find a better way to do this\n      await this.askingTaskRepository.updateOne(createdAskingTask.id, {\n        threadResponseId: createdThreadResponse.id,\n      });\n\n      // Start tracking this task\n      const task = {\n        queryId,\n        lastPolled: Date.now(),\n        isFinalized: false,\n        originalThreadResponseId: input.originalThreadResponseId,\n        threadResponseId: createdThreadResponse.id,\n        question: input.question,\n        adjustmentPayload: {\n          originalThreadResponseId: input.originalThreadResponseId,\n          retrievedTables: input.tables,\n          sqlGenerationReasoning: input.sqlGenerationReasoning,\n        },\n      } as TrackedTask;\n      this.trackedTasks.set(queryId, task);\n      this.trackedTasksById.set(createdThreadResponse.id, task);\n\n      logger.info(`Created adjustment task with queryId: ${queryId}`);\n      return { queryId, createdThreadResponse };\n    } catch (err) {\n      logger.error(`Failed to create adjustment task: ${err}`);\n      throw err;\n    }\n  }\n\n  public async rerunAdjustmentTask(\n    input: RerunAdjustmentTaskInput,\n  ): Promise<{ queryId: string }> {\n    const currentThreadResponse = await this.threadResponseRepository.findOneBy(\n      {\n        id: input.threadResponseId,\n      },\n    );\n    if (!currentThreadResponse) {\n      throw new Error(`Thread response ${input.threadResponseId} not found`);\n    }\n\n    const adjustment = currentThreadResponse.adjustment;\n    if (!adjustment) {\n      throw new Error(\n        `Thread response ${input.threadResponseId} has no adjustment`,\n      );\n    }\n\n    const originalThreadResponse =\n      await this.threadResponseRepository.findOneBy({\n        id: adjustment.payload?.originalThreadResponseId,\n      });\n    if (!originalThreadResponse) {\n      throw new Error(\n        `Original thread response ${adjustment.payload?.originalThreadResponseId} not found`,\n      );\n    }\n\n    // call createAskFeedback on AI service\n    const response = await this.wrenAIAdaptor.createAskFeedback({\n      ...input,\n      tables: adjustment.payload?.retrievedTables,\n      sqlGenerationReasoning: adjustment.payload?.sqlGenerationReasoning,\n      sql: originalThreadResponse.sql,\n      question: originalThreadResponse.question,\n    });\n    const queryId = response.queryId;\n\n    // update asking task with new queryId\n    await this.askingTaskRepository.updateOne(\n      currentThreadResponse.askingTaskId,\n      {\n        queryId,\n\n        // reset detail\n        detail: {\n          adjustment: true,\n          status: AskFeedbackStatus.UNDERSTANDING,\n          response: [],\n          error: null,\n        },\n      },\n    );\n\n    // schedule task\n    const task = {\n      queryId,\n      lastPolled: Date.now(),\n      isFinalized: false,\n      originalThreadResponseId: originalThreadResponse.id,\n      threadResponseId: currentThreadResponse.id,\n      question: originalThreadResponse.question,\n      rerun: true,\n      adjustmentPayload: {\n        originalThreadResponseId: originalThreadResponse.id,\n        retrievedTables: adjustment.payload?.retrievedTables,\n        sqlGenerationReasoning: adjustment.payload?.sqlGenerationReasoning,\n      },\n    } as TrackedTask;\n    this.trackedTasks.set(queryId, task);\n    this.trackedTasksById.set(currentThreadResponse.id, task);\n\n    logger.info(`Rerun adjustment task with queryId: ${queryId}`);\n    return { queryId };\n  }\n\n  public async getAdjustmentResult(\n    queryId: string,\n  ): Promise<TrackedAdjustmentResult | null> {\n    // Check if we're tracking this task in memory\n    const trackedTask = this.trackedTasks.get(queryId);\n\n    if (trackedTask && trackedTask.result) {\n      return {\n        ...trackedTask.result,\n        queryId,\n        taskId: trackedTask.taskId,\n      };\n    }\n\n    // If not in memory or no result yet, check the database\n    return this.getAdjustmentResultFromDB({ queryId });\n  }\n\n  public async getAdjustmentResultById(\n    id: number,\n  ): Promise<TrackedAdjustmentResult | null> {\n    const task = this.trackedTasksById.get(id);\n    if (task) {\n      return this.getAdjustmentResult(task.queryId);\n    }\n\n    return this.getAdjustmentResultFromDB({ taskId: id });\n  }\n\n  public async cancelAdjustmentTask(queryId: string): Promise<void> {\n    await this.wrenAIAdaptor.cancelAskFeedback(queryId);\n\n    // telemetry\n    const eventName = TelemetryEvent.HOME_ADJUST_THREAD_RESPONSE_CANCEL;\n    this.telemetry.sendEvent(eventName, {\n      queryId,\n    });\n  }\n\n  public stopPolling(): void {\n    if (this.pollingIntervalId) {\n      clearInterval(this.pollingIntervalId);\n    }\n  }\n\n  private startPolling(): void {\n    this.pollingIntervalId = setInterval(() => {\n      this.pollTasks();\n    }, this.pollingInterval);\n  }\n\n  private async pollTasks(): Promise<void> {\n    const now = Date.now();\n    const tasksToRemove: string[] = [];\n\n    // Create an array of job functions\n    const jobs = Array.from(this.trackedTasks.entries()).map(\n      ([queryId, task]) =>\n        async () => {\n          try {\n            // Skip if the job is already running\n            if (this.runningJobs.has(queryId)) {\n              return;\n            }\n\n            // Skip finalized tasks that have been in memory too long\n            if (\n              task.isFinalized &&\n              now - task.lastPolled > this.memoryRetentionTime\n            ) {\n              tasksToRemove.push(queryId);\n              return;\n            }\n\n            // Skip finalized tasks\n            if (task.isFinalized) {\n              return;\n            }\n\n            // Mark the job as running\n            this.runningJobs.add(queryId);\n\n            // Poll for updates\n            logger.info(`Polling for updates for task ${queryId}`);\n            const result =\n              await this.wrenAIAdaptor.getAskFeedbackResult(queryId);\n            task.lastPolled = now;\n\n            // if result is not changed, we don't need to update the database\n            if (!this.isResultChanged(task.result, result)) {\n              this.runningJobs.delete(queryId);\n              return;\n            }\n\n            // Check if task is now finalized\n            if (this.isTaskFinalized(result.status)) {\n              task.isFinalized = true;\n              // update thread response if threadResponseId is provided\n              if (task.threadResponseId) {\n                await this.updateThreadResponseWhenTaskFinalized(\n                  task.threadResponseId,\n                  result,\n                );\n              }\n\n              // telemetry\n              const eventName = task.rerun\n                ? TelemetryEvent.HOME_ADJUST_THREAD_RESPONSE_RERUN\n                : TelemetryEvent.HOME_ADJUST_THREAD_RESPONSE;\n              const eventProperties = {\n                taskId: task.taskId,\n                queryId: task.queryId,\n                status: result.status,\n                error: result.error,\n                adjustmentPayload: task.adjustmentPayload,\n              };\n              if (result.status === AskFeedbackStatus.FINISHED) {\n                this.telemetry.sendEvent(eventName, eventProperties);\n              } else {\n                this.telemetry.sendEvent(\n                  eventName,\n                  eventProperties,\n                  WrenService.AI,\n                  false,\n                );\n              }\n\n              logger.info(\n                `Task ${queryId} is finalized with status: ${result.status}`,\n              );\n            }\n\n            // update task in memory if any change\n            task.result = result;\n\n            // update the database\n            logger.info(`Updating task ${queryId} in database`);\n            await this.updateTaskInDatabase({ queryId }, result);\n\n            // Mark the job as finished\n            this.runningJobs.delete(queryId);\n          } catch (err) {\n            this.runningJobs.delete(queryId);\n            logger.error(err.stack);\n            throw err;\n          }\n        },\n    );\n\n    // Run all jobs in parallel\n    Promise.allSettled(jobs.map((job) => job())).then((results) => {\n      // Log any rejected promises\n      results.forEach((result, index) => {\n        if (result.status === 'rejected') {\n          logger.error(`Job ${index} failed: ${result.reason}`);\n        }\n      });\n\n      // Clean up tasks that have been in memory too long\n      if (tasksToRemove.length > 0) {\n        logger.info(\n          `Cleaning up tasks that have been in memory too long. Tasks: ${tasksToRemove.join(\n            ', ',\n          )}`,\n        );\n      }\n      for (const queryId of tasksToRemove) {\n        this.trackedTasks.delete(queryId);\n      }\n    });\n  }\n\n  private async updateThreadResponseWhenTaskFinalized(\n    threadResponseId: number,\n    result: AskFeedbackResult,\n  ): Promise<void> {\n    const response = result?.response?.[0];\n    if (!response) {\n      return;\n    }\n    await this.threadResponseRepository.updateOne(threadResponseId, {\n      sql: response?.sql,\n    });\n  }\n\n  private async getAdjustmentResultFromDB({\n    queryId,\n    taskId,\n  }: {\n    queryId?: string;\n    taskId?: number;\n  }): Promise<TrackedAdjustmentResult | null> {\n    let taskRecord: AskingTask | null = null;\n    if (queryId) {\n      taskRecord = await this.askingTaskRepository.findByQueryId(queryId);\n    } else if (taskId) {\n      taskRecord = await this.askingTaskRepository.findOneBy({ id: taskId });\n    }\n\n    if (!taskRecord) {\n      return null;\n    }\n\n    return {\n      ...(taskRecord?.detail as AskFeedbackResult),\n      queryId: queryId || taskRecord?.queryId,\n      taskId: taskRecord?.id,\n    };\n  }\n\n  private async updateTaskInDatabase(\n    filter: { queryId?: string; taskId?: number },\n    result: AskFeedbackResult,\n  ): Promise<void> {\n    const { queryId, taskId } = filter;\n    let taskRecord: AskingTask | null = null;\n    if (queryId) {\n      taskRecord = await this.askingTaskRepository.findByQueryId(queryId);\n    } else if (taskId) {\n      taskRecord = await this.askingTaskRepository.findOneBy({ id: taskId });\n    }\n\n    if (!taskRecord) {\n      throw new Error('Asking task not found');\n    }\n\n    // update the task\n    await this.askingTaskRepository.updateOne(taskRecord.id, {\n      detail: {\n        adjustment: true,\n        ...result,\n      },\n    });\n  }\n\n  private isTaskFinalized(status: AskFeedbackStatus): boolean {\n    return [\n      AskFeedbackStatus.FINISHED,\n      AskFeedbackStatus.FAILED,\n      AskFeedbackStatus.STOPPED,\n    ].includes(status);\n  }\n\n  private isResultChanged(\n    previousResult: AskFeedbackResult,\n    newResult: AskFeedbackResult,\n  ): boolean {\n    // check status change\n    if (previousResult?.status !== newResult.status) {\n      return true;\n    }\n\n    return false;\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/backgrounds/chart.ts",
    "content": "import { ChartStatus } from '@server/models/adaptor';\nimport { IWrenAIAdaptor } from '@server/adaptors/wrenAIAdaptor';\nimport {\n  IThreadResponseRepository,\n  ThreadResponse,\n} from '@server/repositories';\nimport { getLogger } from '@server/utils/logger';\nimport {\n  PostHogTelemetry,\n  TelemetryEvent,\n  WrenService,\n} from '@server/telemetry/telemetry';\n\nconst logger = getLogger('ChartBackgroundTracker');\nlogger.level = 'debug';\n\nconst isFinalized = (status: ChartStatus) => {\n  return (\n    status === ChartStatus.FINISHED ||\n    status === ChartStatus.FAILED ||\n    status === ChartStatus.STOPPED\n  );\n};\n\nexport class ChartBackgroundTracker {\n  private tasks: Record<number, ThreadResponse> = {};\n  private intervalTime: number;\n  private wrenAIAdaptor: IWrenAIAdaptor;\n  private threadResponseRepository: IThreadResponseRepository;\n  private runningJobs = new Set();\n  private telemetry: PostHogTelemetry;\n\n  constructor({\n    telemetry,\n    wrenAIAdaptor,\n    threadResponseRepository,\n  }: {\n    telemetry: PostHogTelemetry;\n    wrenAIAdaptor: IWrenAIAdaptor;\n    threadResponseRepository: IThreadResponseRepository;\n  }) {\n    this.telemetry = telemetry;\n    this.wrenAIAdaptor = wrenAIAdaptor;\n    this.threadResponseRepository = threadResponseRepository;\n    this.intervalTime = 1000;\n    this.start();\n  }\n\n  private start() {\n    logger.info('Chart background tracker started');\n    setInterval(() => {\n      const jobs = Object.values(this.tasks).map(\n        (threadResponse) => async () => {\n          // check if same job is running\n          if (this.runningJobs.has(threadResponse.id)) {\n            return;\n          }\n\n          // mark the job as running\n          this.runningJobs.add(threadResponse.id);\n\n          // get the chart detail\n          const chartDetail = threadResponse.chartDetail;\n\n          // get the latest result from AI service\n          const result = await this.wrenAIAdaptor.getChartResult(\n            chartDetail.queryId,\n          );\n\n          // check if status change\n          if (chartDetail.status === result.status) {\n            // mark the job as finished\n            logger.debug(\n              `Job ${threadResponse.id} chart status not changed, finished`,\n            );\n            this.runningJobs.delete(threadResponse.id);\n            return;\n          }\n\n          // update database\n          const updatedChartDetail = {\n            queryId: chartDetail.queryId,\n            status: result?.status,\n            error: result?.error,\n            description: result?.response?.reasoning,\n            chartType: result?.response?.chartType?.toUpperCase() || null,\n            chartSchema: result?.response?.chartSchema,\n          };\n          logger.debug(\n            `Job ${threadResponse.id} chart status changed, updating`,\n          );\n          await this.threadResponseRepository.updateOne(threadResponse.id, {\n            chartDetail: updatedChartDetail,\n          });\n\n          // remove the task from tracker if it is finalized\n          if (isFinalized(result.status)) {\n            const eventProperties = {\n              question: threadResponse.question,\n              error: result.error,\n            };\n            if (result.status === ChartStatus.FINISHED) {\n              this.telemetry.sendEvent(\n                TelemetryEvent.HOME_ANSWER_CHART,\n                eventProperties,\n              );\n            } else {\n              this.telemetry.sendEvent(\n                TelemetryEvent.HOME_ANSWER_CHART,\n                eventProperties,\n                WrenService.AI,\n                false,\n              );\n            }\n            logger.debug(\n              `Job ${threadResponse.id} chart is finalized, removing`,\n            );\n            delete this.tasks[threadResponse.id];\n          }\n\n          // mark the job as finished\n          this.runningJobs.delete(threadResponse.id);\n        },\n      );\n\n      // run the jobs\n      Promise.allSettled(jobs.map((job) => job())).then((results) => {\n        // show reason of rejection\n        results.forEach((result, index) => {\n          if (result.status === 'rejected') {\n            logger.error(`Job ${index} failed: ${result.reason}`);\n          }\n        });\n      });\n    }, this.intervalTime);\n  }\n\n  public addTask(threadResponse: ThreadResponse) {\n    this.tasks[threadResponse.id] = threadResponse;\n  }\n\n  public getTasks() {\n    return this.tasks;\n  }\n}\n\nexport class ChartAdjustmentBackgroundTracker {\n  private tasks: Record<number, ThreadResponse> = {};\n  private intervalTime: number;\n  private wrenAIAdaptor: IWrenAIAdaptor;\n  private threadResponseRepository: IThreadResponseRepository;\n  private runningJobs = new Set();\n  private telemetry: PostHogTelemetry;\n\n  constructor({\n    telemetry,\n    wrenAIAdaptor,\n    threadResponseRepository,\n  }: {\n    telemetry: PostHogTelemetry;\n    wrenAIAdaptor: IWrenAIAdaptor;\n    threadResponseRepository: IThreadResponseRepository;\n  }) {\n    this.telemetry = telemetry;\n    this.wrenAIAdaptor = wrenAIAdaptor;\n    this.threadResponseRepository = threadResponseRepository;\n    this.intervalTime = 1000;\n    this.start();\n  }\n\n  private start() {\n    logger.info('Chart adjustment background tracker started');\n    setInterval(() => {\n      const jobs = Object.values(this.tasks).map(\n        (threadResponse) => async () => {\n          // check if same job is running\n          if (this.runningJobs.has(threadResponse.id)) {\n            return;\n          }\n\n          // mark the job as running\n          this.runningJobs.add(threadResponse.id);\n\n          // get the chart detail\n          const chartDetail = threadResponse.chartDetail;\n\n          // get the latest result from AI service\n          const result = await this.wrenAIAdaptor.getChartAdjustmentResult(\n            chartDetail.queryId,\n          );\n\n          // check if status change\n          if (chartDetail.status === result.status) {\n            // mark the job as finished\n            logger.debug(\n              `Job ${threadResponse.id} chart status not changed, finished`,\n            );\n            this.runningJobs.delete(threadResponse.id);\n            return;\n          }\n\n          // update database\n          const updatedChartDetail = {\n            queryId: chartDetail.queryId,\n            status: result?.status,\n            error: result?.error,\n            description: result?.response?.reasoning,\n            chartType: result?.response?.chartType?.toUpperCase() || null,\n            chartSchema: result?.response?.chartSchema,\n            adjustment: true,\n          };\n          logger.debug(\n            `Job ${threadResponse.id} chart status changed, updating`,\n          );\n          await this.threadResponseRepository.updateOne(threadResponse.id, {\n            chartDetail: updatedChartDetail,\n          });\n\n          // remove the task from tracker if it is finalized\n          if (isFinalized(result.status)) {\n            const eventProperties = {\n              question: threadResponse.question,\n              error: result.error,\n            };\n            if (result.status === ChartStatus.FINISHED) {\n              this.telemetry.sendEvent(\n                TelemetryEvent.HOME_ANSWER_ADJUST_CHART,\n                eventProperties,\n              );\n            } else {\n              this.telemetry.sendEvent(\n                TelemetryEvent.HOME_ANSWER_ADJUST_CHART,\n                eventProperties,\n                WrenService.AI,\n                false,\n              );\n            }\n            logger.debug(\n              `Job ${threadResponse.id} chart is finalized, removing`,\n            );\n            delete this.tasks[threadResponse.id];\n          }\n\n          // mark the job as finished\n          this.runningJobs.delete(threadResponse.id);\n        },\n      );\n\n      // run the jobs\n      Promise.allSettled(jobs.map((job) => job())).then((results) => {\n        // show reason of rejection\n        results.forEach((result, index) => {\n          if (result.status === 'rejected') {\n            logger.error(`Job ${index} failed: ${result.reason}`);\n          }\n        });\n      });\n    }, this.intervalTime);\n  }\n\n  public addTask(threadResponse: ThreadResponse) {\n    this.tasks[threadResponse.id] = threadResponse;\n  }\n\n  public getTasks() {\n    return this.tasks;\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/backgrounds/dashboardCacheBackgroundTracker.ts",
    "content": "import { getLogger } from '@server/utils';\nimport {\n  IDashboardRepository,\n  IDashboardItemRepository,\n  IDashboardItemRefreshJobRepository,\n  DashboardCacheRefreshStatus,\n} from '@server/repositories';\nimport {\n  IProjectService,\n  IDeployService,\n  IQueryService,\n} from '@server/services';\nimport { CronExpressionParser } from 'cron-parser';\nimport { v4 as uuidv4 } from 'uuid';\n\nconst logger = getLogger('DashboardCacheBackgroundTracker');\nlogger.level = 'debug';\n\nexport class DashboardCacheBackgroundTracker {\n  private intervalTime: number;\n  private dashboardRepository: IDashboardRepository;\n  private dashboardItemRepository: IDashboardItemRepository;\n  private dashboardItemRefreshJobRepository: IDashboardItemRefreshJobRepository;\n  private projectService: IProjectService;\n  private deployService: IDeployService;\n  private queryService: IQueryService;\n  private runningJobs = new Set<number>();\n\n  constructor({\n    dashboardRepository,\n    dashboardItemRepository,\n    dashboardItemRefreshJobRepository,\n    projectService,\n    deployService,\n    queryService,\n  }: {\n    dashboardRepository: IDashboardRepository;\n    dashboardItemRepository: IDashboardItemRepository;\n    dashboardItemRefreshJobRepository: IDashboardItemRefreshJobRepository;\n    projectService: IProjectService;\n    deployService: IDeployService;\n    queryService: IQueryService;\n  }) {\n    this.dashboardRepository = dashboardRepository;\n    this.dashboardItemRepository = dashboardItemRepository;\n    this.dashboardItemRefreshJobRepository = dashboardItemRefreshJobRepository;\n    this.projectService = projectService;\n    this.deployService = deployService;\n    this.queryService = queryService;\n    this.intervalTime = 60000; // 1 minute\n    this.start();\n  }\n\n  private start(): void {\n    logger.info('Dashboard cache background tracker started');\n    setInterval(() => {\n      this.checkAndRefreshCaches();\n    }, this.intervalTime);\n  }\n\n  private async checkAndRefreshCaches(): Promise<void> {\n    try {\n      // Get all dashboards with cache enabled\n      const dashboards = await this.dashboardRepository.findAllBy({\n        cacheEnabled: true,\n      });\n\n      for (const dashboard of dashboards) {\n        if (!dashboard.scheduleCron || !dashboard.nextScheduledAt) {\n          continue;\n        }\n\n        const now = new Date();\n        const nextScheduledAt = new Date(dashboard.nextScheduledAt);\n\n        // Check if it's time to refresh\n        if (now >= nextScheduledAt) {\n          logger.info(`Start Refreshing cache for dashboard ${dashboard.id}`);\n          await this.refreshDashboardCache(dashboard);\n          logger.info(\n            `Finished Refreshing cache for dashboard ${dashboard.id}`,\n          );\n        }\n      }\n    } catch (error) {\n      logger.error(`Error checking dashboard caches: ${error.message}`);\n    }\n  }\n\n  private async refreshDashboardCache(dashboard: any): Promise<void> {\n    if (this.runningJobs.has(dashboard.id)) {\n      logger.debug(`Dashboard ${dashboard.id} refresh already in progress`);\n      return;\n    }\n\n    this.runningJobs.add(dashboard.id);\n\n    try {\n      // Get all items for this dashboard\n      const items = await this.dashboardItemRepository.findAllBy({\n        dashboardId: dashboard.id,\n      });\n\n      // Get project and deployment info\n      const project = await this.projectService.getCurrentProject();\n      const deployment = await this.deployService.getLastDeployment(project.id);\n      const mdl = deployment.manifest;\n      const hash = uuidv4();\n\n      // Refresh cache for each item\n      await Promise.all(\n        items.map(async (item) => {\n          try {\n            // Create a record for this refresh job\n            const refreshJob =\n              await this.dashboardItemRefreshJobRepository.createOne({\n                hash,\n                dashboardId: dashboard.id,\n                dashboardItemId: item.id,\n                startedAt: new Date(),\n                finishedAt: null,\n                status: DashboardCacheRefreshStatus.IN_PROGRESS,\n                errorMessage: null,\n              });\n\n            try {\n              await this.queryService.preview(item.detail.sql, {\n                project,\n                manifest: mdl,\n                cacheEnabled: true,\n                refresh: true,\n              });\n\n              // Update the record with success\n              await this.dashboardItemRefreshJobRepository.updateOne(\n                refreshJob.id,\n                {\n                  finishedAt: new Date(),\n                  status: DashboardCacheRefreshStatus.SUCCESS,\n                },\n              );\n            } catch (error) {\n              // Update the record with failure\n              await this.dashboardItemRefreshJobRepository.updateOne(\n                refreshJob.id,\n                {\n                  finishedAt: new Date(),\n                  status: DashboardCacheRefreshStatus.FAILED,\n                  errorMessage: error.message,\n                },\n              );\n              logger.debug(\n                `Error refreshing cache for item ${item.id}: ${error.message}`,\n              );\n            }\n          } catch (error) {\n            logger.debug(\n              `Error creating refresh job record for item ${item.id}: ${error.message}`,\n            );\n          }\n        }),\n      );\n\n      // Calculate next scheduled time\n      const nextScheduledAt = this.calculateNextRunTime(dashboard.scheduleCron);\n\n      // Update dashboard with new next scheduled time\n      await this.dashboardRepository.updateOne(dashboard.id, {\n        nextScheduledAt,\n      });\n      logger.info(\n        `Next scheduled time for dashboard ${dashboard.id}: ${nextScheduledAt}`,\n      );\n\n      logger.info(`Successfully refreshed cache for dashboard ${dashboard.id}`);\n    } catch (error) {\n      logger.error(\n        `Error refreshing dashboard ${dashboard.id}: ${error.message}`,\n      );\n    } finally {\n      this.runningJobs.delete(dashboard.id);\n    }\n  }\n\n  private calculateNextRunTime(cronExpression: string): Date | null {\n    try {\n      const interval = CronExpressionParser.parse(cronExpression, {\n        currentDate: new Date(),\n      });\n      return interval.next().toDate();\n    } catch (error) {\n      logger.error(`Failed to parse cron expression: ${error.message}`);\n      return null;\n    }\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/backgrounds/index.ts",
    "content": "export * from './adjustmentBackgroundTracker';\nexport * from './textBasedAnswerBackgroundTracker';\nexport * from './chart';\nexport * from './recommend-question';\nexport * from './dashboardCacheBackgroundTracker';\n"
  },
  {
    "path": "wren-ui/src/apollo/server/backgrounds/recommend-question.ts",
    "content": "import { IProjectRepository } from '../repositories/projectRepository';\nimport { RecommendationQuestionStatus } from '@server/models/adaptor';\nimport { IWrenAIAdaptor } from '../adaptors/wrenAIAdaptor';\nimport { IThreadRepository, Project, Thread } from '../repositories';\nimport {\n  ITelemetry,\n  TelemetryEvent,\n  WrenService,\n} from '../telemetry/telemetry';\nimport { getLogger } from '../utils/logger';\nimport { Logger } from 'log4js';\n\n// PRQ background tracker : project recommend question background tracker\nconst loggerPrefix = 'PRQBT:';\n\nconst isFinalized = (status: RecommendationQuestionStatus) => {\n  return [\n    RecommendationQuestionStatus.FINISHED,\n    RecommendationQuestionStatus.FAILED,\n  ].includes(status);\n};\n\nexport class ProjectRecommendQuestionBackgroundTracker {\n  // tasks is a kv pair of task id and thread response\n  private tasks: Record<number, Project> = {};\n  private intervalTime: number;\n  private wrenAIAdaptor: IWrenAIAdaptor;\n  private projectRepository: IProjectRepository;\n  private runningJobs = new Set();\n  private telemetry: ITelemetry;\n  private logger: Logger;\n\n  constructor({\n    telemetry,\n    wrenAIAdaptor,\n    projectRepository,\n  }: {\n    telemetry: ITelemetry;\n    wrenAIAdaptor: IWrenAIAdaptor;\n    projectRepository: IProjectRepository;\n  }) {\n    this.logger = getLogger('PRQ Background Tracker');\n    this.logger.level = 'debug';\n    this.telemetry = telemetry;\n    this.wrenAIAdaptor = wrenAIAdaptor;\n    this.projectRepository = projectRepository;\n    this.intervalTime = 1000;\n    this.start();\n  }\n\n  public start() {\n    this.logger.info('Recommend question background tracker started');\n    setInterval(() => {\n      const jobs = Object.values(this.tasks).map((project) => async () => {\n        // check if same job is running\n        if (this.runningJobs.has(this.taskKey(project))) {\n          return;\n        }\n\n        // mark the job as running\n        this.runningJobs.add(this.taskKey(project));\n\n        // get the latest result from AI service\n\n        const result =\n          await this.wrenAIAdaptor.getRecommendationQuestionsResult(\n            project.queryId,\n          );\n\n        // check if status change\n        if (\n          project.questionsStatus === result.status &&\n          result.response?.questions.length === (project.questions || []).length\n        ) {\n          // mark the job as finished\n          this.logger.debug(\n            `${loggerPrefix}job ${this.taskKey(project)} status not changed, returning question count: ${result.response?.questions.length || 0}`,\n          );\n          this.runningJobs.delete(this.taskKey(project));\n          return;\n        }\n\n        // update database\n        if (\n          result.status !== project.questionsStatus ||\n          result.response?.questions.length !== (project.questions || []).length\n        ) {\n          this.logger.debug(\n            `${loggerPrefix}job ${this.taskKey(project)} have changes, returning question count: ${result.response?.questions.length || 0}, updating`,\n          );\n          await this.projectRepository.updateOne(project.id, {\n            questionsStatus: result.status.toUpperCase(),\n            questions: result.response?.questions,\n            questionsError: result.error,\n          });\n          project.questionsStatus = result.status;\n          project.questions = result.response?.questions;\n        }\n\n        // remove the task from tracker if it is finalized\n        if (isFinalized(result.status)) {\n          const eventProperties = {\n            projectId: project.id,\n            projectType: project.type,\n            status: result.status,\n            questions: project.questions,\n            error: result.error,\n          };\n          if (result.status === RecommendationQuestionStatus.FINISHED) {\n            this.telemetry.sendEvent(\n              TelemetryEvent.HOME_GENERATE_PROJECT_RECOMMENDATION_QUESTIONS,\n              eventProperties,\n            );\n          } else {\n            this.telemetry.sendEvent(\n              TelemetryEvent.HOME_GENERATE_PROJECT_RECOMMENDATION_QUESTIONS,\n              eventProperties,\n              WrenService.AI,\n              false,\n            );\n          }\n          this.logger.debug(\n            `${loggerPrefix}job ${this.taskKey(project)} is finalized, removing`,\n          );\n          delete this.tasks[this.taskKey(project)];\n        }\n\n        // mark the job as finished\n        this.runningJobs.delete(this.taskKey(project));\n      });\n\n      // run the jobs\n      Promise.allSettled(jobs.map((job) => job())).then((results) => {\n        // show reason of rejection\n        results.forEach((result, index) => {\n          if (result.status === 'rejected') {\n            this.logger.error(`Job ${index} failed: ${result.reason}`);\n          }\n        });\n      });\n    }, this.intervalTime);\n  }\n\n  public addTask(project: Project) {\n    this.tasks[this.taskKey(project)] = project;\n  }\n\n  public getTasks() {\n    return this.tasks;\n  }\n\n  public async initialize() {\n    const projects = await this.projectRepository.findAll();\n    for (const project of projects) {\n      if (\n        this.taskKey(project) &&\n        !isFinalized(project.questionsStatus as RecommendationQuestionStatus)\n      ) {\n        this.addTask(project);\n      }\n    }\n  }\n\n  public taskKey(project: Project) {\n    return project.id;\n  }\n\n  public isExist(project: Project) {\n    return this.tasks[this.taskKey(project)];\n  }\n}\n\nexport class ThreadRecommendQuestionBackgroundTracker {\n  // tasks is a kv pair of task id and thread response\n  private tasks: Record<number, Thread> = {};\n  private intervalTime: number;\n  private wrenAIAdaptor: IWrenAIAdaptor;\n  private threadRepository: IThreadRepository;\n  private runningJobs = new Set();\n  private telemetry: ITelemetry;\n  private logger: Logger;\n\n  constructor({\n    telemetry,\n    wrenAIAdaptor,\n    threadRepository,\n  }: {\n    telemetry: ITelemetry;\n    wrenAIAdaptor: IWrenAIAdaptor;\n    threadRepository: IThreadRepository;\n  }) {\n    this.logger = getLogger('TRQ Background Tracker');\n    this.logger.level = 'debug';\n    this.telemetry = telemetry;\n    this.wrenAIAdaptor = wrenAIAdaptor;\n    this.threadRepository = threadRepository;\n    this.intervalTime = 1000;\n    this.start();\n  }\n\n  public start() {\n    this.logger.info('Recommend question background tracker started');\n    setInterval(() => {\n      const jobs = Object.values(this.tasks).map((thread) => async () => {\n        // check if same job is running\n        if (this.runningJobs.has(this.taskKey(thread))) {\n          return;\n        }\n\n        // mark the job as running\n        this.runningJobs.add(this.taskKey(thread));\n\n        // get the latest result from AI service\n\n        const result =\n          await this.wrenAIAdaptor.getRecommendationQuestionsResult(\n            thread.queryId,\n          );\n\n        // check if status change\n        if (\n          thread.questionsStatus === result.status &&\n          result.response?.questions.length === (thread.questions || []).length\n        ) {\n          // mark the job as finished\n          this.logger.debug(\n            `${loggerPrefix}job ${this.taskKey(thread)} status not changed, returning question count: ${result.response?.questions.length || 0}`,\n          );\n          this.runningJobs.delete(this.taskKey(thread));\n          return;\n        }\n\n        // update database\n        if (\n          result.status !== thread.questionsStatus ||\n          result.response?.questions.length !== (thread.questions || []).length\n        ) {\n          this.logger.debug(\n            `${loggerPrefix}job ${this.taskKey(thread)} have changes, returning question count: ${result.response?.questions.length || 0}, updating`,\n          );\n          await this.threadRepository.updateOne(thread.id, {\n            questionsStatus: result.status.toUpperCase(),\n            questions: result.response?.questions,\n            questionsError: result.error,\n          });\n          thread.questionsStatus = result.status;\n          thread.questions = result.response?.questions;\n        }\n\n        // remove the task from tracker if it is finalized\n        if (isFinalized(result.status)) {\n          const eventProperties = {\n            thread_id: thread.id,\n            status: result.status,\n            questions: thread.questions,\n            error: result.error,\n          };\n          if (result.status === RecommendationQuestionStatus.FINISHED) {\n            this.telemetry.sendEvent(\n              TelemetryEvent.HOME_GENERATE_THREAD_RECOMMENDATION_QUESTIONS,\n              eventProperties,\n            );\n          } else {\n            this.telemetry.sendEvent(\n              TelemetryEvent.HOME_GENERATE_THREAD_RECOMMENDATION_QUESTIONS,\n              eventProperties,\n              WrenService.AI,\n              false,\n            );\n          }\n          this.logger.debug(\n            `${loggerPrefix}job ${this.taskKey(thread)} is finalized, removing`,\n          );\n          delete this.tasks[this.taskKey(thread)];\n        }\n\n        // mark the job as finished\n        this.runningJobs.delete(this.taskKey(thread));\n      });\n\n      // run the jobs\n      Promise.allSettled(jobs.map((job) => job())).then((results) => {\n        // show reason of rejection\n        results.forEach((result, index) => {\n          if (result.status === 'rejected') {\n            this.logger.error(`Job ${index} failed: ${result.reason}`);\n          }\n        });\n      });\n    }, this.intervalTime);\n  }\n\n  public addTask(thread: Thread) {\n    this.tasks[this.taskKey(thread)] = thread;\n  }\n\n  public getTasks() {\n    return this.tasks;\n  }\n\n  public async initialize() {\n    const threads = await this.threadRepository.findAll();\n    for (const thread of threads) {\n      if (\n        !this.tasks[this.taskKey(thread)] &&\n        thread.queryId &&\n        !isFinalized(thread.questionsStatus as RecommendationQuestionStatus)\n      ) {\n        this.addTask(thread);\n      }\n    }\n  }\n\n  public taskKey(thread: Thread) {\n    return thread.id;\n  }\n\n  public isExist(thread: Thread) {\n    return this.tasks[this.taskKey(thread)];\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/backgrounds/textBasedAnswerBackgroundTracker.ts",
    "content": "import { IWrenAIAdaptor } from '../adaptors';\nimport {\n  WrenAILanguage,\n  TextBasedAnswerResult,\n  TextBasedAnswerStatus,\n} from '../models/adaptor';\nimport { ThreadResponse, IThreadResponseRepository } from '../repositories';\nimport {\n  IProjectService,\n  IDeployService,\n  IQueryService,\n  ThreadResponseAnswerStatus,\n  PreviewDataResponse,\n} from '../services';\nimport { getLogger } from '@server/utils';\n\nconst logger = getLogger('TextBasedAnswerBackgroundTracker');\nlogger.level = 'debug';\n\nexport class TextBasedAnswerBackgroundTracker {\n  // tasks is a kv pair of task id and thread response\n  private tasks: Record<number, ThreadResponse> = {};\n  private intervalTime: number;\n  private wrenAIAdaptor: IWrenAIAdaptor;\n  private threadResponseRepository: IThreadResponseRepository;\n  private projectService: IProjectService;\n  private deployService: IDeployService;\n  private queryService: IQueryService;\n  private runningJobs = new Set();\n\n  constructor({\n    wrenAIAdaptor,\n    threadResponseRepository,\n    projectService,\n    deployService,\n    queryService,\n  }: {\n    wrenAIAdaptor: IWrenAIAdaptor;\n    threadResponseRepository: IThreadResponseRepository;\n    projectService: IProjectService;\n    deployService: IDeployService;\n    queryService: IQueryService;\n  }) {\n    this.wrenAIAdaptor = wrenAIAdaptor;\n    this.threadResponseRepository = threadResponseRepository;\n    this.projectService = projectService;\n    this.deployService = deployService;\n    this.queryService = queryService;\n    this.intervalTime = 1000;\n    this.start();\n  }\n\n  private start() {\n    setInterval(async () => {\n      const jobs = Object.values(this.tasks).map(\n        (threadResponse) => async () => {\n          if (\n            this.runningJobs.has(threadResponse.id) ||\n            !threadResponse.answerDetail\n          ) {\n            return;\n          }\n          this.runningJobs.add(threadResponse.id);\n\n          // update the status to fetching data\n          await this.threadResponseRepository.updateOne(threadResponse.id, {\n            answerDetail: {\n              ...threadResponse.answerDetail,\n              status: ThreadResponseAnswerStatus.FETCHING_DATA,\n            },\n          });\n\n          // get sql data\n          const project = await this.projectService.getCurrentProject();\n          const deployment = await this.deployService.getLastDeployment(\n            project.id,\n          );\n          const mdl = deployment.manifest;\n          let data: PreviewDataResponse;\n          try {\n            data = (await this.queryService.preview(threadResponse.sql, {\n              project,\n              manifest: mdl,\n              modelingOnly: false,\n              limit: 500,\n            })) as PreviewDataResponse;\n          } catch (error) {\n            logger.error(`Error when query sql data: ${error}`);\n            await this.threadResponseRepository.updateOne(threadResponse.id, {\n              answerDetail: {\n                ...threadResponse.answerDetail,\n                status: ThreadResponseAnswerStatus.FAILED,\n                error: error?.extensions || error,\n              },\n            });\n            throw error;\n          }\n\n          // request AI service\n          const response = await this.wrenAIAdaptor.createTextBasedAnswer({\n            query: threadResponse.question,\n            sql: threadResponse.sql,\n            sqlData: data,\n            threadId: threadResponse.threadId.toString(),\n            configurations: {\n              language: WrenAILanguage[project.language] || WrenAILanguage.EN,\n            },\n          });\n\n          // update the status to preprocessing\n          await this.threadResponseRepository.updateOne(threadResponse.id, {\n            answerDetail: {\n              ...threadResponse.answerDetail,\n              status: ThreadResponseAnswerStatus.PREPROCESSING,\n            },\n          });\n\n          // polling query id to check the status\n          let result: TextBasedAnswerResult;\n          do {\n            result = await this.wrenAIAdaptor.getTextBasedAnswerResult(\n              response.queryId,\n            );\n            if (result.status === TextBasedAnswerStatus.PREPROCESSING) {\n              await new Promise((resolve) => setTimeout(resolve, 500));\n            }\n          } while (result.status === TextBasedAnswerStatus.PREPROCESSING);\n\n          // update the status to final\n          const updatedAnswerDetail = {\n            queryId: response.queryId,\n            status:\n              result.status === TextBasedAnswerStatus.SUCCEEDED\n                ? ThreadResponseAnswerStatus.STREAMING\n                : ThreadResponseAnswerStatus.FAILED,\n            numRowsUsedInLLM: result.numRowsUsedInLLM,\n            error: result.error,\n          };\n          await this.threadResponseRepository.updateOne(threadResponse.id, {\n            answerDetail: updatedAnswerDetail,\n          });\n\n          delete this.tasks[threadResponse.id];\n\n          // Mark the job as finished\n          this.runningJobs.delete(threadResponse.id);\n        },\n      );\n\n      // Run the jobs\n      Promise.allSettled(jobs.map((job) => job())).then((results) => {\n        // Show reason of rejection\n        results.forEach((result, index) => {\n          if (result.status === 'rejected') {\n            logger.error(`Job ${index} failed: ${result.reason}`);\n          }\n        });\n      });\n    }, this.intervalTime);\n  }\n\n  public addTask(threadResponse: ThreadResponse) {\n    this.tasks[threadResponse.id] = threadResponse;\n  }\n\n  public getTasks() {\n    return this.tasks;\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/config.ts",
    "content": "import { pickBy } from 'lodash';\n\nexport interface IConfig {\n  // wren ui\n  otherServiceUsingDocker: boolean;\n\n  // database\n  dbType: string;\n  // pg\n  pgUrl?: string;\n  debug?: boolean;\n  // sqlite\n  sqliteFile?: string;\n\n  persistCredentialDir?: string;\n\n  // wren engine\n  wrenEngineEndpoint: string;\n\n  // wren AI\n  wrenAIEndpoint: string;\n  generationModel?: string;\n\n  // ibis server\n  experimentalEngineRustVersion?: boolean;\n  ibisServerEndpoint: string;\n\n  // encryption\n  encryptionPassword: string;\n  encryptionSalt: string;\n\n  // telemetry\n  telemetryEnabled?: boolean;\n  posthogApiKey?: string;\n  posthogHost?: string;\n  userUUID?: string;\n\n  // versions\n  wrenUIVersion?: string;\n  wrenEngineVersion?: string;\n  wrenAIVersion?: string;\n  wrenProductVersion?: string;\n\n  // generate recommendation questions max categories\n  projectRecommendationQuestionMaxCategories?: number;\n  projectRecommendationQuestionsMaxQuestions?: number;\n  threadRecommendationQuestionMaxCategories?: number;\n  threadRecommendationQuestionsMaxQuestions?: number;\n}\n\nconst defaultConfig = {\n  // wren ui\n  otherServiceUsingDocker: false,\n\n  // database\n  dbType: 'sqlite',\n\n  // pg\n  pgUrl: 'postgres://postgres:postgres@localhost:5432/admin_ui',\n  debug: false,\n\n  // sqlite\n  sqliteFile: './db.sqlite3',\n\n  persistCredentialDir: `${process.cwd()}/.tmp`,\n\n  // wren engine\n  wrenEngineEndpoint: 'http://localhost:8080',\n\n  // wren AI\n  wrenAIEndpoint: 'http://localhost:5555',\n\n  // ibis server\n  experimentalEngineRustVersion: true,\n  ibisServerEndpoint: 'http://127.0.0.1:8000',\n\n  // encryption\n  encryptionPassword: 'sementic',\n  encryptionSalt: 'layer',\n};\n\nconst config = {\n  // node\n  otherServiceUsingDocker: process.env.OTHER_SERVICE_USING_DOCKER === 'true',\n\n  // database\n  dbType: process.env.DB_TYPE,\n  // pg\n  pgUrl: process.env.PG_URL,\n  debug: process.env.DEBUG === 'true',\n  // sqlite\n  sqliteFile: process.env.SQLITE_FILE,\n\n  persistCredentialDir: (() => {\n    if (\n      process.env.PERSIST_CREDENTIAL_DIR &&\n      process.env.PERSIST_CREDENTIAL_DIR.length > 0\n    ) {\n      return process.env.PERSIST_CREDENTIAL_DIR;\n    }\n    return undefined;\n  })(),\n\n  // wren engine\n  wrenEngineEndpoint: process.env.WREN_ENGINE_ENDPOINT,\n\n  // wren AI\n  wrenAIEndpoint: process.env.WREN_AI_ENDPOINT,\n  generationModel: process.env.GENERATION_MODEL,\n\n  // ibis server\n  experimentalEngineRustVersion:\n    process.env.EXPERIMENTAL_ENGINE_RUST_VERSION === 'true',\n  ibisServerEndpoint: process.env.IBIS_SERVER_ENDPOINT,\n\n  // encryption\n  encryptionPassword: process.env.ENCRYPTION_PASSWORD,\n  encryptionSalt: process.env.ENCRYPTION_SALT,\n\n  // telemetry\n  telemetryEnabled:\n    process.env.TELEMETRY_ENABLED &&\n    process.env.TELEMETRY_ENABLED.toLocaleLowerCase() === 'true',\n  posthogApiKey: process.env.POSTHOG_API_KEY,\n  posthogHost: process.env.POSTHOG_HOST,\n  userUUID: process.env.USER_UUID,\n\n  // versions\n  wrenUIVersion: process.env.WREN_UI_VERSION,\n  wrenEngineVersion: process.env.WREN_ENGINE_VERSION,\n  wrenAIVersion: process.env.WREN_AI_SERVICE_VERSION,\n  wrenProductVersion: process.env.WREN_PRODUCT_VERSION,\n\n  // generate recommendation questions max questions\n  projectRecommendationQuestionMaxCategories: process.env\n    .PROJECT_RECOMMENDATION_QUESTION_MAX_CATEGORIES\n    ? parseInt(process.env.PROJECT_RECOMMENDATION_QUESTION_MAX_CATEGORIES)\n    : 3,\n  projectRecommendationQuestionsMaxQuestions: process.env\n    .PROJECT_RECOMMENDATION_QUESTIONS_MAX_QUESTIONS\n    ? parseInt(process.env.PROJECT_RECOMMENDATION_QUESTIONS_MAX_QUESTIONS)\n    : 3,\n  threadRecommendationQuestionMaxCategories: process.env\n    .THREAD_RECOMMENDATION_QUESTION_MAX_CATEGORIES\n    ? parseInt(process.env.THREAD_RECOMMENDATION_QUESTION_MAX_CATEGORIES)\n    : 3,\n  threadRecommendationQuestionsMaxQuestions: process.env\n    .THREAD_RECOMMENDATION_QUESTIONS_MAX_QUESTIONS\n    ? parseInt(process.env.THREAD_RECOMMENDATION_QUESTIONS_MAX_QUESTIONS)\n    : 1,\n};\n\nexport function getConfig(): IConfig {\n  return { ...defaultConfig, ...pickBy(config) };\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/data/index.ts",
    "content": "export * from './sample';\nexport * from './type';\n"
  },
  {
    "path": "wren-ui/src/apollo/server/data/sample.ts",
    "content": "import { RelationType } from '../types';\nimport { SampleDatasetName } from './type';\n\nexport interface SampleDatasetColumn {\n  name: string;\n  properties?: Record<string, any>;\n}\n\nexport interface SampleDatasetSchema {\n  columnName: string;\n  dataType: string;\n}\nexport interface SampleDatasetTable {\n  filePath: string;\n  tableName: string;\n  primaryKey?: string;\n  // the column order in schema definition should be the same as the column in csv file\n  schema?: SampleDatasetSchema[];\n  columns?: SampleDatasetColumn[];\n  properties?: Record<string, any>;\n}\n\nexport interface SampleDatasetRelationship {\n  fromModelName: string;\n  fromColumnName: string;\n  toModelName: string;\n  toColumnName: string;\n  type: RelationType;\n  description?: string;\n}\nexport interface SuggestedQuestion {\n  question: string;\n  label: string;\n}\n\nexport interface SampleDataset {\n  name: string; // SampleDatasetName\n  tables: SampleDatasetTable[];\n  questions?: SuggestedQuestion[];\n  relations?: SampleDatasetRelationship[];\n}\n\nexport const sampleDatasets: Record<string, SampleDataset> = {\n  hr: {\n    name: SampleDatasetName.HR,\n    tables: [\n      {\n        tableName: 'salaries',\n        filePath:\n          'https://assets.getwren.ai/sample_data/employees/salaries.parquet',\n        schema: [\n          { columnName: 'emp_no', dataType: 'INTEGER' },\n          { columnName: 'salary', dataType: 'INTEGER' },\n          { columnName: 'from_date', dataType: 'DATE' },\n          { columnName: 'to_date', dataType: 'DATE' },\n        ],\n        columns: [\n          {\n            name: 'emp_no',\n            properties: {\n              description: 'The employee number',\n              displayName: 'emp_no',\n            },\n          },\n          {\n            name: 'salary',\n            properties: {\n              description: 'The salary of the employee.',\n              displayName: 'salary',\n            },\n          },\n          {\n            name: 'from_date',\n            properties: {\n              description: 'The start date of the salary period.',\n              displayName: 'from_date',\n            },\n          },\n          {\n            name: 'to_date',\n            properties: {\n              description: 'The end date of the salary period.',\n              displayName: 'to_date',\n            },\n          },\n        ],\n        properties: {\n          description:\n            'Tracks the salary of employees, including the period during which each salary was valid.',\n          displayName: 'salaries',\n        },\n      },\n      {\n        tableName: 'titles',\n        filePath:\n          'https://assets.getwren.ai/sample_data/employees/titles.parquet',\n        schema: [\n          { columnName: 'emp_no', dataType: 'INTEGER' },\n          { columnName: 'title', dataType: 'VARCHAR' },\n          { columnName: 'from_date', dataType: 'DATE' },\n          { columnName: 'to_date', dataType: 'DATE' },\n        ],\n        columns: [\n          {\n            name: 'emp_no',\n            properties: {\n              description: 'The employee number',\n              displayName: 'emp_no',\n            },\n          },\n          {\n            name: 'title',\n            properties: {\n              description:\n                'The title or position held by the employee. Limited to a maximum of 50 characters.',\n              displayName: 'title',\n            },\n          },\n          {\n            name: 'from_date',\n            properties: {\n              description: 'The start date when the employee held this title',\n              displayName: 'from_date',\n            },\n          },\n          {\n            name: 'to_date',\n            properties: {\n              description:\n                'The end date when the employee held this title. This can be NULL if the employee currently holds the title.',\n              displayName: 'to_date',\n            },\n          },\n        ],\n        properties: {\n          description:\n            'Tracks the titles (positions) held by employees, including the period during which they held each title.',\n          displayName: 'titles',\n        },\n      },\n      {\n        tableName: 'dept_emp',\n        filePath:\n          'https://assets.getwren.ai/sample_data/employees/dept_emp.parquet',\n        schema: [\n          { columnName: 'emp_no', dataType: 'INTEGER' },\n          { columnName: 'dept_no', dataType: 'VARCHAR' },\n          { columnName: 'from_date', dataType: 'DATE' },\n          { columnName: 'to_date', dataType: 'DATE' },\n        ],\n        columns: [\n          {\n            name: 'emp_no',\n            properties: {\n              description: 'The employee number.',\n              displayName: 'emp_no',\n            },\n          },\n          {\n            name: 'dept_no',\n            properties: {\n              description:\n                'The department number the employee is associated with, referencing the dept_no in the departments table.',\n              displayName: 'dept_no',\n            },\n          },\n          {\n            name: 'from_date',\n            properties: {\n              description:\n                \"The start date of the employee's association with the department.\",\n              displayName: 'from_date',\n            },\n          },\n          {\n            name: 'to_date',\n            properties: {\n              description:\n                \"The end date of the employee's association with the department\",\n              displayName: 'to_date',\n            },\n          },\n        ],\n        properties: {\n          displayName: 'dept_emp',\n        },\n      },\n      {\n        tableName: 'departments',\n        filePath:\n          'https://assets.getwren.ai/sample_data/employees/departments.parquet',\n        schema: [\n          { columnName: 'dept_name', dataType: 'VARCHAR' },\n          { columnName: 'dept_no', dataType: 'VARCHAR' },\n        ],\n        columns: [\n          {\n            name: 'dept_name',\n            properties: {\n              description:\n                'The name of the department. Limited to a maximum of 40 characters. This column is also unique across the table, ensuring no two departments share the same name',\n              displayName: 'dept_name',\n            },\n          },\n          {\n            name: 'dept_no',\n            properties: {\n              description:\n                'A unique identifier for each department. It serves as the primary key of the table.',\n              displayName: 'dept_no',\n            },\n          },\n        ],\n        properties: {\n          displayName: 'departments',\n        },\n      },\n      {\n        tableName: 'employees',\n        filePath:\n          'https://assets.getwren.ai/sample_data/employees/employees.parquet',\n        schema: [\n          { columnName: 'birth_date', dataType: 'DATE' },\n          { columnName: 'first_name', dataType: 'VARCHAR' },\n          { columnName: 'last_name', dataType: 'VARCHAR' },\n          { columnName: 'gender', dataType: 'VARCHAR' },\n          { columnName: 'hire_date', dataType: 'DATE' },\n          { columnName: 'emp_no', dataType: 'INTEGER' },\n        ],\n        columns: [\n          {\n            name: 'birth_date',\n            properties: {\n              description: 'The birth date of the employee.',\n              displayName: 'birth_date',\n            },\n          },\n          {\n            name: 'first_name',\n            properties: {\n              description:\n                'The first name of the employee. Limited to a maximum of 14 characters.',\n              displayName: 'first_name',\n            },\n          },\n          {\n            name: 'last_name',\n            properties: {\n              description:\n                'The last name of the employee. Limited to a maximum of 16 characters.',\n              displayName: 'last_name',\n            },\n          },\n          {\n            name: 'gender',\n            properties: {\n              description:\n                \"The gender of the employee, with possible values 'M' (Male) or 'F' (Female).\",\n              displayName: 'gender',\n            },\n          },\n          {\n            name: 'hire_date',\n            properties: {\n              description: 'The date when the employee was hired.',\n              displayName: 'hire_date',\n            },\n          },\n          {\n            name: 'emp_no',\n            properties: {\n              description:\n                'A unique identifier for each employee. It serves as the primary key of the table',\n              displayName: 'emp_no',\n            },\n          },\n        ],\n        properties: {\n          description:\n            'Stores basic information about employees such as their employee number, name, gender, birth date, and hire date',\n          displayName: 'employees',\n        },\n      },\n      {\n        tableName: 'dept_manager',\n        filePath:\n          'https://assets.getwren.ai/sample_data/employees/dept_manager.parquet',\n        schema: [\n          { columnName: 'from_date', dataType: 'DATE' },\n          { columnName: 'to_date', dataType: 'DATE' },\n          { columnName: 'emp_no', dataType: 'INTEGER' },\n          { columnName: 'dept_no', dataType: 'VARCHAR' },\n        ],\n        columns: [\n          {\n            name: 'from_date',\n            properties: {\n              description:\n                'The start date of the employee’s managerial role in the department.',\n              displayName: 'from_date',\n            },\n          },\n          {\n            name: 'to_date',\n            properties: {\n              description:\n                'The end date of the employee’s managerial role in the department.',\n              displayName: 'to_date',\n            },\n          },\n          {\n            name: 'emp_no',\n            properties: {\n              description: 'The employee number of the department manager',\n              displayName: 'emp_no',\n            },\n          },\n          {\n            name: 'dept_no',\n            properties: {\n              description:\n                'The department number that the manager is assigned to, referencing the dept_no in the departments table.',\n              displayName: 'dept_no',\n            },\n          },\n        ],\n        properties: {\n          description:\n            'Tracks the assignment of managers to departments, including the period during which they managed a department',\n          displayName: 'dept_manager',\n        },\n      },\n    ],\n    relations: [\n      {\n        fromModelName: 'employees',\n        fromColumnName: 'emp_no',\n        toModelName: 'titles',\n        toColumnName: 'emp_no',\n        type: RelationType.ONE_TO_MANY,\n        description:\n          'Each entry represents a title held by an employee during a specific time period.',\n      },\n      {\n        fromModelName: 'departments',\n        fromColumnName: 'dept_no',\n        toModelName: 'dept_emp',\n        toColumnName: 'dept_no',\n        type: RelationType.ONE_TO_MANY,\n      },\n      {\n        fromModelName: 'employees',\n        fromColumnName: 'emp_no',\n        toModelName: 'salaries',\n        toColumnName: 'emp_no',\n        type: RelationType.ONE_TO_MANY,\n      },\n      {\n        fromModelName: 'dept_manager',\n        fromColumnName: 'emp_no',\n        toModelName: 'employees',\n        toColumnName: 'emp_no',\n        type: RelationType.MANY_TO_ONE,\n      },\n      {\n        fromModelName: 'dept_emp',\n        fromColumnName: 'emp_no',\n        toModelName: 'employees',\n        toColumnName: 'emp_no',\n        type: RelationType.MANY_TO_ONE,\n        description:\n          'meaning an employee can be associated with multiple departments, titles, and salaries over time.',\n      },\n      {\n        fromModelName: 'departments',\n        fromColumnName: 'dept_no',\n        toModelName: 'dept_manager',\n        toColumnName: 'dept_no',\n        type: RelationType.ONE_TO_MANY,\n      },\n    ],\n    questions: [\n      {\n        question: 'What is the average salary for each position?',\n        label: 'Aggregation',\n      },\n      {\n        question:\n          'Compare the average salary of male and female employees in each department.',\n        label: 'Comparison',\n      },\n      {\n        question:\n          'What are the names of the managers and the departments they manage?',\n        label: 'Associating',\n      },\n    ],\n  },\n  music: {\n    name: SampleDatasetName.MUSIC,\n    tables: [\n      {\n        tableName: 'album',\n        filePath: 'https://wrenai-public.s3.amazonaws.com/demo/Music/Album.csv',\n        schema: [\n          { columnName: 'AlbumId', dataType: 'INT' },\n          { columnName: 'Title', dataType: 'varchar' },\n          { columnName: 'ArtistId', dataType: 'INT' },\n        ],\n      },\n      {\n        tableName: 'artist',\n        filePath:\n          'https://wrenai-public.s3.amazonaws.com/demo/Music/Artist.csv',\n        schema: [\n          { columnName: 'ArtistId', dataType: 'INT' },\n          { columnName: 'Name', dataType: 'varchar' },\n        ],\n      },\n      {\n        tableName: 'customer',\n        filePath:\n          'https://wrenai-public.s3.amazonaws.com/demo/Music/Customer.csv',\n        schema: [\n          { columnName: 'CustomerId', dataType: 'BIGINT' },\n          { columnName: 'FirstName', dataType: 'VARCHAR' },\n          { columnName: 'LastName', dataType: 'VARCHAR' },\n          { columnName: 'Company', dataType: 'VARCHAR' },\n          { columnName: 'Address', dataType: 'VARCHAR' },\n          { columnName: 'City', dataType: 'VARCHAR' },\n          { columnName: 'State', dataType: 'VARCHAR' },\n          { columnName: 'Country', dataType: 'VARCHAR' },\n          { columnName: 'PostalCode', dataType: 'VARCHAR' },\n          { columnName: 'Phone', dataType: 'VARCHAR' },\n          { columnName: 'Fax', dataType: 'VARCHAR' },\n          { columnName: 'Email', dataType: 'VARCHAR' },\n          { columnName: 'SupportRepId', dataType: 'BIGINT' },\n        ],\n      },\n      {\n        tableName: 'genre',\n        filePath: 'https://wrenai-public.s3.amazonaws.com/demo/Music/Genre.csv',\n        schema: [\n          { columnName: 'GenreId', dataType: 'BIGINT' },\n          { columnName: 'Name', dataType: 'VARCHAR' },\n        ],\n      },\n      {\n        tableName: 'invoice',\n        filePath:\n          'https://wrenai-public.s3.amazonaws.com/demo/Music/Invoice.csv',\n        schema: [\n          { columnName: 'InvoiceId', dataType: 'BIGINT' },\n          { columnName: 'CustomerId', dataType: 'BIGINT' },\n          { columnName: 'InvoiceDate', dataType: 'Date' },\n          { columnName: 'BillingAddress', dataType: 'VARCHAR' },\n          { columnName: 'BillingCity', dataType: 'VARCHAR' },\n          { columnName: 'BillingState', dataType: 'VARCHAR' },\n          { columnName: 'BillingCountry', dataType: 'VARCHAR' },\n          { columnName: 'BillingPostalCode', dataType: 'VARCHAR' },\n          { columnName: 'Total', dataType: 'DOUBLE' },\n        ],\n      },\n      {\n        tableName: 'invoiceLine',\n        filePath:\n          'https://wrenai-public.s3.amazonaws.com/demo/Music/InvoiceLine.csv',\n        schema: [\n          { columnName: 'InvoiceLineId', dataType: 'BIGINT' },\n          { columnName: 'InvoiceId', dataType: 'BIGINT' },\n          { columnName: 'TrackId', dataType: 'BIGINT' },\n          { columnName: 'UnitPrice', dataType: 'DOUBLE' },\n          { columnName: 'Quantity', dataType: 'BIGINT' },\n        ],\n      },\n      {\n        tableName: 'track',\n        filePath: 'https://wrenai-public.s3.amazonaws.com/demo/Music/Track.csv',\n        schema: [\n          { columnName: 'TrackId', dataType: 'BIGINT' },\n          { columnName: 'Name', dataType: 'VARCHAR' },\n          { columnName: 'AlbumId', dataType: 'BIGINT' },\n          { columnName: 'MediaTypeId', dataType: 'BIGINT' },\n          { columnName: 'GenreId', dataType: 'BIGINT' },\n          { columnName: 'Composer', dataType: 'VARCHAR' },\n          { columnName: 'Milliseconds', dataType: 'BIGINT' },\n          { columnName: 'Bytes', dataType: 'BIGINT' },\n          { columnName: 'UnitPrice', dataType: 'DOUBLE' },\n        ],\n      },\n    ],\n    questions: [\n      {\n        question: 'What are the top 5 selling albums in the US?',\n        label: 'Ranking',\n      },\n      {\n        question: 'What is the total revenue generated from each genre?',\n        label: 'Aggregation',\n      },\n      {\n        question:\n          'Which customers have made purchases of tracks from albums in each genre?',\n        label: 'General',\n      },\n    ],\n    relations: [\n      {\n        fromModelName: 'album',\n        fromColumnName: 'ArtistId',\n        toModelName: 'artist',\n        toColumnName: 'ArtistId',\n        type: RelationType.MANY_TO_ONE,\n      },\n      {\n        fromModelName: 'customer',\n        fromColumnName: 'CustomerId',\n        toModelName: 'invoice',\n        toColumnName: 'CustomerId',\n        type: RelationType.ONE_TO_MANY,\n      },\n      {\n        fromModelName: 'genre',\n        fromColumnName: 'GenreId',\n        toModelName: 'track',\n        toColumnName: 'GenreId',\n        type: RelationType.ONE_TO_MANY,\n      },\n      {\n        fromModelName: 'invoice',\n        fromColumnName: 'InvoiceId',\n        toModelName: 'invoiceLine',\n        toColumnName: 'InvoiceId',\n        type: RelationType.ONE_TO_MANY,\n      },\n      {\n        fromModelName: 'track',\n        fromColumnName: 'TrackId',\n        toModelName: 'invoiceLine',\n        toColumnName: 'TrackId',\n        type: RelationType.ONE_TO_MANY,\n      },\n      // album -> track\n      {\n        fromModelName: 'album',\n        fromColumnName: 'AlbumId',\n        toModelName: 'track',\n        toColumnName: 'AlbumId',\n        type: RelationType.ONE_TO_MANY,\n      },\n    ],\n  },\n  ecommerce: {\n    name: SampleDatasetName.ECOMMERCE,\n    tables: [\n      {\n        tableName: 'olist_customers_dataset',\n        primaryKey: 'customer_id',\n        filePath:\n          'https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_customers_dataset.parquet',\n        properties: {\n          displayName: 'customers',\n        },\n        columns: [\n          {\n            name: 'customer_city',\n            properties: {\n              description: 'Name of the city where the customer is located',\n              displayName: 'customer_city',\n            },\n          },\n          {\n            name: 'customer_id',\n            properties: {\n              description: null,\n              displayName: 'customer_id',\n            },\n          },\n          {\n            name: 'customer_state',\n            properties: {\n              description: 'Name of the state where the customer is located',\n              displayName: 'customer_state',\n            },\n          },\n          {\n            name: 'customer_unique_id',\n            properties: {\n              description: 'Unique id of the customer',\n              displayName: 'customer_unique_id',\n            },\n          },\n          {\n            name: 'customer_zip_code_prefix',\n            properties: {\n              description: 'First 5 digits of customer zip code',\n              displayName: 'customer_zip_code_prefix',\n            },\n          },\n        ],\n        schema: [\n          { columnName: 'customer_city', dataType: 'VARCHAR' },\n          { columnName: 'customer_id', dataType: 'VARCHAR' },\n          { columnName: 'customer_state', dataType: 'VARCHAR' },\n          { columnName: 'customer_unique_id', dataType: 'VARCHAR' },\n          { columnName: 'customer_zip_code_prefix', dataType: 'VARCHAR' },\n        ],\n      },\n      {\n        tableName: 'olist_order_items_dataset',\n        primaryKey: 'order_item_id',\n        filePath:\n          'https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_order_items_dataset.parquet',\n        properties: {\n          displayName: 'order items',\n          description:\n            'This table contains the information related to a specific order containing its shipping cost, products, cost, number of order items, and the seller.',\n        },\n        columns: [\n          {\n            name: 'freight_value',\n            properties: {\n              description:\n                'Cost of shipping associated with the specific order item',\n              displayName: 'freight_value',\n            },\n          },\n          {\n            name: 'order_id',\n            properties: {\n              description:\n                'Unique identifier for the order across the platform',\n              displayName: 'order_id',\n            },\n          },\n          {\n            name: 'order_item_id',\n            properties: {\n              description:\n                'Unique identifier for each item within a specific order',\n              displayName: 'order_item_id',\n            },\n          },\n          {\n            name: 'price',\n            properties: {\n              description: 'Price of the individual item within the order',\n              displayName: 'price',\n            },\n          },\n          {\n            name: 'product_id',\n            properties: {\n              description:\n                'Unique identifier for the product sold in the order.',\n              displayName: 'product_id',\n            },\n          },\n          {\n            name: 'seller_id',\n            properties: {\n              description:\n                'Unique identifier of the seller who fulfilled the order item.',\n              displayName: 'seller_id',\n            },\n          },\n          {\n            name: 'shipping_limit_date',\n            properties: {\n              description:\n                'Deadline for the order item to be shipped by the seller.',\n              displayName: 'shipping_limit_date',\n            },\n          },\n        ],\n        schema: [\n          { columnName: 'freight_value', dataType: 'DOUBLE' },\n          { columnName: 'order_id', dataType: 'VARCHAR' },\n          { columnName: 'order_item_id', dataType: 'BIGINT' },\n          { columnName: 'price', dataType: 'DOUBLE' },\n          { columnName: 'product_id', dataType: 'VARCHAR' },\n          { columnName: 'seller_id', dataType: 'VARCHAR' },\n          { columnName: 'shipping_limit_date', dataType: 'TIMESTAMP' },\n        ],\n      },\n      {\n        tableName: 'olist_orders_dataset',\n        primaryKey: 'order_id',\n        filePath:\n          'https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_orders_dataset.parquet',\n        properties: {\n          displayName: 'orders',\n          description:\n            'This table contains detailed information about customer orders, including timestamps for various stages of the order process (approval, shipping, delivery), as well as the order status and customer identification. It helps track the lifecycle of an order from purchase to delivery.',\n        },\n        columns: [\n          {\n            name: 'customer_id',\n            properties: {\n              description:\n                'Unique identifier for the customer who placed the order.',\n              displayName: 'customer_id',\n            },\n          },\n          {\n            name: 'order_approved_at',\n            properties: {\n              description:\n                'Date and time when the order was approved for processing.',\n              displayName: 'order_approved_at',\n            },\n          },\n          {\n            name: 'order_delivered_carrier_date',\n            properties: {\n              description:\n                'Date when the order was handed over to the carrier or freight forwarder for delivery.',\n              displayName: 'order_delivered_carrier_date',\n            },\n          },\n          {\n            name: 'order_delivered_customer_date',\n            properties: {\n              description: 'Date when the order was delivered to the customer.',\n              displayName: 'order_delivered_customer_date',\n            },\n          },\n          {\n            name: 'order_estimated_delivery_date',\n            properties: {\n              description:\n                'Expected delivery date based on the initial estimate.',\n              displayName: 'order_estimated_delivery_date',\n            },\n          },\n          {\n            name: 'order_id',\n            properties: {\n              description: 'Unique identifier for the specific order',\n              displayName: 'order_id',\n            },\n          },\n          {\n            name: 'order_purchase_timestamp',\n            properties: {\n              description:\n                'Date and time when the order was placed by the customer.',\n              displayName: 'order_purchase_timestamp',\n            },\n          },\n          {\n            name: 'order_status',\n            properties: {\n              description:\n                'Current status of the order (e.g., delivered, shipped, canceled).',\n              displayName: 'order_status',\n            },\n          },\n        ],\n        schema: [\n          { columnName: 'customer_id', dataType: 'VARCHAR' },\n          { columnName: 'order_approved_at', dataType: 'TIMESTAMP' },\n          { columnName: 'order_delivered_carrier_date', dataType: 'TIMESTAMP' },\n          {\n            columnName: 'order_delivered_customer_date',\n            dataType: 'TIMESTAMP',\n          },\n          {\n            columnName: 'order_estimated_delivery_date',\n            dataType: 'TIMESTAMP',\n          },\n          { columnName: 'order_id', dataType: 'VARCHAR' },\n          { columnName: 'order_purchase_timestamp', dataType: 'TIMESTAMP' },\n          { columnName: 'order_status', dataType: 'VARCHAR' },\n        ],\n      },\n      {\n        tableName: 'olist_order_payments_dataset',\n        primaryKey: 'order_id',\n        filePath:\n          'https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_order_payments_dataset.parquet',\n        properties: {\n          displayName: 'order payments',\n          description:\n            'This table contains information about payment details for each order, including payment methods, amounts, installment plans, and payment sequences, helping to track how orders were paid and processed within the e-commerce platform.',\n        },\n        columns: [\n          {\n            name: 'order_id',\n            properties: {\n              description:\n                'Unique identifier for the order associated with the payment.',\n              displayName: 'order_id',\n            },\n          },\n          {\n            name: 'payment_installments',\n            properties: {\n              description:\n                'Number of installments the payment is divided into for the order.',\n              displayName: 'payment_installments',\n            },\n          },\n          {\n            name: 'payment_sequential',\n            properties: {\n              description:\n                'Sequence number for tracking multiple payments within the same order.',\n              displayName: 'payment_sequential',\n            },\n          },\n          {\n            name: 'payment_type',\n            properties: {\n              description:\n                'Method used for the payment, such as credit card, debit, or voucher.',\n              displayName: 'payment_type',\n            },\n          },\n          {\n            name: 'payment_value',\n            properties: {\n              description: 'Total amount paid in the specific transaction.',\n              displayName: 'payment_value',\n            },\n          },\n        ],\n        schema: [\n          { columnName: 'order_id', dataType: 'VARCHAR' },\n          { columnName: 'payment_installments', dataType: 'BIGINT' },\n          { columnName: 'payment_sequential', dataType: 'BIGINT' },\n          { columnName: 'payment_type', dataType: 'VARCHAR' },\n          { columnName: 'payment_value', dataType: 'DOUBLE' },\n        ],\n      },\n      {\n        tableName: 'olist_products_dataset',\n        primaryKey: 'product_id',\n        filePath:\n          'https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_products_dataset.parquet',\n        properties: {\n          displayName: 'products',\n          description:\n            'This table provides detailed information about products, including their category, dimensions, weight, description length, and the number of photos. This helps in managing product details and enhancing the shopping experience on the e-commerce platform.',\n        },\n        columns: [\n          {\n            name: 'product_category_name',\n            properties: {\n              description:\n                'Name of the product category to which the item belongs.',\n              displayName: 'product_category_name',\n            },\n          },\n          {\n            name: 'product_description_lenght',\n            properties: {\n              description: 'Length of the product description in characters.',\n              displayName: 'product_description_lenght',\n            },\n          },\n          {\n            name: 'product_height_cm',\n            properties: {\n              description: 'Height of the product in centimeters.',\n              displayName: 'product_height_cm',\n            },\n          },\n          {\n            name: 'product_id',\n            properties: {\n              description: 'Unique identifier for the product',\n              displayName: 'product_id',\n            },\n          },\n          {\n            name: 'product_length_cm',\n            properties: {\n              description: 'Length of the product in centimeters',\n              displayName: 'product_length_cm',\n            },\n          },\n          {\n            name: 'product_name_lenght',\n            properties: {\n              description: 'Length of the product name in characters',\n              displayName: 'product_name_lenght',\n            },\n          },\n          {\n            name: 'product_photos_qty',\n            properties: {\n              description: 'Number of photos available for the product',\n              displayName: 'product_photos_qty',\n            },\n          },\n          {\n            name: 'product_weight_g',\n            properties: {\n              description: 'Weight of the product in grams',\n              displayName: 'product_weight_g',\n            },\n          },\n          {\n            name: 'product_width_cm',\n            properties: {\n              description: 'Width of the product in centimeters',\n              displayName: 'product_width_cm',\n            },\n          },\n        ],\n        schema: [\n          { columnName: 'product_category_name', dataType: 'VARCHAR' },\n          { columnName: 'product_description_lenght', dataType: 'BIGINT' },\n          { columnName: 'product_height_cm', dataType: 'BIGINT' },\n          { columnName: 'product_id', dataType: 'VARCHAR' },\n          { columnName: 'product_length_cm', dataType: 'BIGINT' },\n          { columnName: 'product_name_lenght', dataType: 'BIGINT' },\n          { columnName: 'product_photos_qty', dataType: 'BIGINT' },\n          { columnName: 'product_weight_g', dataType: 'BIGINT' },\n          { columnName: 'product_width_cm', dataType: 'BIGINT' },\n        ],\n      },\n      {\n        tableName: 'olist_order_reviews_dataset',\n        primaryKey: 'review_id',\n        filePath:\n          'https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_order_reviews_dataset.parquet',\n        properties: {\n          displayName: 'order reviews',\n          description:\n            'This table contains customer reviews for each order, including feedback comments, ratings, and timestamps for when the review was submitted and responded to. It helps track customer satisfaction and review management on the e-commerce platform.',\n        },\n        columns: [\n          {\n            name: 'order_id',\n            properties: {\n              description:\n                'Unique identifier linking the review to the corresponding order.',\n              displayName: 'order_id',\n            },\n          },\n          {\n            name: 'review_answer_timestamp',\n            properties: {\n              description:\n                'Date and time when the review was responded to by the seller',\n              displayName: 'review_answer_timestamp',\n            },\n          },\n          {\n            name: 'review_comment_message',\n            properties: {\n              description:\n                'Detailed feedback or comments provided by the customer regarding the order.',\n              displayName: 'review_comment_message',\n            },\n          },\n          {\n            name: 'review_comment_title',\n            properties: {\n              description: \"Summary or title of the customer's review\",\n              displayName: 'review_comment_title',\n            },\n          },\n          {\n            name: 'review_creation_date',\n            properties: {\n              description:\n                'Date and time when the customer initially submitted the review.',\n              displayName: 'review_creation_date',\n            },\n          },\n          {\n            name: 'review_id',\n            properties: {\n              description: 'Unique identifier for the specific review entry.',\n              displayName: 'review_id',\n            },\n          },\n          {\n            name: 'review_score',\n            properties: {\n              description:\n                'Numeric rating given by the customer, typically ranging from 1 (worst) to 5 (best).',\n              displayName: 'review_score',\n            },\n          },\n        ],\n        schema: [\n          { columnName: 'order_id', dataType: 'VARCHAR' },\n          { columnName: 'review_answer_timestamp', dataType: 'TIMESTAMP' },\n          { columnName: 'review_comment_message', dataType: 'VARCHAR' },\n          { columnName: 'review_comment_title', dataType: 'VARCHAR' },\n          { columnName: 'review_creation_date', dataType: 'TIMESTAMP' },\n          { columnName: 'review_id', dataType: 'VARCHAR' },\n          { columnName: 'review_score', dataType: 'BIGINT' },\n        ],\n      },\n      {\n        tableName: 'olist_geolocation_dataset',\n        primaryKey: '',\n        filePath:\n          'https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_geolocation_dataset.parquet',\n        properties: {\n          displayName: 'geolocation',\n          description:\n            'This table contains detailed information about Brazilian zip codes and their corresponding latitude and longitude coordinates. It can be used to plot maps, calculate distances between sellers and customers, and perform geographic analysis.',\n        },\n        columns: [\n          {\n            name: 'geolocation_city',\n            properties: {\n              displayName: 'geolocation_city',\n              description: 'The city name of the geolocation',\n            },\n          },\n          {\n            name: 'geolocation_lat',\n            properties: {\n              displayName: 'geolocation_lat',\n              description: 'The coordinations for the locations latitude',\n            },\n          },\n          {\n            name: 'geolocation_lng',\n            properties: {\n              displayName: 'geolocation_lng',\n              description: 'The coordinations for the locations longitude',\n            },\n          },\n          {\n            name: 'geolocation_state',\n            properties: {\n              displayName: 'geolocation_state',\n              description: 'The state of the geolocation',\n            },\n          },\n          {\n            name: 'geolocation_zip_code_prefix',\n            properties: {\n              displayName: 'geolocation_zip_code_prefix',\n              description: 'First 5 digits of zip code',\n            },\n          },\n        ],\n        schema: [\n          { columnName: 'geolocation_city', dataType: 'VARCHAR' },\n          { columnName: 'geolocation_lat', dataType: 'DOUBLE' },\n          { columnName: 'geolocation_lng', dataType: 'DOUBLE' },\n          { columnName: 'geolocation_state', dataType: 'VARCHAR' },\n          { columnName: 'geolocation_zip_code_prefix', dataType: 'VARCHAR' },\n        ],\n      },\n      {\n        tableName: 'olist_sellers_dataset',\n        primaryKey: '',\n        filePath:\n          'https://assets.getwren.ai/sample_data/brazilian-ecommerce/olist_sellers_dataset.parquet',\n        properties: {\n          displayName: 'sellers',\n          description:\n            'This table includes data about the sellers that fulfilled orders made. Use it to find the seller location and to identify which seller fulfilled each product.',\n        },\n        columns: [\n          {\n            name: 'seller_city',\n            properties: {\n              description: 'The Brazilian city where the seller is located',\n              displayName: 'seller_city',\n            },\n          },\n          {\n            name: 'seller_id',\n            properties: {\n              description: 'Unique identifier for the seller on the platform',\n              displayName: 'seller_id',\n            },\n          },\n          {\n            name: 'seller_state',\n            properties: {\n              description: 'The Brazilian state where the seller is located',\n              displayName: 'seller_state',\n            },\n          },\n          {\n            name: 'seller_zip_code_prefix',\n            properties: {\n              description: 'First 5 digits of seller zip code',\n              displayName: 'seller_zip_code_prefix',\n            },\n          },\n        ],\n        schema: [\n          { columnName: 'seller_city', dataType: 'VARCHAR' },\n          { columnName: 'seller_id', dataType: 'VARCHAR' },\n          { columnName: 'seller_state', dataType: 'VARCHAR' },\n          { columnName: 'seller_zip_code_prefix', dataType: 'VARCHAR' },\n        ],\n      },\n      {\n        tableName: 'product_category_name_translation',\n        primaryKey: 'product_category_name',\n        filePath:\n          'https://assets.getwren.ai/sample_data/brazilian-ecommerce/product_category_name_translation.parquet',\n        properties: {\n          displayName: 'product category name translation',\n          description:\n            'This table contains translations of product categories from Portuguese to English.',\n        },\n        columns: [\n          {\n            name: 'product_category_name',\n            properties: {\n              description:\n                'Original name of the product category in Portuguese.',\n              displayName: 'product_category_name',\n            },\n          },\n          {\n            name: 'product_category_name_english',\n            properties: {\n              description:\n                'Translated name of the product category in English.',\n              displayName: 'product_category_name_english',\n            },\n          },\n        ],\n        schema: [\n          { columnName: 'product_category_name', dataType: 'VARCHAR' },\n          { columnName: 'product_category_name_english', dataType: 'VARCHAR' },\n        ],\n      },\n    ],\n    questions: [\n      {\n        question:\n          'Which are the top 3 cities with the highest number of orders?',\n        label: 'Ranking',\n      },\n      {\n        question:\n          'What is the average score of reviews submitted for orders placed by customers in each city?',\n        label: 'Aggregation',\n      },\n      {\n        question:\n          'What is the total value of payments made by customers from each state?',\n        label: 'Aggregation',\n      },\n    ],\n    relations: [\n      // orders\n      // orders -> customers\n      {\n        fromModelName: 'olist_orders_dataset',\n        fromColumnName: 'customer_id',\n        toModelName: 'olist_customers_dataset',\n        toColumnName: 'customer_id',\n        type: RelationType.MANY_TO_ONE,\n      },\n      // orders -> items\n      {\n        fromModelName: 'olist_orders_dataset',\n        fromColumnName: 'order_id',\n        toModelName: 'olist_order_items_dataset',\n        toColumnName: 'order_id',\n        type: RelationType.ONE_TO_MANY,\n      },\n      // orders -> reviews\n      {\n        fromModelName: 'olist_orders_dataset',\n        fromColumnName: 'order_id',\n        toModelName: 'olist_order_reviews_dataset',\n        toColumnName: 'order_id',\n        type: RelationType.ONE_TO_MANY,\n      },\n      // orders -> payments\n      {\n        fromModelName: 'olist_orders_dataset',\n        fromColumnName: 'order_id',\n        toModelName: 'olist_order_payments_dataset',\n        toColumnName: 'order_id',\n        type: RelationType.ONE_TO_MANY,\n      },\n      // items -> products\n      {\n        fromModelName: 'olist_order_items_dataset',\n        fromColumnName: 'product_id',\n        toModelName: 'olist_products_dataset',\n        toColumnName: 'product_id',\n        type: RelationType.MANY_TO_ONE,\n      },\n      // items -> sellers\n      {\n        fromModelName: 'olist_order_items_dataset',\n        fromColumnName: 'seller_id',\n        toModelName: 'olist_sellers_dataset',\n        toColumnName: 'seller_id',\n        type: RelationType.MANY_TO_ONE,\n      },\n      // geolocation -> customers (zip code prefix)\n      {\n        fromModelName: 'olist_geolocation_dataset',\n        fromColumnName: 'geolocation_zip_code_prefix',\n        toModelName: 'olist_customers_dataset',\n        toColumnName: 'customer_zip_code_prefix',\n        type: RelationType.ONE_TO_MANY,\n      },\n      // geolocation -> sellers (zip code prefix)\n      {\n        fromModelName: 'olist_geolocation_dataset',\n        fromColumnName: 'geolocation_zip_code_prefix',\n        toModelName: 'olist_sellers_dataset',\n        toColumnName: 'seller_zip_code_prefix',\n        type: RelationType.ONE_TO_MANY,\n      },\n      // product category name translation -> products\n      {\n        fromModelName: 'product_category_name_translation',\n        fromColumnName: 'product_category_name',\n        toModelName: 'olist_products_dataset',\n        toColumnName: 'product_category_name',\n        type: RelationType.ONE_TO_MANY,\n      },\n    ],\n  },\n  nba: {\n    name: SampleDatasetName.NBA,\n    tables: [\n      {\n        tableName: 'game',\n        primaryKey: 'Id',\n        filePath:\n          'https://wrenai-public.s3.amazonaws.com/demo/v0.3.0/NBA/game.csv',\n        columns: [\n          {\n            name: 'Id',\n          },\n          {\n            name: 'SeasonId',\n          },\n          {\n            name: 'TeamIdHome',\n          },\n          {\n            name: 'WlHome',\n          },\n          {\n            name: 'Min',\n          },\n          {\n            name: 'FgmHome',\n            properties: {\n              description: 'number of field goals made by the home team.',\n            },\n          },\n          {\n            name: 'FgaHome',\n            properties: {\n              description: 'number of field goals attempted by the home team.',\n            },\n          },\n          {\n            name: 'threepHome',\n            properties: {\n              description:\n                'number of three point field goals made by the home team.',\n            },\n          },\n          {\n            name: 'threepaHome',\n            properties: {\n              description:\n                'number of three point field goals attempted by the home team.',\n            },\n          },\n          {\n            name: 'FtmHome',\n            properties: {\n              description: 'number of free throws made by the home team.',\n            },\n          },\n          {\n            name: 'FtaHome',\n            properties: {\n              description: 'number of free throws attempted by the home team.',\n            },\n          },\n          {\n            name: 'OrebHome',\n            properties: {\n              description: 'number of offensive rebounds by the home team.',\n            },\n          },\n          {\n            name: 'DrebHome',\n            properties: {\n              description: 'number of defensive rebounds by the home team.',\n            },\n          },\n          {\n            name: 'RebHome',\n            properties: { description: 'number of rebounds by the home team.' },\n          },\n          {\n            name: 'AstHome',\n            properties: { description: 'number of assists by the home team.' },\n          },\n          {\n            name: 'StlHome',\n            properties: { description: 'number of steels by the home team.' },\n          },\n          {\n            name: 'BlkHome',\n            properties: { description: 'number of blocks by the home team.' },\n          },\n          {\n            name: 'TovHome',\n            properties: {\n              description: 'number of turnovers by the home team.',\n            },\n          },\n          {\n            name: 'PfHome',\n            properties: {\n              description: 'number of personal fouls by the home team.',\n            },\n          },\n          {\n            name: 'PtsHome',\n            properties: { description: 'Total score of the home team.' },\n          },\n          {\n            name: 'PlusMimusHome',\n          },\n          {\n            name: 'TeamIdAway',\n          },\n          {\n            name: 'WlAway',\n          },\n          {\n            name: 'FgmAway',\n            properties: {\n              description: 'number of field goals made by the away team.',\n            },\n          },\n          {\n            name: 'FgaAway',\n            properties: {\n              description: 'number of field goals attempted by the away team.',\n            },\n          },\n          {\n            name: 'threepAway',\n            properties: {\n              description:\n                'number of three point field goals made by the away team.',\n            },\n          },\n          {\n            name: 'threepaAway',\n            properties: {\n              description:\n                'number of three point field goals attempted by the away team.',\n            },\n          },\n          {\n            name: 'FtmAway',\n            properties: {\n              description: 'number of free throws made by the away team.',\n            },\n          },\n          {\n            name: 'FtaAway',\n            properties: {\n              description: 'number of free throws attempted by the away team.',\n            },\n          },\n          {\n            name: 'OrebAway',\n            properties: {\n              description: 'number of offensive rebounds by the away team.',\n            },\n          },\n          {\n            name: 'DrebAway',\n            properties: {\n              description: 'number of defensive rebounds by the away team.',\n            },\n          },\n          {\n            name: 'RebAway',\n            properties: { description: 'number of rebounds by the away team.' },\n          },\n          {\n            name: 'AstAway',\n            properties: { description: 'number of assists by the away team.' },\n          },\n          {\n            name: 'StlAway',\n            properties: { description: 'number of steels by the away team.' },\n          },\n          {\n            name: 'BlkAway',\n            properties: { description: 'number of blocks by the away team.' },\n          },\n          {\n            name: 'TovAway',\n            properties: {\n              description: 'number of turnovers by the away team.',\n            },\n          },\n          {\n            name: 'PfAway',\n            properties: {\n              description: 'number of personal fouls by the away team.',\n            },\n          },\n          {\n            name: 'PtsAway',\n            properties: { description: 'Total score of the away team.' },\n          },\n          {\n            name: 'PlusMimusAway',\n          },\n          {\n            name: 'seasonType',\n          },\n        ],\n        schema: [\n          { columnName: 'SeasonId', dataType: 'BIGINT' },\n          { columnName: 'TeamIdHome', dataType: 'BIGINT' },\n          { columnName: 'Id', dataType: 'BIGINT' },\n          { columnName: 'GameDate', dataType: 'DATE' },\n          { columnName: 'WlHome', dataType: 'VARCHAR' },\n          { columnName: 'Min', dataType: 'BIGINT' },\n          { columnName: 'FgmHome', dataType: 'BIGINT' },\n          { columnName: 'FgaHome', dataType: 'BIGINT' },\n          { columnName: 'FgPct_home', dataType: 'DOUBLE' },\n          { columnName: 'threepHome', dataType: 'BIGINT' },\n          { columnName: 'threepaHome', dataType: 'BIGINT' },\n          { columnName: 'fg3_pct_home', dataType: 'DOUBLE' },\n          { columnName: 'FtmHome', dataType: 'BIGINT' },\n          { columnName: 'FtaHome', dataType: 'BIGINT' },\n          { columnName: 'ft_pct_home', dataType: 'DOUBLE' },\n          { columnName: 'OrebHome', dataType: 'BIGINT' },\n          { columnName: 'DrebHome', dataType: 'BIGINT' },\n          { columnName: 'RebHome', dataType: 'BIGINT' },\n          { columnName: 'AstHome', dataType: 'BIGINT' },\n          { columnName: 'StlHome', dataType: 'BIGINT' },\n          { columnName: 'BlkHome', dataType: 'BIGINT' },\n          { columnName: 'TovHome', dataType: 'BIGINT' },\n          { columnName: 'PfHome', dataType: 'BIGINT' },\n          { columnName: 'PtsHome', dataType: 'BIGINT' },\n          { columnName: 'PlusMinusHome', dataType: 'BIGINT' },\n          { columnName: 'TeamIdAway', dataType: 'BIGINT' },\n          { columnName: 'WlAway', dataType: 'VARCHAR' },\n          { columnName: 'FgmAway', dataType: 'BIGINT' },\n          { columnName: 'FgaAway', dataType: 'BIGINT' },\n          { columnName: 'fg_pct_away', dataType: 'DOUBLE' },\n          { columnName: 'threepAway', dataType: 'BIGINT' },\n          { columnName: 'threepaAway', dataType: 'BIGINT' },\n          { columnName: 'Fg3_pct_away', dataType: 'DOUBLE' },\n          { columnName: 'FtmAway', dataType: 'BIGINT' },\n          { columnName: 'FtaAway', dataType: 'BIGINT' },\n          { columnName: 'Ft_pct_away', dataType: 'DOUBLE' },\n          { columnName: 'OrebAway', dataType: 'BIGINT' },\n          { columnName: 'DrebAway', dataType: 'BIGINT' },\n          { columnName: 'RebAway', dataType: 'BIGINT' },\n          { columnName: 'AstAway', dataType: 'BIGINT' },\n          { columnName: 'StlAway', dataType: 'BIGINT' },\n          { columnName: 'BlkAway', dataType: 'BIGINT' },\n          { columnName: 'TovAway', dataType: 'BIGINT' },\n          { columnName: 'PfAway', dataType: 'BIGINT' },\n          { columnName: 'PtsAway', dataType: 'BIGINT' },\n          { columnName: 'PlusMinusAway', dataType: 'BIGINT' },\n          { columnName: 'SeasonType', dataType: 'VARCHAR' },\n        ],\n        properties: {\n          description:\n            'This table describes the game statistics for both the home and away teams in each NBA game. Turnover percentage is the number of possessions that end in a turnover. The formula for turnover percentage (TOV%) is \"TOV% = (Tov ÷ (FGA + (0.44 x FTA) + Tov)) x 100%\".',\n        },\n      },\n      {\n        tableName: 'line_score',\n        primaryKey: 'GameId',\n        filePath:\n          'https://wrenai-public.s3.amazonaws.com/demo/v0.3.0/NBA/line_score.csv',\n        columns: [\n          {\n            name: 'GameId',\n          },\n          {\n            name: 'GameDate',\n          },\n          {\n            name: 'GameSequence',\n          },\n          {\n            name: 'TeamIdHome',\n          },\n          {\n            name: 'TeamWinsLossesHome',\n          },\n          {\n            name: 'PtsQtr1Home',\n            properties: {\n              description: 'The score of the home team in the first quarter.',\n            },\n          },\n          {\n            name: 'PtsQtr2Home',\n            properties: {\n              description: 'The score of the home team in the second quarter.',\n            },\n          },\n          {\n            name: 'PtsQtr3Home',\n            properties: {\n              description: 'The score of the home team in the third quarter.',\n            },\n          },\n          {\n            name: 'PtsQtr4Home',\n            properties: {\n              description: 'The score of the home team in the fourth quarter.',\n            },\n          },\n          {\n            name: 'PtsOt1Home',\n            properties: {\n              description:\n                'The score of the home team in the overtime. The value of 0 indicates that the game did not go into overtime.',\n            },\n          },\n          {\n            name: 'PtsHome',\n            properties: { description: 'Total score of the home team.' },\n          },\n          {\n            name: 'TeamIdAway',\n          },\n          {\n            name: 'TeamWinsLossesAway',\n          },\n          {\n            name: 'PtsQtr1Away',\n            properties: {\n              description: 'The score of the away team in the first quarter.',\n            },\n          },\n          {\n            name: 'PtsQtr2Away',\n            properties: {\n              description: 'The score of the away team in the second quarter.',\n            },\n          },\n          {\n            name: 'PtsQtr3Away',\n            properties: {\n              description: 'The score of the away team in the third quarter.',\n            },\n          },\n          {\n            name: 'PtsQtr4Away',\n            properties: {\n              description: 'The score of the away team in the fourth quarter.',\n            },\n          },\n          {\n            name: 'PtsOt1Away',\n            properties: {\n              description:\n                'The score of the away team in the overtime. The value of 0 indicates that the game did not go into overtime.',\n            },\n          },\n          {\n            name: 'PtsAway',\n            properties: { description: 'Total score of the away team.' },\n          },\n        ],\n        schema: [\n          { columnName: 'GameDate', dataType: 'DATE' },\n          { columnName: 'GameSequence', dataType: 'BIGINT' },\n          { columnName: 'GameId', dataType: 'BIGINT' },\n          { columnName: 'TeamIdHome', dataType: 'BIGINT' },\n          { columnName: 'TeamWinsLossesHome', dataType: 'VARCHAR' },\n          { columnName: 'PtsQtr1Home', dataType: 'BIGINT' },\n          { columnName: 'PtsQtr2Home', dataType: 'BIGINT' },\n          { columnName: 'PtsQtr3Home', dataType: 'BIGINT' },\n          { columnName: 'PtsQtr4Home', dataType: 'BIGINT' },\n          { columnName: 'PtsOt1Home', dataType: 'BIGINT' },\n          { columnName: 'PtsHome', dataType: 'BIGINT' },\n          { columnName: 'TeamIdAway', dataType: 'BIGINT' },\n          { columnName: 'TeamWinsLossesAway', dataType: 'VARCHAR' },\n          { columnName: 'PtsQtr1Away', dataType: 'BIGINT' },\n          { columnName: 'PtsQtr2Away', dataType: 'BIGINT' },\n          { columnName: 'PtsQtr3Away', dataType: 'BIGINT' },\n          { columnName: 'PtsQtr4Away', dataType: 'BIGINT' },\n          { columnName: 'PtsOt1Away', dataType: 'BIGINT' },\n          { columnName: 'PtsAway', dataType: 'BIGINT' },\n        ],\n        properties: {\n          description:\n            'This table describes the scores and total score for each quarter or overtime of an NBA game, detailing the scores for both the home team and the away team.',\n        },\n      },\n      {\n        tableName: 'player_games',\n        primaryKey: 'Id',\n        filePath:\n          'https://wrenai-public.s3.amazonaws.com/demo/v0.3.0/NBA/player_game.csv',\n        columns: [\n          {\n            name: 'Id',\n          },\n          {\n            name: 'GameId',\n          },\n          {\n            name: 'PlayerId',\n          },\n          {\n            name: 'Date',\n          },\n          {\n            name: 'Age',\n            properties: { description: 'player age. The format is \"age-days\"' },\n          },\n          {\n            name: 'Tm',\n            properties: { description: 'team affiliation.' },\n          },\n          {\n            name: 'Opp',\n            properties: { description: 'opposing team.' },\n          },\n          {\n            name: 'MP',\n            properties: { description: 'minutes played' },\n          },\n          {\n            name: 'FG',\n            properties: {\n              description: 'number of two point field goals made.',\n            },\n          },\n          {\n            name: 'FGA',\n            properties: {\n              description:\n                'number of two point field goals attempted (do not include free throws).',\n            },\n          },\n          {\n            name: 'threeP',\n            properties: {\n              description: 'number of three point field goals made.',\n            },\n          },\n          {\n            name: 'threePA',\n            properties: {\n              description: 'number of three point field goals attempted.',\n            },\n          },\n          {\n            name: 'FT',\n            properties: { description: 'number of free throws made.' },\n          },\n          {\n            name: 'FTA',\n            properties: { description: 'number of free throws attempted.' },\n          },\n          {\n            name: 'ORB',\n            properties: { description: 'number of offensive rebounds.' },\n          },\n          {\n            name: 'DRB',\n            properties: { description: 'number of defensive rebounds.' },\n          },\n          {\n            name: 'AST',\n            properties: { description: 'number of assists.' },\n          },\n          {\n            name: 'STL',\n            properties: { description: 'number of Steals.' },\n          },\n          {\n            name: 'BLK',\n            properties: { description: 'number of blocks.' },\n          },\n          {\n            name: 'TOV',\n            properties: { description: 'number of turnovers allowed' },\n          },\n          {\n            name: 'PF',\n            properties: { description: 'number of personal fouls' },\n          },\n          {\n            name: 'PTS',\n            properties: { description: 'total score' },\n          },\n        ],\n        schema: [\n          { columnName: 'Id', dataType: 'BIGINT' },\n          { columnName: 'PlayerID', dataType: 'BIGINT' },\n          { columnName: 'GameID', dataType: 'BIGINT' },\n          { columnName: 'Date', dataType: 'DATE' },\n          { columnName: 'Age', dataType: 'VARCHAR' }, // 35-032\n          { columnName: 'Tm', dataType: 'VARCHAR' },\n          { columnName: 'Opp', dataType: 'VARCHAR' },\n          { columnName: 'MP', dataType: 'VARCHAR' }, // 37:25:00\n          { columnName: 'FG', dataType: 'BIGINT' },\n          { columnName: 'FGA', dataType: 'BIGINT' },\n          { columnName: 'threeP', dataType: 'BIGINT' },\n          { columnName: 'threePA', dataType: 'BIGINT' },\n          { columnName: 'FT', dataType: 'BIGINT' },\n          { columnName: 'FTA', dataType: 'BIGINT' },\n          { columnName: 'ORB', dataType: 'BIGINT' },\n          { columnName: 'DRB', dataType: 'BIGINT' },\n          { columnName: 'TRB', dataType: 'BIGINT' },\n          { columnName: 'AST', dataType: 'BIGINT' },\n          { columnName: 'STL', dataType: 'BIGINT' },\n          { columnName: 'BLK', dataType: 'BIGINT' },\n          { columnName: 'TOV', dataType: 'BIGINT' },\n          { columnName: 'PF', dataType: 'BIGINT' },\n          { columnName: 'PTS', dataType: 'BIGINT' },\n        ],\n        properties: {\n          description:\n            'This table describes the game statistics for each NBA player in every game. Turnover percentage is the number of possessions that end in a turnover. The formula for turnover percentage (TOV%) is \"TOV% = (Tov ÷ (FGA + (0.44 x FTA) + Tov)) x 100%\".',\n        },\n      },\n      {\n        tableName: 'player',\n        primaryKey: 'Id',\n        filePath:\n          'https://wrenai-public.s3.amazonaws.com/demo/v0.3.0/NBA/player.csv',\n        columns: [\n          {\n            name: 'Id',\n          },\n          {\n            name: 'TeamId',\n          },\n          {\n            name: 'FullName',\n          },\n          {\n            name: 'FirstName',\n          },\n          {\n            name: 'LastName',\n          },\n        ],\n        schema: [\n          { columnName: 'Id', dataType: 'BIGINT' },\n          { columnName: 'TeamId', dataType: 'BIGINT' },\n          { columnName: 'FullName', dataType: 'VARCHAR' },\n          { columnName: 'FirstName', dataType: 'VARCHAR' },\n          { columnName: 'LastName', dataType: 'VARCHAR' },\n        ],\n        properties: {\n          description:\n            'This table describes NBA players by their ID, name, and team affiliation.',\n        },\n      },\n      {\n        tableName: 'team',\n        primaryKey: 'Id',\n        filePath:\n          'https://wrenai-public.s3.amazonaws.com/demo/v0.3.0/NBA/team.csv',\n        columns: [\n          {\n            name: 'Id',\n          },\n          {\n            name: 'FullName',\n          },\n          {\n            name: 'Abbreviation',\n          },\n          {\n            name: 'Nickname',\n          },\n          {\n            name: 'City',\n          },\n          {\n            name: 'State',\n          },\n          {\n            name: 'YearFounded',\n          },\n        ],\n        schema: [\n          { columnName: 'Id', dataType: 'BIGINT' },\n          { columnName: 'FullName', dataType: 'VARCHAR' },\n          { columnName: 'Abbreviation', dataType: 'VARCHAR' },\n          { columnName: 'Nickname', dataType: 'VARCHAR' },\n          { columnName: 'City', dataType: 'VARCHAR' },\n          { columnName: 'State', dataType: 'VARCHAR' },\n          { columnName: 'YearFounded', dataType: 'INT' },\n        ],\n        properties: {\n          description:\n            'This table describes NBA teams by their ID, team name, team abbreviation, and founding date.',\n        },\n      },\n    ],\n    questions: [\n      {\n        question:\n          'How many three-pointers were made by each player in each game?',\n        label: 'Aggregation',\n      },\n      {\n        question:\n          'What is the differences in turnover rates between teams with high and low average scores?',\n        label: 'Comparison',\n      },\n      {\n        question:\n          'Which teams had the highest average points scored per game throughout the season?',\n        label: 'Ranking',\n      },\n    ],\n    relations: [\n      {\n        fromModelName: 'game',\n        fromColumnName: 'Id',\n        toModelName: 'line_score',\n        toColumnName: 'GameId',\n        type: RelationType.ONE_TO_MANY,\n      },\n      {\n        fromModelName: 'line_score',\n        fromColumnName: 'GameId',\n        toModelName: 'player_games',\n        toColumnName: 'GameID',\n        type: RelationType.ONE_TO_MANY,\n      },\n      {\n        fromModelName: 'player',\n        fromColumnName: 'TeamId',\n        toModelName: 'team',\n        toColumnName: 'Id',\n        type: RelationType.ONE_TO_ONE,\n      },\n      {\n        fromModelName: 'team',\n        fromColumnName: 'Id',\n        toModelName: 'game',\n        toColumnName: 'TeamIdHome',\n        type: RelationType.ONE_TO_MANY,\n      },\n    ],\n  },\n};\n\nexport const buildInitSql = (datasetName: SampleDatasetName) => {\n  const selectedDataset = sampleDatasets[datasetName.toLowerCase()];\n\n  return selectedDataset.tables\n    .map((table) => {\n      const schema = table.schema\n        ?.map(({ columnName, dataType }) => `'${columnName}': '${dataType}'`)\n        .join(', ');\n      const fileExtension = table.filePath.split('.').pop();\n      const createTableStatement = (fileType: string, schema?: string) => {\n        if (fileType !== 'csv' && fileType !== 'parquet') {\n          throw new Error(`Unsupported file type: ${fileType}`);\n        }\n        const baseStatement = `CREATE TABLE ${table.tableName} AS select * FROM read_${fileType}('${table.filePath}'`;\n        const schemaPart =\n          fileType === 'csv' && schema ? `, columns={${schema}}` : '';\n        const headerPart = fileType === 'csv' ? ',header=true' : '';\n        return `${baseStatement}${headerPart}${schemaPart});`;\n      };\n\n      return createTableStatement(fileExtension, schema);\n    })\n    .join('\\n');\n};\n\nexport const getRelations = (datasetName: SampleDatasetName) => {\n  const selectedDataset = sampleDatasets[datasetName.toLowerCase()];\n  return selectedDataset.relations;\n};\n\nexport const getSampleAskQuestions = (datasetName: SampleDatasetName) => {\n  const selectedDataset = sampleDatasets[datasetName.toLowerCase()];\n  return selectedDataset.questions;\n};\n"
  },
  {
    "path": "wren-ui/src/apollo/server/data/type.ts",
    "content": "export enum SampleDatasetName {\n  MUSIC = 'MUSIC',\n  NBA = 'NBA',\n  ECOMMERCE = 'ECOMMERCE',\n  HR = 'HR',\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/dataSource.ts",
    "content": "import {\n  IbisBigQueryConnectionInfo,\n  IbisPostgresConnectionInfo,\n  HostBasedConnectionInfo,\n  UrlBasedConnectionInfo,\n  IbisSnowflakeConnectionInfo,\n  IbisTrinoConnectionInfo,\n  IbisAthenaConnectionInfo,\n  IbisRedshiftConnectionType,\n  IbisRedshiftConnectionInfo,\n  IbisDatabricksConnectionType,\n  IbisDatabricksConnectionInfo,\n} from './adaptors/ibisAdaptor';\nimport {\n  ATHENA_CONNECTION_INFO,\n  BIG_QUERY_CONNECTION_INFO,\n  DUCKDB_CONNECTION_INFO,\n  MYSQL_CONNECTION_INFO,\n  POSTGRES_CONNECTION_INFO,\n  MS_SQL_CONNECTION_INFO,\n  WREN_AI_CONNECTION_INFO,\n  CLICK_HOUSE_CONNECTION_INFO,\n  TRINO_CONNECTION_INFO,\n  SNOWFLAKE_CONNECTION_INFO,\n  ORACLE_CONNECTION_INFO,\n  REDSHIFT_CONNECTION_INFO,\n  REDSHIFT_IAM_AUTH,\n  REDSHIFT_PASSWORD_AUTH,\n  DATABRICKS_CONNECTION_INFO,\n  DATABRICKS_PERSONAL_ACCESS_TOKEN_AUTH,\n  DATABRICKS_SERVICE_PRINCIPAL_AUTH,\n} from './repositories';\nimport { DataSourceName } from './types';\nimport { getConfig } from './config';\nimport { Encryptor } from './utils';\n\nconst config = getConfig();\nconst encryptor = new Encryptor(config);\n\nexport function encryptConnectionInfo(\n  dataSourceType: DataSourceName,\n  connectionInfo: WREN_AI_CONNECTION_INFO,\n) {\n  return dataSource[dataSourceType].sensitiveProps.reduce(\n    (acc, prop: string) => {\n      const value = connectionInfo[prop];\n      if (value) {\n        const encryption = encryptor.encrypt(\n          JSON.parse(JSON.stringify({ [prop]: value })),\n        );\n        return { ...acc, [prop]: encryption };\n      }\n      return acc;\n    },\n    connectionInfo,\n  );\n}\n\nexport function toIbisConnectionInfo(dataSourceType, connectionInfo) {\n  return dataSource[dataSourceType].toIbisConnectionInfo(connectionInfo);\n}\n\nexport function toMultipleIbisConnectionInfos(dataSourceType, connectionInfo) {\n  if (!dataSource[dataSourceType].toMultipleIbisConnectionInfos) {\n    return null;\n  }\n  return dataSource[dataSourceType].toMultipleIbisConnectionInfos(\n    connectionInfo,\n  );\n}\n\ninterface IDataSourceConnectionInfo<C, I> {\n  sensitiveProps: string[];\n  toIbisConnectionInfo(connectionInfo: C): I;\n  toMultipleIbisConnectionInfos?(connectionInfo: C): I[];\n}\n\nconst dataSource = {\n  // Athena\n  [DataSourceName.ATHENA]: {\n    sensitiveProps: ['awsSecretKey', 'webIdentityToken'],\n    toIbisConnectionInfo(connectionInfo) {\n      const decryptedConnectionInfo = decryptConnectionInfo(\n        DataSourceName.ATHENA,\n        connectionInfo,\n      );\n      const {\n        awsAccessKey,\n        awsRegion,\n        awsSecretKey,\n        s3StagingDir,\n        schema,\n        webIdentityToken,\n        roleArn,\n        roleSessionName,\n      } = decryptedConnectionInfo as ATHENA_CONNECTION_INFO;\n\n      // Base fields shared by both authentication methods\n      const base = {\n        region_name: awsRegion,\n        s3_staging_dir: s3StagingDir,\n        schema_name: schema,\n      };\n      // If OIDC fields are provided → send OIDC config\n      if (webIdentityToken && roleArn) {\n        return {\n          ...base,\n          web_identity_token: webIdentityToken,\n          role_arn: roleArn,\n          ...(roleSessionName && { role_session_name: roleSessionName }),\n        } satisfies IbisAthenaConnectionInfo;\n      }\n      // Otherwise → fallback to AWS access key authentication\n      return {\n        ...base,\n        aws_access_key_id: awsAccessKey,\n        aws_secret_access_key: awsSecretKey,\n      } satisfies IbisAthenaConnectionInfo;\n    },\n  } as IDataSourceConnectionInfo<\n    ATHENA_CONNECTION_INFO,\n    IbisAthenaConnectionInfo\n  >,\n\n  // BigQuery\n  [DataSourceName.BIG_QUERY]: {\n    sensitiveProps: ['credentials'],\n    toIbisConnectionInfo(connectionInfo) {\n      const decryptedConnectionInfo = decryptConnectionInfo(\n        DataSourceName.BIG_QUERY,\n        connectionInfo,\n      );\n      const { projectId, datasetId, credentials } =\n        decryptedConnectionInfo as BIG_QUERY_CONNECTION_INFO;\n      const base64Credentials = Buffer.from(\n        JSON.stringify(credentials),\n      ).toString('base64');\n      const res: IbisBigQueryConnectionInfo = {\n        project_id: projectId,\n        dataset_id: datasetId,\n        credentials: base64Credentials,\n      };\n      return res;\n    },\n  } as IDataSourceConnectionInfo<\n    BIG_QUERY_CONNECTION_INFO,\n    IbisBigQueryConnectionInfo\n  >,\n\n  // Postgres\n  [DataSourceName.POSTGRES]: {\n    sensitiveProps: ['password'],\n    toIbisConnectionInfo(connectionInfo) {\n      const decryptedConnectionInfo = decryptConnectionInfo(\n        DataSourceName.POSTGRES,\n        connectionInfo,\n      );\n      const { host, port, database, user, password, ssl } =\n        decryptedConnectionInfo as POSTGRES_CONNECTION_INFO;\n\n      // url encode password\n      const encodedPassword = encodeURIComponent(password);\n      let connectionUrl = `postgresql://${user}:${encodedPassword}@${host}:${port}/${database}?`;\n      if (ssl) {\n        connectionUrl += 'sslmode=require';\n      }\n      return {\n        connectionUrl,\n      };\n    },\n  } as IDataSourceConnectionInfo<\n    POSTGRES_CONNECTION_INFO,\n    IbisPostgresConnectionInfo\n  >,\n\n  // mysql\n  [DataSourceName.MYSQL]: {\n    sensitiveProps: ['password'],\n    toIbisConnectionInfo(connectionInfo) {\n      const decryptedConnectionInfo = decryptConnectionInfo(\n        DataSourceName.MYSQL,\n        connectionInfo,\n      );\n      const { host, port, database, user, password, ssl } =\n        decryptedConnectionInfo as MYSQL_CONNECTION_INFO;\n      return {\n        host,\n        port,\n        database,\n        user,\n        password,\n        sslMode: ssl ? 'ENABLED' : 'DISABLED',\n      };\n    },\n  } as IDataSourceConnectionInfo<\n    MYSQL_CONNECTION_INFO,\n    HostBasedConnectionInfo\n  >,\n\n  // Oracle\n  [DataSourceName.ORACLE]: {\n    sensitiveProps: ['password', 'dsn'],\n    toIbisConnectionInfo(connectionInfo) {\n      const decryptedConnectionInfo = decryptConnectionInfo(\n        DataSourceName.ORACLE,\n        connectionInfo,\n      );\n      const { host, port, database, user, password, dsn } =\n        decryptedConnectionInfo as ORACLE_CONNECTION_INFO;\n      return Object.entries({\n        host,\n        port,\n        database,\n        user,\n        password,\n        dsn,\n      }).reduce((acc, [key, value]) => {\n        if (value !== undefined && value !== '') {\n          acc[key] = value;\n        }\n        return acc;\n      }, {});\n    },\n  } as IDataSourceConnectionInfo<\n    ORACLE_CONNECTION_INFO,\n    HostBasedConnectionInfo\n  >,\n\n  // SQL Server\n  [DataSourceName.MSSQL]: {\n    sensitiveProps: ['password'],\n    toIbisConnectionInfo(connectionInfo) {\n      const decryptedConnectionInfo = decryptConnectionInfo(\n        DataSourceName.MSSQL,\n        connectionInfo,\n      );\n      const { host, port, database, user, password, trustServerCertificate } =\n        decryptedConnectionInfo as MS_SQL_CONNECTION_INFO;\n\n      return {\n        host,\n        port,\n        database,\n        user,\n        password,\n        ...(trustServerCertificate && {\n          kwargs: { trustServerCertificate: 'YES' },\n        }),\n      };\n    },\n  } as IDataSourceConnectionInfo<\n    MS_SQL_CONNECTION_INFO,\n    HostBasedConnectionInfo\n  >,\n\n  // Click House\n  [DataSourceName.CLICK_HOUSE]: {\n    sensitiveProps: ['password'],\n    toIbisConnectionInfo(connectionInfo) {\n      const decryptedConnectionInfo = decryptConnectionInfo(\n        DataSourceName.CLICK_HOUSE,\n        connectionInfo,\n      );\n      const { host, port, database, user, password, ssl } =\n        decryptedConnectionInfo as CLICK_HOUSE_CONNECTION_INFO;\n      const encodedPassword = encodeURIComponent(password);\n      let connectionUrl = `clickhouse://${user}:${encodedPassword}@${host}:${port}/${database}?`;\n      if (ssl) {\n        connectionUrl += 'secure=1';\n      }\n      return { connectionUrl };\n    },\n  } as IDataSourceConnectionInfo<\n    CLICK_HOUSE_CONNECTION_INFO,\n    UrlBasedConnectionInfo\n  >,\n  [DataSourceName.TRINO]: {\n    sensitiveProps: ['password'],\n    toIbisConnectionInfo(connectionInfo) {\n      const { host, password, port, schemas, username, ssl } =\n        decryptConnectionInfo(\n          DataSourceName.TRINO,\n          connectionInfo,\n        ) as TRINO_CONNECTION_INFO;\n      // pick first schema from schemas\n      const [catalog, schema] = schemas.split(',')?.[0]?.split('.') ?? [];\n      if (!catalog || !schema) {\n        throw new Error('Invalid schema format, expected catalog.schema');\n      }\n      return {\n        host: ssl ? `https://${host}` : `http://${host}`,\n        port,\n        catalog,\n        schema,\n        user: username,\n        password,\n      };\n    },\n    toMultipleIbisConnectionInfos(connectionInfo) {\n      const { host, port, schemas, username, password, ssl } =\n        decryptConnectionInfo(\n          DataSourceName.TRINO,\n          connectionInfo,\n        ) as TRINO_CONNECTION_INFO;\n\n      // Helper function to parse and validate schema\n      const parseSchema = (schemaStr: string) => {\n        const trimmed = schemaStr.trim();\n        const [catalog, schema] = trimmed.split('.');\n        if (!catalog || !schema) {\n          throw new Error(\n            `Invalid schema format: \"${trimmed}\". Expected format: catalog.schema`,\n          );\n        }\n        return { catalog, schema };\n      };\n\n      // schemas format will be `catalog.schema, catalog.schema, ...`\n      const schemasArray = schemas.split(',').filter(Boolean);\n      if (schemasArray.length === 0) {\n        throw new Error(\n          'No valid schemas provided. Expected format: catalog.schema[, catalog.schema, ...]',\n        );\n      }\n\n      return schemasArray.map((schema) => {\n        const { catalog, schema: schemaName } = parseSchema(schema);\n\n        return {\n          host: ssl ? `https://${host}` : `http://${host}`,\n          port,\n          catalog,\n          schema: schemaName,\n          user: username,\n          password,\n        };\n      });\n    },\n  } as IDataSourceConnectionInfo<\n    TRINO_CONNECTION_INFO,\n    IbisTrinoConnectionInfo\n  >,\n\n  // Snowflake\n  [DataSourceName.SNOWFLAKE]: {\n    sensitiveProps: ['password', 'privateKey'],\n    toIbisConnectionInfo(connectionInfo) {\n      const decryptedConnectionInfo = decryptConnectionInfo(\n        DataSourceName.SNOWFLAKE,\n        connectionInfo,\n      );\n      const {\n        user,\n        password,\n        account,\n        database,\n        schema,\n        warehouse,\n        privateKey,\n      } = decryptedConnectionInfo as SNOWFLAKE_CONNECTION_INFO;\n\n      return {\n        user,\n        account,\n        database,\n        schema,\n        warehouse: warehouse ?? undefined,\n        password: password ?? undefined,\n        private_key: privateKey ?? undefined,\n      };\n    },\n  } as IDataSourceConnectionInfo<\n    SNOWFLAKE_CONNECTION_INFO,\n    IbisSnowflakeConnectionInfo\n  >,\n\n  // DuckDB\n  [DataSourceName.DUCKDB]: {\n    sensitiveProps: [],\n    toIbisConnectionInfo(_connectionInfo) {\n      throw new Error('Not implemented');\n    },\n  } as IDataSourceConnectionInfo<DUCKDB_CONNECTION_INFO, unknown>,\n\n  // Redshift\n  [DataSourceName.REDSHIFT]: {\n    sensitiveProps: ['password', 'awsSecretKey'],\n    toIbisConnectionInfo(connectionInfo) {\n      const decryptedConnectionInfo = decryptConnectionInfo(\n        DataSourceName.REDSHIFT,\n        connectionInfo,\n      );\n\n      const { redshiftType } =\n        decryptedConnectionInfo as REDSHIFT_CONNECTION_INFO;\n\n      // using password authentication\n      if (redshiftType === IbisRedshiftConnectionType.REDSHIFT) {\n        const { host, port, database, user, password } =\n          decryptedConnectionInfo as REDSHIFT_PASSWORD_AUTH;\n        return {\n          redshift_type: redshiftType,\n          host,\n          port,\n          database,\n          user,\n          password,\n        };\n      }\n\n      // using IAM authentication\n      if (redshiftType === IbisRedshiftConnectionType.REDSHIFT_IAM) {\n        const {\n          clusterIdentifier,\n          user,\n          database,\n          awsRegion,\n          awsAccessKey,\n          awsSecretKey,\n        } = decryptedConnectionInfo as REDSHIFT_IAM_AUTH;\n\n        return {\n          redshift_type: redshiftType,\n          cluster_identifier: clusterIdentifier,\n          user,\n          database,\n          region: awsRegion,\n          access_key_id: awsAccessKey,\n          access_key_secret: awsSecretKey,\n        };\n      }\n\n      throw new Error(\n        'Invalid Redshift connection info: must use either password or IAM authentication',\n      );\n    },\n  } as IDataSourceConnectionInfo<\n    REDSHIFT_CONNECTION_INFO,\n    IbisRedshiftConnectionInfo\n  >,\n\n  // Databricks\n  [DataSourceName.DATABRICKS]: {\n    sensitiveProps: ['accessToken', 'clientSecret'],\n    toIbisConnectionInfo(connectionInfo) {\n      const decryptedConnectionInfo = decryptConnectionInfo(\n        DataSourceName.DATABRICKS,\n        connectionInfo,\n      );\n\n      const { databricksType } =\n        decryptedConnectionInfo as DATABRICKS_CONNECTION_INFO;\n\n      if (databricksType === IbisDatabricksConnectionType.TOKEN) {\n        const { serverHostname, httpPath, accessToken } =\n          decryptedConnectionInfo as DATABRICKS_PERSONAL_ACCESS_TOKEN_AUTH;\n\n        return {\n          databricks_type: databricksType,\n          serverHostname,\n          httpPath,\n          accessToken,\n        };\n      }\n\n      if (databricksType === IbisDatabricksConnectionType.SERVICE_PRINCIPAL) {\n        const {\n          serverHostname,\n          httpPath,\n          clientId,\n          clientSecret,\n          azureTenantId,\n        } = decryptedConnectionInfo as DATABRICKS_SERVICE_PRINCIPAL_AUTH;\n\n        return {\n          databricks_type: databricksType,\n          serverHostname,\n          httpPath,\n          clientId,\n          clientSecret,\n          azureTenantId,\n        };\n      }\n\n      throw new Error(\n        'Invalid Databricks connection info: must use either personal access token or service principal authentication',\n      );\n    },\n  } as IDataSourceConnectionInfo<\n    DATABRICKS_CONNECTION_INFO,\n    IbisDatabricksConnectionInfo\n  >,\n};\n\nfunction decryptConnectionInfo(\n  dataSourceType: DataSourceName,\n  connectionInfo: WREN_AI_CONNECTION_INFO,\n): WREN_AI_CONNECTION_INFO {\n  return dataSource[dataSourceType].sensitiveProps.reduce(\n    (acc, prop: string) => {\n      const value = connectionInfo[prop];\n      if (value) {\n        const decryption = encryptor.decrypt(value);\n        const decryptedValue = JSON.parse(decryption)[prop];\n        return { ...acc, [prop]: decryptedValue };\n      }\n      return acc;\n    },\n    connectionInfo,\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/index.ts",
    "content": "export * from './schema';\nexport * from './resolvers';\n"
  },
  {
    "path": "wren-ui/src/apollo/server/managers/dataSourceSchemaDetector.ts",
    "content": "import { camelCase, differenceWith, isEmpty, isEqual, uniqBy } from 'lodash';\nimport { IContext } from '@server/types';\nimport { getLogger } from 'log4js';\nimport { SchemaChange } from '@server/repositories/schemaChangeRepository';\nimport { Model, ModelColumn, RelationInfo } from '../repositories';\n\nconst logger = getLogger('DataSourceSchemaDetector');\nlogger.level = 'debug';\n\nexport type DataSourceSchema = {\n  name: string;\n  columns: {\n    name: string;\n    type: string;\n  }[];\n};\n\nexport type DataSourceSchemaChange = {\n  [SchemaChangeType.DELETED_TABLES]?: DataSourceSchema[];\n  [SchemaChangeType.DELETED_COLUMNS]?: DataSourceSchema[];\n  [SchemaChangeType.MODIFIED_COLUMNS]?: DataSourceSchema[];\n};\n\nexport type DataSourceSchemaResolve = {\n  [SchemaChangeType.DELETED_TABLES]?: boolean;\n  [SchemaChangeType.DELETED_COLUMNS]?: boolean;\n  [SchemaChangeType.MODIFIED_COLUMNS]?: boolean;\n};\n\nexport enum SchemaChangeType {\n  // the tables has been deleted\n  DELETED_TABLES = 'deletedTables',\n  // the columns has been deleted\n  DELETED_COLUMNS = 'deletedColumns',\n  // the columns type has been changed\n  MODIFIED_COLUMNS = 'modifiedColumns',\n}\n\ninterface AffectedResources {\n  sourceTableName: string;\n  referenceName: string;\n  displayName: string;\n  modelId: number;\n  columns: Array<{\n    sourceColumnName: string;\n    displayName: string;\n    type: string;\n  }>;\n  relationships: Array<{\n    id: number;\n    displayName: string;\n    referenceName: string;\n  }>;\n  calculatedFields: ModelColumn[];\n}\n\nexport interface IDataSourceSchemaDetector {\n  detectSchemaChange(): Promise<boolean>;\n  resolveSchemaChange(type: string): Promise<void>;\n  getAffectedResources(\n    changes: DataSourceSchema[],\n    {\n      models,\n      modelColumns,\n      modelRelationships,\n    }: {\n      models: Model[];\n      modelColumns: ModelColumn[];\n      modelRelationships: RelationInfo[];\n    },\n  ): AffectedResources[];\n}\n\nexport default class DataSourceSchemaDetector\n  implements IDataSourceSchemaDetector\n{\n  public ctx: IContext;\n  public projectId: number;\n\n  constructor({ ctx, projectId }: { ctx: IContext; projectId: number }) {\n    this.ctx = ctx;\n    this.projectId = projectId;\n  }\n\n  public async detectSchemaChange() {\n    const diffSchema = await this.getDiffSchema();\n    if (diffSchema) {\n      await this.addSchemaChange(diffSchema);\n    } else {\n      // Mark resolve all in last schema change if it has unresolved flag when no schema change detected.\n      const lastSchemaChange =\n        await this.ctx.schemaChangeRepository.findLastSchemaChange(\n          this.projectId,\n        );\n      if (lastSchemaChange !== null) {\n        const hasUnresolved = Object.values(lastSchemaChange.resolve).some(\n          (resolve) => !resolve,\n        );\n        if (hasUnresolved) {\n          await this.updateResolveToSchemaChange(\n            lastSchemaChange,\n            Object.values(SchemaChangeType),\n          );\n        }\n      }\n    }\n\n    return !!diffSchema;\n  }\n\n  public async resolveSchemaChange(type: string) {\n    const schemaChangeType = camelCase(type) as SchemaChangeType;\n    const supportedTypes = [\n      SchemaChangeType.DELETED_TABLES,\n      SchemaChangeType.DELETED_COLUMNS,\n    ];\n    if (!supportedTypes.includes(schemaChangeType)) {\n      throw new Error('Resolved scheme change type is not supported.');\n    }\n\n    const lastSchemaChange =\n      await this.ctx.schemaChangeRepository.findLastSchemaChange(\n        this.projectId,\n      );\n    const changes = lastSchemaChange?.change[schemaChangeType];\n    const isResolved = lastSchemaChange?.resolve[schemaChangeType];\n\n    if (isResolved) {\n      throw new Error(\n        `Schema change \"${schemaChangeType}\" has nothing to resolve.`,\n      );\n    }\n\n    const models = await this.ctx.modelRepository.findAllBy({\n      projectId: this.projectId,\n    });\n\n    const modelIds = models.map((model) => model.id);\n    const modelColumns =\n      await this.ctx.modelColumnRepository.findColumnsByModelIds(modelIds);\n\n    const modelRelationships =\n      await this.ctx.relationRepository.findRelationInfoBy({\n        modelIds,\n      });\n\n    const affectedResources = this.getAffectedResources(changes, {\n      models,\n      modelColumns,\n      modelRelationships,\n    });\n\n    /**\n     * Handle resolve scheme change for DELETED_TABLES / DELETED_COLUMNS\n     *  1. Remove all affected calculated fields\n     *  2. Remove all affected columns if DELETED_COLUMNS\n     *  3. Remove all affected tables if DELETED_TABLES\n     *\n     *  Considering that we have set up foreign keys, some data will be automatically deleted in cascade,\n     *  so there is no need to perform additional deletions. (E.g., relationships, model's column)\n     */\n    await Promise.all(\n      affectedResources.map(async (resource) => {\n        // both DELETED_TABLES and DELETED_COLUMNS need to remove all affected calculated fields\n        logger.debug(\n          `Start to remove all affected calculated fields \"${resource.calculatedFields.map(\n            (column) => `${column.displayName} (${column.referenceName})`,\n          )}\".`,\n        );\n\n        const columnIds = resource.calculatedFields.map((column) => column.id);\n        await this.ctx.modelColumnRepository.deleteAllByColumnIds(columnIds);\n\n        // remove columns if SchemaChangeType is DELETED_COLUMNS\n        if (schemaChangeType === SchemaChangeType.DELETED_COLUMNS) {\n          const affectedColumnNames = resource.columns.map(\n            (column) => column.sourceColumnName,\n          );\n\n          logger.debug(\n            `Start to remove columns \"${affectedColumnNames}\" from model \"${resource.referenceName}\".`,\n          );\n\n          await this.ctx.modelColumnRepository.deleteAllBySourceColumnNames(\n            resource.modelId,\n            affectedColumnNames,\n          );\n        }\n        return;\n      }),\n    );\n\n    // remove tables if SchemaChangeType is DELETED_TABLES\n    if (schemaChangeType === SchemaChangeType.DELETED_TABLES) {\n      // delete models\n      const affectedTableNames = changes.map((table) => table.name);\n\n      logger.debug(\n        `Start to remove tables \"${affectedTableNames}\" from models.`,\n      );\n\n      await this.ctx.modelRepository.deleteAllBySourceTableNames(\n        affectedTableNames,\n      );\n    }\n\n    // update resolve flag\n    await this.updateResolveToSchemaChange(lastSchemaChange, [\n      schemaChangeType,\n    ]);\n  }\n\n  /**\n   * According to affected models and column data, we also need to find affected resources, including calculated fields and relationships.\n   *\n   * Find all affected resources include:\n   *  - columns (called \"affected column\")\n   *  - relationships (called \"affected relationship\")\n   *  - calculated fields:\n   *    - calculated fields which were affected by affected columns\n   *    - calculated fields which were affected by affected relationships\n   */\n  public getAffectedResources(\n    changes: DataSourceSchema[],\n    {\n      models,\n      modelColumns,\n      modelRelationships,\n    }: {\n      models: Model[];\n      modelColumns: ModelColumn[];\n      modelRelationships: RelationInfo[];\n    },\n  ) {\n    const affectedModels = models.filter(\n      (model) =>\n        changes.findIndex((table) => table.name === model.sourceTableName) !==\n        -1,\n    );\n\n    const affectedResources = affectedModels.map((model) => {\n      const affectedColumns = changes.find(\n        (table) => table.name === model.sourceTableName,\n      ).columns;\n\n      const allCalculatedFields = modelColumns.filter(\n        (column) => column.isCalculated,\n      );\n\n      const affectedMaterials = affectedColumns.reduce(\n        (result, column) => {\n          const affectedColumn = modelColumns.find(\n            (modelColumn) =>\n              modelColumn.sourceColumnName === column.name &&\n              modelColumn.modelId === model.id,\n          );\n\n          result.columns.push({\n            sourceColumnName: column.name,\n            displayName: affectedColumn.displayName,\n            type: column.type,\n          });\n\n          // collect affected calculated fields if it's target column\n          const affectedCalculatedFieldsByColumnId = allCalculatedFields.filter(\n            (calculatedField) => {\n              const lineage = JSON.parse(calculatedField.lineage);\n              return (\n                lineage && lineage[lineage.length - 1] === affectedColumn.id\n              );\n            },\n          );\n\n          result.calculatedFields.push(...affectedCalculatedFieldsByColumnId);\n\n          // collect affected relationships\n          const affectedRelationships = modelRelationships\n            .map((relationship) =>\n              [relationship.fromColumnId, relationship.toColumnId].includes(\n                affectedColumn.id,\n              )\n                ? relationship\n                : null,\n            )\n            .filter((relationship) => !!relationship);\n\n          affectedRelationships.forEach((relationship) => {\n            const referenceName =\n              model.referenceName === relationship.fromModelName\n                ? relationship.toModelName\n                : relationship.fromModelName;\n\n            const displayName = models.find(\n              (model) => model.referenceName === referenceName,\n            )?.displayName;\n\n            result.relationships.push({\n              displayName,\n              id: relationship.id,\n              referenceName,\n            });\n\n            // collect affected calculated fields if the relationship is in use\n            const affectedCalculatedFieldsByRelationshipId =\n              allCalculatedFields.filter((calculatedField) => {\n                const lineage = JSON.parse(calculatedField.lineage);\n\n                // pop the column ID from the lineage\n                lineage.pop();\n                return lineage && lineage.includes(relationship.id);\n              });\n\n            result.calculatedFields.push(\n              ...affectedCalculatedFieldsByRelationshipId,\n            );\n          });\n\n          return result;\n        },\n        { columns: [], relationships: [], calculatedFields: [] },\n      );\n\n      // unique calculated fields by id since it can be duplicated\n      const calculatedFields = uniqBy(affectedMaterials.calculatedFields, 'id');\n\n      return {\n        sourceTableName: model.sourceTableName,\n        displayName: model.displayName,\n        referenceName: model.referenceName,\n        modelId: model.id,\n        ...affectedMaterials,\n        calculatedFields,\n      };\n    });\n\n    return affectedResources;\n  }\n\n  private async getDiffSchema() {\n    logger.info('Start to detect Data Source Schema changes.');\n    const currentSchema = await this.getCurrentSchema();\n    const latestSchema = await this.getLatestSchema();\n\n    const diffSchema = currentSchema.reduce((result, currentTable) => {\n      const lastestTable = latestSchema.find(\n        (table) => table.name === currentTable.name,\n      );\n      // If the table is not found in the latest schema, it means the table has been deleted.\n      if (!lastestTable) {\n        result[SchemaChangeType.DELETED_TABLES] = [\n          ...(result[SchemaChangeType.DELETED_TABLES] || []),\n          currentTable,\n        ];\n        return result;\n      }\n\n      // If the table is found in the latest schema, we need to diff the columns.\n      const diffColumns = differenceWith(\n        currentTable.columns,\n        lastestTable.columns,\n        isEqual,\n      );\n      if (diffColumns.length > 0) {\n        const deletedColumnChange = { name: currentTable.name, columns: [] };\n        const modifiedColumnChange = { name: currentTable.name, columns: [] };\n\n        for (const currentColumn of diffColumns) {\n          const latestColumn = lastestTable.columns.find(\n            (column) => column.name === currentColumn.name,\n          );\n          // If the column is not found in the latest schema, it means the column has been deleted.\n          if (!latestColumn) {\n            deletedColumnChange.columns.push(currentColumn);\n            continue;\n          }\n          // If the column is found in the latest schema, it means the column has been modified.\n          // save latest column as modified column\n          modifiedColumnChange.columns.push(latestColumn);\n        }\n\n        // If there are any deleted or modified columns, we need to add them to the result.\n        if (deletedColumnChange.columns.length > 0) {\n          result[SchemaChangeType.DELETED_COLUMNS] = [\n            ...(result[SchemaChangeType.DELETED_COLUMNS] || []),\n            deletedColumnChange,\n          ];\n        }\n        if (modifiedColumnChange.columns.length > 0) {\n          result[SchemaChangeType.MODIFIED_COLUMNS] = [\n            ...(result[SchemaChangeType.MODIFIED_COLUMNS] || []),\n            modifiedColumnChange,\n          ];\n        }\n      }\n\n      return result;\n    }, {});\n\n    if (!isEmpty(diffSchema)) {\n      logger.debug('Diff Schema:', JSON.stringify(diffSchema));\n      logger.info('Data Source Schema has changed.');\n      return diffSchema as DataSourceSchemaChange;\n    }\n\n    logger.info('No changes in Data Source Schema.');\n    return null;\n  }\n\n  private async addSchemaChange(diffSchema: DataSourceSchemaChange) {\n    const getResolveState = (change) => (!!change ? false : undefined);\n\n    const lastSchemaChange =\n      await this.ctx.schemaChangeRepository.findLastSchemaChange(\n        this.projectId,\n      );\n    // If the schema change is the same as the last one, we don't need to create a new one.\n    const isNewSchemaChange =\n      JSON.stringify(lastSchemaChange?.change) !== JSON.stringify(diffSchema);\n\n    if (isNewSchemaChange) {\n      await this.ctx.schemaChangeRepository.createOne({\n        projectId: this.projectId,\n        change: diffSchema,\n        // Set the resolve to false if there are any changes. It will set resolve to true once the schema has been synced.\n        resolve: {\n          [SchemaChangeType.DELETED_TABLES]: getResolveState(\n            diffSchema[SchemaChangeType.DELETED_TABLES],\n          ),\n          [SchemaChangeType.DELETED_COLUMNS]: getResolveState(\n            diffSchema[SchemaChangeType.DELETED_COLUMNS],\n          ),\n          [SchemaChangeType.MODIFIED_COLUMNS]: getResolveState(\n            diffSchema[SchemaChangeType.MODIFIED_COLUMNS],\n          ),\n        },\n      });\n    }\n  }\n\n  private async getCurrentSchema(): Promise<DataSourceSchema[]> {\n    const models = await this.ctx.modelRepository.findAllBy({\n      projectId: this.projectId,\n    });\n    const modelIds = models.map((model) => model.id);\n    const modelColumns =\n      await this.ctx.modelColumnRepository.findColumnsByModelIds(modelIds);\n    const result = models.map((model) => {\n      return {\n        name: model.sourceTableName,\n        columns: modelColumns\n          .filter(\n            (column) => column.modelId === model.id && !column.isCalculated,\n          )\n          .map((column) => ({\n            name: column.sourceColumnName,\n            type: column.type,\n          })),\n      };\n    });\n    return result;\n  }\n\n  private async getLatestSchema(): Promise<DataSourceSchema[]> {\n    const project = await this.ctx.projectRepository.findOneBy({\n      id: this.projectId,\n    });\n    const latestDataSourceTables =\n      await this.ctx.projectService.getProjectDataSourceTables(project);\n    const result = latestDataSourceTables.map((table) => {\n      return {\n        name: table.name,\n        columns: table.columns.map((column) => {\n          return {\n            name: column.name,\n            type: column.type,\n          };\n        }),\n      };\n    });\n    return result;\n  }\n\n  private async updateResolveToSchemaChange(\n    lastSchemaChange: SchemaChange,\n    schemaChangeTypes: SchemaChangeType[],\n  ) {\n    await this.ctx.schemaChangeRepository.updateOne(lastSchemaChange.id, {\n      resolve: {\n        ...lastSchemaChange.resolve,\n        ...schemaChangeTypes.reduce(\n          (result, type) => ({ ...result, [type]: true }),\n          {},\n        ),\n      },\n    });\n    logger.info(`Schema change \"${schemaChangeTypes}\" resolved successfully.`);\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/mdl/mdlBuilder.ts",
    "content": "import { isEmpty, isNil, pickBy } from 'lodash';\nimport {\n  Model,\n  ModelColumn,\n  ModelNestedColumn,\n  Project,\n  RelationInfo,\n  View,\n} from '../repositories';\nimport {\n  Manifest,\n  ModelMDL,\n  TableReference,\n  WrenEngineDataSourceType,\n} from './type';\nimport { getLogger } from '@server/utils';\nimport { getConfig } from '@server/config';\nimport { DataSourceName } from '../types';\n\nconst logger = getLogger('MDLBuilder');\nlogger.level = 'debug';\n\nconst config = getConfig();\n\nexport interface MDLBuilderBuildFromOptions {\n  project: Project;\n  models: Model[];\n  columns?: ModelColumn[];\n  nestedColumns?: ModelNestedColumn[];\n  relations?: RelationInfo[];\n  views: View[];\n  relatedModels?: Model[];\n  relatedColumns?: ModelColumn[];\n  relatedRelations?: RelationInfo[];\n}\n\nexport interface IMDLBuilder {\n  build(): Manifest; //facade method to build the manifest json\n}\n\n// responsible to generate a valid manifest json\nexport class MDLBuilder implements IMDLBuilder {\n  private manifest: Manifest;\n\n  private project: Project;\n  private readonly models: Model[];\n  private readonly columns: ModelColumn[];\n  private readonly nestedColumns: ModelNestedColumn[];\n  private readonly relations: RelationInfo[];\n  private readonly views: View[];\n\n  // related models, columns, and relations are used as the reference to build calculatedField expression or other\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  private readonly relatedModels: Model[];\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  private readonly relatedColumns: ModelColumn[];\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  private readonly relatedRelations: RelationInfo[];\n\n  constructor(builderOptions: MDLBuilderBuildFromOptions) {\n    const {\n      project,\n      models,\n      columns,\n      nestedColumns,\n      relations,\n      views,\n      relatedModels,\n      relatedColumns,\n      relatedRelations,\n    } = builderOptions;\n    this.project = project;\n    this.models = models.sort((a, b) => a.id - b.id);\n    this.columns = columns.sort((a, b) => a.id - b.id);\n    this.nestedColumns = nestedColumns;\n    this.relations = relations.sort((a, b) => a.id - b.id);\n    this.views = views || [];\n    this.relatedModels = relatedModels;\n    this.relatedColumns = relatedColumns;\n    this.relatedRelations = relatedRelations;\n\n    // init manifest\n    this.manifest = {};\n  }\n\n  public build(): Manifest {\n    this.addProject();\n    this.addModel();\n    this.addNormalField();\n    this.addRelation();\n    this.addCalculatedField();\n    this.addView();\n    this.postProcessManifest();\n    return this.getManifest();\n  }\n\n  public getManifest(): Manifest {\n    return this.manifest;\n  }\n\n  public addModel(): void {\n    if (!isEmpty(this.manifest.models)) {\n      return;\n    }\n    this.manifest.models = this.models.map((model: Model) => {\n      const properties = model.properties ? JSON.parse(model.properties) : {};\n      // put displayName in properties\n      if (model.displayName) {\n        properties.displayName = model.displayName;\n      }\n      const tableReference = this.buildTableReference(model);\n\n      return {\n        name: model.referenceName,\n        columns: [],\n        tableReference,\n        // can only have one of refSql or tableReference\n        refSql: this.useRustWrenEngine()\n          ? null\n          : tableReference\n            ? null\n            : model.refSql,\n        cached: model.cached ? true : false,\n        refreshTime: model.refreshTime,\n        properties: {\n          displayName: model.displayName,\n          description: properties.description,\n        },\n        primaryKey: '', // will be modified in addColumn\n      } as ModelMDL;\n    });\n  }\n\n  public addView(): void {\n    if (!isEmpty(this.manifest.views)) {\n      return;\n    }\n    this.manifest.views = this.views.map((view: View) => {\n      const properties = JSON.parse(view.properties) || {};\n\n      // filter out properties that are not null or undefined\n      // and are in the list of properties that are allowed\n      const viewProperties = pickBy(properties, (value, key) => {\n        return (\n          !isNil(value) &&\n          ['displayName', 'description', 'question', 'summary'].includes(key)\n        );\n      });\n\n      return {\n        name: view.name,\n        statement: view.statement,\n        properties: {\n          ...viewProperties,\n\n          // viewId will be passed back in other APIs\n          // to identify the view\n          viewId: view.id.toString(),\n        },\n      };\n    });\n  }\n\n  public addNormalField(): void {\n    // should addModel first\n    if (isEmpty(this.manifest.models)) {\n      logger.debug('No model in manifest, should build model first');\n      return;\n    }\n    this.columns\n      .filter(({ isCalculated }) => !isCalculated)\n      .forEach((column: ModelColumn) => {\n        // validate manifest.model exist\n        const modelRefName = this.models.find(\n          (model: any) => model.id === column.modelId,\n        )?.referenceName;\n        if (!modelRefName) {\n          logger.debug(\n            `Build MDL Column Error: can not find model, modelId ${column.modelId}, columnId: ${column.id}`,\n          );\n          return;\n        }\n        const model = this.manifest.models.find(\n          (model: any) => model.name === modelRefName,\n        );\n\n        // modify model primary key\n        if (column.isPk) {\n          model.primaryKey = column.referenceName;\n        }\n\n        // add column into model\n        if (!model.columns) {\n          model.columns = [];\n        }\n        const properties = column.properties\n          ? JSON.parse(column.properties)\n          : {};\n        // put displayName in properties\n        if (column.displayName) {\n          properties.displayName = column.displayName;\n        }\n        // put nested columns in properties\n        if (column.type.includes('STRUCT')) {\n          const nestedColumns = this.nestedColumns.filter(\n            (nestedColumn) => nestedColumn.columnId === column.id,\n          );\n          nestedColumns.forEach((column) => {\n            if (column.displayName) {\n              properties[`nestedDisplayName.${column.sourceColumnName}`] =\n                column.displayName;\n            }\n            if (column.properties?.description) {\n              properties[`nestedDescription.${column.sourceColumnName}`] =\n                column.properties.description;\n            }\n          }, {});\n        }\n        const expression = this.getColumnExpression(column, model);\n        model.columns.push({\n          name: column.referenceName,\n          type: column.type,\n          isCalculated: column.isCalculated ? true : false,\n          notNull: column.notNull ? true : false,\n          expression,\n          properties: properties,\n        });\n      });\n  }\n\n  public addCalculatedField(): void {\n    // should addModel first\n    if (isEmpty(this.manifest.models)) {\n      logger.debug('No model in manifest, should build model first');\n      return;\n    }\n    this.columns\n      .filter(({ isCalculated }) => isCalculated)\n      .forEach((column: ModelColumn) => {\n        // validate manifest.model exist\n        const relatedModel = this.relatedModels.find(\n          (model: any) => model.id === column.modelId,\n        );\n        const model = this.manifest.models.find(\n          (model: any) => model.name === relatedModel.referenceName,\n        );\n        if (!model) {\n          logger.debug(\n            `Build MDL Column Error: can not find model, modelId \"${column.modelId}\", columnId: \"${column.id}\"`,\n          );\n          return;\n        }\n        const expression = this.getColumnExpression(column, model);\n        const columnValue = {\n          name: column.referenceName,\n          type: column.type,\n          isCalculated: true,\n          expression,\n          notNull: column.notNull ? true : false,\n          properties: JSON.parse(column.properties),\n        };\n        model.columns.push(columnValue);\n      });\n  }\n\n  public insertCalculatedField(\n    modelName: string,\n    calculatedField: ModelColumn,\n  ) {\n    const model = this.manifest.models.find(\n      (model: any) => model.name === modelName,\n    );\n    if (!model) {\n      logger.debug(`Can not find model \"${modelName}\" to add calculated field`);\n      return;\n    }\n    // if calculated field is already in the model, skip\n    if (\n      model.columns.find(\n        (column: any) => column.name === calculatedField.referenceName,\n      )\n    ) {\n      return;\n    }\n    const expression = this.getColumnExpression(calculatedField, model);\n    const columnValue = {\n      name: calculatedField.referenceName,\n      type: calculatedField.type,\n      isCalculated: true,\n      expression,\n      notNull: calculatedField.notNull ? true : false,\n      properties: JSON.parse(calculatedField.properties),\n    };\n    model.columns.push(columnValue);\n  }\n\n  public addRelation(): void {\n    this.manifest.relationships = this.relations.map(\n      (relation: RelationInfo) => {\n        const {\n          name,\n          joinType,\n          fromModelName,\n          fromColumnName,\n          toModelName,\n          toColumnName,\n        } = relation;\n        const condition = this.getRelationCondition(relation);\n        this.addRelationColumn(fromModelName, {\n          modelReferenceName: toModelName,\n          columnReferenceName: toColumnName,\n          relation: name,\n        });\n        this.addRelationColumn(toModelName, {\n          modelReferenceName: fromModelName,\n          columnReferenceName: fromColumnName,\n          relation: name,\n        });\n\n        const properties = relation.properties\n          ? JSON.parse(relation.properties)\n          : {};\n\n        return {\n          name: name,\n          models: [fromModelName, toModelName],\n          joinType: joinType,\n          condition,\n          properties,\n        };\n      },\n    );\n  }\n\n  public addProject(): void {\n    this.manifest.schema = this.project.schema;\n    this.manifest.catalog = this.project.catalog;\n    const dataSource = this.buildDataSource();\n    if (dataSource) {\n      this.manifest.dataSource = dataSource;\n    }\n  }\n\n  protected addRelationColumn(\n    modelName: string,\n    columnData: {\n      modelReferenceName: string;\n      columnReferenceName: string;\n      relation: string;\n    },\n  ) {\n    const model = this.manifest.models.find(\n      (model: any) => model.name === modelName,\n    );\n    if (!model) {\n      logger.debug(`Can not find model \"${modelName}\" to add relation column`);\n      return;\n    }\n    if (!model.columns) {\n      model.columns = [];\n    }\n    // check if the modelReferenceName is already in the model column\n    const modelNameDuplicated = model.columns.find(\n      (column: any) => column.name === columnData.modelReferenceName,\n    );\n    const column = {\n      name: modelNameDuplicated\n        ? `${columnData.modelReferenceName}_${columnData.columnReferenceName}`\n        : columnData.modelReferenceName,\n      type: columnData.modelReferenceName,\n      properties: null,\n      relationship: columnData.relation,\n      isCalculated: false,\n      notNull: false,\n    };\n    model.columns.push(column);\n  }\n\n  protected getColumnExpression(\n    column: ModelColumn,\n    currentModel?: Partial<ModelMDL>,\n  ): string {\n    if (!column.isCalculated) {\n      // columns existed in the data source.\n      // Provide original column name in expression to MDL if referenceName has converted.\n      if (column.sourceColumnName !== column.referenceName) {\n        return `\"${column.sourceColumnName}\"`;\n      }\n      return '';\n    }\n    // calculated field\n    const lineage = JSON.parse(column.lineage) as number[];\n    // lineage = [relationId1, relationId2, ..., columnId]\n    const fieldExpression = Object.entries<number>(lineage).reduce(\n      (acc, [index, id]) => {\n        const isLast = parseInt(index) == lineage.length - 1;\n        if (isLast) {\n          // id is columnId\n          const columnReferenceName = this.relatedColumns.find(\n            (relatedColumn) => relatedColumn.id === id,\n          )?.referenceName;\n          acc.push(`\\\"${columnReferenceName}\\\"`);\n          return acc;\n        }\n        // id is relationId\n        const usedRelation = this.relatedRelations.find(\n          (relatedRelation) => relatedRelation.id === id,\n        );\n        const relationColumnName = currentModel!.columns.find(\n          (c) => c.relationship === usedRelation.name,\n        ).name;\n        // move to next model\n        const nextModelName =\n          currentModel.name === usedRelation.fromModelName\n            ? usedRelation.toModelName\n            : usedRelation.fromModelName;\n        const nextModel = this.manifest.models.find(\n          (model) => model.name === nextModelName,\n        );\n        currentModel = nextModel;\n        acc.push(relationColumnName);\n        return acc;\n      },\n      [],\n    );\n    return `${column.aggregation}(${fieldExpression.join('.')})`;\n  }\n\n  protected getRelationCondition(relation: RelationInfo): string {\n    //TODO phase2: implement the expression for relation condition\n    const { fromColumnName, toColumnName, fromModelName, toModelName } =\n      relation;\n    return `\"${fromModelName}\".${fromColumnName} = \"${toModelName}\".${toColumnName}`;\n  }\n\n  private buildTableReference(model: Model): TableReference | null {\n    const modelProps =\n      model.properties && typeof model.properties === 'string'\n        ? JSON.parse(model.properties)\n        : {};\n    if (!modelProps.table) {\n      return null;\n    }\n    return {\n      catalog: modelProps.catalog || null,\n      schema: modelProps.schema || null,\n      table: modelProps.table,\n    };\n  }\n  private postProcessManifest() {\n    if (this.useRustWrenEngine()) {\n      // 1. remove all the key that the value is null\n      this.manifest.models = this.manifest.models?.map((model) => {\n        model.columns.map((column) => {\n          column.properties = pickBy(\n            column.properties,\n            (value) => value !== null,\n          );\n          return column;\n        });\n        return pickBy(model, (value) => value !== null);\n      });\n      this.manifest.views = this.manifest.views?.map((view) => {\n        return pickBy(view, (value) => value !== null);\n      });\n      this.manifest.relationships = this.manifest.relationships?.map(\n        (relationship) => {\n          return pickBy(relationship, (value) => value !== null);\n        },\n      );\n      this.manifest.enumDefinitions = this.manifest.enumDefinitions?.map(\n        (enumDefinition) => {\n          return pickBy(enumDefinition, (value) => value !== null);\n        },\n      );\n      // 2. remove expression if it's empty string\n      this.manifest.models?.forEach((model) => {\n        model.columns?.forEach((column) => {\n          if (column.expression === '') {\n            delete column.expression;\n          }\n        });\n      });\n    }\n  }\n  private useRustWrenEngine(): boolean {\n    return !!config.experimentalEngineRustVersion;\n  }\n  private buildDataSource(): WrenEngineDataSourceType {\n    const type = this.project.type;\n    if (!type) {\n      return;\n    }\n    switch (type) {\n      case DataSourceName.ATHENA:\n        return WrenEngineDataSourceType.ATHENA;\n      case DataSourceName.BIG_QUERY:\n        return WrenEngineDataSourceType.BIGQUERY;\n      case DataSourceName.DUCKDB:\n        return WrenEngineDataSourceType.DUCKDB;\n      case DataSourceName.POSTGRES:\n        return WrenEngineDataSourceType.POSTGRES;\n      case DataSourceName.MYSQL:\n        return WrenEngineDataSourceType.MYSQL;\n      case DataSourceName.ORACLE:\n        return WrenEngineDataSourceType.ORACLE;\n      case DataSourceName.MSSQL:\n        return WrenEngineDataSourceType.MSSQL;\n      case DataSourceName.CLICK_HOUSE:\n        return WrenEngineDataSourceType.CLICKHOUSE;\n      case DataSourceName.TRINO:\n        return WrenEngineDataSourceType.TRINO;\n      case DataSourceName.SNOWFLAKE:\n        return WrenEngineDataSourceType.SNOWFLAKE;\n      case DataSourceName.REDSHIFT:\n        return WrenEngineDataSourceType.REDSHIFT;\n      case DataSourceName.DATABRICKS:\n        return WrenEngineDataSourceType.DATABRICKS;\n      default:\n        throw new Error(\n          `Unsupported data source type: ${type} found when building manifest`,\n        );\n    }\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/mdl/test/mdlBuilder.test.ts",
    "content": "import { DataSourceName } from '@server/types';\nimport {\n  Model,\n  Project,\n  ModelColumn,\n  ModelNestedColumn,\n  RelationInfo,\n  View,\n  BIG_QUERY_CONNECTION_INFO,\n} from '../../repositories';\nimport { MDLBuilder, MDLBuilderBuildFromOptions } from '../mdlBuilder';\nimport { ModelMDL, RelationMDL, ViewMDL } from '../type';\n\ndescribe('MDLBuilder', () => {\n  let mdlBuilder: MDLBuilder;\n\n  describe('build', () => {\n    it('should return a manifest', () => {\n      const builderOptions = {\n        project: {},\n        models: [],\n        columns: [],\n        nestedColumns: [],\n        relations: [],\n        relatedModels: [],\n        relatedColumns: [],\n        relatedRelations: [],\n      } as MDLBuilderBuildFromOptions;\n      mdlBuilder = new MDLBuilder(builderOptions);\n\n      const manifest = mdlBuilder.build();\n      expect(manifest).toBeDefined();\n    });\n\n    it('should return a manifest with models & columns & relations.', () => {\n      // Arrange\n      const project = {\n        id: 1,\n        type: DataSourceName.BIG_QUERY,\n        displayName: 'my project',\n        connectionInfo: {\n          projectId: 'bq-project-id',\n          datasetId: 'bq-project-id.my-dataset',\n          credentials: 'my-credential',\n        } as BIG_QUERY_CONNECTION_INFO,\n        catalog: 'wrenai',\n        schema: 'public',\n        sampleDataset: null,\n      } as Project;\n      const models = [\n        {\n          id: 1,\n          projectId: 1,\n          displayName: 'order',\n          sourceTableName: 'order',\n          referenceName: 'order',\n          refSql: 'SELECT * FROM order',\n          cached: false,\n          refreshTime: null,\n          properties: JSON.stringify({\n            description: 'foo table',\n            schema: 'my-dataset',\n            catalog: 'bq-project-id',\n            table: 'order',\n          }),\n        },\n        {\n          id: 2,\n          projectId: 1,\n          displayName: 'customer',\n          sourceTableName: 'customer',\n          referenceName: 'customer',\n          refSql: 'SELECT * FROM customer',\n          cached: false,\n          refreshTime: null,\n          properties: JSON.stringify({\n            schema: null,\n            catalog: null,\n            table: 'customer',\n          }),\n        },\n      ] as Model[];\n      const columns = [\n        {\n          id: 1,\n          modelId: 1,\n          isCalculated: false,\n          displayName: 'orderKey',\n          referenceName: 'orderKey',\n          sourceColumnName: 'orderKey',\n          aggregation: null,\n          lineage: null,\n          customExpression: null,\n          type: 'STRING',\n          notNull: true,\n          isPk: true,\n          properties: JSON.stringify({ description: 'bar' }),\n        },\n        {\n          id: 2,\n          modelId: 2,\n          isCalculated: false,\n          displayName: 'orderKey',\n          referenceName: 'orderKey',\n          sourceColumnName: 'orderKey',\n          aggregation: null,\n          lineage: null,\n          customExpression: null,\n          type: 'STRING',\n          notNull: true,\n          isPk: false,\n          properties: null,\n        },\n        {\n          id: 3,\n          modelId: 2,\n          isCalculated: false,\n          displayName: 'event_params',\n          referenceName: 'event_params',\n          sourceColumnName: 'event_params',\n          aggregation: null,\n          lineage: null,\n          customExpression: null,\n          type: 'ARRAY<STRUCT<key STRING>>',\n          notNull: true,\n          isPk: false,\n          properties: null,\n        },\n      ] as ModelColumn[];\n      const nestedColumns = [\n        {\n          id: 1,\n          modelId: 2,\n          columnId: 3,\n          columnPath: ['event_params', 'key'],\n          displayName: 'event_params.key',\n          referenceName: 'event_params.key',\n          sourceColumnName: 'event_params.key',\n          type: 'STRING',\n          properties: { description: 'bar' },\n        },\n      ] as ModelNestedColumn[];\n      const relations = [\n        {\n          id: 1,\n          projectId: 1,\n          name: 'OrderCustomer',\n          fromColumnId: 1,\n          toColumnId: 2,\n          joinType: 'oneToMany',\n          fromModelId: 1,\n          fromModelName: 'order',\n          fromColumnName: 'orderKey',\n          toModelId: 2,\n          toModelName: 'customer',\n          toColumnName: 'orderKey',\n          properties: JSON.stringify({\n            description: 'the relationship between orders and customers',\n          }),\n        },\n      ] as RelationInfo[];\n      const builderOptions = {\n        project,\n        models,\n        columns,\n        nestedColumns,\n        relations,\n        relatedModels: [],\n        relatedColumns: [],\n        relatedRelations: [],\n      } as MDLBuilderBuildFromOptions;\n      mdlBuilder = new MDLBuilder(builderOptions);\n\n      // Act\n      const manifest = mdlBuilder.build();\n\n      // Assert\n      const expectedModels = [\n        {\n          name: 'order',\n          tableReference: {\n            schema: 'my-dataset',\n            catalog: 'bq-project-id',\n            table: 'order',\n          },\n          refSql: null,\n          columns: [\n            {\n              name: 'orderKey',\n              expression: '',\n              type: 'STRING',\n              isCalculated: false,\n              notNull: true,\n              properties: { description: 'bar', displayName: 'orderKey' },\n            },\n            {\n              name: 'customer',\n              type: 'customer',\n              isCalculated: false,\n              relationship: 'OrderCustomer',\n              properties: null,\n              notNull: false,\n            },\n          ],\n          cached: false,\n          refreshTime: null,\n          primaryKey: 'orderKey',\n          properties: {\n            description: 'foo table',\n            displayName: 'order',\n          },\n        },\n        {\n          name: 'customer',\n          tableReference: {\n            schema: null,\n            catalog: null,\n            table: 'customer',\n          },\n          refSql: null,\n          columns: [\n            {\n              name: 'orderKey',\n              expression: '',\n              type: 'STRING',\n              isCalculated: false,\n              notNull: true,\n              properties: { displayName: 'orderKey' },\n            },\n            {\n              name: 'event_params',\n              expression: '',\n              type: 'ARRAY<STRUCT<key STRING>>',\n              isCalculated: false,\n              notNull: true,\n              properties: {\n                displayName: 'event_params',\n                'nestedDisplayName.event_params.key': 'event_params.key',\n                'nestedDescription.event_params.key': 'bar',\n              },\n            },\n            {\n              name: 'order',\n              type: 'order',\n              isCalculated: false,\n              relationship: 'OrderCustomer',\n              notNull: false,\n              properties: null,\n            },\n          ],\n          primaryKey: '',\n          cached: false,\n          refreshTime: null,\n          properties: {\n            description: undefined,\n            displayName: 'customer',\n          },\n        },\n      ] as ModelMDL[];\n\n      const expectedRelationships = [\n        {\n          name: 'OrderCustomer',\n          models: ['order', 'customer'],\n          joinType: 'oneToMany',\n          condition: '\"order\".orderKey = \"customer\".orderKey',\n          properties: {\n            description: 'the relationship between orders and customers',\n          },\n        },\n      ] as RelationMDL[];\n\n      expect(manifest.models).toEqual(expectedModels);\n      expect(manifest.relationships).toEqual(expectedRelationships);\n    });\n  });\n\n  it('should return a manifest with models & columns & nestedColumns & relations & views.', () => {\n    // Arrange\n    const project = {\n      id: 1,\n      type: DataSourceName.BIG_QUERY,\n      displayName: 'my project',\n      connectionInfo: {\n        projectId: 'bq-project-id',\n        datasetId: 'my-dataset',\n        credentials: 'my-credential',\n      } as BIG_QUERY_CONNECTION_INFO,\n      catalog: 'wrenai',\n      schema: 'public',\n      sampleDataset: null,\n    } as Project;\n    const models = [\n      {\n        id: 1,\n        projectId: 1,\n        displayName: 'order',\n        sourceTableName: 'order',\n        referenceName: 'order',\n        refSql: 'SELECT * FROM order',\n        cached: false,\n        refreshTime: null,\n        properties: JSON.stringify({\n          description: 'foo table',\n          catalog: 'bq-project-id',\n          schema: 'my-dataset',\n          table: 'order',\n        }),\n      },\n      {\n        id: 2,\n        projectId: 1,\n        displayName: 'customer',\n        sourceTableName: 'customer',\n        referenceName: 'customer',\n        refSql: 'SELECT * FROM customer',\n        cached: false,\n        refreshTime: null,\n        properties: JSON.stringify({\n          catalog: 'bq-project-id',\n          schema: 'my-dataset',\n          table: 'customer',\n        }),\n      },\n    ] as Model[];\n    const columns = [\n      {\n        id: 1,\n        modelId: 1,\n        isCalculated: false,\n        displayName: 'orderKey',\n        referenceName: 'orderKey',\n        sourceColumnName: 'orderKey',\n        aggregation: null,\n        lineage: null,\n        customExpression: null,\n        type: 'STRING',\n        notNull: true,\n        isPk: true,\n        properties: JSON.stringify({ description: 'bar' }),\n      },\n      {\n        id: 2,\n        modelId: 2,\n        isCalculated: false,\n        displayName: 'orderKey',\n        referenceName: 'orderKey',\n        sourceColumnName: 'orderKey',\n        aggregation: null,\n        lineage: null,\n        customExpression: null,\n        type: 'STRING',\n        notNull: true,\n        isPk: false,\n        properties: null,\n      },\n      {\n        id: 3,\n        modelId: 2,\n        isCalculated: false,\n        displayName: 'event_params',\n        referenceName: 'event_params',\n        sourceColumnName: 'event_params',\n        aggregation: null,\n        lineage: null,\n        customExpression: null,\n        type: 'ARRAY<STRUCT<key STRING>>',\n        notNull: true,\n        isPk: false,\n        properties: null,\n      },\n    ] as ModelColumn[];\n    const nestedColumns = [\n      {\n        id: 1,\n        modelId: 2,\n        columnId: 3,\n        columnPath: ['event_params', 'key'],\n        displayName: 'event_params.key',\n        referenceName: 'event_params.key',\n        sourceColumnName: 'event_params.key',\n        type: 'STRING',\n        properties: { description: 'bar' },\n      },\n    ] as ModelNestedColumn[];\n    const relations = [\n      {\n        id: 1,\n        projectId: 1,\n        name: 'OrderCustomer',\n        fromColumnId: 1,\n        toColumnId: 2,\n        joinType: 'oneToMany',\n        fromModelId: 1,\n        fromModelName: 'order',\n        fromColumnName: 'orderKey',\n        toModelId: 2,\n        toModelName: 'customer',\n        toColumnName: 'orderKey',\n        properties: JSON.stringify({\n          description: 'the relationship between orders and customers',\n        }),\n      },\n    ] as RelationInfo[];\n    const views = [\n      {\n        id: 1,\n        projectId: 1,\n        name: 'view',\n        statement: 'select * from order',\n        cached: false,\n        properties: JSON.stringify({\n          description: 'foo view',\n          displayName: 'view',\n        }),\n      },\n    ] as View[];\n\n    const builderOptions = {\n      project,\n      models,\n      views,\n      columns,\n      nestedColumns,\n      relations,\n      relatedModels: [],\n      relatedColumns: [],\n      relatedRelations: [],\n    } as MDLBuilderBuildFromOptions;\n    mdlBuilder = new MDLBuilder(builderOptions);\n\n    // Act\n    const manifest = mdlBuilder.build();\n\n    // Assert\n    const expectedModels = [\n      {\n        name: 'order',\n        refSql: null,\n        tableReference: {\n          schema: 'my-dataset',\n          catalog: 'bq-project-id',\n          table: 'order',\n        },\n        columns: [\n          {\n            name: 'orderKey',\n            expression: '',\n            type: 'STRING',\n            isCalculated: false,\n            notNull: true,\n            properties: { description: 'bar', displayName: 'orderKey' },\n          },\n          {\n            name: 'customer',\n            type: 'customer',\n            isCalculated: false,\n            relationship: 'OrderCustomer',\n            notNull: false,\n            properties: null,\n          },\n        ],\n        cached: false,\n        refreshTime: null,\n        primaryKey: 'orderKey',\n        properties: { description: 'foo table', displayName: 'order' },\n      },\n      {\n        name: 'customer',\n        refSql: null,\n        tableReference: {\n          schema: 'my-dataset',\n          catalog: 'bq-project-id',\n          table: 'customer',\n        },\n        columns: [\n          {\n            name: 'orderKey',\n            expression: '',\n            type: 'STRING',\n            isCalculated: false,\n            notNull: true,\n            properties: { displayName: 'orderKey' },\n          },\n          {\n            name: 'event_params',\n            expression: '',\n            type: 'ARRAY<STRUCT<key STRING>>',\n            isCalculated: false,\n            notNull: true,\n            properties: {\n              displayName: 'event_params',\n              'nestedDisplayName.event_params.key': 'event_params.key',\n              'nestedDescription.event_params.key': 'bar',\n            },\n          },\n          {\n            name: 'order',\n            type: 'order',\n            isCalculated: false,\n            relationship: 'OrderCustomer',\n            notNull: false,\n            properties: null,\n          },\n        ],\n        primaryKey: '',\n        cached: false,\n        refreshTime: null,\n        properties: { description: undefined, displayName: 'customer' },\n      },\n    ] as ModelMDL[];\n\n    const expectedRelationships = [\n      {\n        name: 'OrderCustomer',\n        models: ['order', 'customer'],\n        joinType: 'oneToMany',\n        condition: '\"order\".orderKey = \"customer\".orderKey',\n        properties: {\n          description: 'the relationship between orders and customers',\n        },\n      },\n    ] as RelationMDL[];\n\n    const expectedViews = [\n      {\n        name: 'view',\n        statement: 'select * from order',\n        properties: {\n          description: 'foo view',\n          displayName: 'view',\n          viewId: '1',\n        },\n      },\n    ] as ViewMDL[];\n\n    expect(manifest.models).toEqual(expectedModels);\n    expect(manifest.relationships).toEqual(expectedRelationships);\n    expect(manifest.views).toEqual(expectedViews);\n  });\n\n  it('should return correct expression in calculated field.', () => {\n    const models = [\n      // customer model\n      {\n        id: 1,\n        projectId: 1,\n        displayName: 'customer',\n        sourceTableName: 'customer',\n        referenceName: 'customer',\n        refSql: 'SELECT * FROM customer',\n        cached: false,\n        refreshTime: null,\n        properties: null,\n      },\n      // order model\n      {\n        id: 2,\n        projectId: 1,\n        displayName: 'order',\n        sourceTableName: 'order',\n        referenceName: 'order',\n        refSql: 'SELECT * FROM order',\n        cached: false,\n        refreshTime: null,\n        properties: null,\n      },\n      // payment model\n      {\n        id: 3,\n        projectId: 1,\n        displayName: 'payment',\n        sourceTableName: 'payment',\n        referenceName: 'payment',\n        refSql: 'SELECT * FROM payment',\n        cached: false,\n        refreshTime: null,\n        properties: null,\n      },\n    ] as Model[];\n    const columns = [\n      // customer columns: id, name, total_payment\n      {\n        id: 1,\n        modelId: 1,\n        isCalculated: false,\n        displayName: 'id',\n        referenceName: 'id',\n        sourceColumnName: 'id',\n        aggregation: null,\n        lineage: null,\n        customExpression: null,\n        type: 'STRING',\n        notNull: true,\n        isPk: true,\n        properties: null,\n      },\n      {\n        id: 2,\n        modelId: 1,\n        isCalculated: false,\n        displayName: 'name',\n        referenceName: 'name',\n        sourceColumnName: 'name',\n        aggregation: null,\n        lineage: null,\n        customExpression: null,\n        type: 'STRING',\n        notNull: true,\n        isPk: false,\n        properties: null,\n      },\n      {\n        id: 3,\n        modelId: 1,\n        isCalculated: true,\n        displayName: 'total_payment',\n        referenceName: 'total_payment',\n        sourceColumnName: 'total_payment',\n        aggregation: 'sum',\n        lineage: JSON.stringify([1, 2, 8]),\n        customExpression: null,\n        type: 'FLOAT',\n        notNull: true,\n        isPk: false,\n        properties: null,\n      },\n      // order columns: id, customer_id, payment_id\n      {\n        id: 4,\n        modelId: 2,\n        isCalculated: false,\n        displayName: 'id',\n        referenceName: 'id',\n        sourceColumnName: 'id',\n        aggregation: null,\n        lineage: null,\n        customExpression: null,\n        type: 'STRING',\n        notNull: true,\n        isPk: true,\n        properties: null,\n      },\n      {\n        id: 5,\n        modelId: 2,\n        isCalculated: false,\n        displayName: 'customer_id',\n        referenceName: 'customer_id',\n        sourceColumnName: 'customer_id',\n        aggregation: null,\n        lineage: null,\n        customExpression: null,\n        type: 'STRING',\n        notNull: true,\n        isPk: false,\n        properties: null,\n      },\n      {\n        id: 6,\n        modelId: 2,\n        isCalculated: false,\n        displayName: 'payment_id',\n        referenceName: 'payment_id',\n        sourceColumnName: 'payment_id',\n        aggregation: null,\n        lineage: null,\n        customExpression: null,\n        type: 'STRING',\n        notNull: true,\n        isPk: false,\n        properties: null,\n      },\n      // payment columns: id, amount\n      {\n        id: 7,\n        modelId: 3,\n        isCalculated: false,\n        displayName: 'id',\n        referenceName: 'id',\n        sourceColumnName: 'id',\n        aggregation: null,\n        lineage: null,\n        customExpression: null,\n        type: 'STRING',\n        notNull: true,\n        isPk: true,\n        properties: null,\n      },\n      {\n        id: 8,\n        modelId: 3,\n        isCalculated: false,\n        displayName: 'amount',\n        referenceName: 'amount',\n        sourceColumnName: 'amount',\n        aggregation: null,\n        lineage: null,\n        customExpression: null,\n        type: 'FLOAT',\n        notNull: true,\n        isPk: false,\n        properties: null,\n      },\n    ] as ModelColumn[];\n    const relations = [\n      {\n        id: 1,\n        projectId: 1,\n        name: 'OrderCustomer',\n        joinType: 'ManyToOne',\n        fromModelId: 2,\n        fromModelName: 'order',\n        fromColumnId: 5,\n        fromColumnName: 'customer_id',\n        toModelId: 1,\n        toModelName: 'customer',\n        toColumnId: 1,\n        toColumnName: 'id',\n      },\n      {\n        id: 2,\n        projectId: 1,\n        name: 'OrderPayment',\n        joinType: 'oneToMany',\n        fromModelId: 2,\n        fromModelName: 'order',\n        fromColumnId: 6,\n        fromColumnName: 'payment_id',\n        toModelId: 3,\n        toModelName: 'payment',\n        toColumnId: 7,\n        toColumnName: 'id',\n      },\n    ];\n    const builderOptions = {\n      project: {\n        schema: 'public',\n        catalog: 'wrenai',\n      },\n      models,\n      columns,\n      relations,\n      relatedModels: models,\n      relatedColumns: columns,\n      relatedRelations: relations,\n    } as MDLBuilderBuildFromOptions;\n    mdlBuilder = new MDLBuilder(builderOptions);\n\n    const manifest = mdlBuilder.build();\n\n    const customerModel = manifest.models.find((m) => m.name === 'customer');\n    const totalPaymentColumn = customerModel.columns.find(\n      (c) => c.name === 'total_payment',\n    );\n    expect(totalPaymentColumn.expression).toEqual(\n      'sum(order.payment.\"amount\")',\n    );\n  });\n\n  it.each(Object.values(DataSourceName))(\n    `should return correct data source type`,\n    (type) => {\n      const project = {\n        id: 1,\n        type,\n        displayName: 'my project',\n        connectionInfo: {\n          projectId: 'bq-project-id',\n          datasetId: 'bq-project-id.my-dataset',\n          credentials: 'my-credential',\n        } as BIG_QUERY_CONNECTION_INFO,\n        catalog: 'wrenai',\n        schema: 'public',\n        sampleDataset: null,\n      } as Project;\n      const models = [] as Model[];\n      const columns = [] as ModelColumn[];\n      const nestedColumns = [] as ModelNestedColumn[];\n      const relations = [] as RelationInfo[];\n      const views = [] as View[];\n      const builderOptions = {\n        project,\n        models,\n        columns,\n        nestedColumns,\n        relations,\n        views,\n      } as MDLBuilderBuildFromOptions;\n      mdlBuilder = new MDLBuilder(builderOptions);\n      const manifest = mdlBuilder.build();\n      expect(manifest.dataSource).toBeDefined();\n      expect(manifest.dataSource).not.toBeNull();\n    },\n  );\n});\n"
  },
  {
    "path": "wren-ui/src/apollo/server/mdl/type.ts",
    "content": "export interface ColumnMDL {\n  name: string; // eg: \"orderkey\", \"custkey\", \"orderstatus\"\n  type?: string; // eg: \"integer\", \"string\", \"relationName\"\n  isCalculated: boolean; // eg: true, false\n  notNull?: boolean; // eg: true, false\n  relationship?: string; //eg: OrdersCustomer\n  properties?: {\n    description?: string; // eg: \"the key of each order\"\n    displayName?: string; // eg: \"Order Key\"\n  };\n  expression?: string; // eg: \"SUM(orders.totalprice)\"\n}\n\nexport interface ModelMDL {\n  name: string; // eg: \"OrdersModel\", \"LineitemModel\"\n  refSql?: string; // eg: \"select * from orders\", \"select * from lineitem\"\n  tableReference?: TableReference;\n  columns?: ColumnMDL[];\n  primaryKey?: string; // eg: \"orderkey\", \"custkey\"\n  cached: boolean; // eg true, false\n  refreshTime?: string; // eg: \"30.00m\"\n  properties?: {\n    description?: string; // eg: \"tpch tiny orders table\"\n    displayName?: string; // eg: \"Orders\"\n  };\n}\n\nexport interface RelationMDL {\n  name: string; // eg: \"OrdersCustomer\"\n  models: string[]; // eg: [\"OrdersModel\", \"CustomerModel\"]\n  joinType: string; // eg: \"MANY_TO_ONE\"\n  condition: string; // eg: \"OrdersModel.custkey = CustomerModel.custkey\"\n  manySideSortKeys?: {\n    name: string; // eg: \"orderkey\"\n    descending: boolean; // eg: false\n  }[];\n  description?: string; // eg: \"the relationship between orders and customers\"\n  properties?: {\n    description?: string; // eg: \"the relationship between orders and customers\"\n  };\n}\n\nexport interface EnumDefinition {\n  name: string; // eg: \"OrderStatus\"\n  values: {\n    name: string; // eg: \"PENDING\", \"PROCESSING\"\n    value: string; // eg: \"pending\", \"processing\"\n    properties?: {\n      description?: string; // eg: \"pending\"\n    };\n  }[];\n  description?: string; // eg: \"the status of an order\"\n  properties?: {\n    description?: string; // eg: \"the status of an order\"\n  };\n}\n\nexport interface ViewMDL {\n  name: string;\n  statement: string;\n  properties?: {\n    displayName?: string;\n    description?: string;\n    viewId?: string;\n    question?: string;\n    summary?: string;\n  };\n}\n\nexport interface Manifest {\n  catalog?: string; // eg: \"test-catalog\"\n  schema?: string; // eg: \"test-schema\"\n  dataSource?: WrenEngineDataSourceType;\n  models?: Partial<ModelMDL>[]; // use partial since Rust version doesn't support null values, we need to remove all the null values\n  relationships?: Partial<RelationMDL>[]; // use partial since Rust version doesn't support null values, we need to remove all the null values\n  enumDefinitions?: Partial<EnumDefinition>[]; // use partial since Rust version doesn't support null values, we need to remove all the null values\n  views?: Partial<ViewMDL>[]; // use partial since Rust version doesn't support null values, we need to remove all the null values\n}\n\nexport interface TableReference {\n  schema?: string;\n  catalog?: string;\n  table: string;\n}\n\nexport enum WrenEngineDataSourceType {\n  ATHENA = 'ATHENA',\n  BIGQUERY = 'BIGQUERY',\n  CANNER = 'CANNER',\n  CLICKHOUSE = 'CLICKHOUSE',\n  MSSQL = 'MSSQL',\n  ORACLE = 'ORACLE',\n  MYSQL = 'MYSQL',\n  POSTGRES = 'POSTGRES',\n  SNOWFLAKE = 'SNOWFLAKE',\n  TRINO = 'TRINO',\n  DUCKDB = 'DUCKDB',\n  REDSHIFT = 'REDSHIFT',\n  DATABRICKS = 'DATABRICKS',\n\n  // accepted by the wren engine, but not supported by the wren ui\n  DATAFUSION = 'DATAFUSION',\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/models/adaptor.ts",
    "content": "import * as Errors from '@server/utils/error';\nimport { Manifest } from '@server/mdl/type';\nimport { ThreadResponse } from '../repositories';\n\n// Add branded types for SQL strings\ntype Brand<T, B> = T & { __brand: B };\n\nexport type DialectSQL = Brand<string, 'DialectSQL'>;\nexport type WrenSQL = Brand<string, 'WrenSQL'>;\n\nexport interface WrenAIError {\n  code: Errors.GeneralErrorCodes;\n  message: string;\n}\n\nexport enum WrenAIDeployStatusEnum {\n  SUCCESS = 'SUCCESS',\n  FAILED = 'FAILED',\n}\n\nexport interface WrenAIDeployResponse {\n  status: WrenAIDeployStatusEnum;\n  error?: string;\n}\n\nexport enum WrenAISystemStatus {\n  INDEXING = 'INDEXING',\n  FINISHED = 'FINISHED',\n  FAILED = 'FAILED',\n}\n\nexport enum WrenAILanguage {\n  EN = 'English',\n  ES = 'Spanish',\n  FR = 'French',\n  ZH_TW = 'Traditional Chinese',\n  ZH_CN = 'Simplified Chinese',\n  DE = 'German',\n  PT = 'Portuguese',\n  RU = 'Russian',\n  JA = 'Japanese',\n  KO = 'Korean',\n  IT = 'Italian',\n  FA_IR = 'Persian',\n  AR = 'Arabic',\n  NL = 'Dutch',\n  AZ_AZ = 'Azerbaijani',\n  TR = 'Turkish',\n}\n\nexport interface DeployData {\n  manifest: Manifest;\n  hash: string;\n}\n\n// ask\nexport interface AskStep {\n  summary: string;\n  sql: string;\n  cteName: string;\n}\n\nexport interface AskHistory {\n  sql: string;\n  question: string;\n}\n\nexport interface ProjectConfigurations {\n  language?: string;\n  timezone?: { name: string };\n}\n\nexport interface AskInput {\n  query: string;\n  deployId: string;\n  histories?: ThreadResponse[];\n  configurations?: ProjectConfigurations;\n}\n\nexport interface AsyncQueryResponse {\n  queryId: string;\n}\n\nexport enum AskResultStatus {\n  UNDERSTANDING = 'UNDERSTANDING',\n  SEARCHING = 'SEARCHING',\n  PLANNING = 'PLANNING',\n  GENERATING = 'GENERATING',\n  CORRECTING = 'CORRECTING',\n  FINISHED = 'FINISHED',\n  FAILED = 'FAILED',\n  STOPPED = 'STOPPED',\n}\n\nexport enum AskResultType {\n  GENERAL = 'GENERAL',\n  TEXT_TO_SQL = 'TEXT_TO_SQL',\n  MISLEADING_QUERY = 'MISLEADING_QUERY',\n}\n\n// if it's view, viewId will be returned as well. It means the candidate is originally saved in mdl as a view.\n// if it's llm, viewId will not be returned. It means the candidate is generated by AI service.\n// if it's sql_pair, sqlpairId will be returned as well. It means the candidate is generated by sql_pair.\nexport enum AskCandidateType {\n  VIEW = 'VIEW',\n  LLM = 'LLM',\n  SQL_PAIR = 'SQL_PAIR',\n}\n\nexport interface AskResponse<R, S> {\n  type: AskResultType | null;\n  status: S;\n  response: R | null;\n  error: WrenAIError | null;\n}\n\nexport interface AskDetailInput {\n  query: string;\n  sql: string;\n  configurations?: ProjectConfigurations;\n}\n\nexport type AskDetailResult = AskResponse<\n  {\n    description: string;\n    steps: AskStep[];\n  },\n  AskResultStatus\n>;\n\nexport type AskResult = AskResponse<\n  Array<{\n    type: AskCandidateType;\n    sql: string;\n    viewId?: number | null;\n    sqlpairId?: number | null;\n  }>,\n  AskResultStatus\n> & {\n  rephrasedQuestion?: string;\n  intentReasoning?: string;\n  sqlGenerationReasoning?: string;\n  retrievedTables?: string[];\n  invalidSql?: string;\n  traceId?: string;\n};\n\nexport enum RecommendationQuestionStatus {\n  GENERATING = 'GENERATING',\n  FINISHED = 'FINISHED',\n  FAILED = 'FAILED',\n}\n\nexport type RecommendationQuestionsInput = {\n  // JSON string of the MDL (Model Definition Language)\n  manifest: Manifest;\n  // Optional list of previous questions\n  previousQuestions?: string[];\n  // Optional project ID\n  projectId?: string;\n  // Optional max number of questions to generate (default: 5)\n  maxQuestions?: number;\n  // Optional max number of categories (default: 3)\n  maxCategories?: number;\n  regenerate?: boolean; // Optional regenerate questions (default: false)\n  // Optional configuration settings\n  configuration?: ProjectConfigurations;\n};\n\nexport type RecommendationQuestion = {\n  question: string;\n  category: string; // category for the question\n  sql: string; // validated sql for this question, can be used in generateAskDetail\n};\n\nexport type RecommendationQuestionsResult = AskResponse<\n  {\n    questions: RecommendationQuestion[];\n  },\n  RecommendationQuestionStatus\n>;\n\n// text-based answer\nexport interface TextBasedAnswerInput {\n  query: string;\n  sql: string;\n  sqlData: any;\n  threadId?: string;\n  userId?: string;\n  configurations?: ProjectConfigurations;\n}\n\nexport enum TextBasedAnswerStatus {\n  PREPROCESSING = 'PREPROCESSING',\n  SUCCEEDED = 'SUCCEEDED',\n  FAILED = 'FAILED',\n}\n\nexport interface TextBasedAnswerResult {\n  status: TextBasedAnswerStatus;\n  numRowsUsedInLLM?: number;\n  error?: WrenAIError;\n}\n\nexport enum ChartStatus {\n  FETCHING = 'FETCHING',\n  GENERATING = 'GENERATING',\n  FINISHED = 'FINISHED',\n  FAILED = 'FAILED',\n  STOPPED = 'STOPPED',\n}\n\nexport enum ChartType {\n  BAR = 'bar',\n  GROUPED_BAR = 'grouped_bar',\n  STACKED_BAR = 'stacked_bar',\n  LINE = 'line',\n  MULTI_LINE = 'multi_line',\n  PIE = 'pie',\n  AREA = 'area',\n}\n\nexport interface ChartInput {\n  query: string;\n  sql: string;\n  projectId?: string;\n  configurations?: ProjectConfigurations;\n}\n\nexport interface ChartAdjustmentOption {\n  chartType: ChartType;\n  xAxis?: string;\n  yAxis?: string;\n  xOffset?: string;\n  color?: string;\n  theta?: string;\n}\n\nexport interface ChartAdjustmentInput {\n  query: string;\n  sql: string;\n  adjustmentOption: ChartAdjustmentOption;\n  chartSchema: Record<string, any>;\n  projectId?: string;\n  configurations?: ProjectConfigurations;\n}\n\nexport interface ChartResponse {\n  reasoning: string;\n  chartType: ChartType;\n  chartSchema: Record<string, any>;\n}\n\nexport interface ChartResult {\n  status: ChartStatus;\n  response?: ChartResponse;\n  error?: WrenAIError;\n}\n\nexport enum SqlPairStatus {\n  INDEXING = 'INDEXING',\n  FINISHED = 'FINISHED',\n  FAILED = 'FAILED',\n}\nexport interface SqlPairResult {\n  status: SqlPairStatus;\n  error?: WrenAIError;\n}\n\nexport interface QuestionInput {\n  sqls: string[];\n  projectId: number;\n  configurations?: ProjectConfigurations;\n}\n\nexport enum QuestionsStatus {\n  GENERATING = 'GENERATING',\n  SUCCEEDED = 'SUCCEEDED',\n  FAILED = 'FAILED',\n}\n\nexport interface QuestionsResult {\n  status: QuestionsStatus;\n  error?: WrenAIError;\n  questions?: string[];\n  trace_id?: string;\n}\n\nexport interface GenerateInstructionInput {\n  id: number;\n  projectId: number;\n  instruction: string;\n  questions: string[];\n  isDefault: boolean;\n}\n\nexport enum InstructionStatus {\n  INDEXING = 'INDEXING',\n  FINISHED = 'FINISHED',\n  FAILED = 'FAILED',\n}\nexport interface InstructionResult {\n  status: InstructionStatus;\n  error?: WrenAIError;\n}\n\n// ask feedback\nexport interface AskFeedbackInput {\n  question: string;\n  tables: string[];\n  sqlGenerationReasoning: string;\n  sql: string;\n  projectId: number;\n  configurations?: ProjectConfigurations;\n}\n\nexport enum AskFeedbackStatus {\n  UNDERSTANDING = 'UNDERSTANDING',\n  GENERATING = 'GENERATING',\n  CORRECTING = 'CORRECTING',\n  FINISHED = 'FINISHED',\n  FAILED = 'FAILED',\n  STOPPED = 'STOPPED',\n}\n\nexport interface AskFeedbackResult {\n  status: AskFeedbackStatus;\n  error?: WrenAIError;\n  response: Array<{\n    type: AskCandidateType.LLM;\n    sql: string;\n  }>;\n  traceId?: string;\n  invalidSql?: string;\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/models/dashboard.ts",
    "content": "import { DashboardItem } from '@server/repositories';\n\nexport interface PreviewItemResponse {\n  data: Record<string, any>[];\n  cacheHit: boolean;\n  cacheCreatedAt: string | null;\n  cacheOverrodeAt: string | null;\n  override: boolean;\n}\n\nexport enum ScheduleFrequencyEnum {\n  WEEKLY = 'WEEKLY',\n  DAILY = 'DAILY',\n  CUSTOM = 'CUSTOM',\n  NEVER = 'NEVER',\n}\n\nexport enum CacheScheduleDayEnum {\n  SUN = 'SUN',\n  MON = 'MON',\n  TUE = 'TUE',\n  WED = 'WED',\n  THU = 'THU',\n  FRI = 'FRI',\n  SAT = 'SAT',\n}\n\nexport interface DashboardSchedule {\n  frequency: ScheduleFrequencyEnum;\n  timezone: string;\n  day: CacheScheduleDayEnum;\n  hour: number;\n  minute: number;\n  cron: string;\n}\n\nexport interface SetDashboardCacheData {\n  cacheEnabled: boolean;\n  schedule: DashboardSchedule | null;\n}\n\nexport interface DetailedDashboard {\n  id: number;\n  projectId: number;\n  name: string;\n  cacheEnabled: boolean;\n  scheduleFrequency: ScheduleFrequencyEnum | null;\n  timezone: string | null; // e.g. 'America/New_York', 'Asia/Taipei'\n  scheduleCron: string | null; // cron expression string\n  nextScheduledAt: string | null; // Next scheduled run timestamp\n  items: DashboardItem[];\n}\n\nexport const DAYS = [\n  CacheScheduleDayEnum.SUN,\n  CacheScheduleDayEnum.MON,\n  CacheScheduleDayEnum.TUE,\n  CacheScheduleDayEnum.WED,\n  CacheScheduleDayEnum.THU,\n  CacheScheduleDayEnum.FRI,\n  CacheScheduleDayEnum.SAT,\n];\n"
  },
  {
    "path": "wren-ui/src/apollo/server/models/index.ts",
    "content": "export * from './model';\nexport * from './instruction';\nexport * from './adaptor';\nexport * from './dashboard';\n"
  },
  {
    "path": "wren-ui/src/apollo/server/models/instruction.ts",
    "content": "export interface InstructionInput {\n  projectId: number;\n  instruction: string;\n  questions: string[];\n  isDefault: boolean;\n}\n\nexport interface UpdateInstructionInput {\n  id: number;\n  projectId: number;\n  instruction: string;\n  questions: string[];\n  isDefault: boolean;\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/models/model.ts",
    "content": "export interface CreateModelData {\n  sourceTableName: string;\n  fields: [string];\n  primaryKey: string;\n}\n\nexport interface UpdateModelData {\n  fields: [string];\n  primaryKey: string;\n}\n\nexport interface NestedColumnMetadataInput {\n  id: number;\n  displayName: string;\n  description: string;\n}\n\nexport interface ColumnMetadataInput {\n  id: number;\n  displayName: string;\n  description: string;\n}\n\nexport interface CalculatedFieldMetadataInput {\n  id: number;\n  description: string;\n}\n\nexport interface RelationshipMetadataInput {\n  id: number;\n  description: string;\n}\n\nexport interface ViewColumnMetadataInput {\n  referenceName: string;\n  description: string;\n}\n\nexport interface UpdateModelMetadataInput {\n  displayName: string;\n  description: string;\n  columns: Array<ColumnMetadataInput>;\n  nestedColumns: Array<NestedColumnMetadataInput>;\n  calculatedFields: Array<CalculatedFieldMetadataInput>;\n  relationships: Array<RelationshipMetadataInput>;\n}\n\nexport interface UpdateViewMetadataInput {\n  displayName: string;\n  description: string;\n  columns: Array<ViewColumnMetadataInput>;\n}\n\nexport enum ExpressionName {\n  ABS = 'ABS',\n  AVG = 'AVG',\n  COUNT = 'COUNT',\n  MAX = 'MAX',\n  MIN = 'MIN',\n  SUM = 'SUM',\n  CBRT = 'CBRT',\n  CEIL = 'CEIL',\n  EXP = 'EXP',\n  FLOOR = 'FLOOR',\n  LN = 'LN',\n  LOG10 = 'LOG10',\n  ROUND = 'ROUND',\n  SIGN = 'SIGN',\n  LENGTH = 'LENGTH',\n  REVERSE = 'REVERSE',\n}\n\nexport interface CreateCalculatedFieldData {\n  modelId: number;\n  name: string; //displayName\n  expression: ExpressionName;\n  lineage: number[];\n}\n\nexport interface UpdateCalculatedFieldData {\n  name: string; //displayName\n  expression: ExpressionName;\n  lineage: number[];\n}\n\nexport interface CheckCalculatedFieldCanQueryData {\n  referenceName: string;\n  expression: ExpressionName;\n  lineage: number[];\n}\n\nexport interface PreviewSQLData {\n  sql: string;\n  projectId?: string;\n  limit?: number;\n  dryRun?: boolean;\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/apiHistoryRepository.ts",
    "content": "import {\n  camelCase,\n  isPlainObject,\n  mapKeys,\n  mapValues,\n  snakeCase,\n} from 'lodash';\nimport { BaseRepository, IBasicRepository } from './baseRepository';\nimport { Knex } from 'knex';\n\nexport enum ApiType {\n  GENERATE_SQL = 'GENERATE_SQL',\n  RUN_SQL = 'RUN_SQL',\n  GENERATE_VEGA_CHART = 'GENERATE_VEGA_CHART',\n  GENERATE_SUMMARY = 'GENERATE_SUMMARY',\n  ASK = 'ASK',\n  GET_INSTRUCTIONS = 'GET_INSTRUCTIONS',\n  CREATE_INSTRUCTION = 'CREATE_INSTRUCTION',\n  UPDATE_INSTRUCTION = 'UPDATE_INSTRUCTION',\n  DELETE_INSTRUCTION = 'DELETE_INSTRUCTION',\n  GET_SQL_PAIRS = 'GET_SQL_PAIRS',\n  CREATE_SQL_PAIR = 'CREATE_SQL_PAIR',\n  UPDATE_SQL_PAIR = 'UPDATE_SQL_PAIR',\n  DELETE_SQL_PAIR = 'DELETE_SQL_PAIR',\n  GET_MODELS = 'GET_MODELS',\n  STREAM_ASK = 'STREAM_ASK',\n  STREAM_GENERATE_SQL = 'STREAM_GENERATE_SQL',\n}\n\nexport interface ApiHistory {\n  id?: string;\n  projectId: number;\n  apiType: ApiType;\n  threadId?: string;\n  headers?: Record<string, string>;\n  requestPayload?: Record<string, any>;\n  responsePayload?: Record<string, any>;\n  statusCode?: number;\n  durationMs?: number;\n  createdAt?: string;\n  updatedAt?: string;\n}\n\nexport interface PaginationOptions {\n  offset: number;\n  limit: number;\n  orderBy?: Record<string, 'asc' | 'desc'>;\n}\n\nexport interface IApiHistoryRepository extends IBasicRepository<ApiHistory> {\n  count(\n    filter?: Partial<ApiHistory>,\n    dateFilter?: { startDate?: Date; endDate?: Date },\n  ): Promise<number>;\n  findAllWithPagination(\n    filter?: Partial<ApiHistory>,\n    dateFilter?: { startDate?: Date; endDate?: Date },\n    pagination?: PaginationOptions,\n  ): Promise<ApiHistory[]>;\n}\n\nexport class ApiHistoryRepository\n  extends BaseRepository<ApiHistory>\n  implements IApiHistoryRepository\n{\n  private readonly jsonbColumns = [\n    'headers',\n    'requestPayload',\n    'responsePayload',\n  ];\n\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'api_history' });\n  }\n\n  /**\n   * Count API history records with filtering\n   */\n  public async count(\n    filter?: Partial<ApiHistory>,\n    dateFilter?: { startDate?: Date; endDate?: Date },\n  ): Promise<number> {\n    let query = this.knex(this.tableName).count('id as count');\n\n    if (filter) {\n      query = query.where(this.transformToDBData(filter));\n    }\n\n    if (dateFilter) {\n      if (dateFilter.startDate) {\n        query = query.where('created_at', '>=', dateFilter.startDate);\n      }\n\n      if (dateFilter.endDate) {\n        query = query.where('created_at', '<=', dateFilter.endDate);\n      }\n    }\n\n    const result = await query;\n    return parseInt(result[0].count as string, 10);\n  }\n\n  /**\n   * Find API history records with pagination\n   */\n  public async findAllWithPagination(\n    filter?: Partial<ApiHistory>,\n    dateFilter?: { startDate?: Date; endDate?: Date },\n    pagination?: PaginationOptions,\n  ): Promise<ApiHistory[]> {\n    let query = this.knex(this.tableName).select('*');\n\n    if (filter) {\n      query = query.where(this.transformToDBData(filter));\n    }\n\n    if (dateFilter) {\n      if (dateFilter.startDate) {\n        query = query.where('created_at', '>=', dateFilter.startDate);\n      }\n\n      if (dateFilter.endDate) {\n        query = query.where('created_at', '<=', dateFilter.endDate);\n      }\n    }\n\n    if (pagination) {\n      if (pagination.orderBy) {\n        Object.entries(pagination.orderBy).forEach(([field, direction]) => {\n          query = query.orderBy(this.camelToSnakeCase(field), direction);\n        });\n      } else {\n        // Default sort by created_at desc\n        query = query.orderBy('created_at', 'desc');\n      }\n\n      query = query.offset(pagination.offset).limit(pagination.limit);\n    }\n\n    const result = await query;\n    return result.map(this.transformFromDBData);\n  }\n\n  protected override transformFromDBData = (data: any): ApiHistory => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const camelCaseData = mapKeys(data, (_value, key) => camelCase(key));\n    const formattedData = mapValues(camelCaseData, (value, key) => {\n      if (this.jsonbColumns.includes(key)) {\n        // The value from Sqlite will be string type, while the value from PG is JSON object\n        if (typeof value === 'string') {\n          if (!value) return value;\n          try {\n            return JSON.parse(value);\n          } catch (error) {\n            console.error(`Failed to parse JSON for ${key}:`, error);\n            return value; // Return raw value if parsing fails\n          }\n        } else {\n          return value;\n        }\n      }\n      return value;\n    }) as ApiHistory;\n    return formattedData;\n  };\n\n  protected override transformToDBData = (data: any) => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const transformedData = mapValues(data, (value, key) => {\n      if (this.jsonbColumns.includes(key)) {\n        return JSON.stringify(value);\n      } else {\n        return value;\n      }\n    });\n    return mapKeys(transformedData, (_value, key) => snakeCase(key));\n  };\n\n  /**\n   * Convert camelCase to snake_case for DB column names\n   */\n  private camelToSnakeCase(str: string): string {\n    return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/askingTaskRepository.ts",
    "content": "import { Knex } from 'knex';\nimport { BaseRepository, IBasicRepository } from './baseRepository';\nimport {\n  camelCase,\n  isPlainObject,\n  mapKeys,\n  mapValues,\n  snakeCase,\n} from 'lodash';\nimport { AskFeedbackResult, AskResult } from '../models/adaptor';\n\nexport type AskingTaskDetail =\n  | AskResult\n  | (AskFeedbackResult & {\n      adjustment?: boolean;\n    });\n\nexport interface AskingTask {\n  id: number;\n  queryId: string;\n  question?: string;\n  detail?: AskingTaskDetail;\n  threadId?: number;\n  threadResponseId?: number;\n  createdAt: Date;\n  updatedAt: Date;\n}\n\nexport interface IAskingTaskRepository extends IBasicRepository<AskingTask> {\n  findByQueryId(queryId: string): Promise<AskingTask | null>;\n}\n\nexport class AskingTaskRepository\n  extends BaseRepository<AskingTask>\n  implements IAskingTaskRepository\n{\n  private readonly jsonbColumns = ['detail'];\n\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'asking_task' });\n  }\n\n  public async findByQueryId(queryId: string): Promise<AskingTask | null> {\n    return this.findOneBy({ queryId });\n  }\n\n  protected override transformFromDBData = (data: any) => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const camelCaseData = mapKeys(data, (_value, key) => camelCase(key));\n    const transformData = mapValues(camelCaseData, (value, key) => {\n      if (this.jsonbColumns.includes(key)) {\n        if (typeof value === 'string') {\n          return value ? JSON.parse(value) : value;\n        }\n        return value;\n      }\n      return value;\n    });\n    return transformData as AskingTask;\n  };\n\n  protected override transformToDBData = (data: any) => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const transformedData = mapValues(data, (value, key) => {\n      if (this.jsonbColumns.includes(key)) {\n        return JSON.stringify(value);\n      } else {\n        return value;\n      }\n    });\n    return mapKeys(transformedData, (_value, key) => snakeCase(key));\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/baseRepository.ts",
    "content": "import { Knex } from 'knex';\nimport { camelCase, isPlainObject, mapKeys, snakeCase } from 'lodash';\n\nexport interface IQueryOptions {\n  tx?: Knex.Transaction;\n  order?: string;\n  limit?: number;\n}\n\nexport interface IBasicRepository<T> {\n  transaction: () => Promise<Knex.Transaction>;\n  commit: (tx: Knex.Transaction) => Promise<void>;\n  rollback: (tx: Knex.Transaction) => Promise<void>;\n  findOneBy: (\n    filter: Partial<T>,\n    queryOptions?: IQueryOptions,\n  ) => Promise<T | null>;\n  findAllBy: (filter: Partial<T>, queryOptions?: IQueryOptions) => Promise<T[]>;\n  findAll: (queryOptions?: IQueryOptions) => Promise<T[]>;\n  createOne: (data: Partial<T>, queryOptions?: IQueryOptions) => Promise<T>;\n  createMany: (\n    data: Partial<T>[],\n    queryOptions?: IQueryOptions,\n  ) => Promise<T[]>;\n  updateOne: (\n    id: string | number,\n    data: Partial<T>,\n    queryOptions?: IQueryOptions,\n  ) => Promise<T>;\n  deleteOne: (\n    id: string | number,\n    queryOptions?: IQueryOptions,\n  ) => Promise<number>;\n  deleteMany: (\n    ids: (string | number)[],\n    queryOptions?: IQueryOptions,\n  ) => Promise<number>;\n  deleteAllBy: (\n    where: Partial<T>,\n    queryOptions?: IQueryOptions,\n  ) => Promise<number>;\n}\n\nexport class BaseRepository<T> implements IBasicRepository<T> {\n  protected knex: Knex;\n  protected tableName: string;\n\n  constructor({ knexPg, tableName }: { knexPg: Knex; tableName: string }) {\n    this.knex = knexPg;\n    this.tableName = tableName;\n  }\n\n  public async transaction() {\n    return await this.knex.transaction();\n  }\n\n  public async commit(tx: Knex.Transaction) {\n    await tx.commit();\n  }\n\n  public async rollback(tx: Knex.Transaction) {\n    await tx.rollback();\n  }\n\n  public async findOneBy(filter: Partial<T>, queryOptions?: IQueryOptions) {\n    const executer = queryOptions?.tx ? queryOptions.tx : this.knex;\n    const query = executer(this.tableName).where(\n      this.transformToDBData(filter),\n    );\n    if (queryOptions?.limit) {\n      query.limit(queryOptions.limit);\n    }\n    const result = await query;\n    return result && result.length > 0\n      ? this.transformFromDBData(result[0])\n      : null;\n  }\n\n  public async findAllBy(filter: Partial<T>, queryOptions?: IQueryOptions) {\n    const executer = queryOptions?.tx ? queryOptions.tx : this.knex;\n    // format filter keys to snake_case\n\n    const query = executer(this.tableName).where(\n      this.transformToDBData(filter),\n    );\n    if (queryOptions?.order) {\n      query.orderBy(queryOptions.order);\n    }\n    const result = await query;\n    return result.map(this.transformFromDBData);\n  }\n\n  public async findAll(queryOptions?: IQueryOptions) {\n    const executer = queryOptions?.tx ? queryOptions.tx : this.knex;\n    const query = executer(this.tableName);\n    if (queryOptions?.order) {\n      query.orderBy(queryOptions.order);\n    }\n    if (queryOptions?.limit) {\n      query.limit(queryOptions.limit);\n    }\n    const result = await query;\n    return result.map(this.transformFromDBData);\n  }\n\n  public async createOne(data: Partial<T>, queryOptions?: IQueryOptions) {\n    const executer = queryOptions?.tx ? queryOptions.tx : this.knex;\n    const [result] = await executer(this.tableName)\n      .insert(this.transformToDBData(data))\n      .returning('*');\n    return this.transformFromDBData(result);\n  }\n\n  public async createMany(data: Partial<T>[], queryOptions?: IQueryOptions) {\n    const executer = queryOptions?.tx ? queryOptions.tx : this.knex;\n    const batchSize = 100;\n    const batchCount = Math.ceil(data.length / batchSize);\n    const result = [];\n    for (let i = 0; i < batchCount; i++) {\n      const start = i * batchSize;\n      const end = Math.min((i + 1) * batchSize, data.length);\n      const batchValues = data.slice(start, end);\n      const chunk = await executer(this.tableName)\n        .insert(batchValues.map(this.transformToDBData))\n        .returning('*');\n      result.push(...chunk);\n    }\n\n    return result.map((data) => this.transformFromDBData(data));\n  }\n\n  public async updateOne(\n    id: string | number,\n    data: Partial<T>,\n    queryOptions?: IQueryOptions,\n  ) {\n    const executer = queryOptions?.tx ? queryOptions.tx : this.knex;\n    const [result] = await executer(this.tableName)\n      .where({ id })\n      .update(this.transformToDBData(data))\n      .returning('*');\n    return this.transformFromDBData(result);\n  }\n\n  public async deleteOne(id: string, queryOptions?: IQueryOptions) {\n    const executer = queryOptions?.tx ? queryOptions.tx : this.knex;\n    const builder = executer.from(this.tableName).where({ id }).delete();\n    return await builder;\n  }\n\n  public async deleteMany(\n    ids: (string | number)[],\n    queryOptions?: IQueryOptions,\n  ) {\n    const executer = queryOptions?.tx ? queryOptions.tx : this.knex;\n    const builder = executer.from(this.tableName).whereIn('id', ids).delete();\n    return await builder;\n  }\n\n  public deleteAllBy = async (\n    where: Partial<T>,\n    queryOptions?: IQueryOptions,\n  ) => {\n    const executer = queryOptions?.tx ? queryOptions.tx : this.knex;\n    const builder = executer(this.tableName)\n      .where(this.transformToDBData(where))\n      .delete();\n    return await builder;\n  };\n\n  protected transformToDBData = (data: Partial<T>) => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    return mapKeys(data, (_value, key) => snakeCase(key));\n  };\n\n  protected transformFromDBData = (data: any): T => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const camelCaseData = mapKeys(data, (_value, key) => camelCase(key));\n    return camelCaseData as T;\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/dashboardItemRefreshJobRepository.ts",
    "content": "import { Knex } from 'knex';\nimport { BaseRepository, IBasicRepository } from './baseRepository';\n\nexport enum DashboardCacheRefreshStatus {\n  IN_PROGRESS = 'in_progress',\n  SUCCESS = 'success',\n  FAILED = 'failed',\n}\n\nexport interface DashboardItemRefreshJob {\n  id: number;\n  hash: string;\n  dashboardId: number;\n  dashboardItemId: number;\n  startedAt: Date;\n  finishedAt: Date | null;\n  status: DashboardCacheRefreshStatus;\n  errorMessage: string | null;\n  createdAt: Date;\n  updatedAt: Date;\n}\n\nexport interface IDashboardItemRefreshJobRepository\n  extends IBasicRepository<DashboardItemRefreshJob> {}\n\nexport class DashboardItemRefreshJobRepository\n  extends BaseRepository<DashboardItemRefreshJob>\n  implements IDashboardItemRefreshJobRepository\n{\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'dashboard_item_refresh_job' });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/dashboardItemRepository.ts",
    "content": "import { Knex } from 'knex';\nimport { BaseRepository, IBasicRepository } from './baseRepository';\nimport {\n  camelCase,\n  isPlainObject,\n  mapKeys,\n  mapValues,\n  snakeCase,\n} from 'lodash';\n\nexport enum DashboardItemType {\n  // AI chart types, refer to ChartType in adaptor.ts\n  AREA = 'AREA',\n  BAR = 'BAR',\n  GROUPED_BAR = 'GROUPED_BAR',\n  LINE = 'LINE',\n  PIE = 'PIE',\n  STACKED_BAR = 'STACKED_BAR',\n  // other types\n  TABLE = 'TABLE',\n  NUMBER = 'NUMBER',\n}\n\nexport interface DashboardItemLayout {\n  x: number;\n  y: number;\n  w: number;\n  h: number;\n}\n\nexport interface DashboardItemDetail {\n  sql: string;\n  chartSchema?: Record<string, any>;\n}\n\nexport interface DashboardItem {\n  id: number;\n  dashboardId: number;\n  type: DashboardItemType;\n  layout: DashboardItemLayout;\n  detail: DashboardItemDetail;\n  displayName?: string;\n}\n\nexport interface IDashboardItemRepository\n  extends IBasicRepository<DashboardItem> {}\n\nexport class DashboardItemRepository\n  extends BaseRepository<DashboardItem>\n  implements IDashboardItemRepository\n{\n  private readonly jsonbColumns = ['layout', 'detail'];\n\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'dashboard_item' });\n  }\n\n  protected override transformFromDBData = (data: any) => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const camelCaseData = mapKeys(data, (_value, key) => camelCase(key));\n    const transformData = mapValues(camelCaseData, (value, key) => {\n      if (this.jsonbColumns.includes(key)) {\n        if (typeof value === 'string') {\n          return value ? JSON.parse(value) : value;\n        } else {\n          return value;\n        }\n      }\n      return value;\n    });\n    return transformData as DashboardItem;\n  };\n\n  protected override transformToDBData = (data: any) => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const transformedData = mapValues(data, (value, key) => {\n      if (this.jsonbColumns.includes(key)) {\n        return JSON.stringify(value);\n      } else {\n        return value;\n      }\n    });\n    return mapKeys(transformedData, (_value, key) => snakeCase(key));\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/dashboardRepository.ts",
    "content": "import { Knex } from 'knex';\nimport { BaseRepository, IBasicRepository } from './baseRepository';\nimport { ScheduleFrequencyEnum } from '@server/models/dashboard';\n\nexport interface Dashboard {\n  id: number;\n  projectId: number;\n  name: string;\n  cacheEnabled: boolean;\n  scheduleFrequency: ScheduleFrequencyEnum | null;\n  scheduleTimezone: string | null; // e.g. 'America/New_York', 'Asia/Taipei'\n  scheduleCron: string | null; // cron expression string\n  nextScheduledAt: Date | null; // Next scheduled run timestamp\n}\n\nexport interface IDashboardRepository extends IBasicRepository<Dashboard> {}\n\nexport class DashboardRepository\n  extends BaseRepository<Dashboard>\n  implements IDashboardRepository\n{\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'dashboard' });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/deployLogRepository.ts",
    "content": "import { Knex } from 'knex';\nimport { BaseRepository, IBasicRepository } from './baseRepository';\nimport { camelCase, isPlainObject, mapKeys, mapValues } from 'lodash';\n\nexport interface Deploy {\n  id: number; // ID\n  projectId: number; // Reference to project.id\n  manifest: object; // Model manifest\n  hash: string;\n  status: string; // Deploy status\n  error: string; // Error message\n}\n\nexport enum DeployStatusEnum {\n  IN_PROGRESS = 'IN_PROGRESS',\n  SUCCESS = 'SUCCESS',\n  FAILED = 'FAILED',\n}\n\nexport interface IDeployLogRepository extends IBasicRepository<Deploy> {\n  findLastProjectDeployLog(projectId: number): Promise<Deploy | null>;\n  findInProgressProjectDeployLog(projectId: number): Promise<Deploy | null>;\n}\n\nexport class DeployLogRepository\n  extends BaseRepository<Deploy>\n  implements IDeployLogRepository\n{\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'deploy_log' });\n  }\n\n  public async findLastProjectDeployLog(projectId: number) {\n    const res = await this.knex\n      .select('*')\n      .from(this.tableName)\n      .where(\n        this.transformToDBData({ projectId, status: DeployStatusEnum.SUCCESS }),\n      )\n      .orderBy('created_at', 'desc')\n      .first();\n    return (res && this.transformFromDBData(res)) || null;\n  }\n\n  public async findInProgressProjectDeployLog(projectId: number) {\n    const res = await this.knex\n      .select('*')\n      .from(this.tableName)\n      .where(\n        this.transformToDBData({\n          projectId,\n          status: DeployStatusEnum.IN_PROGRESS,\n        }),\n      )\n      .orderBy('created_at', 'desc')\n      .first();\n    return (res && this.transformFromDBData(res)) || null;\n  }\n\n  public override transformFromDBData: (data: any) => Deploy = (data: any) => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const camelCaseData = mapKeys(data, (_value, key) => camelCase(key));\n    const formattedData = mapValues(camelCaseData, (value, key) => {\n      if (['manifest'].includes(key)) {\n        // sqlite return a string for json field, but postgres return an object\n        return typeof value === 'string' ? JSON.parse(value) : value;\n      }\n      return value;\n    });\n    return formattedData as Deploy;\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/index.ts",
    "content": "export * from './baseRepository';\nexport * from './learningRepository';\nexport * from './modelRepository';\nexport * from './projectRepository';\nexport * from './modelColumnRepository';\nexport * from './modelNestedColumnRepository';\nexport * from './relationshipRepository';\nexport * from './metricsRepository';\nexport * from './metricsMeasureRepository';\nexport * from './deployLogRepository';\nexport * from './viewRepository';\nexport * from './threadRepository';\nexport * from './threadResponseRepository';\nexport * from './schemaChangeRepository';\nexport * from './dashboardRepository';\nexport * from './dashboardItemRepository';\nexport * from './sqlPairRepository';\nexport * from './askingTaskRepository';\nexport * from './instructionRepository';\nexport * from './apiHistoryRepository';\nexport * from './dashboardItemRefreshJobRepository';\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/instructionRepository.ts",
    "content": "import { Knex } from 'knex';\nimport { BaseRepository, IBasicRepository } from './baseRepository';\nimport {\n  camelCase,\n  isPlainObject,\n  mapKeys,\n  mapValues,\n  snakeCase,\n} from 'lodash';\n\nexport interface Instruction {\n  id: number;\n  projectId: number;\n  instruction: string;\n  questions: string[];\n  isDefault: boolean;\n  createdAt: string;\n  updatedAt: string;\n}\n\nexport interface IInstructionRepository extends IBasicRepository<Instruction> {}\n\nexport class InstructionRepository\n  extends BaseRepository<Instruction>\n  implements IInstructionRepository\n{\n  private readonly jsonbColumns = ['questions'];\n\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'instruction' });\n  }\n\n  protected override transformFromDBData = (data: any) => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const camelCaseData = mapKeys(data, (_value, key) => camelCase(key));\n    const transformData = mapValues(camelCaseData, (value, key) => {\n      if (this.jsonbColumns.includes(key)) {\n        if (typeof value === 'string') {\n          return value ? JSON.parse(value) : value;\n        } else {\n          return value;\n        }\n      }\n      return value;\n    });\n    return transformData as Instruction;\n  };\n\n  protected override transformToDBData = (data: any) => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const transformedData = mapValues(data, (value, key) => {\n      if (this.jsonbColumns.includes(key)) {\n        return JSON.stringify(value);\n      } else {\n        return value;\n      }\n    });\n    return mapKeys(transformedData, (_value, key) => snakeCase(key));\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/learningRepository.ts",
    "content": "import { Knex } from 'knex';\nimport { BaseRepository, IBasicRepository } from './baseRepository';\nimport {\n  camelCase,\n  isPlainObject,\n  mapKeys,\n  mapValues,\n  snakeCase,\n} from 'lodash';\n\nexport interface Learning {\n  id: number; // ID\n  userId: string; // Reference to config userUUID\n  paths: string[]; // The learning paths, array of learning stories\n}\n\nexport interface ILearningRepository extends IBasicRepository<Learning> {}\n\nexport class LearningRepository\n  extends BaseRepository<Learning>\n  implements ILearningRepository\n{\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'learning' });\n  }\n\n  protected override transformToDBData = (data: any) => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const transformedData = mapValues(data, (value, key) => {\n      if (['paths'].includes(key)) {\n        return value ? JSON.stringify(value) : null;\n      }\n      return value;\n    });\n    return mapKeys(transformedData, (_value, key) => snakeCase(key));\n  };\n\n  protected override transformFromDBData = (data: any): Learning => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const camelCaseData = mapKeys(data, (_value, key) => camelCase(key));\n    const formattedData = mapValues(camelCaseData, (value, key) => {\n      if (['paths'].includes(key)) {\n        // The value from Sqlite will be string type, while the value from PG is JSON object\n        if (typeof value === 'string') {\n          return value ? JSON.parse(value) : value;\n        } else {\n          return value;\n        }\n      }\n      return value;\n    }) as Learning;\n    return formattedData;\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/metricsMeasureRepository.ts",
    "content": "import { Knex } from 'knex';\nimport { BaseRepository, IBasicRepository } from './baseRepository';\n\nexport interface MetricMeasure {\n  id: number; // ID\n  metricId: number; // Reference to metric ID\n  name: string; // Measure name\n  expression: string; // Expression for the measure\n  granularity?: string; // Granularity for the measure, eg: \"day\", \"hour\", \"minute\", \"year\"\n}\n\nexport interface IMetricMeasureRepository\n  extends IBasicRepository<MetricMeasure> {}\n\nexport class MetricMeasureRepository\n  extends BaseRepository<MetricMeasure>\n  implements IMetricMeasureRepository\n{\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'metric_measure' });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/metricsRepository.ts",
    "content": "import { Knex } from 'knex';\nimport { BaseRepository, IBasicRepository } from './baseRepository';\n\nexport interface Metric {\n  id: number; // ID\n  projectId: number; // Reference to project.id\n  name: string; // Metric name\n  type: string; // Metric type, ex: \"simple\" or \"cumulative\"\n  cached: boolean; // Model is cached or not\n  refreshTime?: string; // Contain a number followed by a time unit (ns, us, ms, s, m, h, d). For example, \"2h\"\n\n  // metric can based on model or another metric\n  modelId?: number; // Reference to model.id\n  metricId?: number; // Reference to metric.id\n  properties?: string; // Metric properties, a json string, the description and displayName should be stored here\n}\n\nexport interface IMetricRepository extends IBasicRepository<Metric> {}\n\nexport class MetricRepository\n  extends BaseRepository<Metric>\n  implements IMetricRepository\n{\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'metric' });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/modelColumnRepository.ts",
    "content": "import { Knex } from 'knex';\nimport {\n  BaseRepository,\n  IBasicRepository,\n  IQueryOptions,\n} from './baseRepository';\n\nexport interface ModelColumn {\n  id: number; // ID\n  modelId: number; // Reference to model ID\n  isCalculated: boolean; // Is calculated field\n  displayName: string; // Column name displayed in UI\n  referenceName: string; // The name used in the MDL structure and when querying the data\n  sourceColumnName: string; // The column name in the datasource\n  aggregation?: string; // Expression for the column, could be custom field or calculated field expression\n  lineage?: string; // The selected field in calculated field, array of ids\n  customExpression?: string; // For custom field or custom expression of calculated field\n  type: string; // Data type, refer to the column type in the datasource\n  notNull: boolean; // Is not null\n  isPk: boolean; // Is primary key of the table\n  properties?: string; // Column properties, a json string, the description and displayName should be stored here\n}\n\nexport interface IModelColumnRepository extends IBasicRepository<ModelColumn> {\n  findColumnsByModelIds(\n    modelIds: number[],\n    queryOptions?: IQueryOptions,\n  ): Promise<ModelColumn[]>;\n  findColumnsByIds(\n    ids: number[],\n    queryOptions?: IQueryOptions,\n  ): Promise<ModelColumn[]>;\n  deleteByModelIds(\n    modelIds: number[],\n    queryOptions?: IQueryOptions,\n  ): Promise<void>;\n  resetModelPrimaryKey(modelId: number): Promise<void>;\n  setModelPrimaryKey(modelId: number, sourceColumnName: string): Promise<void>;\n  deleteAllBySourceColumnNames(\n    modelId: number,\n    sourceColumnNames: string[],\n    queryOptions?: IQueryOptions,\n  ): Promise<number>;\n  deleteAllByColumnIds(\n    columnIds: number[],\n    queryOptions?: IQueryOptions,\n  ): Promise<void>;\n}\n\nexport class ModelColumnRepository\n  extends BaseRepository<ModelColumn>\n  implements IModelColumnRepository\n{\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'model_column' });\n  }\n\n  public async findColumnsByModelIds(modelIds, queryOptions?: IQueryOptions) {\n    if (queryOptions && queryOptions.tx) {\n      const { tx } = queryOptions;\n      const result = await tx(this.tableName)\n        .whereIn('model_id', modelIds)\n        .select('*');\n      return result.map((r) => this.transformFromDBData(r));\n    }\n    const result = await this.knex<ModelColumn>('model_column')\n      .whereIn('model_id', modelIds)\n      .select('*');\n    return result.map((r) => this.transformFromDBData(r));\n  }\n\n  public async findColumnsByIds(ids: number[], queryOptions?: IQueryOptions) {\n    if (queryOptions && queryOptions.tx) {\n      const { tx } = queryOptions;\n      const result = await tx(this.tableName).whereIn('id', ids).select('*');\n      return result.map((r) => this.transformFromDBData(r));\n    }\n    const result = await this.knex<ModelColumn>('model_column')\n      .whereIn('id', ids)\n      .select('*');\n    return result.map((r) => this.transformFromDBData(r));\n  }\n\n  public async deleteByModelIds(\n    modelIds: number[],\n    queryOptions?: IQueryOptions,\n  ) {\n    if (queryOptions && queryOptions.tx) {\n      const { tx } = queryOptions;\n      await tx(this.tableName).whereIn('model_id', modelIds).delete();\n      return;\n    }\n    await this.knex<ModelColumn>('model_column')\n      .whereIn('model_id', modelIds)\n      .delete();\n  }\n\n  public async resetModelPrimaryKey(modelId: number) {\n    await this.knex<ModelColumn>('model_column')\n      .where(this.transformToDBData({ modelId }))\n      .update(this.transformToDBData({ isPk: false }));\n  }\n  public async setModelPrimaryKey(modelId: number, sourceColumnName: string) {\n    await this.knex<ModelColumn>('model_column')\n      .where(this.transformToDBData({ modelId, sourceColumnName }))\n      .update(this.transformToDBData({ isPk: true }));\n  }\n\n  public async deleteAllBySourceColumnNames(\n    modelId: number,\n    sourceColumnNames: string[],\n    queryOptions?: IQueryOptions,\n  ): Promise<number> {\n    const executer = queryOptions?.tx ? queryOptions.tx : this.knex;\n    const builder = executer(this.tableName)\n      .where(this.transformToDBData({ modelId }))\n      .whereIn('source_column_name', sourceColumnNames)\n      .delete();\n    return await builder;\n  }\n\n  public async deleteAllByColumnIds(\n    columnIds: number[],\n    queryOptions?: IQueryOptions,\n  ): Promise<void> {\n    const executer = queryOptions?.tx ? queryOptions.tx : this.knex;\n    await executer<ModelColumn>(this.tableName)\n      .whereIn('id', columnIds)\n      .delete();\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/modelNestedColumnRepository.ts",
    "content": "import { Knex } from 'knex';\nimport { BaseRepository, IBasicRepository } from './baseRepository';\nimport {\n  camelCase,\n  isPlainObject,\n  mapKeys,\n  mapValues,\n  snakeCase,\n} from 'lodash';\n\nexport interface ModelNestedColumn {\n  id: number; // ID\n  modelId: number; // Reference to model ID\n  columnId: number; // Reference to column ID\n  columnPath: string[];\n  displayName: string; // Nested column name displayed in UI\n  referenceName: string; // The name used in the MDL structure and when querying the data\n  sourceColumnName: string; // The nested column name in the datasource\n  type: string; // Data type, refer to the nested column type in the datasource\n  properties?: Record<string, any>; // Nested column properties, a json string, the description should be stored here\n}\n\nexport interface IModelNestedColumnRepository\n  extends IBasicRepository<ModelNestedColumn> {\n  findNestedColumnsByModelIds(modelIds: number[]): Promise<ModelNestedColumn[]>;\n  findNestedColumnsByIds(ids: number[]): Promise<ModelNestedColumn[]>;\n}\n\nexport class ModelNestedColumnRepository\n  extends BaseRepository<ModelNestedColumn>\n  implements IModelNestedColumnRepository\n{\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'model_nested_column' });\n  }\n\n  public findNestedColumnsByModelIds = async (modelIds: number[]) => {\n    const result = await this.knex(this.tableName)\n      .select('*')\n      .whereIn('model_id', modelIds);\n    return result.map((r) => this.transformFromDBData(r));\n  };\n\n  public findNestedColumnsByIds = async (ids: number[]) => {\n    const result = await this.knex(this.tableName)\n      .select('*')\n      .whereIn('id', ids);\n    return result.map((r) => this.transformFromDBData(r));\n  };\n\n  protected override transformToDBData = (data: any) => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const transformedData = mapValues(data, (value, key) => {\n      if (['columnPath', 'properties'].includes(key)) {\n        return value ? JSON.stringify(value) : null;\n      }\n      return value;\n    });\n    return mapKeys(transformedData, (_value, key) => snakeCase(key));\n  };\n\n  protected override transformFromDBData = (data: any): ModelNestedColumn => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const camelCaseData = mapKeys(data, (_value, key) => camelCase(key));\n    const formattedData = mapValues(camelCaseData, (value, key) => {\n      if (['columnPath', 'properties'].includes(key)) {\n        // The value from Sqlite will be string type, while the value from PG is JSON object\n        if (typeof value === 'string') {\n          return value ? JSON.parse(value) : value;\n        } else {\n          return value;\n        }\n      }\n      return value;\n    }) as ModelNestedColumn;\n    return formattedData;\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/modelRepository.ts",
    "content": "import { Knex } from 'knex';\nimport {\n  BaseRepository,\n  IBasicRepository,\n  IQueryOptions,\n} from './baseRepository';\n\nexport interface Model {\n  id: number; // ID\n  projectId: number; // Reference to project.id\n  displayName: string; // Model name displayed in UI\n  sourceTableName: string; // the table name in the datasource\n  referenceName: string; // the name used in the MDL structure\n  refSql: string; // Reference SQL\n  cached: boolean; // Model is cached or not\n  refreshTime: string | null; // Contain a number followed by a time unit (ns, us, ms, s, m, h, d). For example, \"2h\"\n  properties: string | null; // Model properties, a json string, the description and displayName should be stored here\n}\n\nexport interface IModelRepository extends IBasicRepository<Model> {\n  findAllByIds(ids: number[]): Promise<Model[]>;\n  deleteAllBySourceTableNames(\n    sourceTableNames: string[],\n    queryOptions?: IQueryOptions,\n  ): Promise<number>;\n}\n\nexport class ModelRepository\n  extends BaseRepository<Model>\n  implements IModelRepository\n{\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'model' });\n  }\n  public async findAllByIds(ids: number[]) {\n    const res = await this.knex<Model>(this.tableName).whereIn('id', ids);\n    return res.map((r) => this.transformFromDBData(r));\n  }\n\n  public async deleteAllBySourceTableNames(\n    sourceTableNames: string[],\n    queryOptions?: IQueryOptions,\n  ) {\n    const executer = queryOptions?.tx ? queryOptions.tx : this.knex;\n    const builder = executer(this.tableName)\n      .whereIn('source_table_name', sourceTableNames)\n      .delete();\n    return await builder;\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/projectRepository.ts",
    "content": "import { Knex } from 'knex';\nimport { BaseRepository, IBasicRepository } from './baseRepository';\nimport {\n  camelCase,\n  isPlainObject,\n  mapKeys,\n  mapValues,\n  snakeCase,\n  isEmpty,\n} from 'lodash';\nimport { DataSourceName } from '@server/types';\nimport {\n  IbisRedshiftConnectionType,\n  IbisDatabricksConnectionType,\n} from '@server/adaptors/ibisAdaptor';\n\nexport interface BIG_QUERY_CONNECTION_INFO {\n  projectId: string;\n  datasetId: string;\n  credentials: string;\n}\nexport interface POSTGRES_CONNECTION_INFO {\n  host: string;\n  port: number;\n  user: string;\n  password: string;\n  database: string;\n  ssl: boolean;\n}\n\nexport interface MYSQL_CONNECTION_INFO {\n  host: string;\n  port: number;\n  user: string;\n  password: string;\n  database: string;\n  ssl: boolean;\n}\n\nexport interface ORACLE_CONNECTION_INFO {\n  user: string;\n  password: string;\n  host?: string;\n  port?: number;\n  database?: string;\n  dsn?: string;\n}\n\nexport interface MS_SQL_CONNECTION_INFO {\n  host: string;\n  port: number;\n  user: string;\n  password: string;\n  database: string;\n  trustServerCertificate: boolean;\n}\n\nexport interface CLICK_HOUSE_CONNECTION_INFO {\n  host: string;\n  port: number;\n  user: string;\n  password: string;\n  database: string;\n  ssl: boolean;\n}\n\nexport interface TRINO_CONNECTION_INFO {\n  host: string;\n  port: number;\n  schemas: string;\n  username: string;\n  password: string;\n  ssl: boolean;\n}\n\nexport interface SNOWFLAKE_CONNECTION_INFO {\n  user: string;\n  account: string;\n  database: string;\n  schema: string;\n  password?: string;\n  privateKey?: string;\n  warehouse?: string;\n}\n\nexport interface DUCKDB_CONNECTION_INFO {\n  initSql: string;\n  extensions: Array<string>;\n  configurations: Record<string, any>;\n}\n\nexport interface ATHENA_CONNECTION_INFO {\n  database: string;\n  schema: string;\n  s3StagingDir: string;\n  awsRegion: string;\n  awsAccessKey?: string;\n  awsSecretKey?: string;\n  webIdentityToken?: string;\n  roleArn?: string;\n  roleSessionName?: string;\n}\n\nexport interface REDSHIFT_PASSWORD_AUTH {\n  host: string;\n  port: number;\n  user: string;\n  password: string;\n  database: string;\n  redshiftType: IbisRedshiftConnectionType;\n}\n\nexport interface REDSHIFT_IAM_AUTH {\n  clusterIdentifier: string;\n  user: string;\n  database: string;\n  awsRegion: string;\n  awsAccessKey: string;\n  awsSecretKey: string;\n  redshiftType: IbisRedshiftConnectionType;\n}\n\nexport interface DATABRICKS_PERSONAL_ACCESS_TOKEN_AUTH {\n  serverHostname: string;\n  httpPath: string;\n  accessToken: string;\n  databricksType: IbisDatabricksConnectionType;\n}\n\nexport interface DATABRICKS_SERVICE_PRINCIPAL_AUTH {\n  serverHostname: string;\n  httpPath: string;\n  clientId: string;\n  clientSecret: string;\n  azureTenantId?: string;\n  databricksType: IbisDatabricksConnectionType;\n}\n\nexport type REDSHIFT_CONNECTION_INFO =\n  | REDSHIFT_PASSWORD_AUTH\n  | REDSHIFT_IAM_AUTH;\n\nexport type DATABRICKS_CONNECTION_INFO =\n  | DATABRICKS_PERSONAL_ACCESS_TOKEN_AUTH\n  | DATABRICKS_SERVICE_PRINCIPAL_AUTH;\n\nexport type WREN_AI_CONNECTION_INFO =\n  | ATHENA_CONNECTION_INFO\n  | BIG_QUERY_CONNECTION_INFO\n  | POSTGRES_CONNECTION_INFO\n  | MYSQL_CONNECTION_INFO\n  | ORACLE_CONNECTION_INFO\n  | DUCKDB_CONNECTION_INFO\n  | MS_SQL_CONNECTION_INFO\n  | CLICK_HOUSE_CONNECTION_INFO\n  | TRINO_CONNECTION_INFO\n  | SNOWFLAKE_CONNECTION_INFO\n  | REDSHIFT_CONNECTION_INFO\n  | DATABRICKS_CONNECTION_INFO;\n\nexport interface RecommendationQuestionResult {\n  question: string;\n  category: string; // category for the question\n  sql: string; // validated sql for this question, can be used in generateAskDetail\n}\n\nexport interface Project {\n  id: number; // ID\n  type: DataSourceName; // Project datasource type. ex: bigquery, mysql, postgresql, mongodb, etc\n  version: string; // Project datasource version\n  displayName: string; // Project display name\n  catalog: string; // Catalog name\n  schema: string; // Schema name\n  sampleDataset: string; // Sample dataset name\n  connectionInfo: WREN_AI_CONNECTION_INFO;\n  language?: string; // Project language\n\n  // The recommended questions generated by AI\n  queryId?: string;\n  questions?: RecommendationQuestionResult[];\n  questionsStatus?: string;\n  questionsError?: object;\n}\n\nexport interface IProjectRepository extends IBasicRepository<Project> {\n  getCurrentProject: () => Promise<Project>;\n}\n\nexport class ProjectRepository\n  extends BaseRepository<Project>\n  implements IProjectRepository\n{\n  private jsonTypeColumns = ['questions', 'questions_error', 'connection_info'];\n\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'project' });\n  }\n\n  public async getCurrentProject() {\n    const projects = await this.findAll({\n      order: 'id',\n      limit: 1,\n    });\n    if (!projects.length) {\n      throw new Error('No project found');\n    }\n    return projects[0];\n  }\n\n  public override transformFromDBData: (data: any) => Project = (data: any) => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected db data');\n    }\n    const formattedData = mapValues(data, (value, key) => {\n      if (this.jsonTypeColumns.includes(key) && typeof value === 'string') {\n        // should return {} if value is null / {}, use value ? {} : JSON.parse(value) will throw error when value is null\n        return isEmpty(value) ? {} : JSON.parse(value);\n      }\n      if (key === 'type') {\n        return DataSourceName[value];\n      }\n      return value;\n    });\n    const camelCaseData = mapKeys(formattedData, (_value, key) =>\n      camelCase(key),\n    );\n    return camelCaseData as Project;\n  };\n\n  public override transformToDBData: (data: Project) => any = (\n    data: Project,\n  ) => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected db data');\n    }\n    const snakeCaseData = mapKeys(data, (_value, key) => snakeCase(key));\n    const formattedData = mapValues(snakeCaseData, (value, key) => {\n      if (this.jsonTypeColumns.includes(key) && typeof value !== 'string') {\n        return JSON.stringify(value);\n      }\n      return value;\n    });\n    return formattedData;\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/relationshipRepository.ts",
    "content": "import { Knex } from 'knex';\nimport {\n  BaseRepository,\n  IBasicRepository,\n  IQueryOptions,\n} from './baseRepository';\nimport { RelationData } from '../types';\n\nexport interface Relation {\n  id: number; // ID\n  projectId: number; // Reference to project.id\n  name: string; // Relation name\n  joinType: string; // Join type, eg:\"MANY_TO_ONE\", \"ONE_TO_MANY\", \"MANY_TO_MANY\"\n  condition: string; // Join condition, ex: \"OrdersModel.custkey = CustomerModel.custkey\"\n  fromColumnId: number; // from column id, \"{fromColumn} {joinType} {toColumn}\"\n  toColumnId: number; // to column id, \"{fromColumn} {joinType} {toColumn}\"\n  properties: string | null; // Model properties, a json string, the description should be stored here\n}\n\nexport interface ExtraRelationInfo {\n  fromModelId: number;\n  fromModelName: string;\n  fromModelDisplayName: string;\n  fromColumnName: string;\n  fromColumnDisplayName: string;\n  toModelId: number;\n  toModelName: string;\n  toModelDisplayName: string;\n  toColumnName: string;\n  toColumnDisplayName: string;\n}\n\nexport type RelationInfo = Relation & ExtraRelationInfo;\n\nexport interface IRelationRepository extends IBasicRepository<Relation> {\n  findRelationsBy(\n    filter: { columnIds?: number[]; modelIds?: number[] },\n    queryOptions?: IQueryOptions,\n  ): Promise<Relation[]>;\n  findRelationsByIds(\n    ids: number[],\n    queryOptions?: IQueryOptions,\n  ): Promise<Relation[]>;\n  deleteRelationsByColumnIds(\n    columnIds: number[],\n    queryOptions?: IQueryOptions,\n  ): Promise<void>;\n  findRelationInfoBy(\n    filter: {\n      projectId?: number;\n      columnIds?: number[];\n      modelIds?: number[];\n    },\n    queryOptions?: IQueryOptions,\n  ): Promise<RelationInfo[]>;\n  findExistedRelationBetweenModels(\n    relation: RelationData,\n  ): Promise<RelationInfo[]>;\n}\n\nexport class RelationRepository\n  extends BaseRepository<Relation>\n  implements IRelationRepository\n{\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'relation' });\n  }\n\n  public async findRelationsBy(\n    { columnIds, modelIds },\n    queryOptions?: IQueryOptions,\n  ) {\n    let executer = this.knex;\n    if (queryOptions && queryOptions.tx) {\n      const { tx } = queryOptions;\n      executer = tx;\n    }\n    // select the leftModel name and rightModel name along with relation\n    const builder = executer(this.tableName)\n      .join(\n        'model_column AS fmc',\n        `${this.tableName}.from_column_id`,\n        '=',\n        'fmc.id',\n      )\n      .join(\n        'model_column AS tmc',\n        `${this.tableName}.to_column_id`,\n        '=',\n        'tmc.id',\n      );\n    if (columnIds && columnIds.length > 0) {\n      builder\n        .whereIn(`${this.tableName}.from_column_id`, columnIds)\n        .orWhereIn(`${this.tableName}.to_column_id`, columnIds);\n    }\n    if (modelIds && modelIds.length > 0) {\n      builder\n        .whereIn('fmc.model_id', modelIds)\n        .orWhereIn('tmc.model_id', modelIds);\n    }\n\n    const result = await builder.select(\n      `${this.tableName}.*`,\n      'fmc.model_id AS fromModelId',\n      'tmc.model_id AS toModelId',\n    );\n    return result.map((r) => this.transformFromDBData(r));\n  }\n\n  public async findRelationsByIds(ids: number[], queryOptions?: IQueryOptions) {\n    let executer = this.knex;\n    if (queryOptions && queryOptions.tx) {\n      const { tx } = queryOptions;\n      executer = tx;\n    }\n\n    const result = await executer(this.tableName)\n      .whereIn('id', ids)\n      .select('*');\n    return result.map((r) => this.transformFromDBData(r));\n  }\n\n  public async deleteRelationsByColumnIds(\n    columnIds: number[],\n    queryOptions?: IQueryOptions,\n  ) {\n    if (queryOptions && queryOptions.tx) {\n      const { tx } = queryOptions;\n      await tx(this.tableName)\n        .whereIn('from_column_id', columnIds)\n        .orWhereIn('to_column_id', columnIds)\n        .delete();\n      return;\n    }\n    await this.knex(this.tableName)\n      .whereIn('from_column_id', columnIds)\n      .orWhereIn('to_column_id', columnIds)\n      .delete();\n  }\n\n  public async findRelationInfoBy(filter, queryOptions) {\n    const { projectId, columnIds, modelIds } = filter;\n    let executer = this.knex;\n    if (queryOptions && queryOptions.tx) {\n      const { tx } = queryOptions;\n      executer = tx;\n    }\n    // select the leftModel name and rightModel name along with relation\n    const builder = executer(this.tableName)\n      .join(\n        'model_column AS fmc',\n        `${this.tableName}.from_column_id`,\n        '=',\n        'fmc.id',\n      )\n      .join(\n        'model_column AS tmc',\n        `${this.tableName}.to_column_id`,\n        '=',\n        'tmc.id',\n      )\n      .join('model AS fm', 'fmc.model_id', '=', 'fm.id')\n      .join('model AS tm', 'tmc.model_id', '=', 'tm.id');\n\n    if (projectId) {\n      builder.where(`${this.tableName}.project_id`, projectId);\n    } else if (columnIds && columnIds.length > 0) {\n      builder\n        .whereIn(`${this.tableName}.from_column_id`, columnIds)\n        .orWhereIn(`${this.tableName}.to_column_id`, columnIds);\n    } else if (modelIds && modelIds.length > 0) {\n      builder\n        .whereIn('fmc.model_id', modelIds)\n        .orWhereIn('tmc.model_id', modelIds);\n    }\n\n    const result = await builder.select(\n      `${this.tableName}.*`,\n      'fm.id AS fromModelId',\n      'fm.reference_name AS fromModelName',\n      'fm.display_name AS fromModelDisplayName',\n      'tm.id AS toModelId',\n      'tm.reference_name AS toModelName',\n      'tm.display_name AS toModelDisplayName',\n      'fmc.reference_name AS fromColumnName',\n      'fmc.display_name AS fromColumnDisplayName',\n      'tmc.reference_name AS toColumnName',\n      'tmc.display_name AS toColumnDisplayName',\n    );\n    return result.map((r) => this.transformFromDBData(r)) as RelationInfo[];\n  }\n\n  public async findExistedRelationBetweenModels(relation: RelationData) {\n    const { fromModelId, fromColumnId, toModelId, toColumnId } = relation;\n    const query = this.knex(this.tableName)\n      .join(\n        'model_column AS fmc',\n        `${this.tableName}.from_column_id`,\n        '=',\n        'fmc.id',\n      )\n      .join(\n        'model_column AS tmc',\n        `${this.tableName}.to_column_id`,\n        '=',\n        'tmc.id',\n      )\n      // duplicate relationship check\n      .whereRaw(\n        `fmc.model_id = ? And ${this.tableName}.from_column_id = ? And tmc.model_id = ? And ${this.tableName}.to_column_id = ?`,\n        [fromModelId, fromColumnId, toModelId, toColumnId],\n      )\n      // reverse relationship check\n      .orWhereRaw(\n        `fmc.model_id = ? And ${this.tableName}.from_column_id = ? And tmc.model_id = ? And ${this.tableName}.to_column_id = ?`,\n        [toModelId, toColumnId, fromModelId, fromColumnId],\n      )\n      .select(`${this.tableName}.*`);\n    const result = await query;\n    return result.map((r) => this.transformFromDBData(r)) as RelationInfo[];\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/schemaChangeRepository.ts",
    "content": "import { Knex } from 'knex';\nimport { BaseRepository, IBasicRepository } from './baseRepository';\nimport {\n  camelCase,\n  isPlainObject,\n  mapKeys,\n  mapValues,\n  snakeCase,\n} from 'lodash';\nimport {\n  DataSourceSchemaChange,\n  DataSourceSchemaResolve,\n} from '@server/managers/dataSourceSchemaDetector';\n\nexport interface SchemaChange {\n  id: number; // ID\n  projectId: number; // Reference to project.id\n  change: DataSourceSchemaChange; // Schema change\n  resolve: DataSourceSchemaResolve; // Save resolve\n  createdAt: string; // Created at\n  updateAt: string; // Updated at\n}\n\nexport interface ISchemaChangeRepository\n  extends IBasicRepository<SchemaChange> {\n  findLastSchemaChange(projectId: number): Promise<SchemaChange | null>;\n}\n\nexport class SchemaChangeRepository\n  extends BaseRepository<SchemaChange>\n  implements ISchemaChangeRepository\n{\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'schema_change' });\n  }\n\n  public async findLastSchemaChange(projectId: number) {\n    const res = await this.knex\n      .select('*')\n      .from(this.tableName)\n      .where(this.transformToDBData({ projectId }))\n      .orderBy('created_at', 'desc')\n      .first();\n    return (res && this.transformFromDBData(res)) || null;\n  }\n\n  protected override transformToDBData = (data: any) => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const transformedData = mapValues(data, (value, key) => {\n      if (['change', 'resolve'].includes(key)) {\n        return value ? JSON.stringify(value) : null;\n      }\n      return value;\n    });\n    return mapKeys(transformedData, (_value, key) => snakeCase(key));\n  };\n\n  protected override transformFromDBData = (data: any): SchemaChange => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const camelCaseData = mapKeys(data, (_value, key) => camelCase(key));\n    const formattedData = mapValues(camelCaseData, (value, key) => {\n      if (['change', 'resolve'].includes(key)) {\n        // The value from Sqlite will be string type, while the value from PG is JSON object\n        if (typeof value === 'string') {\n          return value ? JSON.parse(value) : value;\n        } else {\n          return value;\n        }\n      }\n      return value;\n    }) as SchemaChange;\n    return formattedData;\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/sqlPairRepository.ts",
    "content": "import { Knex } from 'knex';\nimport { BaseRepository, IBasicRepository } from './baseRepository';\n\nexport interface SqlPair {\n  id: number; // ID\n  projectId: number; // Reference to project.id\n  sql: string; // SQL query\n  question: string; // Natural language question\n  createdAt?: string; // Date and time when the SQL pair was created\n  updatedAt?: string; // Date and time when the SQL pair was last updated\n}\n\nexport interface ISqlPairRepository extends IBasicRepository<SqlPair> {}\n\nexport class SqlPairRepository\n  extends BaseRepository<SqlPair>\n  implements ISqlPairRepository\n{\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'sql_pair' });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/threadRepository.ts",
    "content": "import { Knex } from 'knex';\nimport { BaseRepository, IBasicRepository } from './baseRepository';\nimport {\n  camelCase,\n  isPlainObject,\n  mapKeys,\n  mapValues,\n  snakeCase,\n} from 'lodash';\n\nexport interface ThreadRecommendationQuestionResult {\n  question: string;\n  category: string;\n  sql: string;\n}\n\nexport interface Thread {\n  id: number; // ID\n  projectId: number; // Reference to project.id\n  summary: string; // Thread summary\n\n  // recommend question\n  queryId?: string; // Query ID\n  questions?: ThreadRecommendationQuestionResult[]; // Recommended questions\n  questionsStatus?: string; // Status of the recommended questions\n  questionsError?: object; // Error of the recommended questions\n}\n\nexport interface IThreadRepository extends IBasicRepository<Thread> {\n  listAllTimeDescOrder(projectId: number): Promise<Thread[]>;\n}\n\nexport class ThreadRepository\n  extends BaseRepository<Thread>\n  implements IThreadRepository\n{\n  private readonly jsonbColumns = ['questions', 'questionsError'];\n\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'thread' });\n  }\n\n  public async listAllTimeDescOrder(projectId: number): Promise<Thread[]> {\n    const threads = await this.knex(this.tableName)\n      .where(this.transformToDBData({ projectId }))\n      .orderBy('created_at', 'desc');\n    return threads.map((thread) => this.transformFromDBData(thread));\n  }\n\n  protected override transformFromDBData = (data: any): Thread => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const camelCaseData = mapKeys(data, (_value, key) => camelCase(key));\n    const transformData = mapValues(camelCaseData, (value, key) => {\n      if (this.jsonbColumns.includes(key)) {\n        if (typeof value === 'string') {\n          return value ? JSON.parse(value) : value;\n        } else {\n          return value;\n        }\n      }\n      return value;\n    });\n    return transformData as Thread;\n  };\n\n  protected override transformToDBData = (data: any) => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const transformedData = mapValues(data, (value, key) => {\n      if (this.jsonbColumns.includes(key)) {\n        return JSON.stringify(value);\n      } else {\n        return value;\n      }\n    });\n    return mapKeys(transformedData, (_value, key) => snakeCase(key));\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/threadResponseRepository.ts",
    "content": "import { Knex } from 'knex';\nimport {\n  BaseRepository,\n  IBasicRepository,\n  IQueryOptions,\n} from './baseRepository';\nimport { camelCase, isPlainObject, mapKeys, mapValues } from 'lodash';\nimport { AskResultStatus } from '@server/models/adaptor';\n\nexport interface DetailStep {\n  summary: string;\n  sql: string;\n  cteName: string;\n}\n\nexport interface ThreadResponseBreakdownDetail {\n  queryId: string;\n  status: string;\n  error?: object;\n  description?: string;\n  steps?: Array<DetailStep>;\n}\n\nexport interface ThreadResponseAnswerDetail {\n  queryId?: string;\n  status: string;\n  error?: object;\n  numRowsUsedInLLM?: number;\n  content?: string;\n}\n\nexport interface ThreadResponseChartDetail {\n  queryId?: string;\n  status: string;\n  error?: object;\n  description?: string;\n  chartType?: string;\n  chartSchema?: Record<string, any>;\n  adjustment?: boolean;\n}\n\nexport enum ThreadResponseAdjustmentType {\n  REASONING = 'REASONING',\n  APPLY_SQL = 'APPLY_SQL',\n}\n\nexport type ThreadResponseAdjustmentReasoningPayload = {\n  originalThreadResponseId?: number;\n  retrievedTables?: string[];\n  sqlGenerationReasoning?: string;\n};\n\nexport type ThreadResponseAdjustmentApplySqlPayload = {\n  originalThreadResponseId?: number;\n  sql?: string;\n};\n\nexport interface ThreadResponseAdjustment {\n  type: ThreadResponseAdjustmentType;\n  // todo: I think we could use a better way to do this instead of using a union type\n  payload: ThreadResponseAdjustmentReasoningPayload &\n    ThreadResponseAdjustmentApplySqlPayload;\n}\n\nexport interface ThreadResponse {\n  id: number; // ID\n  askingTaskId?: number; // Reference to asking_task.id\n  viewId?: number; // View ID, if the response is from a view\n  threadId: number; // Reference to thread.id\n  question: string; // Thread response question\n  sql?: string; // SQL query generated by AI service\n  answerDetail?: ThreadResponseAnswerDetail; // AI generated text-based answer detail\n  breakdownDetail?: ThreadResponseBreakdownDetail; // Thread response breakdown detail\n  chartDetail?: ThreadResponseChartDetail; // Thread response chart detail\n  adjustment?: ThreadResponseAdjustment; // Thread response adjustment\n}\n\nexport interface IThreadResponseRepository\n  extends IBasicRepository<ThreadResponse> {\n  getResponsesWithThread(\n    threadId: number,\n    limit?: number,\n  ): Promise<ThreadResponse[]>;\n}\n\nexport class ThreadResponseRepository\n  extends BaseRepository<ThreadResponse>\n  implements IThreadResponseRepository\n{\n  private readonly jsonbColumns = [\n    'answerDetail',\n    'breakdownDetail',\n    'chartDetail',\n    'adjustment',\n  ];\n\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'thread_response' });\n  }\n\n  public async getResponsesWithThread(threadId: number, limit?: number) {\n    const query = this.knex(this.tableName)\n      .select('thread_response.*')\n      .where({ thread_id: threadId })\n      .leftJoin('thread', 'thread.id', 'thread_response.thread_id');\n\n    if (limit) {\n      query.orderBy('created_at', 'desc').limit(limit);\n    }\n\n    return (await query)\n      .map((res) => {\n        // turn object keys into camelCase\n        return mapKeys(res, (_, key) => camelCase(key));\n      })\n      .map((res) => {\n        // JSON.parse detail and error\n        const answerDetail =\n          res.answerDetail && typeof res.answerDetail === 'string'\n            ? JSON.parse(res.answerDetail)\n            : res.answerDetail;\n        const breakdownDetail =\n          res.breakdownDetail && typeof res.breakdownDetail === 'string'\n            ? JSON.parse(res.breakdownDetail)\n            : res.breakdownDetail;\n        const chartDetail =\n          res.chartDetail && typeof res.chartDetail === 'string'\n            ? JSON.parse(res.chartDetail)\n            : res.chartDetail;\n        const adjustment =\n          res.adjustment && typeof res.adjustment === 'string'\n            ? JSON.parse(res.adjustment)\n            : res.adjustment;\n        return {\n          ...res,\n          answerDetail: answerDetail || null,\n          breakdownDetail: breakdownDetail || null,\n          chartDetail: chartDetail || null,\n          adjustment: adjustment || null,\n        };\n      }) as ThreadResponse[];\n  }\n\n  public async updateOne(\n    id: string | number,\n    data: Partial<{\n      status: AskResultStatus;\n      sql: string;\n      viewId: number;\n      answerDetail: ThreadResponseAnswerDetail;\n      breakdownDetail: ThreadResponseBreakdownDetail;\n      chartDetail: ThreadResponseChartDetail;\n      adjustment: ThreadResponseAdjustment;\n    }>,\n    queryOptions?: IQueryOptions,\n  ) {\n    const transformedData = {\n      status: data.status ? data.status : undefined,\n      sql: data.sql ? data.sql : undefined,\n      viewId: data.viewId ? data.viewId : undefined,\n      answerDetail: data.answerDetail\n        ? JSON.stringify(data.answerDetail)\n        : undefined,\n      breakdownDetail: data.breakdownDetail\n        ? JSON.stringify(data.breakdownDetail)\n        : undefined,\n      chartDetail: data.chartDetail\n        ? JSON.stringify(data.chartDetail)\n        : undefined,\n      adjustment: data.adjustment ? JSON.stringify(data.adjustment) : undefined,\n    };\n    const executer = queryOptions?.tx ? queryOptions.tx : this.knex;\n    const [result] = await executer(this.tableName)\n      .where({ id })\n      .update(this.transformToDBData(transformedData as any))\n      .returning('*');\n    return this.transformFromDBData(result);\n  }\n\n  protected override transformFromDBData = (data: any): ThreadResponse => {\n    if (!isPlainObject(data)) {\n      throw new Error('Unexpected dbdata');\n    }\n    const camelCaseData = mapKeys(data, (_value, key) => camelCase(key));\n    const formattedData = mapValues(camelCaseData, (value, key) => {\n      if (this.jsonbColumns.includes(key)) {\n        // The value from Sqlite will be string type, while the value from PG is JSON object\n        if (typeof value === 'string') {\n          return value ? JSON.parse(value) : value;\n        } else {\n          return value;\n        }\n      }\n      return value;\n    }) as ThreadResponse;\n    return formattedData;\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/repositories/viewRepository.ts",
    "content": "import { Knex } from 'knex';\nimport { BaseRepository, IBasicRepository } from './baseRepository';\n\nexport interface View {\n  id: number; // ID\n  projectId: number; // Reference to project.id\n  name: string; // The view name\n  statement: string; // The SQL statement of this view\n  cached: boolean; // View is cached or not\n  refreshTime?: string; // Contain a number followed by a time unit (ns, us, ms, s, m, h, d). For example, \"2h\"\n  properties?: string; // View properties, a json string, the description and displayName should be stored here\n}\n\nexport interface IViewRepository extends IBasicRepository<View> {}\n\nexport class ViewRepository\n  extends BaseRepository<View>\n  implements IViewRepository\n{\n  constructor(knexPg: Knex) {\n    super({ knexPg, tableName: 'view' });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/resolvers/apiHistoryResolver.ts",
    "content": "import { ApiType, ApiHistory } from '@server/repositories/apiHistoryRepository';\nimport { IContext } from '@server/types';\n\nexport interface ApiHistoryFilter {\n  apiType?: ApiType;\n  statusCode?: number;\n  threadId?: string;\n  projectId?: number;\n  startDate?: string;\n  endDate?: string;\n}\n\nexport interface ApiHistoryPagination {\n  offset: number;\n  limit: number;\n}\n\n/**\n * Sanitize response payload to remove large data fields\n * This prevents excessive data transfer when displaying API history\n * @param payload The response payload to sanitize\n * @param apiType The type of API that generated this response\n */\nconst sanitizeResponsePayload = (payload: any, apiType?: ApiType): any => {\n  if (!payload) return payload;\n\n  const sanitized = { ...payload };\n\n  // Handle specifically RUN_SQL responses that contain large record sets\n  if (apiType === ApiType.RUN_SQL) {\n    // Remove records array but keep metadata about how many records were returned\n    if (sanitized.records && Array.isArray(sanitized.records)) {\n      const recordCount = sanitized.records.length;\n      sanitized.records = [`${recordCount} records omitted`];\n    }\n  }\n\n  // Handle specifically GENERATE_VEGA_CHART responses that contain large data values\n  if (apiType === ApiType.GENERATE_VEGA_CHART) {\n    // Remove vegaSpec.data.values array but keep the structure\n    if (\n      sanitized.vegaSpec?.data?.values &&\n      Array.isArray(sanitized.vegaSpec.data.values)\n    ) {\n      const dataCount = sanitized.vegaSpec.data.values.length;\n      sanitized.vegaSpec.data.values = [`${dataCount} data points omitted`];\n    }\n  }\n\n  return sanitized;\n};\n\nexport class ApiHistoryResolver {\n  constructor() {\n    this.getApiHistory = this.getApiHistory.bind(this);\n  }\n\n  /**\n   * Get API history with filtering and pagination\n   */\n  public async getApiHistory(\n    _root: unknown,\n    args: {\n      filter?: ApiHistoryFilter;\n      pagination: ApiHistoryPagination;\n    },\n    ctx: IContext,\n  ) {\n    const { filter, pagination } = args;\n    const { offset, limit } = pagination;\n\n    // Build filter criteria\n    const filterCriteria: Partial<ApiHistory> = {};\n\n    if (filter) {\n      if (filter.apiType) {\n        filterCriteria.apiType = filter.apiType;\n      }\n\n      if (filter.statusCode) {\n        filterCriteria.statusCode = filter.statusCode;\n      }\n\n      if (filter.threadId) {\n        filterCriteria.threadId = filter.threadId;\n      }\n\n      if (filter.projectId) {\n        filterCriteria.projectId = filter.projectId;\n      }\n    }\n\n    // Handle date filtering\n    const dateFilter: { startDate?: Date; endDate?: Date } = {};\n    if (filter?.startDate) {\n      dateFilter.startDate = new Date(filter.startDate);\n    }\n    if (filter?.endDate) {\n      dateFilter.endDate = new Date(filter.endDate);\n    }\n\n    // Get total count for pagination info\n    const total = await ctx.apiHistoryRepository.count(\n      filterCriteria,\n      dateFilter,\n    );\n\n    if (total === 0 || total <= offset) {\n      return {\n        items: [],\n        total,\n        hasMore: false,\n      };\n    }\n\n    // Get paginated items\n    const items = await ctx.apiHistoryRepository.findAllWithPagination(\n      filterCriteria,\n      dateFilter,\n      {\n        offset,\n        limit,\n        orderBy: { createdAt: 'desc' },\n      },\n    );\n\n    return {\n      items,\n      total,\n      hasMore: offset + limit < total,\n    };\n  }\n\n  /**\n   * Resolver for ApiHistoryResponse fields\n   */\n  public getApiHistoryNestedResolver = () => ({\n    createdAt: (apiHistory: ApiHistory) => {\n      return apiHistory.createdAt\n        ? new Date(apiHistory.createdAt).toISOString()\n        : null;\n    },\n    updatedAt: (apiHistory: ApiHistory) => {\n      return apiHistory.updatedAt\n        ? new Date(apiHistory.updatedAt).toISOString()\n        : null;\n    },\n    responsePayload: (apiHistory: ApiHistory) => {\n      if (!apiHistory.responsePayload) return null;\n\n      // If the response payload is an array, return it as is\n      if (Array.isArray(apiHistory.responsePayload))\n        return apiHistory.responsePayload;\n\n      // Otherwise, sanitize the response payload\n      return sanitizeResponsePayload(\n        apiHistory.responsePayload,\n        apiHistory.apiType,\n      );\n    },\n  });\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/resolvers/askingResolver.ts",
    "content": "import {\n  WrenAIError,\n  WrenAILanguage,\n  AskResultStatus,\n  AskResultType,\n  RecommendationQuestionStatus,\n  ChartAdjustmentOption,\n  AskFeedbackStatus,\n} from '@server/models/adaptor';\nimport { Thread } from '../repositories/threadRepository';\nimport {\n  DetailStep,\n  ThreadResponse,\n} from '../repositories/threadResponseRepository';\nimport { reduce } from 'lodash';\nimport { IContext } from '../types';\nimport { getLogger } from '@server/utils';\nimport { safeFormatSQL } from '@server/utils/sqlFormat';\nimport {\n  AskingDetailTaskInput,\n  constructCteSql,\n  ThreadRecommendQuestionResult,\n} from '../services/askingService';\nimport {\n  SuggestedQuestion,\n  SampleDatasetName,\n  getSampleAskQuestions,\n} from '../data';\nimport { TelemetryEvent, WrenService } from '../telemetry/telemetry';\nimport { TrackedAskingResult } from '../services';\n\nconst logger = getLogger('AskingResolver');\nlogger.level = 'debug';\n\nexport interface SuggestedQuestionResponse {\n  questions: SuggestedQuestion[];\n}\n\nexport interface Task {\n  id: string;\n}\n\nexport interface AdjustmentTask {\n  queryId: string;\n  status: AskFeedbackStatus;\n  error: WrenAIError | null;\n  sql: string;\n  traceId: string;\n  invalidSql?: string;\n}\n\nexport interface AskingTask {\n  type: AskResultType | null;\n  status: AskResultStatus;\n  candidates: Array<{\n    sql: string;\n  }>;\n  error: WrenAIError | null;\n  rephrasedQuestion?: string;\n  intentReasoning?: string;\n  sqlGenerationReasoning?: string;\n  retrievedTables?: string[];\n  invalidSql?: string;\n  traceId?: string;\n  queryId?: string;\n}\n\n// DetailedThread is a type that represents a detailed thread, which is a thread with responses.\nexport interface DetailedThread {\n  id: number; // ID\n  sql: string; // SQL\n  responses: ThreadResponse[];\n}\n\nexport interface RecommendedQuestionsTask {\n  questions: {\n    question: string;\n    category: string;\n    sql: string;\n  }[];\n  status: RecommendationQuestionStatus;\n  error: WrenAIError | null;\n}\n\nexport class AskingResolver {\n  constructor() {\n    this.createAskingTask = this.createAskingTask.bind(this);\n    this.cancelAskingTask = this.cancelAskingTask.bind(this);\n    this.rerunAskingTask = this.rerunAskingTask.bind(this);\n    this.getAskingTask = this.getAskingTask.bind(this);\n    this.createThread = this.createThread.bind(this);\n    this.getThread = this.getThread.bind(this);\n    this.updateThread = this.updateThread.bind(this);\n    this.deleteThread = this.deleteThread.bind(this);\n    this.listThreads = this.listThreads.bind(this);\n    this.createThreadResponse = this.createThreadResponse.bind(this);\n    this.updateThreadResponse = this.updateThreadResponse.bind(this);\n    this.getResponse = this.getResponse.bind(this);\n    this.previewData = this.previewData.bind(this);\n    this.previewBreakdownData = this.previewBreakdownData.bind(this);\n    this.getSuggestedQuestions = this.getSuggestedQuestions.bind(this);\n    this.createInstantRecommendedQuestions =\n      this.createInstantRecommendedQuestions.bind(this);\n    this.getInstantRecommendedQuestions =\n      this.getInstantRecommendedQuestions.bind(this);\n    this.generateThreadRecommendationQuestions =\n      this.generateThreadRecommendationQuestions.bind(this);\n    this.generateProjectRecommendationQuestions =\n      this.generateProjectRecommendationQuestions.bind(this);\n\n    this.getThreadRecommendationQuestions =\n      this.getThreadRecommendationQuestions.bind(this);\n    this.generateThreadResponseBreakdown =\n      this.generateThreadResponseBreakdown.bind(this);\n    this.generateThreadResponseAnswer =\n      this.generateThreadResponseAnswer.bind(this);\n    this.generateThreadResponseChart =\n      this.generateThreadResponseChart.bind(this);\n    this.adjustThreadResponseChart = this.adjustThreadResponseChart.bind(this);\n    this.transformAskingTask = this.transformAskingTask.bind(this);\n\n    this.adjustThreadResponse = this.adjustThreadResponse.bind(this);\n    this.cancelAdjustThreadResponseAnswer =\n      this.cancelAdjustThreadResponseAnswer.bind(this);\n    this.rerunAdjustThreadResponseAnswer =\n      this.rerunAdjustThreadResponseAnswer.bind(this);\n    this.getAdjustmentTask = this.getAdjustmentTask.bind(this);\n  }\n\n  public async generateProjectRecommendationQuestions(\n    _root: any,\n    _args: any,\n    ctx: IContext,\n  ): Promise<boolean> {\n    await ctx.projectService.generateProjectRecommendationQuestions();\n    return true;\n  }\n\n  public async generateThreadRecommendationQuestions(\n    _root: any,\n    args: { threadId: number },\n    ctx: IContext,\n  ): Promise<boolean> {\n    const { threadId } = args;\n    const askingService = ctx.askingService;\n    await askingService.generateThreadRecommendationQuestions(threadId);\n    return true;\n  }\n\n  public async getThreadRecommendationQuestions(\n    _root: any,\n    args: { threadId: number },\n    ctx: IContext,\n  ): Promise<ThreadRecommendQuestionResult> {\n    const { threadId } = args;\n    const askingService = ctx.askingService;\n    return askingService.getThreadRecommendationQuestions(threadId);\n  }\n\n  public async getSuggestedQuestions(\n    _root: any,\n    _args: any,\n    ctx: IContext,\n  ): Promise<SuggestedQuestionResponse> {\n    const project = await ctx.projectService.getCurrentProject();\n    const { sampleDataset } = project;\n    if (!sampleDataset) {\n      return { questions: [] };\n    }\n    const questions = getSampleAskQuestions(sampleDataset as SampleDatasetName);\n    return { questions };\n  }\n\n  public async createAskingTask(\n    _root: any,\n    args: { data: { question: string; threadId?: number } },\n    ctx: IContext,\n  ): Promise<Task> {\n    const { question, threadId } = args.data;\n    const project = await ctx.projectService.getCurrentProject();\n\n    const askingService = ctx.askingService;\n    const data = { question };\n    const task = await askingService.createAskingTask(data, {\n      threadId,\n      language: WrenAILanguage[project.language] || WrenAILanguage.EN,\n    });\n    ctx.telemetry.sendEvent(TelemetryEvent.HOME_ASK_CANDIDATE, {\n      question,\n      taskId: task.id,\n    });\n    return task;\n  }\n\n  public async cancelAskingTask(\n    _root: any,\n    args: { taskId: string },\n    ctx: IContext,\n  ): Promise<boolean> {\n    const { taskId } = args;\n    const askingService = ctx.askingService;\n    await askingService.cancelAskingTask(taskId);\n    return true;\n  }\n\n  public async getAskingTask(\n    _root: any,\n    args: { taskId: string },\n    ctx: IContext,\n  ): Promise<AskingTask> {\n    const { taskId } = args;\n    const askingService = ctx.askingService;\n    const askResult = await askingService.getAskingTask(taskId);\n\n    if (!askResult) {\n      return null;\n    }\n\n    // telemetry\n    const eventName = TelemetryEvent.HOME_ASK_CANDIDATE;\n    if (askResult.status === AskResultStatus.FINISHED) {\n      ctx.telemetry.sendEvent(eventName, {\n        taskId,\n        status: askResult.status,\n        candidates: askResult.response,\n      });\n    }\n    if (askResult.status === AskResultStatus.FAILED) {\n      ctx.telemetry.sendEvent(\n        eventName,\n        {\n          taskId,\n          status: askResult.status,\n          error: askResult.error,\n        },\n        WrenService.AI,\n        false,\n      );\n    }\n\n    return this.transformAskingTask(askResult, ctx);\n  }\n\n  public async createThread(\n    _root: any,\n    args: {\n      data: {\n        question?: string;\n        taskId?: string;\n        // if we use recommendation questions, sql will be provided\n        sql?: string;\n      };\n    },\n    ctx: IContext,\n  ): Promise<Thread> {\n    const { data } = args;\n\n    const askingService = ctx.askingService;\n\n    // if taskId is provided, use the result from the asking task\n    // otherwise, use the input data\n    let threadInput: AskingDetailTaskInput;\n    if (data.taskId) {\n      const askingTask = await askingService.getAskingTask(data.taskId);\n      if (!askingTask) {\n        throw new Error(`Asking task ${data.taskId} not found`);\n      }\n\n      threadInput = {\n        question: askingTask.question,\n        trackedAskingResult: askingTask,\n      };\n    } else {\n      // when we use recommendation questions, there's no task to track\n      threadInput = data;\n    }\n\n    const eventName = TelemetryEvent.HOME_CREATE_THREAD;\n    try {\n      const thread = await askingService.createThread(threadInput);\n      ctx.telemetry.sendEvent(eventName, {});\n      return thread;\n    } catch (err: any) {\n      ctx.telemetry.sendEvent(\n        eventName,\n        { error: err.message },\n        err.extensions?.service,\n        false,\n      );\n      throw err;\n    }\n    // telemetry\n  }\n\n  public async getThread(\n    _root: any,\n    args: { threadId: number },\n    ctx: IContext,\n  ): Promise<DetailedThread> {\n    const { threadId } = args;\n\n    const askingService = ctx.askingService;\n    const responses = await askingService.getResponsesWithThread(threadId);\n    // reduce responses to group by thread id\n    const thread = reduce(\n      responses,\n      (acc, response) => {\n        if (!acc.id) {\n          acc.id = response.threadId;\n          acc.sql = response.sql;\n          acc.responses = [];\n        }\n\n        acc.responses.push({\n          id: response.id,\n          viewId: response.viewId,\n          threadId: response.threadId,\n          question: response.question,\n          sql: response.sql,\n          askingTaskId: response.askingTaskId,\n          breakdownDetail: response.breakdownDetail,\n          answerDetail: response.answerDetail,\n          chartDetail: response.chartDetail,\n          adjustment: response.adjustment,\n        });\n\n        return acc;\n      },\n      {} as any,\n    );\n\n    return thread;\n  }\n\n  public async updateThread(\n    _root: any,\n    args: { where: { id: number }; data: { summary: string } },\n    ctx: IContext,\n  ): Promise<Thread> {\n    const { where, data } = args;\n\n    const askingService = ctx.askingService;\n    const eventName = TelemetryEvent.HOME_UPDATE_THREAD_SUMMARY;\n    const newSummary = data.summary;\n    try {\n      const thread = await askingService.updateThread(where.id, data);\n      // telemetry\n      ctx.telemetry.sendEvent(eventName, {\n        new_summary: newSummary,\n      });\n      return thread;\n    } catch (err: any) {\n      ctx.telemetry.sendEvent(\n        eventName,\n        {\n          new_summary: newSummary,\n        },\n        err.extensions?.service,\n        false,\n      );\n      throw err;\n    }\n  }\n\n  public async deleteThread(\n    _root: any,\n    args: { where: { id: number } },\n    ctx: IContext,\n  ): Promise<boolean> {\n    const { where } = args;\n\n    const askingService = ctx.askingService;\n    await askingService.deleteThread(where.id);\n    return true;\n  }\n\n  public async listThreads(\n    _root: any,\n    _args: any,\n    ctx: IContext,\n  ): Promise<Thread[]> {\n    const threads = await ctx.askingService.listThreads();\n    return threads;\n  }\n\n  public async createThreadResponse(\n    _root: any,\n    args: {\n      threadId: number;\n      data: {\n        question?: string;\n        taskId?: string;\n        // if we use recommendation questions, sql will be provided\n        sql?: string;\n      };\n    },\n    ctx: IContext,\n  ): Promise<ThreadResponse> {\n    const { threadId, data } = args;\n\n    const askingService = ctx.askingService;\n    const eventName = TelemetryEvent.HOME_ASK_FOLLOWUP_QUESTION;\n\n    // if taskId is provided, use the result from the asking task\n    // otherwise, use the input data\n    let threadResponseInput: AskingDetailTaskInput;\n    if (data.taskId) {\n      const askingTask = await askingService.getAskingTask(data.taskId);\n      if (!askingTask) {\n        throw new Error(`Asking task ${data.taskId} not found`);\n      }\n\n      threadResponseInput = {\n        question: askingTask.question,\n        trackedAskingResult: askingTask,\n      };\n    } else {\n      // when we use recommendation questions, there's no task to track\n      threadResponseInput = data;\n    }\n\n    try {\n      const response = await askingService.createThreadResponse(\n        threadResponseInput,\n        threadId,\n      );\n      ctx.telemetry.sendEvent(eventName, { data });\n      return response;\n    } catch (err: any) {\n      ctx.telemetry.sendEvent(\n        eventName,\n        { data, error: err.message },\n        err.extensions?.service,\n        false,\n      );\n      throw err;\n    }\n  }\n\n  public async updateThreadResponse(\n    _root: any,\n    args: { where: { id: number }; data: { sql: string } },\n    ctx: IContext,\n  ): Promise<ThreadResponse> {\n    const { where, data } = args;\n    const askingService = ctx.askingService;\n    const response = await askingService.updateThreadResponse(where.id, data);\n    return response;\n  }\n\n  public async rerunAskingTask(\n    _root: any,\n    args: { responseId: number },\n    ctx: IContext,\n  ): Promise<Task> {\n    const { responseId } = args;\n    const askingService = ctx.askingService;\n    const project = await ctx.projectService.getCurrentProject();\n\n    const task = await askingService.rerunAskingTask(responseId, {\n      language: WrenAILanguage[project.language] || WrenAILanguage.EN,\n    });\n    ctx.telemetry.sendEvent(TelemetryEvent.HOME_RERUN_ASKING_TASK, {\n      responseId,\n    });\n    return task;\n  }\n\n  public async adjustThreadResponse(\n    _root: any,\n    args: {\n      responseId: number;\n      data: {\n        tables?: string[];\n        sqlGenerationReasoning?: string;\n        sql?: string;\n      };\n    },\n    ctx: IContext,\n  ): Promise<ThreadResponse> {\n    const { responseId, data } = args;\n    const askingService = ctx.askingService;\n    const project = await ctx.projectService.getCurrentProject();\n\n    if (data.sql) {\n      const response = await askingService.adjustThreadResponseWithSQL(\n        responseId,\n        {\n          sql: data.sql,\n        },\n      );\n      ctx.telemetry.sendEvent(\n        TelemetryEvent.HOME_ADJUST_THREAD_RESPONSE_WITH_SQL,\n        {\n          sql: data.sql,\n          responseId,\n        },\n      );\n      return response;\n    }\n\n    return askingService.adjustThreadResponseAnswer(\n      responseId,\n      {\n        projectId: project.id,\n        tables: data.tables,\n        sqlGenerationReasoning: data.sqlGenerationReasoning,\n      },\n      {\n        language: WrenAILanguage[project.language] || WrenAILanguage.EN,\n      },\n    );\n  }\n\n  public async cancelAdjustThreadResponseAnswer(\n    _root: any,\n    args: { taskId: string },\n    ctx: IContext,\n  ): Promise<boolean> {\n    const { taskId } = args;\n    const askingService = ctx.askingService;\n    await askingService.cancelAdjustThreadResponseAnswer(taskId);\n    return true;\n  }\n\n  public async rerunAdjustThreadResponseAnswer(\n    _root: any,\n    args: { responseId: number },\n    ctx: IContext,\n  ): Promise<boolean> {\n    const { responseId } = args;\n    const askingService = ctx.askingService;\n    const project = await ctx.projectService.getCurrentProject();\n    await askingService.rerunAdjustThreadResponseAnswer(\n      responseId,\n      project.id,\n      {\n        language: WrenAILanguage[project.language] || WrenAILanguage.EN,\n      },\n    );\n    return true;\n  }\n\n  public async getAdjustmentTask(\n    _root: any,\n    args: { taskId: string },\n    ctx: IContext,\n  ): Promise<AdjustmentTask> {\n    const { taskId } = args;\n    const askingService = ctx.askingService;\n    const adjustmentTask = await askingService.getAdjustmentTask(taskId);\n    return {\n      queryId: adjustmentTask?.queryId,\n      status: adjustmentTask?.status,\n      error: adjustmentTask?.error,\n      sql: adjustmentTask?.response?.[0]?.sql,\n      traceId: adjustmentTask?.traceId,\n      invalidSql: adjustmentTask?.invalidSql\n        ? safeFormatSQL(adjustmentTask.invalidSql)\n        : null,\n    };\n  }\n\n  public async generateThreadResponseBreakdown(\n    _root: any,\n    args: { responseId: number },\n    ctx: IContext,\n  ): Promise<ThreadResponse> {\n    const project = await ctx.projectService.getCurrentProject();\n    const { responseId } = args;\n    const askingService = ctx.askingService;\n    const breakdownDetail = await askingService.generateThreadResponseBreakdown(\n      responseId,\n      { language: WrenAILanguage[project.language] || WrenAILanguage.EN },\n    );\n    return breakdownDetail;\n  }\n\n  public async generateThreadResponseAnswer(\n    _root: any,\n    args: { responseId: number },\n    ctx: IContext,\n  ): Promise<ThreadResponse> {\n    const project = await ctx.projectService.getCurrentProject();\n    const { responseId } = args;\n    const askingService = ctx.askingService;\n    return askingService.generateThreadResponseAnswer(responseId, {\n      language: WrenAILanguage[project.language] || WrenAILanguage.EN,\n    });\n  }\n\n  public async generateThreadResponseChart(\n    _root: any,\n    args: { responseId: number },\n    ctx: IContext,\n  ): Promise<ThreadResponse> {\n    const project = await ctx.projectService.getCurrentProject();\n    const { responseId } = args;\n    const askingService = ctx.askingService;\n    return askingService.generateThreadResponseChart(responseId, {\n      language: WrenAILanguage[project.language] || WrenAILanguage.EN,\n    });\n  }\n\n  public async adjustThreadResponseChart(\n    _root: any,\n    args: { responseId: number; data: ChartAdjustmentOption },\n    ctx: IContext,\n  ): Promise<ThreadResponse> {\n    const project = await ctx.projectService.getCurrentProject();\n    const { responseId, data } = args;\n    const askingService = ctx.askingService;\n    return askingService.adjustThreadResponseChart(responseId, data, {\n      language: WrenAILanguage[project.language] || WrenAILanguage.EN,\n    });\n  }\n\n  public async getResponse(\n    _root: any,\n    args: { responseId: number },\n    ctx: IContext,\n  ): Promise<ThreadResponse> {\n    const { responseId } = args;\n    const askingService = ctx.askingService;\n    const response = await askingService.getResponse(responseId);\n\n    return response;\n  }\n\n  public async previewData(\n    _root: any,\n    args: { where: { responseId: number; stepIndex?: number; limit?: number } },\n    ctx: IContext,\n  ): Promise<any> {\n    const { responseId, limit } = args.where;\n    const askingService = ctx.askingService;\n    const data = await askingService.previewData(responseId, limit);\n    return data;\n  }\n\n  public async previewBreakdownData(\n    _root: any,\n    args: { where: { responseId: number; stepIndex?: number; limit?: number } },\n    ctx: IContext,\n  ): Promise<any> {\n    const { responseId, stepIndex, limit } = args.where;\n    const askingService = ctx.askingService;\n    const data = await askingService.previewBreakdownData(\n      responseId,\n      stepIndex,\n      limit,\n    );\n    return data;\n  }\n\n  public async createInstantRecommendedQuestions(\n    _root: any,\n    args: { data: { previousQuestions?: string[] } },\n    ctx: IContext,\n  ): Promise<Task> {\n    const { data } = args;\n    const askingService = ctx.askingService;\n    return askingService.createInstantRecommendedQuestions(data);\n  }\n\n  public async getInstantRecommendedQuestions(\n    _root: any,\n    args: { taskId: string },\n    ctx: IContext,\n  ): Promise<RecommendedQuestionsTask> {\n    const { taskId } = args;\n    const askingService = ctx.askingService;\n    const result = await askingService.getInstantRecommendedQuestions(taskId);\n    return {\n      questions: result.response?.questions || [],\n      status: result.status,\n      error: result.error,\n    };\n  }\n\n  /**\n   * Nested resolvers\n   */\n  public getThreadResponseNestedResolver = () => ({\n    view: async (parent: ThreadResponse, _args: any, ctx: IContext) => {\n      const viewId = parent.viewId;\n      if (!viewId) return null;\n      const view = await ctx.viewRepository.findOneBy({ id: viewId });\n      const displayName = view.properties\n        ? JSON.parse(view.properties)?.displayName\n        : view.name;\n      return { ...view, displayName };\n    },\n    answerDetail: (parent: ThreadResponse, _args: any, _ctx: IContext) => {\n      if (!parent?.answerDetail) return null;\n\n      const { content, ...rest } = parent.answerDetail;\n\n      if (!content) return parent.answerDetail;\n\n      const formattedContent = content\n        // replace the \\\\n to \\n\n        .replace(/\\\\n/g, '\\n')\n        // replace the \\\\\\\" to \\\",\n        .replace(/\\\\\"/g, '\"');\n\n      return {\n        ...rest,\n        content: formattedContent,\n      };\n    },\n    sql: (parent: ThreadResponse, _args: any, _ctx: IContext) => {\n      if (parent.breakdownDetail && parent.breakdownDetail.steps) {\n        // construct sql from breakdownDetail\n        return safeFormatSQL(constructCteSql(parent.breakdownDetail.steps));\n      }\n      return parent.sql ? safeFormatSQL(parent.sql) : null;\n    },\n    askingTask: async (parent: ThreadResponse, _args: any, ctx: IContext) => {\n      if (parent.adjustment) {\n        return null;\n      }\n      const askingService = ctx.askingService;\n      const askingTask = await askingService.getAskingTaskById(\n        parent.askingTaskId,\n      );\n      if (!askingTask) return null;\n      return this.transformAskingTask(askingTask, ctx);\n    },\n    adjustmentTask: async (\n      parent: ThreadResponse,\n      _args: any,\n      ctx: IContext,\n    ): Promise<AdjustmentTask> => {\n      if (!parent.adjustment) {\n        return null;\n      }\n      const askingService = ctx.askingService;\n      const adjustmentTask = await askingService.getAdjustmentTaskById(\n        parent.askingTaskId,\n      );\n      if (!adjustmentTask) return null;\n      return {\n        queryId: adjustmentTask?.queryId,\n        status: adjustmentTask?.status,\n        error: adjustmentTask?.error,\n        sql: adjustmentTask?.response?.[0]?.sql,\n        traceId: adjustmentTask?.traceId,\n        invalidSql: adjustmentTask?.invalidSql\n          ? safeFormatSQL(adjustmentTask.invalidSql)\n          : null,\n      };\n    },\n  });\n\n  public getDetailStepNestedResolver = () => ({\n    sql: (parent: DetailStep, _args: any, _ctx: IContext) => {\n      return safeFormatSQL(parent.sql);\n    },\n  });\n\n  public getResultCandidateNestedResolver = () => ({\n    sql: (parent: any, _args: any, _ctx: IContext) => {\n      return safeFormatSQL(parent.sql);\n    },\n    view: async (parent: any, _args: any, ctx: IContext) => {\n      const viewId = parent.view?.id;\n      if (!viewId) return parent.view;\n      const view = await ctx.viewRepository.findOneBy({ id: viewId });\n\n      const displayName = view.properties\n        ? JSON.parse(view.properties).displayName\n        : view.name;\n      return {\n        ...parent.view,\n        displayName,\n      };\n    },\n  });\n\n  private async transformAskingTask(\n    askingTask: TrackedAskingResult,\n    ctx: IContext,\n  ): Promise<AskingTask> {\n    // construct candidates from response\n    const candidates = await Promise.all(\n      (askingTask.response || []).map(async (response) => {\n        const view = response.viewId\n          ? await ctx.viewRepository.findOneBy({ id: response.viewId })\n          : null;\n        const sqlPair = response.sqlpairId\n          ? await ctx.sqlPairRepository.findOneBy({ id: response.sqlpairId })\n          : null;\n        return {\n          type: response.type,\n          sql: response.sql,\n          view,\n          sqlPair,\n        };\n      }),\n    );\n\n    // When the task got cancelled, the type is not set\n    // we set it to TEXT_TO_SQL as default\n    const type =\n      askingTask?.status === AskResultStatus.STOPPED && !askingTask.type\n        ? AskResultType.TEXT_TO_SQL\n        : askingTask.type;\n    return {\n      type,\n      status: askingTask.status,\n      error: askingTask.error,\n      candidates,\n      queryId: askingTask.queryId,\n      rephrasedQuestion: askingTask.rephrasedQuestion,\n      intentReasoning: askingTask.intentReasoning,\n      sqlGenerationReasoning: askingTask.sqlGenerationReasoning,\n      retrievedTables: askingTask.retrievedTables,\n      invalidSql: askingTask.invalidSql\n        ? safeFormatSQL(askingTask.invalidSql)\n        : null,\n      traceId: askingTask.traceId,\n    };\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/resolvers/dashboardResolver.ts",
    "content": "import { IContext } from '@server/types';\nimport { ChartType } from '@server/models/adaptor';\nimport {\n  UpdateDashboardItemLayouts,\n  PreviewDataResponse,\n  DEFAULT_PREVIEW_LIMIT,\n} from '@server/services';\nimport {\n  Dashboard,\n  DashboardItem,\n  DashboardItemType,\n} from '@server/repositories';\nimport { getLogger } from '@server/utils';\nimport {\n  SetDashboardCacheData,\n  DashboardSchedule,\n  PreviewItemResponse,\n} from '@server/models/dashboard';\n\nconst logger = getLogger('DashboardResolver');\nlogger.level = 'debug';\n\nexport class DashboardResolver {\n  constructor() {\n    this.getDashboard = this.getDashboard.bind(this);\n    this.getDashboardItems = this.getDashboardItems.bind(this);\n    this.createDashboardItem = this.createDashboardItem.bind(this);\n    this.updateDashboardItem = this.updateDashboardItem.bind(this);\n    this.deleteDashboardItem = this.deleteDashboardItem.bind(this);\n    this.updateDashboardItemLayouts =\n      this.updateDashboardItemLayouts.bind(this);\n    this.previewItemSQL = this.previewItemSQL.bind(this);\n    this.setDashboardSchedule = this.setDashboardSchedule.bind(this);\n  }\n\n  public async getDashboard(\n    _root: any,\n    _args: any,\n    ctx: IContext,\n  ): Promise<\n    Omit<Dashboard, 'nextScheduledAt'> & {\n      schedule: DashboardSchedule;\n      items: DashboardItem[];\n      nextScheduledAt: string | null;\n    }\n  > {\n    const dashboard = await ctx.dashboardService.getCurrentDashboard();\n    if (!dashboard) {\n      throw new Error('Dashboard not found.');\n    }\n    const schedule = ctx.dashboardService.parseCronExpression(dashboard);\n    const items = await ctx.dashboardService.getDashboardItems(dashboard.id);\n    return {\n      ...dashboard,\n      nextScheduledAt: dashboard.nextScheduledAt\n        ? new Date(dashboard.nextScheduledAt).toISOString()\n        : null,\n      schedule,\n      items,\n    };\n  }\n\n  public async getDashboardItems(\n    _root: any,\n    _args: any,\n    ctx: IContext,\n  ): Promise<DashboardItem[]> {\n    const dashboard = await ctx.dashboardService.getCurrentDashboard();\n    if (!dashboard) {\n      throw new Error('Dashboard not found.');\n    }\n    return await ctx.dashboardService.getDashboardItems(dashboard.id);\n  }\n\n  public async createDashboardItem(\n    _root: any,\n    args: { data: { itemType: DashboardItemType; responseId: number } },\n    ctx: IContext,\n  ): Promise<DashboardItem> {\n    const { responseId, itemType } = args.data;\n    const dashboard = await ctx.dashboardService.getCurrentDashboard();\n    const response = await ctx.askingService.getResponse(responseId);\n\n    if (!response) {\n      throw new Error(`Thread response not found. responseId: ${responseId}`);\n    }\n    if (!Object.keys(ChartType).includes(itemType)) {\n      throw new Error(`Chart type not supported. responseId: ${responseId}`);\n    }\n    if (!response.chartDetail?.chartSchema) {\n      throw new Error(\n        `Chart schema not found in thread response. responseId: ${responseId}`,\n      );\n    }\n\n    // query with cache enabled\n    const project = await ctx.projectService.getCurrentProject();\n    const deployment = await ctx.deployService.getLastDeployment(project.id);\n    const mdl = deployment.manifest;\n    await ctx.queryService.preview(response.sql, {\n      project,\n      manifest: mdl,\n      limit: DEFAULT_PREVIEW_LIMIT,\n      cacheEnabled: true,\n      refresh: true,\n    });\n\n    return await ctx.dashboardService.createDashboardItem({\n      dashboardId: dashboard.id,\n      type: itemType,\n      sql: response.sql,\n      chartSchema: response.chartDetail?.chartSchema,\n    });\n  }\n\n  public async updateDashboardItem(\n    _root: any,\n    args: { where: { id: number }; data: { displayName: string } },\n    ctx: IContext,\n  ): Promise<DashboardItem> {\n    const { id } = args.where;\n    const { displayName } = args.data;\n    const item = await ctx.dashboardService.getDashboardItem(id);\n    if (!item) {\n      throw new Error(`Dashboard item not found. id: ${id}`);\n    }\n    return await ctx.dashboardService.updateDashboardItem(id, { displayName });\n  }\n\n  public async deleteDashboardItem(\n    _root: any,\n    args: { where: { id: number } },\n    ctx: IContext,\n  ): Promise<boolean> {\n    const { id } = args.where;\n    const item = await ctx.dashboardService.getDashboardItem(id);\n    if (!item) {\n      throw new Error(`Dashboard item not found. id: ${id}`);\n    }\n    return await ctx.dashboardService.deleteDashboardItem(id);\n  }\n\n  public async updateDashboardItemLayouts(\n    _root: any,\n    args: { data: { layouts: UpdateDashboardItemLayouts } },\n    ctx: IContext,\n  ): Promise<DashboardItem[]> {\n    const { layouts } = args.data;\n    if (layouts.length === 0) {\n      throw new Error('Layouts are required.');\n    }\n    return await ctx.dashboardService.updateDashboardItemLayouts(layouts);\n  }\n\n  public async previewItemSQL(\n    _root: any,\n    args: { data: { itemId: number; limit?: number; refresh?: boolean } },\n    ctx: IContext,\n  ): Promise<PreviewItemResponse> {\n    const { itemId, limit, refresh } = args.data;\n    try {\n      const item = await ctx.dashboardService.getDashboardItem(itemId);\n      const { cacheEnabled } = await ctx.dashboardService.getCurrentDashboard();\n      const project = await ctx.projectService.getCurrentProject();\n      const deployment = await ctx.deployService.getLastDeployment(project.id);\n      const mdl = deployment.manifest;\n      const data = (await ctx.queryService.preview(item.detail.sql, {\n        project,\n        manifest: mdl,\n        limit: limit || DEFAULT_PREVIEW_LIMIT,\n        cacheEnabled,\n        refresh: refresh || false,\n      })) as PreviewDataResponse;\n\n      // handle data to [{ column1: value1, column2: value2, ... }]\n      const values = data.data.map((val) => {\n        return data.columns.reduce((acc, col, index) => {\n          acc[col.name] = val[index];\n          return acc;\n        }, {});\n      });\n      return {\n        cacheHit: data.cacheHit || false,\n        cacheCreatedAt: data.cacheCreatedAt || null,\n        cacheOverrodeAt: data.cacheOverrodeAt || null,\n        override: data.override || false,\n        data: values,\n      } as PreviewItemResponse;\n    } catch (error) {\n      logger.error(`Error previewing SQL item ${itemId}: ${error}`);\n      throw error;\n    }\n  }\n\n  public async setDashboardSchedule(\n    _root: any,\n    args: { data: SetDashboardCacheData },\n    ctx: IContext,\n  ): Promise<Dashboard> {\n    try {\n      const dashboard = await ctx.dashboardService.getCurrentDashboard();\n      if (!dashboard) {\n        throw new Error('Dashboard not found.');\n      }\n\n      return await ctx.dashboardService.setDashboardSchedule(\n        dashboard.id,\n        args.data,\n      );\n    } catch (error) {\n      logger.error(`Failed to set dashboard schedule: ${error.message}`);\n      throw error;\n    }\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/resolvers/diagramResolver.ts",
    "content": "import { v4 as uuidv4 } from 'uuid';\nimport {\n  Model,\n  ModelColumn,\n  ModelNestedColumn,\n  RelationInfo,\n  View,\n} from '@server/repositories';\nimport {\n  Diagram,\n  DiagramModel,\n  DiagramModelField,\n  DiagramModelRelationField,\n  NodeType,\n  IContext,\n  RelationType,\n  DiagramView,\n} from '@server/types';\nimport { ColumnMDL, Manifest } from '@server/mdl/type';\nimport { getLogger } from '@server/utils';\nimport { MDLBuilder } from '../mdl/mdlBuilder';\n\nconst logger = getLogger('DiagramResolver');\nlogger.level = 'debug';\n\nexport class DiagramResolver {\n  constructor() {\n    this.getDiagram = this.getDiagram.bind(this);\n  }\n\n  public async getDiagram(\n    _root: any,\n    _args: any,\n    ctx: IContext,\n  ): Promise<Diagram> {\n    const project = await ctx.projectRepository.getCurrentProject();\n    const models = await ctx.modelRepository.findAllBy({\n      projectId: project.id,\n    });\n\n    const modelIds = models.map((model) => model.id);\n    const modelColumns =\n      await ctx.modelColumnRepository.findColumnsByModelIds(modelIds);\n    const modelNestedColumns =\n      await ctx.modelNestedColumnRepository.findNestedColumnsByModelIds(\n        modelIds,\n      );\n    const modelRelations = await ctx.relationRepository.findRelationInfoBy({\n      columnIds: modelColumns.map((column) => column.id),\n    });\n    const views = await ctx.viewRepository.findAllBy({\n      projectId: project.id,\n    });\n\n    const builder = new MDLBuilder({\n      project,\n      models,\n      columns: modelColumns,\n      nestedColumns: modelNestedColumns,\n      relations: modelRelations,\n      views,\n      relatedModels: models,\n      relatedColumns: modelColumns,\n      relatedRelations: modelRelations,\n    });\n\n    const manifest = builder.build();\n\n    return this.buildDiagram(\n      models,\n      modelColumns,\n      modelNestedColumns,\n      modelRelations,\n      views,\n      manifest,\n    );\n  }\n\n  private buildDiagram(\n    models: Model[],\n    modelColumns: ModelColumn[],\n    modelNestedColumns: ModelNestedColumn[],\n    relations: RelationInfo[],\n    views: View[],\n    manifest: Manifest,\n  ): Diagram {\n    const diagramModels = models.map((model) => {\n      const transformedModel = this.transformModel(model);\n      const allColumns = modelColumns.filter(\n        (column) => column.modelId === model.id,\n      );\n      const modelMDL = manifest.models.find(\n        (modelMDL) => modelMDL.name === model.referenceName,\n      );\n      allColumns.forEach((column) => {\n        const columnRelations = relations\n          .map((relation) =>\n            [relation.fromColumnId, relation.toColumnId].includes(column.id)\n              ? relation\n              : null,\n          )\n          .filter((relation) => !!relation);\n\n        if (columnRelations.length > 0) {\n          columnRelations.forEach((relation) => {\n            const transformedRelationField = this.transformModelRelationField({\n              relation,\n              currentModel: model,\n              models,\n            });\n            transformedModel.relationFields.push(transformedRelationField);\n          });\n        }\n\n        if (column.isCalculated) {\n          transformedModel.calculatedFields.push(\n            this.transformCalculatedField(column, modelMDL.columns),\n          );\n        } else {\n          const nestedColumns = modelNestedColumns.filter(\n            (nestedColumn) => nestedColumn.columnId === column.id,\n          );\n          transformedModel.fields.push(\n            this.transformNormalField(column, nestedColumns),\n          );\n        }\n      });\n      return transformedModel;\n    });\n\n    const diagramViews = views.map(this.transformView);\n    return { models: diagramModels, views: diagramViews };\n  }\n\n  private transformModel(model: Model): DiagramModel {\n    const properties = JSON.parse(model.properties);\n    return {\n      id: uuidv4(),\n      modelId: model.id,\n      nodeType: NodeType.MODEL,\n      displayName: model.displayName,\n      referenceName: model.referenceName,\n      sourceTableName: model.sourceTableName,\n      refSql: model.refSql,\n      refreshTime: model.refreshTime,\n      cached: model.cached,\n      description: properties?.description,\n      fields: [],\n      calculatedFields: [],\n      relationFields: [],\n    };\n  }\n\n  private transformNormalField(\n    column: ModelColumn,\n    nestedColumns: ModelNestedColumn[],\n  ): DiagramModelField {\n    const properties = JSON.parse(column.properties);\n    return {\n      id: uuidv4(),\n      columnId: column.id,\n      nodeType: column.isCalculated\n        ? NodeType.CALCULATED_FIELD\n        : NodeType.FIELD,\n      type: column.type,\n      displayName: column.displayName,\n      referenceName: column.referenceName,\n      description: properties?.description,\n      isPrimaryKey: column.isPk,\n      expression: column.aggregation,\n      nestedFields: nestedColumns.length\n        ? nestedColumns.map((nestedColumn) => ({\n            id: uuidv4(),\n            nestedColumnId: nestedColumn.id,\n            columnPath: nestedColumn.columnPath,\n            type: nestedColumn.type,\n            displayName: nestedColumn.displayName,\n            referenceName: nestedColumn.referenceName,\n            description: nestedColumn.properties?.description,\n          }))\n        : null,\n    };\n  }\n\n  private transformCalculatedField(\n    column: ModelColumn,\n    columnsMDL: ColumnMDL[],\n  ): DiagramModelField {\n    const properties = JSON.parse(column.properties);\n    const lineage = JSON.parse(column.lineage);\n    const columnMDL = columnsMDL.find(\n      ({ name }) => name === column.referenceName,\n    );\n    return {\n      id: uuidv4(),\n      columnId: column.id,\n      nodeType: NodeType.CALCULATED_FIELD,\n      aggregation: column.aggregation,\n      lineage,\n      type: column.type,\n      displayName: column.displayName,\n      referenceName: column.referenceName,\n      description: properties?.description,\n      isPrimaryKey: column.isPk,\n      expression: columnMDL.expression,\n    };\n  }\n\n  private transformModelRelationField({\n    relation,\n    currentModel,\n    models,\n  }: {\n    relation: RelationInfo;\n    currentModel: Model;\n    models: Model[];\n  }): DiagramModelRelationField {\n    const referenceName =\n      currentModel.referenceName === relation.fromModelName\n        ? relation.toModelName\n        : relation.fromModelName;\n    const displayName = models.find(\n      (model) => model.referenceName === referenceName,\n    )?.displayName;\n    const properties = relation.properties\n      ? JSON.parse(relation.properties)\n      : null;\n    return {\n      id: uuidv4(),\n      relationId: relation.id,\n      nodeType: NodeType.RELATION,\n      displayName,\n      referenceName,\n      type: relation.joinType as RelationType,\n      fromModelId: relation.fromModelId,\n      fromModelName: relation.fromModelName,\n      fromModelDisplayName: relation.fromModelDisplayName,\n      fromColumnId: relation.fromColumnId,\n      fromColumnName: relation.fromColumnName,\n      fromColumnDisplayName: relation.fromColumnDisplayName,\n      toModelId: relation.toModelId,\n      toModelName: relation.toModelName,\n      toModelDisplayName: relation.toModelDisplayName,\n      toColumnId: relation.toColumnId,\n      toColumnName: relation.toColumnName,\n      toColumnDisplayName: relation.toColumnDisplayName,\n      description: properties?.description,\n    };\n  }\n\n  private transformView(view: View): DiagramView {\n    const properties = JSON.parse(view.properties);\n    const fields = (properties?.columns || []).map((column: any) => ({\n      id: uuidv4(),\n      nodeType: NodeType.FIELD,\n      type: column.type,\n      displayName: column.name,\n      referenceName: column.name,\n      description: column?.properties?.description,\n    }));\n\n    return {\n      id: uuidv4(),\n      viewId: view.id,\n      nodeType: NodeType.VIEW,\n      statement: view.statement,\n      referenceName: view.name,\n      displayName: properties?.displayName || view.name,\n      fields,\n      description: properties?.description,\n    };\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/resolvers/instructionResolver.ts",
    "content": "import { IContext } from '@server/types';\nimport { UpdateInstructionInput } from '@server/models';\nimport { Instruction } from '@server/repositories/instructionRepository';\nimport { getLogger } from '@server/utils';\nimport { TelemetryEvent, TrackTelemetry } from '@server/telemetry/telemetry';\n\nconst logger = getLogger('InstructionResolver');\nlogger.level = 'debug';\n\nexport class InstructionResolver {\n  constructor() {\n    this.getInstructions = this.getInstructions.bind(this);\n    this.createInstruction = this.createInstruction.bind(this);\n    this.updateInstruction = this.updateInstruction.bind(this);\n    this.deleteInstruction = this.deleteInstruction.bind(this);\n  }\n\n  public async getInstructions(\n    _root: any,\n    _args: any,\n    ctx: IContext,\n  ): Promise<Instruction[]> {\n    try {\n      const project = await ctx.projectService.getCurrentProject();\n      return await ctx.instructionService.getInstructions(project.id);\n    } catch (error) {\n      logger.error(`Error getting instructions: ${error}`);\n      throw error;\n    }\n  }\n\n  @TrackTelemetry(TelemetryEvent.KNOWLEDGE_CREATE_INSTRUCTION)\n  public async createInstruction(\n    _root: any,\n    args: {\n      data: {\n        instruction: string;\n        questions: string[];\n        isDefault: boolean;\n      };\n    },\n    ctx: IContext,\n  ): Promise<Instruction> {\n    const { instruction, questions, isDefault } = args.data;\n    const project = await ctx.projectService.getCurrentProject();\n    return await ctx.instructionService.createInstruction({\n      instruction,\n      questions,\n      isDefault,\n      projectId: project.id,\n    });\n  }\n\n  @TrackTelemetry(TelemetryEvent.KNOWLEDGE_UPDATE_INSTRUCTION)\n  public async updateInstruction(\n    _root: any,\n    args: {\n      data: Pick<\n        UpdateInstructionInput,\n        'instruction' | 'questions' | 'isDefault'\n      >;\n      where: { id: number };\n    },\n    ctx: IContext,\n  ): Promise<Instruction> {\n    const { id } = args.where;\n    const { instruction, questions, isDefault } = args.data;\n    if (!id) {\n      throw new Error('Instruction ID is required.');\n    }\n    const project = await ctx.projectService.getCurrentProject();\n    return await ctx.instructionService.updateInstruction({\n      id,\n      projectId: project.id,\n      instruction,\n      questions,\n      isDefault,\n    });\n  }\n\n  @TrackTelemetry(TelemetryEvent.KNOWLEDGE_DELETE_INSTRUCTION)\n  public async deleteInstruction(\n    _root: any,\n    args: { where: { id: number } },\n    ctx: IContext,\n  ): Promise<boolean> {\n    const { id } = args.where;\n    const project = await ctx.projectService.getCurrentProject();\n    await ctx.instructionService.deleteInstruction(id, project.id);\n    return true;\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/resolvers/learningResolver.ts",
    "content": "import { IContext } from '@server/types';\nimport { getConfig } from '@server/config';\n\nimport { getLogger } from '@server/utils';\nimport { uniq } from 'lodash';\n\nconst config = getConfig();\n\nconst logger = getLogger('LearingResolver');\nlogger.level = 'debug';\n\nexport class LearningResolver {\n  constructor() {\n    this.getLearningRecord = this.getLearningRecord.bind(this);\n    this.saveLearningRecord = this.saveLearningRecord.bind(this);\n  }\n\n  public async getLearningRecord(\n    _root: any,\n    _args: any,\n    ctx: IContext,\n  ): Promise<any> {\n    const result = await ctx.learningRepository.findAll();\n    return { paths: result[0]?.paths || [] };\n  }\n\n  public async saveLearningRecord(\n    _root: any,\n    args: any,\n    ctx: IContext,\n  ): Promise<any> {\n    const { path } = args.data;\n    const result = await ctx.learningRepository.findAll();\n\n    if (!result.length) {\n      return await ctx.learningRepository.createOne({\n        userId: config?.userUUID,\n        paths: [path],\n      });\n    }\n\n    const [record] = result;\n    return await ctx.learningRepository.updateOne(record.id, {\n      userId: config?.userUUID,\n      paths: uniq([...record.paths, path]),\n    });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/resolvers/modelResolver.ts",
    "content": "import {\n  CreateModelData,\n  UpdateModelData,\n  UpdateModelMetadataInput,\n  CreateCalculatedFieldData,\n  UpdateCalculatedFieldData,\n  UpdateViewMetadataInput,\n  PreviewSQLData,\n} from '../models';\nimport {\n  DataSourceName,\n  IContext,\n  RelationData,\n  UpdateRelationData,\n} from '../types';\nimport { getLogger, transformInvalidColumnName } from '@server/utils';\nimport { DeployResponse } from '../services/deployService';\nimport { safeFormatSQL } from '@server/utils/sqlFormat';\nimport { isEmpty, isNil } from 'lodash';\nimport { replaceAllowableSyntax, validateDisplayName } from '../utils/regex';\nimport { Model, ModelColumn } from '../repositories';\nimport {\n  findColumnsToUpdate,\n  getPreviewColumnsStr,\n  handleNestedColumns,\n  replaceInvalidReferenceName,\n  updateModelPrimaryKey,\n} from '../utils/model';\nimport { CompactTable, PreviewDataResponse } from '@server/services';\nimport { TelemetryEvent } from '../telemetry/telemetry';\n\nconst logger = getLogger('ModelResolver');\nlogger.level = 'debug';\n\nexport enum SyncStatusEnum {\n  IN_PROGRESS = 'IN_PROGRESS',\n  SYNCRONIZED = 'SYNCRONIZED',\n  UNSYNCRONIZED = 'UNSYNCRONIZED',\n}\n\nexport class ModelResolver {\n  constructor() {\n    // model & model column\n    this.listModels = this.listModels.bind(this);\n    this.getModel = this.getModel.bind(this);\n    this.createModel = this.createModel.bind(this);\n    this.updateModel = this.updateModel.bind(this);\n    this.deleteModel = this.deleteModel.bind(this);\n    this.updateModelMetadata = this.updateModelMetadata.bind(this);\n    this.deploy = this.deploy.bind(this);\n    this.getMDL = this.getMDL.bind(this);\n    this.checkModelSync = this.checkModelSync.bind(this);\n\n    // view\n    this.listViews = this.listViews.bind(this);\n    this.getView = this.getView.bind(this);\n    this.validateView = this.validateView.bind(this);\n    this.createView = this.createView.bind(this);\n    this.deleteView = this.deleteView.bind(this);\n    this.updateViewMetadata = this.updateViewMetadata.bind(this);\n\n    // preview\n    this.previewModelData = this.previewModelData.bind(this);\n    this.previewViewData = this.previewViewData.bind(this);\n    this.previewSql = this.previewSql.bind(this);\n    this.getNativeSql = this.getNativeSql.bind(this);\n\n    // calculated field\n    this.createCalculatedField = this.createCalculatedField.bind(this);\n    this.validateCalculatedField = this.validateCalculatedField.bind(this);\n    this.updateCalculatedField = this.updateCalculatedField.bind(this);\n    this.deleteCalculatedField = this.deleteCalculatedField.bind(this);\n\n    // relation\n    this.createRelation = this.createRelation.bind(this);\n    this.updateRelation = this.updateRelation.bind(this);\n    this.deleteRelation = this.deleteRelation.bind(this);\n  }\n\n  public async createRelation(\n    _root: any,\n    args: { data: RelationData },\n    ctx: IContext,\n  ) {\n    const { data } = args;\n\n    const eventName = TelemetryEvent.MODELING_CREATE_RELATION;\n    try {\n      const relation = await ctx.modelService.createRelation(data);\n      ctx.telemetry.sendEvent(eventName, { data });\n      return relation;\n    } catch (err: any) {\n      ctx.telemetry.sendEvent(\n        eventName,\n        { data: data, error: err.message },\n        err.extensions?.service,\n        false,\n      );\n      throw err;\n    }\n  }\n\n  public async updateRelation(\n    _root: any,\n    args: { data: UpdateRelationData; where: { id: number } },\n    ctx: IContext,\n  ) {\n    const { data, where } = args;\n    const eventName = TelemetryEvent.MODELING_UPDATE_RELATION;\n    try {\n      const relation = await ctx.modelService.updateRelation(data, where.id);\n      ctx.telemetry.sendEvent(eventName, { data });\n      return relation;\n    } catch (err: any) {\n      ctx.telemetry.sendEvent(\n        eventName,\n        { data: data, error: err.message },\n        err.extensions?.service,\n        false,\n      );\n      throw err;\n    }\n  }\n\n  public async deleteRelation(\n    _root: any,\n    args: { where: { id: number } },\n    ctx: IContext,\n  ) {\n    const relationId = args.where.id;\n    await ctx.modelService.deleteRelation(relationId);\n    return true;\n  }\n\n  public async createCalculatedField(\n    _root: any,\n    _args: { data: CreateCalculatedFieldData },\n    ctx: IContext,\n  ) {\n    const eventName = TelemetryEvent.MODELING_CREATE_CF;\n    try {\n      const column = await ctx.modelService.createCalculatedField(_args.data);\n      ctx.telemetry.sendEvent(eventName, { data: _args.data });\n      return column;\n    } catch (err: any) {\n      ctx.telemetry.sendEvent(\n        eventName,\n        { data: _args.data, error: err.message },\n        err.extensions?.service,\n        false,\n      );\n      throw err;\n    }\n  }\n\n  public async validateCalculatedField(_root: any, args: any, ctx: IContext) {\n    const { name, modelId, columnId } = args.data;\n    return await ctx.modelService.validateCalculatedFieldNaming(\n      name,\n      modelId,\n      columnId,\n    );\n  }\n\n  public async updateCalculatedField(\n    _root: any,\n    _args: { data: UpdateCalculatedFieldData; where: { id: number } },\n    ctx: IContext,\n  ) {\n    const { data, where } = _args;\n\n    const eventName = TelemetryEvent.MODELING_UPDATE_CF;\n    try {\n      const column = await ctx.modelService.updateCalculatedField(\n        data,\n        where.id,\n      );\n      ctx.telemetry.sendEvent(eventName, { data });\n      return column;\n    } catch (err: any) {\n      ctx.telemetry.sendEvent(\n        eventName,\n        { data: data, error: err.message },\n        err.extensions?.service,\n        false,\n      );\n      throw err;\n    }\n  }\n\n  public async deleteCalculatedField(_root: any, args: any, ctx: IContext) {\n    const columnId = args.where.id;\n    // check column exist and is calculated field\n    const column = await ctx.modelColumnRepository.findOneBy({ id: columnId });\n    if (!column || !column.isCalculated) {\n      throw new Error('Calculated field not found');\n    }\n    await ctx.modelColumnRepository.deleteOne(columnId);\n    return true;\n  }\n\n  public async checkModelSync(_root: any, _args: any, ctx: IContext) {\n    const { id } = await ctx.projectService.getCurrentProject();\n    const { manifest } = await ctx.mdlService.makeCurrentModelMDL();\n    const currentHash = ctx.deployService.createMDLHash(manifest, id);\n    const lastDeploy = await ctx.deployService.getLastDeployment(id);\n    const lastDeployHash = lastDeploy?.hash;\n    const inProgressDeployment =\n      await ctx.deployService.getInProgressDeployment(id);\n    if (inProgressDeployment) {\n      return { status: SyncStatusEnum.IN_PROGRESS };\n    }\n    return currentHash == lastDeployHash\n      ? { status: SyncStatusEnum.SYNCRONIZED }\n      : { status: SyncStatusEnum.UNSYNCRONIZED };\n  }\n\n  public async deploy(\n    _root: any,\n    args: { force: boolean },\n    ctx: IContext,\n  ): Promise<DeployResponse> {\n    const project = await ctx.projectService.getCurrentProject();\n    if (!project.version && project.type !== DataSourceName.DUCKDB) {\n      const version =\n        await ctx.projectService.getProjectDataSourceVersion(project);\n      await ctx.projectService.updateProject(project.id, {\n        version,\n      });\n    }\n    const { manifest } = await ctx.mdlService.makeCurrentModelMDL();\n    const deployRes = await ctx.deployService.deploy(\n      manifest,\n      project.id,\n      args.force,\n    );\n\n    // only generating for user's data source\n    if (project.sampleDataset === null) {\n      await ctx.projectService.generateProjectRecommendationQuestions();\n    }\n    return deployRes;\n  }\n\n  public async getMDL(_root: any, args: { hash: string }, ctx: IContext) {\n    const mdl = await ctx.deployService.getMDLByHash(args.hash);\n    return {\n      hash: args.hash,\n      mdl,\n    };\n  }\n\n  public async listModels(_root: any, _args: any, ctx: IContext) {\n    const { id: projectId } = await ctx.projectService.getCurrentProject();\n    const models = await ctx.modelRepository.findAllBy({ projectId });\n    const modelIds = models.map((m) => m.id);\n    const modelColumnList =\n      await ctx.modelColumnRepository.findColumnsByModelIds(modelIds);\n    const modelNestedColumnList =\n      await ctx.modelNestedColumnRepository.findNestedColumnsByModelIds(\n        modelIds,\n      );\n    const result = [];\n    for (const model of models) {\n      const modelFields = modelColumnList\n        .filter((c) => c.modelId === model.id)\n        .map((c) => ({\n          ...c,\n          properties: JSON.parse(c.properties),\n          nestedColumns: c.type.includes('STRUCT')\n            ? modelNestedColumnList.filter((nc) => nc.columnId === c.id)\n            : undefined,\n        }));\n      const fields = modelFields.filter((c) => !c.isCalculated);\n      const calculatedFields = modelFields.filter((c) => c.isCalculated);\n      result.push({\n        ...model,\n        fields,\n        calculatedFields,\n        properties: {\n          ...JSON.parse(model.properties),\n        },\n      });\n    }\n    return result;\n  }\n\n  public async getModel(_root: any, args: any, ctx: IContext) {\n    const modelId = args.where.id;\n    const model = await ctx.modelRepository.findOneBy({ id: modelId });\n    if (!model) {\n      throw new Error('Model not found');\n    }\n\n    const modelColumns = await ctx.modelColumnRepository.findColumnsByModelIds([\n      model.id,\n    ]);\n    const modelNestedColumns = await ctx.modelNestedColumnRepository.findAllBy({\n      modelId: model.id,\n    });\n\n    const columns = modelColumns.map((c) => ({\n      ...c,\n      properties: JSON.parse(c.properties),\n      nestedColumns: c.type.includes('STRUCT')\n        ? modelNestedColumns.filter((nc) => nc.columnId === c.id)\n        : undefined,\n    }));\n    const relations = (\n      await ctx.relationRepository.findRelationsBy({\n        columnIds: modelColumns.map((c) => c.id),\n      })\n    ).map((r) => ({\n      ...r,\n      type: r.joinType,\n      properties: r.properties ? JSON.parse(r.properties) : {},\n    }));\n\n    return {\n      ...model,\n      fields: columns.filter((c) => !c.isCalculated),\n      calculatedFields: columns.filter((c) => c.isCalculated),\n      relations,\n      properties: {\n        ...JSON.parse(model.properties),\n      },\n    };\n  }\n\n  public async createModel(\n    _root: any,\n    args: { data: CreateModelData },\n    ctx: IContext,\n  ) {\n    const { sourceTableName, fields, primaryKey } = args.data;\n    try {\n      const model = await this.handleCreateModel(\n        ctx,\n        sourceTableName,\n        fields,\n        primaryKey,\n      );\n      ctx.telemetry.sendEvent(TelemetryEvent.MODELING_CREATE_MODEL, {\n        data: args.data,\n      });\n      return model;\n    } catch (error: any) {\n      ctx.telemetry.sendEvent(\n        TelemetryEvent.MODELING_CREATE_MODEL,\n        { data: args.data, error },\n        error.extensions?.service,\n        false,\n      );\n      throw error;\n    }\n  }\n\n  private async handleCreateModel(\n    ctx: IContext,\n    sourceTableName: string,\n    fields: [string],\n    primaryKey: string,\n  ) {\n    const project = await ctx.projectService.getCurrentProject();\n    const dataSourceTables =\n      await ctx.projectService.getProjectDataSourceTables(project);\n    this.validateTableExist(sourceTableName, dataSourceTables);\n    this.validateColumnsExist(sourceTableName, fields, dataSourceTables);\n\n    // create model\n    const dataSourceTable = dataSourceTables.find(\n      (table) => table.name === sourceTableName,\n    );\n    if (!dataSourceTable) {\n      throw new Error('Table not found in the data source');\n    }\n    const properties = dataSourceTable?.properties;\n    const modelValue = {\n      projectId: project.id,\n      displayName: sourceTableName, //use table name as displayName, referenceName and tableName\n      referenceName: replaceInvalidReferenceName(sourceTableName),\n      sourceTableName: sourceTableName,\n      cached: false,\n      refreshTime: null,\n      properties: properties ? JSON.stringify(properties) : null,\n    } as Partial<Model>;\n    const model = await ctx.modelRepository.createOne(modelValue);\n\n    // create columns\n    const compactColumns = dataSourceTable.columns.filter((c) =>\n      fields.includes(c.name),\n    );\n    const columnValues = compactColumns.map(\n      (column) =>\n        ({\n          modelId: model.id,\n          isCalculated: false,\n          displayName: column.name,\n          referenceName: transformInvalidColumnName(column.name),\n          sourceColumnName: column.name,\n          type: column.type || 'string',\n          notNull: column.notNull || false,\n          isPk: primaryKey === column.name,\n          properties: column.properties\n            ? JSON.stringify(column.properties)\n            : null,\n        }) as Partial<ModelColumn>,\n    );\n    const columns = await ctx.modelColumnRepository.createMany(columnValues);\n\n    // create nested columns\n    const nestedColumnValues = compactColumns.flatMap((compactColumn) => {\n      const column = columns.find(\n        (c) => c.sourceColumnName === compactColumn.name,\n      );\n      if (!column) return [];\n      return handleNestedColumns(compactColumn, {\n        modelId: column.modelId,\n        columnId: column.id,\n        sourceColumnName: column.sourceColumnName,\n      });\n    });\n    await ctx.modelNestedColumnRepository.createMany(nestedColumnValues);\n    logger.info(`Model created: ${JSON.stringify(model)}`);\n\n    return model;\n  }\n\n  public async updateModel(\n    _root: any,\n    args: { data: UpdateModelData; where: { id: number } },\n    ctx: IContext,\n  ) {\n    const { fields, primaryKey } = args.data;\n    try {\n      const model = await this.handleUpdateModel(ctx, args, fields, primaryKey);\n      ctx.telemetry.sendEvent(TelemetryEvent.MODELING_UPDATE_MODEL, {\n        data: args.data,\n      });\n      return model;\n    } catch (err: any) {\n      ctx.telemetry.sendEvent(\n        TelemetryEvent.MODELING_UPDATE_MODEL,\n        { data: args.data, error: err.message },\n        err.extensions?.service,\n        false,\n      );\n      throw err;\n    }\n  }\n\n  private async handleUpdateModel(\n    ctx: IContext,\n    args: { data: UpdateModelData; where: { id: number } },\n    fields: [string],\n    primaryKey: string,\n  ) {\n    const project = await ctx.projectService.getCurrentProject();\n    const dataSourceTables =\n      await ctx.projectService.getProjectDataSourceTables(project);\n    const model = await ctx.modelRepository.findOneBy({ id: args.where.id });\n    const existingColumns = await ctx.modelColumnRepository.findAllBy({\n      modelId: model.id,\n      isCalculated: false,\n    });\n    const { sourceTableName } = model;\n    this.validateTableExist(sourceTableName, dataSourceTables);\n    this.validateColumnsExist(sourceTableName, fields, dataSourceTables);\n\n    const sourceTableColumns = dataSourceTables.find(\n      (table) => table.name === sourceTableName,\n    )?.columns;\n    const { toDeleteColumnIds, toCreateColumns, toUpdateColumns } =\n      findColumnsToUpdate(fields, existingColumns, sourceTableColumns);\n    await updateModelPrimaryKey(\n      ctx.modelColumnRepository,\n      model.id,\n      primaryKey,\n    );\n\n    // delete columns\n    if (toDeleteColumnIds.length) {\n      await ctx.modelColumnRepository.deleteMany(toDeleteColumnIds);\n    }\n\n    // create columns\n    if (toCreateColumns.length) {\n      const compactColumns = sourceTableColumns.filter((sourceColumn) =>\n        toCreateColumns.includes(sourceColumn.name),\n      );\n      const columnValues = compactColumns.map((column) => {\n        const columnValue = {\n          modelId: model.id,\n          isCalculated: false,\n          displayName: column.name,\n          sourceColumnName: column.name,\n          referenceName: transformInvalidColumnName(column.name),\n          type: column.type || 'string',\n          notNull: column.notNull,\n          isPk: primaryKey === column.name,\n          properties: column.properties\n            ? JSON.stringify(column.properties)\n            : null,\n        } as Partial<ModelColumn>;\n        return columnValue;\n      });\n      const columns = await ctx.modelColumnRepository.createMany(columnValues);\n\n      // create nested columns\n      const nestedColumnValues = compactColumns.flatMap((compactColumn) => {\n        const column = columns.find(\n          (c) => c.sourceColumnName === compactColumn.name,\n        );\n        return handleNestedColumns(compactColumn, {\n          modelId: column.modelId,\n          columnId: column.id,\n          sourceColumnName: column.sourceColumnName,\n        });\n      });\n      await ctx.modelNestedColumnRepository.createMany(nestedColumnValues);\n    }\n\n    // update columns\n    if (toUpdateColumns.length) {\n      for (const { id, sourceColumnName, type } of toUpdateColumns) {\n        const column = await ctx.modelColumnRepository.updateOne(id, { type });\n\n        // if the struct type is changed, need to re-create nested columns\n        if (type.includes('STRUCT')) {\n          const sourceColumn = sourceTableColumns.find(\n            (sourceColumn) => sourceColumn.name === sourceColumnName,\n          );\n          await ctx.modelNestedColumnRepository.deleteAllBy({\n            columnId: column.id,\n          });\n          await ctx.modelNestedColumnRepository.createMany(\n            handleNestedColumns(sourceColumn, {\n              modelId: column.modelId,\n              columnId: column.id,\n              sourceColumnName: sourceColumnName,\n            }),\n          );\n        }\n      }\n    }\n\n    logger.info(`Model updated: ${JSON.stringify(model)}`);\n    return model;\n  }\n\n  // delete model\n  public async deleteModel(_root: any, args: any, ctx: IContext) {\n    const modelId = args.where.id;\n    const model = await ctx.modelRepository.findOneBy({ id: modelId });\n    if (!model) {\n      throw new Error('Model not found');\n    }\n\n    // related columns and relationships will be deleted in cascade\n    await ctx.modelRepository.deleteOne(modelId);\n    return true;\n  }\n\n  // update model metadata\n  public async updateModelMetadata(\n    _root: any,\n    args: { where: { id: number }; data: UpdateModelMetadataInput },\n    ctx: IContext,\n  ): Promise<boolean> {\n    const modelId = args.where.id;\n    const data = args.data;\n\n    // check if model exists\n    const model = await ctx.modelRepository.findOneBy({ id: modelId });\n    if (!model) {\n      throw new Error('Model not found');\n    }\n    const eventName = TelemetryEvent.MODELING_UPDATE_MODEL_METADATA;\n    try {\n      // update model metadata\n      await this.handleUpdateModelMetadata(data, model, ctx, modelId);\n\n      // todo: considering using update ... from statement to do a batch update\n      // update column metadata\n      if (!isEmpty(data.columns)) {\n        // find the columns that match the user requested columns\n        await this.handleUpdateColumnMetadata(data, ctx);\n      }\n\n      // update nested column metadata\n      if (!isEmpty(data.nestedColumns)) {\n        await this.handleUpdateNestedColumnMetadata(data, ctx);\n      }\n\n      // update calculated field metadata\n      if (!isEmpty(data.calculatedFields)) {\n        await this.handleUpdateCFMetadata(data, ctx);\n      }\n\n      // update relationship metadata\n      if (!isEmpty(data.relationships)) {\n        await this.handleUpdateRelationshipMetadata(data, ctx);\n      }\n\n      ctx.telemetry.sendEvent(eventName, { data });\n      return true;\n    } catch (err: any) {\n      ctx.telemetry.sendEvent(\n        eventName,\n        { data: data, error: err.message },\n        err.extensions?.service,\n        false,\n      );\n      throw err;\n    }\n  }\n\n  private async handleUpdateModelMetadata(\n    data: UpdateModelMetadataInput,\n    model: Model,\n    ctx: IContext,\n    modelId: number,\n  ) {\n    const modelMetadata: any = {};\n\n    // if displayName is not null, or undefined, update the displayName\n    if (!isNil(data.displayName)) {\n      modelMetadata.displayName = this.determineMetadataValue(data.displayName);\n    }\n\n    // if description is not null, or undefined, update the description in properties\n    if (!isNil(data.description)) {\n      const properties = isNil(model.properties)\n        ? {}\n        : JSON.parse(model.properties);\n\n      properties.description = this.determineMetadataValue(data.description);\n      modelMetadata.properties = JSON.stringify(properties);\n    }\n\n    if (!isEmpty(modelMetadata)) {\n      await ctx.modelRepository.updateOne(modelId, modelMetadata);\n    }\n  }\n\n  private async handleUpdateRelationshipMetadata(\n    data: UpdateModelMetadataInput,\n    ctx: IContext,\n  ) {\n    const relationshipIds = data.relationships.map((r) => r.id);\n    const relationships =\n      await ctx.relationRepository.findRelationsByIds(relationshipIds);\n    for (const rel of relationships) {\n      const requestedMetadata = data.relationships.find((r) => r.id === rel.id);\n\n      const relationMetadata: any = {};\n\n      if (!isNil(requestedMetadata.description)) {\n        const properties = rel.properties ? JSON.parse(rel.properties) : {};\n        properties.description = this.determineMetadataValue(\n          requestedMetadata.description,\n        );\n        relationMetadata.properties = JSON.stringify(properties);\n      }\n\n      if (!isEmpty(relationMetadata)) {\n        await ctx.relationRepository.updateOne(rel.id, relationMetadata);\n      }\n    }\n  }\n\n  private async handleUpdateCFMetadata(\n    data: UpdateModelMetadataInput,\n    ctx: IContext,\n  ) {\n    const calculatedFieldIds = data.calculatedFields.map((c) => c.id);\n    const modelColumns =\n      await ctx.modelColumnRepository.findColumnsByIds(calculatedFieldIds);\n    for (const col of modelColumns) {\n      const requestedMetadata = data.calculatedFields.find(\n        (c) => c.id === col.id,\n      );\n\n      const columnMetadata: any = {};\n      // check if description is empty\n      // if description is empty, skip the update\n      // if description is not empty, update the description in properties\n      if (!isNil(requestedMetadata.description)) {\n        const properties = col.properties ? JSON.parse(col.properties) : {};\n        properties.description = this.determineMetadataValue(\n          requestedMetadata.description,\n        );\n        columnMetadata.properties = JSON.stringify(properties);\n      }\n\n      if (!isEmpty(columnMetadata)) {\n        await ctx.modelColumnRepository.updateOne(col.id, columnMetadata);\n      }\n    }\n  }\n\n  private async handleUpdateColumnMetadata(\n    data: UpdateModelMetadataInput,\n    ctx: IContext,\n  ) {\n    const columnIds = data.columns.map((c) => c.id);\n    const modelColumns =\n      await ctx.modelColumnRepository.findColumnsByIds(columnIds);\n    for (const col of modelColumns) {\n      const requestedMetadata = data.columns.find((c) => c.id === col.id);\n\n      // update metadata\n      const columnMetadata: any = {};\n\n      if (!isNil(requestedMetadata.displayName)) {\n        columnMetadata.displayName = this.determineMetadataValue(\n          requestedMetadata.displayName,\n        );\n      }\n\n      if (!isNil(requestedMetadata.description)) {\n        const properties = col.properties ? JSON.parse(col.properties) : {};\n        properties.description = this.determineMetadataValue(\n          requestedMetadata.description,\n        );\n        columnMetadata.properties = JSON.stringify(properties);\n      }\n\n      if (!isEmpty(columnMetadata)) {\n        await ctx.modelColumnRepository.updateOne(col.id, columnMetadata);\n      }\n    }\n  }\n\n  private async handleUpdateNestedColumnMetadata(\n    data: UpdateModelMetadataInput,\n    ctx: IContext,\n  ) {\n    const nestedColumnIds = data.nestedColumns.map((nc) => nc.id);\n    const modelNestedColumns =\n      await ctx.modelNestedColumnRepository.findNestedColumnsByIds(\n        nestedColumnIds,\n      );\n    for (const col of modelNestedColumns) {\n      const requestedMetadata = data.nestedColumns.find((c) => c.id === col.id);\n\n      const nestedColumnMetadata: any = {};\n\n      if (!isNil(requestedMetadata.displayName)) {\n        nestedColumnMetadata.displayName = this.determineMetadataValue(\n          requestedMetadata.displayName,\n        );\n      }\n\n      if (!isNil(requestedMetadata.description)) {\n        nestedColumnMetadata.properties = {\n          ...col.properties,\n          description: this.determineMetadataValue(\n            requestedMetadata.description,\n          ),\n        };\n      }\n\n      if (!isEmpty(nestedColumnMetadata)) {\n        await ctx.modelNestedColumnRepository.updateOne(\n          col.id,\n          nestedColumnMetadata,\n        );\n      }\n    }\n  }\n\n  // list views\n  public async listViews(_root: any, _args: any, ctx: IContext) {\n    const { id } = await ctx.projectService.getCurrentProject();\n    const views = await ctx.viewRepository.findAllBy({ projectId: id });\n    return views.map((view) => ({\n      ...view,\n      displayName: view.properties\n        ? JSON.parse(view.properties)?.displayName\n        : view.name,\n    }));\n  }\n\n  public async getView(_root: any, args: any, ctx: IContext) {\n    const viewId = args.where.id;\n    const view = await ctx.viewRepository.findOneBy({ id: viewId });\n    if (!view) {\n      throw new Error('View not found');\n    }\n    const displayName = view.properties\n      ? JSON.parse(view.properties)?.displayName\n      : view.name;\n    return { ...view, displayName };\n  }\n\n  // validate a view name\n  public async validateView(_root: any, args: any, ctx: IContext) {\n    const { name } = args.data;\n    return this.validateViewName(name, ctx);\n  }\n\n  // create view from sql of a response\n  public async createView(_root: any, args: any, ctx: IContext) {\n    const { name: displayName, responseId, rephrasedQuestion } = args.data;\n\n    // validate view name\n    const validateResult = await this.validateViewName(displayName, ctx);\n    if (!validateResult.valid) {\n      throw new Error(validateResult.message);\n    }\n\n    // create view\n    const project = await ctx.projectService.getCurrentProject();\n    const { manifest } = await ctx.deployService.getLastDeployment(project.id);\n\n    // get sql statement of a response\n    const response = await ctx.askingService.getResponse(responseId);\n    if (!response) {\n      throw new Error(`Thread response ${responseId} not found`);\n    }\n\n    // construct cte sql and format it\n    const statement = safeFormatSQL(response.sql);\n\n    // describe columns\n    const { columns } = await ctx.queryService.describeStatement(statement, {\n      project,\n      limit: 1,\n      modelingOnly: false,\n      manifest,\n    });\n\n    if (isEmpty(columns)) {\n      throw new Error('Failed to describe statement');\n    }\n\n    // properties\n    const properties = {\n      displayName,\n      columns,\n\n      // properties from the thread response\n      responseId, // helpful for mapping back to the thread response\n      question: rephrasedQuestion,\n    };\n\n    const eventName = TelemetryEvent.HOME_CREATE_VIEW;\n    const eventProperties = {\n      statement,\n      displayName,\n    };\n    // create view\n    try {\n      const name = replaceAllowableSyntax(displayName);\n      const view = await ctx.viewRepository.createOne({\n        projectId: project.id,\n        name,\n        statement,\n        properties: JSON.stringify(properties),\n      });\n\n      // telemetry\n      ctx.telemetry.sendEvent(eventName, eventProperties);\n\n      return { ...view, displayName };\n    } catch (err: any) {\n      ctx.telemetry.sendEvent(\n        eventName,\n        {\n          ...eventProperties,\n          error: err,\n        },\n        err.extensions?.service,\n        false,\n      );\n\n      throw err;\n    }\n  }\n\n  // delete view\n  public async deleteView(_root: any, args: any, ctx: IContext) {\n    const viewId = args.where.id;\n    const view = await ctx.viewRepository.findOneBy({ id: viewId });\n    if (!view) {\n      throw new Error('View not found');\n    }\n    await ctx.viewRepository.deleteOne(viewId);\n    return true;\n  }\n\n  public async previewModelData(_root: any, args: any, ctx: IContext) {\n    const modelId = args.where.id;\n    const model = await ctx.modelRepository.findOneBy({ id: modelId });\n    if (!model) {\n      throw new Error('Model not found');\n    }\n    const project = await ctx.projectService.getCurrentProject();\n    const { manifest } = await ctx.mdlService.makeCurrentModelMDL();\n    const modelColumns = await ctx.modelColumnRepository.findColumnsByModelIds([\n      model.id,\n    ]);\n    const sql = `select ${getPreviewColumnsStr(modelColumns)} from \"${model.referenceName}\"`;\n\n    const data = (await ctx.queryService.preview(sql, {\n      project,\n      modelingOnly: false,\n      manifest,\n    })) as PreviewDataResponse;\n\n    return data;\n  }\n\n  public async previewViewData(_root: any, args: any, ctx: IContext) {\n    const { id: viewId, limit } = args.where;\n    const view = await ctx.viewRepository.findOneBy({ id: viewId });\n    if (!view) {\n      throw new Error('View not found');\n    }\n    const { manifest } = await ctx.mdlService.makeCurrentModelMDL();\n    const project = await ctx.projectService.getCurrentProject();\n\n    const data = (await ctx.queryService.preview(view.statement, {\n      project,\n      limit,\n      manifest,\n      modelingOnly: false,\n    })) as PreviewDataResponse;\n    return data;\n  }\n\n  // Notice: this is used by AI service.\n  // any change to this resolver should be synced with AI service.\n  public async previewSql(\n    _root: any,\n    args: { data: PreviewSQLData },\n    ctx: IContext,\n  ) {\n    const { sql, projectId, limit, dryRun } = args.data;\n    const project = projectId\n      ? await ctx.projectService.getProjectById(parseInt(projectId))\n      : await ctx.projectService.getCurrentProject();\n    const { manifest } = await ctx.deployService.getLastDeployment(project.id);\n    return await ctx.queryService.preview(sql, {\n      project,\n      limit: limit,\n      modelingOnly: false,\n      manifest,\n      dryRun,\n    });\n  }\n\n  public async getNativeSql(\n    _root: any,\n    args: { responseId: number },\n    ctx: IContext,\n  ): Promise<string> {\n    const { responseId } = args;\n\n    // If using a sample dataset, native SQL is not supported\n    const project = await ctx.projectService.getCurrentProject();\n    if (project.sampleDataset) {\n      throw new Error(`Doesn't support Native SQL`);\n    }\n    const { manifest } = await ctx.mdlService.makeCurrentModelMDL();\n\n    // get sql statement of a response\n    const response = await ctx.askingService.getResponse(responseId);\n    if (!response) {\n      throw new Error(`Thread response ${responseId} not found`);\n    }\n\n    // construct cte sql and format it\n    let nativeSql: string;\n    if (project.type === DataSourceName.DUCKDB) {\n      logger.info(`Getting native sql from wren engine`);\n      nativeSql = await ctx.wrenEngineAdaptor.getNativeSQL(response.sql, {\n        manifest,\n        modelingOnly: false,\n      });\n    } else {\n      logger.info(`Getting native sql from ibis server`);\n      nativeSql = await ctx.ibisServerAdaptor.getNativeSql({\n        dataSource: project.type,\n        sql: response.sql,\n        mdl: manifest,\n      });\n    }\n    const language = project.type === DataSourceName.MSSQL ? 'tsql' : undefined;\n    return safeFormatSQL(nativeSql, { language });\n  }\n\n  public async updateViewMetadata(\n    _root: any,\n    args: { where: { id: number }; data: UpdateViewMetadataInput },\n    ctx: IContext,\n  ): Promise<boolean> {\n    const viewId = args.where.id;\n    const data = args.data;\n\n    // check if view exists\n    const view = await ctx.viewRepository.findOneBy({ id: viewId });\n    if (!view) {\n      throw new Error('View not found');\n    }\n\n    // update view metadata\n    const properties = JSON.parse(view.properties);\n    let newName = view.name;\n    // if displayName is not null, or undefined, update the displayName\n    if (!isNil(data.displayName)) {\n      await this.validateViewName(data.displayName, ctx, viewId);\n      newName = replaceAllowableSyntax(data.displayName);\n      properties.displayName = this.determineMetadataValue(data.displayName);\n    }\n\n    // if description is not null, or undefined, update the description in properties\n    if (!isNil(data.description)) {\n      properties.description = this.determineMetadataValue(data.description);\n    }\n\n    // view column metadata\n    if (!isEmpty(data.columns)) {\n      const viewColumns = properties.columns;\n      for (const col of viewColumns) {\n        const requestedMetadata = data.columns.find(\n          (c) => c.referenceName === col.name,\n        );\n\n        if (!isNil(requestedMetadata.description)) {\n          col.properties = col.properties || {};\n          col.properties.description = this.determineMetadataValue(\n            requestedMetadata.description,\n          );\n        }\n      }\n\n      properties.columns = viewColumns;\n    }\n\n    await ctx.viewRepository.updateOne(viewId, {\n      name: newName,\n      properties: JSON.stringify(properties),\n    });\n\n    return true;\n  }\n\n  private determineMetadataValue(value: string) {\n    // if it's empty string, meaning users want to remove the value\n    // so we return null\n    if (value === '') {\n      return null;\n    }\n\n    // otherwise, return the value\n    return value;\n  }\n\n  // validate view name\n  private async validateViewName(\n    viewDisplayName: string,\n    ctx: IContext,\n    selfView?: number,\n  ): Promise<{ valid: boolean; message?: string }> {\n    // check if view name is valid\n    // a-z, A-Z, 0-9, _, - are allowed and cannot start with number\n    const { valid, message } = validateDisplayName(viewDisplayName);\n    if (!valid) {\n      return {\n        valid: false,\n        message,\n      };\n    }\n    const referenceName = replaceAllowableSyntax(viewDisplayName);\n    // check if view name is duplicated\n    const { id } = await ctx.projectService.getCurrentProject();\n    const views = await ctx.viewRepository.findAllBy({ projectId: id });\n    if (views.find((v) => v.name === referenceName && v.id !== selfView)) {\n      return {\n        valid: false,\n        message: `Generated view name \"${referenceName}\" is duplicated`,\n      };\n    }\n\n    return {\n      valid: true,\n    };\n  }\n\n  private validateTableExist(\n    tableName: string,\n    dataSourceTables: CompactTable[],\n  ) {\n    if (!dataSourceTables.find((c) => c.name === tableName)) {\n      throw new Error(`Table ${tableName} not found in the data Source`);\n    }\n  }\n\n  private validateColumnsExist(\n    tableName: string,\n    fields: string[],\n    dataSourceTables: CompactTable[],\n  ) {\n    const tableColumns = dataSourceTables.find(\n      (c) => c.name === tableName,\n    )?.columns;\n    for (const field of fields) {\n      if (!tableColumns.find((c) => c.name === field)) {\n        throw new Error(\n          `Column \"${field}\" not found in table \"${tableName}\" in the data Source`,\n        );\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/resolvers/projectResolver.ts",
    "content": "import {\n  AnalysisRelationInfo,\n  DataSource,\n  DataSourceName,\n  DataSourceProperties,\n  IContext,\n  RelationData,\n  RelationType,\n  SampleDatasetData,\n} from '../types';\nimport {\n  trim,\n  getLogger,\n  replaceInvalidReferenceName,\n  transformInvalidColumnName,\n  handleNestedColumns,\n} from '@server/utils';\nimport {\n  DUCKDB_CONNECTION_INFO,\n  Model,\n  ModelColumn,\n  Project,\n} from '../repositories';\nimport {\n  SampleDatasetName,\n  SampleDatasetRelationship,\n  buildInitSql,\n  getRelations,\n  sampleDatasets,\n} from '@server/data';\nimport { snakeCase } from 'lodash';\nimport { CompactTable, ProjectData } from '../services';\nimport { DuckDBPrepareOptions } from '@server/adaptors/wrenEngineAdaptor';\nimport DataSourceSchemaDetector, {\n  SchemaChangeType,\n} from '@server/managers/dataSourceSchemaDetector';\nimport { encryptConnectionInfo } from '../dataSource';\nimport { TelemetryEvent } from '../telemetry/telemetry';\n\nconst logger = getLogger('DataSourceResolver');\nlogger.level = 'debug';\n\nexport enum OnboardingStatusEnum {\n  NOT_STARTED = 'NOT_STARTED',\n  DATASOURCE_SAVED = 'DATASOURCE_SAVED',\n  ONBOARDING_FINISHED = 'ONBOARDING_FINISHED',\n  WITH_SAMPLE_DATASET = 'WITH_SAMPLE_DATASET',\n}\n\nexport class ProjectResolver {\n  constructor() {\n    this.getSettings = this.getSettings.bind(this);\n    this.updateCurrentProject = this.updateCurrentProject.bind(this);\n    this.resetCurrentProject = this.resetCurrentProject.bind(this);\n    this.saveDataSource = this.saveDataSource.bind(this);\n    this.updateDataSource = this.updateDataSource.bind(this);\n    this.listDataSourceTables = this.listDataSourceTables.bind(this);\n    this.saveTables = this.saveTables.bind(this);\n    this.autoGenerateRelation = this.autoGenerateRelation.bind(this);\n    this.saveRelations = this.saveRelations.bind(this);\n    this.getOnboardingStatus = this.getOnboardingStatus.bind(this);\n    this.startSampleDataset = this.startSampleDataset.bind(this);\n    this.triggerDataSourceDetection =\n      this.triggerDataSourceDetection.bind(this);\n    this.getSchemaChange = this.getSchemaChange.bind(this);\n    this.getProjectRecommendationQuestions =\n      this.getProjectRecommendationQuestions.bind(this);\n  }\n\n  public async getSettings(_root: any, _arg: any, ctx: IContext) {\n    const project = await ctx.projectService.getCurrentProject();\n    const generalConnectionInfo =\n      ctx.projectService.getGeneralConnectionInfo(project);\n    const dataSourceType = project.type;\n\n    return {\n      productVersion: ctx.config.wrenProductVersion || '',\n      dataSource: {\n        type: dataSourceType,\n        properties: {\n          displayName: project.displayName,\n          ...generalConnectionInfo,\n        } as DataSourceProperties,\n        sampleDataset: project.sampleDataset,\n      },\n      language: project.language,\n    };\n  }\n\n  public async getProjectRecommendationQuestions(\n    _root: any,\n    _arg: any,\n    ctx: IContext,\n  ) {\n    return ctx.projectService.getProjectRecommendationQuestions();\n  }\n\n  public async updateCurrentProject(\n    _root: any,\n    arg: { data: { language: string } },\n    ctx: IContext,\n  ) {\n    const { language } = arg.data;\n    const project = await ctx.projectService.getCurrentProject();\n    await ctx.projectRepository.updateOne(project.id, {\n      language,\n    });\n\n    // only generating for user's data source\n    if (project.sampleDataset === null) {\n      await ctx.projectService.generateProjectRecommendationQuestions();\n    }\n    return true;\n  }\n\n  public async resetCurrentProject(_root: any, _arg: any, ctx: IContext) {\n    let project;\n    try {\n      project = await ctx.projectService.getCurrentProject();\n    } catch {\n      // no project found\n      return true;\n    }\n    const eventName = TelemetryEvent.SETTING_RESET_PROJECT;\n    try {\n      const id = project.id;\n      await ctx.schemaChangeRepository.deleteAllBy({ projectId: id });\n      await ctx.deployService.deleteAllByProjectId(id);\n      await ctx.askingService.deleteAllByProjectId(id);\n      await ctx.modelService.deleteAllViewsByProjectId(id);\n      await ctx.modelService.deleteAllModelsByProjectId(id);\n      await ctx.projectService.deleteProject(id);\n      await ctx.wrenAIAdaptor.delete(id);\n\n      // telemetry\n      ctx.telemetry.sendEvent(eventName, {\n        projectId: id,\n        dataSourceType: project.type,\n      });\n    } catch (err: any) {\n      ctx.telemetry.sendEvent(\n        eventName,\n        { dataSourceType: project.type, error: err.message },\n        err.extensions?.service,\n        false,\n      );\n      throw err;\n    }\n\n    return true;\n  }\n\n  public async startSampleDataset(\n    _root: any,\n    _arg: { data: SampleDatasetData },\n    ctx: IContext,\n  ) {\n    const { name } = _arg.data;\n    const dataset = sampleDatasets[snakeCase(name)];\n    if (!dataset) {\n      throw new Error('Sample dataset not found');\n    }\n    if (!(name in SampleDatasetName)) {\n      throw new Error('Invalid sample dataset name');\n    }\n    const eventName = TelemetryEvent.CONNECTION_START_SAMPLE_DATASET;\n    const eventProperties = {\n      datasetName: name,\n    };\n    try {\n      // create duckdb datasource\n      const initSql = buildInitSql(name as SampleDatasetName);\n      const duckdbDatasourceProperties = {\n        initSql,\n        extensions: [],\n        configurations: {},\n      };\n      await this.saveDataSource(\n        _root,\n        {\n          data: {\n            type: DataSourceName.DUCKDB,\n            properties: duckdbDatasourceProperties,\n          } as DataSource,\n        },\n        ctx,\n      );\n      const project = await ctx.projectService.getCurrentProject();\n\n      // list all the tables in the data source\n      const tables = await this.listDataSourceTables(_root, _arg, ctx);\n      const tableNames = tables.map((table) => table.name);\n\n      // save tables as model and modelColumns\n      await this.overwriteModelsAndColumns(tableNames, ctx, project);\n\n      await ctx.modelService.updatePrimaryKeys(dataset.tables);\n      await ctx.modelService.batchUpdateModelProperties(dataset.tables);\n      await ctx.modelService.batchUpdateColumnProperties(dataset.tables);\n\n      // save relations\n      const relations = getRelations(name as SampleDatasetName);\n      const models = await ctx.modelRepository.findAll();\n      const columns = await ctx.modelColumnRepository.findAll();\n      const mappedRelations = this.buildRelationInput(\n        relations,\n        models,\n        columns,\n      );\n      await ctx.modelService.saveRelations(mappedRelations);\n\n      // mark current project as using sample dataset\n      await ctx.projectRepository.updateOne(project.id, {\n        sampleDataset: name,\n      });\n      await this.deploy(ctx);\n      // telemetry\n      ctx.telemetry.sendEvent(eventName, eventProperties);\n      return { name };\n    } catch (err: any) {\n      ctx.telemetry.sendEvent(\n        eventName,\n        { ...eventProperties, error: err.message },\n        err.extensions?.service,\n        false,\n      );\n      throw err;\n    }\n  }\n\n  public async getOnboardingStatus(_root: any, _arg: any, ctx: IContext) {\n    let project: Project | null;\n    try {\n      project = await ctx.projectRepository.getCurrentProject();\n    } catch (_err: any) {\n      return {\n        status: OnboardingStatusEnum.NOT_STARTED,\n      };\n    }\n    const { id, sampleDataset } = project;\n    if (sampleDataset) {\n      return {\n        status: OnboardingStatusEnum.WITH_SAMPLE_DATASET,\n      };\n    }\n    const models = await ctx.modelRepository.findAllBy({ projectId: id });\n    if (!models.length) {\n      return {\n        status: OnboardingStatusEnum.DATASOURCE_SAVED,\n      };\n    } else {\n      return {\n        status: OnboardingStatusEnum.ONBOARDING_FINISHED,\n      };\n    }\n  }\n\n  public async saveDataSource(\n    _root: any,\n    args: {\n      data: DataSource;\n    },\n    ctx: IContext,\n  ) {\n    const { type, properties } = args.data;\n    // Currently only can create one project\n    await this.resetCurrentProject(_root, args, ctx);\n\n    const { displayName, ...connectionInfo } = properties;\n    const project = await ctx.projectService.createProject({\n      displayName,\n      type,\n      connectionInfo,\n    } as ProjectData);\n    logger.debug(`Project created.`);\n\n    // init dashboard\n    logger.debug('Dashboard init...');\n    await ctx.dashboardService.initDashboard();\n    logger.debug('Dashboard created.');\n\n    const eventName = TelemetryEvent.CONNECTION_SAVE_DATA_SOURCE;\n    const eventProperties = {\n      dataSourceType: type,\n    };\n\n    // try to connect to the data source\n    try {\n      // handle duckdb connection\n      if (type === DataSourceName.DUCKDB) {\n        connectionInfo as DUCKDB_CONNECTION_INFO;\n        await this.buildDuckDbEnvironment(ctx, {\n          initSql: connectionInfo.initSql,\n          extensions: connectionInfo.extensions,\n          configurations: connectionInfo.configurations,\n        });\n      } else {\n        // handle other data source\n        await ctx.projectService.getProjectDataSourceTables(project);\n        const version =\n          await ctx.projectService.getProjectDataSourceVersion(project);\n        await ctx.projectService.updateProject(project.id, {\n          version,\n        });\n        logger.debug(`Data source tables fetched`);\n      }\n      // telemetry\n      ctx.telemetry.sendEvent(eventName, eventProperties);\n    } catch (err) {\n      logger.error(\n        'Failed to get project tables',\n        JSON.stringify(err, null, 2),\n      );\n      await ctx.projectRepository.deleteOne(project.id);\n      ctx.telemetry.sendEvent(\n        eventName,\n        { eventProperties, error: err.message },\n        err.extensions?.service,\n        false,\n      );\n      throw err;\n    }\n\n    return {\n      type: project.type,\n      properties: {\n        displayName: project.displayName,\n        ...ctx.projectService.getGeneralConnectionInfo(project),\n      },\n    };\n  }\n\n  public async updateDataSource(\n    _root: any,\n    args: { data: DataSource },\n    ctx: IContext,\n  ) {\n    const { properties } = args.data;\n    const { displayName, ...connectionInfo } = properties;\n    const project = await ctx.projectService.getCurrentProject();\n    const dataSourceType = project.type;\n\n    // only new connection info needed to encrypt\n    const toUpdateConnectionInfo = encryptConnectionInfo(\n      dataSourceType,\n      connectionInfo as any,\n    );\n\n    if (dataSourceType === DataSourceName.DUCKDB) {\n      // prepare duckdb environment in wren-engine\n      const { initSql, extensions, configurations } =\n        toUpdateConnectionInfo as DUCKDB_CONNECTION_INFO;\n      await this.buildDuckDbEnvironment(ctx, {\n        initSql,\n        extensions,\n        configurations,\n      });\n    } else {\n      const updatedProject = {\n        ...project,\n        displayName,\n        connectionInfo: {\n          ...project.connectionInfo,\n          ...toUpdateConnectionInfo,\n        },\n      } as Project;\n\n      await ctx.projectService.getProjectDataSourceTables(updatedProject);\n      logger.debug(`Data source tables fetched`);\n    }\n    const updatedProject = await ctx.projectRepository.updateOne(project.id, {\n      displayName,\n      connectionInfo: { ...project.connectionInfo, ...toUpdateConnectionInfo },\n    });\n    return {\n      type: updatedProject.type,\n      properties: {\n        displayName: updatedProject.displayName,\n        ...ctx.projectService.getGeneralConnectionInfo(updatedProject),\n      },\n    };\n  }\n\n  public async listDataSourceTables(_root: any, _arg, ctx: IContext) {\n    return await ctx.projectService.getProjectDataSourceTables();\n  }\n\n  public async saveTables(\n    _root: any,\n    arg: {\n      data: { tables: string[] };\n    },\n    ctx: IContext,\n  ) {\n    const eventName = TelemetryEvent.CONNECTION_SAVE_TABLES;\n\n    // get current project\n    const project = await ctx.projectService.getCurrentProject();\n    try {\n      // delete existing models and columns\n      const { models, columns } = await this.overwriteModelsAndColumns(\n        arg.data.tables,\n        ctx,\n        project,\n      );\n      // telemetry\n      ctx.telemetry.sendEvent(eventName, {\n        dataSourceType: project.type,\n        tablesCount: models.length,\n        columnsCount: columns.length,\n      });\n\n      // async deploy to wren-engine and ai service\n      this.deploy(ctx);\n      return { models: models, columns };\n    } catch (err: any) {\n      ctx.telemetry.sendEvent(\n        eventName,\n        { dataSourceType: project.type, error: err.message },\n        err.extensions?.service,\n        false,\n      );\n      throw err;\n    }\n  }\n\n  public async autoGenerateRelation(_root: any, _arg: any, ctx: IContext) {\n    const project = await ctx.projectService.getCurrentProject();\n\n    // get models and columns\n    const models = await ctx.modelRepository.findAllBy({\n      projectId: project.id,\n    });\n    const modelIds = models.map((m) => m.id);\n    const columns =\n      await ctx.modelColumnRepository.findColumnsByModelIds(modelIds);\n    const constraints =\n      await ctx.projectService.getProjectSuggestedConstraint(project);\n\n    // generate relation\n    const relations = [];\n    for (const constraint of constraints) {\n      const {\n        constraintTable,\n        constraintColumn,\n        constraintedTable,\n        constraintedColumn,\n      } = constraint;\n      // validate tables and columns exists in our models and model columns\n      const fromModel = models.find(\n        (m) => m.sourceTableName === constraintTable,\n      );\n      const toModel = models.find(\n        (m) => m.sourceTableName === constraintedTable,\n      );\n      if (!fromModel || !toModel) {\n        continue;\n      }\n      const fromColumn = columns.find(\n        (c) =>\n          c.modelId === fromModel.id && c.sourceColumnName === constraintColumn,\n      );\n      const toColumn = columns.find(\n        (c) =>\n          c.modelId === toModel.id && c.sourceColumnName === constraintedColumn,\n      );\n      if (!fromColumn || !toColumn) {\n        continue;\n      }\n      // create relation\n      const relation: AnalysisRelationInfo = {\n        // upper case the first letter of the sourceTableName\n        name: constraint.constraintName,\n        fromModelId: fromModel.id,\n        fromModelReferenceName: fromModel.referenceName,\n        fromColumnId: fromColumn.id,\n        fromColumnReferenceName: fromColumn.referenceName,\n        toModelId: toModel.id,\n        toModelReferenceName: toModel.referenceName,\n        toColumnId: toColumn.id,\n        toColumnReferenceName: toColumn.referenceName,\n        // TODO: add join type\n        type: RelationType.ONE_TO_MANY,\n      };\n      relations.push(relation);\n    }\n    // group by model\n    return models.map(({ id, displayName, referenceName }) => ({\n      id,\n      displayName,\n      referenceName,\n      relations: relations.filter(\n        (relation) =>\n          relation.fromModelId === id &&\n          // exclude self-referential relationship\n          relation.toModelId !== relation.fromModelId,\n      ),\n    }));\n  }\n\n  public async saveRelations(\n    _root: any,\n    arg: { data: { relations: RelationData[] } },\n    ctx: IContext,\n  ) {\n    const eventName = TelemetryEvent.CONNECTION_SAVE_RELATION;\n    try {\n      const savedRelations = await ctx.modelService.saveRelations(\n        arg.data.relations,\n      );\n      // async deploy\n      this.deploy(ctx);\n      ctx.telemetry.sendEvent(eventName, {\n        relationCount: savedRelations.length,\n      });\n      return savedRelations;\n    } catch (err: any) {\n      ctx.telemetry.sendEvent(\n        eventName,\n        { error: err.message },\n        err.extensions?.service,\n        false,\n      );\n      throw err;\n    }\n  }\n\n  public async getSchemaChange(_root: any, _arg: any, ctx: IContext) {\n    const project = await ctx.projectService.getCurrentProject();\n    const lastSchemaChange =\n      await ctx.schemaChangeRepository.findLastSchemaChange(project.id);\n\n    if (!lastSchemaChange) {\n      return {\n        deletedTables: null,\n        deletedColumns: null,\n        modifiedColumns: null,\n        lastSchemaChangeTime: null,\n      };\n    }\n\n    const models = await ctx.modelRepository.findAllBy({\n      projectId: project.id,\n    });\n    const modelIds = models.map((model) => model.id);\n    const modelColumns =\n      await ctx.modelColumnRepository.findColumnsByModelIds(modelIds);\n\n    const modelRelationships = await ctx.relationRepository.findRelationInfoBy({\n      modelIds,\n    });\n\n    const schemaDetector = new DataSourceSchemaDetector({\n      ctx,\n      projectId: project.id,\n    });\n\n    const resolves = lastSchemaChange.resolve;\n    const unresolvedChanges = Object.keys(resolves).reduce((result, key) => {\n      const isResolved = resolves[key];\n      const changes = lastSchemaChange.change[key];\n      // return if resolved or no changes\n      if (isResolved || !changes) return result;\n\n      // Mapping with affected models and columns and affected calculated fields and relationships data into schema change\n      const affecteds = schemaDetector.getAffectedResources(changes, {\n        models,\n        modelColumns,\n        modelRelationships,\n      });\n\n      const affectedChanges = affecteds.length ? affecteds : null;\n      return { ...result, [key]: affectedChanges };\n    }, {});\n\n    return {\n      ...unresolvedChanges,\n      lastSchemaChangeTime: lastSchemaChange.createdAt,\n    };\n  }\n\n  public async triggerDataSourceDetection(\n    _root: any,\n    _arg: any,\n    ctx: IContext,\n  ) {\n    const project = await ctx.projectService.getCurrentProject();\n    const schemaDetector = new DataSourceSchemaDetector({\n      ctx,\n      projectId: project.id,\n    });\n    const eventName = TelemetryEvent.MODELING_DETECT_SCHEMA_CHANGE;\n    try {\n      const hasSchemaChange = await schemaDetector.detectSchemaChange();\n      ctx.telemetry.sendEvent(eventName, { hasSchemaChange });\n      return hasSchemaChange;\n    } catch (error: any) {\n      ctx.telemetry.sendEvent(\n        eventName,\n        { error },\n        error.extensions?.service,\n        false,\n      );\n      throw error;\n    }\n  }\n\n  public async resolveSchemaChange(\n    _root: any,\n    arg: { where: { type: SchemaChangeType } },\n    ctx: IContext,\n  ) {\n    const { type } = arg.where;\n    const project = await ctx.projectService.getCurrentProject();\n    const schemaDetector = new DataSourceSchemaDetector({\n      ctx,\n      projectId: project.id,\n    });\n    const eventName = TelemetryEvent.MODELING_RESOLVE_SCHEMA_CHANGE;\n    try {\n      await schemaDetector.resolveSchemaChange(type);\n      ctx.telemetry.sendEvent(eventName, { type });\n    } catch (error) {\n      ctx.telemetry.sendEvent(\n        eventName,\n        { type, error },\n        error.extensions?.service,\n        false,\n      );\n      throw error;\n    }\n    return true;\n  }\n\n  private async deploy(ctx: IContext) {\n    const project = await ctx.projectService.getCurrentProject();\n    const { manifest } = await ctx.mdlService.makeCurrentModelMDL();\n    const deployRes = await ctx.deployService.deploy(manifest, project.id);\n\n    // only generating for user's data source\n    if (project.sampleDataset === null) {\n      await ctx.projectService.generateProjectRecommendationQuestions();\n    }\n    return deployRes;\n  }\n\n  private buildRelationInput(\n    relations: SampleDatasetRelationship[],\n    models: Model[],\n    columns: ModelColumn[],\n  ) {\n    const relationInput = relations.map((relation) => {\n      const { fromModelName, fromColumnName, toModelName, toColumnName, type } =\n        relation;\n      const fromModelId = models.find(\n        (model) => model.sourceTableName === fromModelName,\n      )?.id;\n      const toModelId = models.find(\n        (model) => model.sourceTableName === toModelName,\n      )?.id;\n      if (!fromModelId || !toModelId) {\n        throw new Error(\n          `Model not found, fromModelName \"${fromModelName}\" to toModelName: \"${toModelName}\"`,\n        );\n      }\n\n      const fromColumnId = columns.find(\n        (column) =>\n          column.referenceName === fromColumnName &&\n          column.modelId === fromModelId,\n      )?.id;\n      const toColumnId = columns.find(\n        (column) =>\n          column.referenceName === toColumnName && column.modelId === toModelId,\n      )?.id;\n      if (!fromColumnId || !toColumnId) {\n        throw new Error(\n          `Column not found fromColumnName: ${fromColumnName} toColumnName: ${toColumnName}`,\n        );\n      }\n      return {\n        fromModelId,\n        fromColumnId,\n        toModelId,\n        toColumnId,\n        type,\n        description: relation.description,\n      } as RelationData;\n    });\n    return relationInput;\n  }\n\n  private async overwriteModelsAndColumns(\n    tables: string[],\n    ctx: IContext,\n    project: Project,\n  ) {\n    // delete existing models and columns\n    await ctx.modelService.deleteAllModelsByProjectId(project.id);\n\n    const compactTables: CompactTable[] =\n      await ctx.projectService.getProjectDataSourceTables(project);\n\n    const selectedTables = compactTables.filter((table) =>\n      tables.includes(table.name),\n    );\n\n    // create models\n    const modelValues = selectedTables.map((table) => {\n      const properties = table?.properties;\n      // compactTable contain schema and catalog, these information are for building tableReference in mdl\n      const model = {\n        projectId: project.id,\n        displayName: table.name, // use table name as displayName, referenceName and tableName\n        referenceName: replaceInvalidReferenceName(table.name),\n        sourceTableName: table.name,\n        cached: false,\n        refreshTime: null,\n        properties: properties ? JSON.stringify(properties) : null,\n      } as Partial<Model>;\n      return model;\n    });\n    const models = await ctx.modelRepository.createMany(modelValues);\n\n    // create columns\n    const columnValues = selectedTables.flatMap((table) => {\n      const compactColumns = table.columns;\n      const primaryKey = table.primaryKey;\n      const model = models.find((m) => m.sourceTableName === table.name);\n      return compactColumns.map(\n        (column) =>\n          ({\n            modelId: model.id,\n            isCalculated: false,\n            displayName: column.name,\n            referenceName: transformInvalidColumnName(column.name),\n            sourceColumnName: column.name,\n            type: column.type || 'string',\n            notNull: column.notNull || false,\n            isPk: primaryKey === column.name,\n            properties: column.properties\n              ? JSON.stringify(column.properties)\n              : null,\n          }) as Partial<ModelColumn>,\n      );\n    });\n    const columns = await ctx.modelColumnRepository.createMany(columnValues);\n\n    // create nested columns\n    const compactColumns = selectedTables.flatMap((table) => table.columns);\n    const nestedColumnValues = compactColumns.flatMap((compactColumn) => {\n      const column = columns.find(\n        (c) => c.sourceColumnName === compactColumn.name,\n      );\n      return handleNestedColumns(compactColumn, {\n        modelId: column.modelId,\n        columnId: column.id,\n        sourceColumnName: column.sourceColumnName,\n      });\n    });\n    await ctx.modelNestedColumnRepository.createMany(nestedColumnValues);\n\n    return { models, columns };\n  }\n\n  private concatInitSql(initSql: string, extensions: string[]) {\n    const installExtensions = extensions\n      .map((ext) => `INSTALL ${ext};`)\n      .join('\\n');\n    return trim(`${installExtensions}\\n${initSql}`);\n  }\n\n  private async buildDuckDbEnvironment(\n    ctx: IContext,\n    options: {\n      initSql: string;\n      extensions: string[];\n      configurations: Record<string, any>;\n    },\n  ): Promise<void> {\n    const { initSql, extensions, configurations } = options;\n    const initSqlWithExtensions = this.concatInitSql(initSql, extensions);\n    await ctx.wrenEngineAdaptor.prepareDuckDB({\n      sessionProps: configurations,\n      initSql: initSqlWithExtensions,\n    } as DuckDBPrepareOptions);\n\n    // check can list dataset table\n    await ctx.wrenEngineAdaptor.listTables();\n\n    // patch wren-engine config\n    const config = {\n      'wren.datasource.type': 'duckdb',\n    };\n    await ctx.wrenEngineAdaptor.patchConfig(config);\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/resolvers/sqlPairResolver.ts",
    "content": "import { IContext } from '@server/types/context';\nimport { SqlPair } from '@server/repositories';\nimport * as Errors from '@server/utils/error';\nimport { TelemetryEvent, TrackTelemetry } from '@server/telemetry/telemetry';\nimport { DialectSQL, WrenSQL } from '@server/models/adaptor';\nimport { safeFormatSQL } from '@server/utils/sqlFormat';\n\nexport class SqlPairResolver {\n  constructor() {\n    this.getProjectSqlPairs = this.getProjectSqlPairs.bind(this);\n    this.createSqlPair = this.createSqlPair.bind(this);\n    this.updateSqlPair = this.updateSqlPair.bind(this);\n    this.deleteSqlPair = this.deleteSqlPair.bind(this);\n    this.generateQuestion = this.generateQuestion.bind(this);\n    this.modelSubstitute = this.modelSubstitute.bind(this);\n  }\n\n  public async getProjectSqlPairs(\n    _root: unknown,\n    _arg: any,\n    ctx: IContext,\n  ): Promise<SqlPair[]> {\n    const project = await ctx.projectService.getCurrentProject();\n    return ctx.sqlPairService.getProjectSqlPairs(project.id);\n  }\n\n  @TrackTelemetry(TelemetryEvent.KNOWLEDGE_CREATE_SQL_PAIR)\n  public async createSqlPair(\n    _root: unknown,\n    arg: {\n      data: {\n        sql: string;\n        question: string;\n      };\n    },\n    ctx: IContext,\n  ): Promise<SqlPair> {\n    const project = await ctx.projectService.getCurrentProject();\n    await this.validateSql(arg.data.sql, ctx);\n    return await ctx.sqlPairService.createSqlPair(project.id, arg.data);\n  }\n\n  @TrackTelemetry(TelemetryEvent.KNOWLEDGE_UPDATE_SQL_PAIR)\n  public async updateSqlPair(\n    _root: unknown,\n    arg: {\n      data: {\n        sql?: string;\n        question?: string;\n      };\n      where: {\n        id: number;\n      };\n    },\n    ctx: IContext,\n  ): Promise<SqlPair> {\n    const project = await ctx.projectService.getCurrentProject();\n    await this.validateSql(arg.data.sql, ctx);\n    return ctx.sqlPairService.editSqlPair(project.id, arg.where.id, arg.data);\n  }\n\n  @TrackTelemetry(TelemetryEvent.KNOWLEDGE_DELETE_SQL_PAIR)\n  public async deleteSqlPair(\n    _root: unknown,\n    arg: {\n      where: {\n        id: number;\n      };\n    },\n    ctx: IContext,\n  ): Promise<boolean> {\n    const project = await ctx.projectService.getCurrentProject();\n    return ctx.sqlPairService.deleteSqlPair(project.id, arg.where.id);\n  }\n\n  public async generateQuestion(\n    _root: unknown,\n    arg: {\n      data: {\n        sql: string;\n      };\n    },\n    ctx: IContext,\n  ) {\n    const project = await ctx.projectService.getCurrentProject();\n    const questions = await ctx.sqlPairService.generateQuestions(project, [\n      arg.data.sql,\n    ]);\n    return questions[0];\n  }\n\n  public async modelSubstitute(\n    _root: unknown,\n    arg: {\n      data: {\n        sql: DialectSQL;\n      };\n    },\n    ctx: IContext,\n  ): Promise<WrenSQL> {\n    const project = await ctx.projectService.getCurrentProject();\n    const lastDeployment = await ctx.deployService.getLastDeployment(\n      project.id,\n    );\n    const manifest = lastDeployment.manifest;\n\n    const wrenSQL = await ctx.sqlPairService.modelSubstitute(\n      arg.data.sql as DialectSQL,\n      {\n        project,\n        manifest,\n      },\n    );\n    return safeFormatSQL(wrenSQL, { language: 'postgresql' }) as WrenSQL;\n  }\n\n  private async validateSql(sql: string, ctx: IContext) {\n    const project = await ctx.projectService.getCurrentProject();\n    const lastDeployment = await ctx.deployService.getLastDeployment(\n      project.id,\n    );\n    const manifest = lastDeployment.manifest;\n    try {\n      await ctx.queryService.preview(sql, {\n        manifest,\n        project,\n        dryRun: true,\n      });\n    } catch (err) {\n      throw Errors.create(Errors.GeneralErrorCodes.INVALID_SQL_ERROR, {\n        customMessage: err.message,\n      });\n    }\n  }\n\n  public getSqlPairNestedResolver = () => ({\n    createdAt: (sqlPair: SqlPair, _args: any, _ctx: IContext) => {\n      return new Date(sqlPair.createdAt).toISOString();\n    },\n    updatedAt: (sqlPair: SqlPair, _args: any, _ctx: IContext) => {\n      return new Date(sqlPair.updatedAt).toISOString();\n    },\n  });\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/resolvers.ts",
    "content": "import GraphQLJSON from 'graphql-type-json';\nimport { ProjectResolver } from './resolvers/projectResolver';\nimport { ModelResolver } from './resolvers/modelResolver';\nimport { AskingResolver } from './resolvers/askingResolver';\nimport { DiagramResolver } from './resolvers/diagramResolver';\nimport { LearningResolver } from './resolvers/learningResolver';\nimport { DashboardResolver } from './resolvers/dashboardResolver';\nimport { SqlPairResolver } from './resolvers/sqlPairResolver';\nimport { InstructionResolver } from './resolvers/instructionResolver';\nimport { ApiHistoryResolver } from './resolvers/apiHistoryResolver';\nimport { convertColumnType } from '@server/utils';\nimport { DialectSQLScalar } from './scalars';\n\nconst projectResolver = new ProjectResolver();\nconst modelResolver = new ModelResolver();\nconst askingResolver = new AskingResolver();\nconst diagramResolver = new DiagramResolver();\nconst learningResolver = new LearningResolver();\nconst dashboardResolver = new DashboardResolver();\nconst sqlPairResolver = new SqlPairResolver();\nconst instructionResolver = new InstructionResolver();\nconst apiHistoryResolver = new ApiHistoryResolver();\nconst resolvers = {\n  JSON: GraphQLJSON,\n  DialectSQL: DialectSQLScalar,\n  Query: {\n    listDataSourceTables: projectResolver.listDataSourceTables,\n    autoGenerateRelation: projectResolver.autoGenerateRelation,\n    listModels: modelResolver.listModels,\n    model: modelResolver.getModel,\n    onboardingStatus: projectResolver.getOnboardingStatus,\n    modelSync: modelResolver.checkModelSync,\n    diagram: diagramResolver.getDiagram,\n    schemaChange: projectResolver.getSchemaChange,\n\n    // Ask\n    askingTask: askingResolver.getAskingTask,\n    suggestedQuestions: askingResolver.getSuggestedQuestions,\n    instantRecommendedQuestions: askingResolver.getInstantRecommendedQuestions,\n\n    // Adjustment\n    adjustmentTask: askingResolver.getAdjustmentTask,\n\n    // Thread\n    thread: askingResolver.getThread,\n    threads: askingResolver.listThreads,\n    threadResponse: askingResolver.getResponse,\n    nativeSql: modelResolver.getNativeSql,\n\n    // Views\n    listViews: modelResolver.listViews,\n    view: modelResolver.getView,\n\n    // Settings\n    settings: projectResolver.getSettings,\n    getMDL: modelResolver.getMDL,\n\n    // Learning\n    learningRecord: learningResolver.getLearningRecord,\n\n    // Recommendation questions\n    getThreadRecommendationQuestions:\n      askingResolver.getThreadRecommendationQuestions,\n    getProjectRecommendationQuestions:\n      projectResolver.getProjectRecommendationQuestions,\n\n    // Dashboard\n    dashboardItems: dashboardResolver.getDashboardItems,\n    dashboard: dashboardResolver.getDashboard,\n\n    // SQL Pairs\n    sqlPairs: sqlPairResolver.getProjectSqlPairs,\n    // Instructions\n    instructions: instructionResolver.getInstructions,\n\n    // API History\n    apiHistory: apiHistoryResolver.getApiHistory,\n  },\n  Mutation: {\n    deploy: modelResolver.deploy,\n    saveDataSource: projectResolver.saveDataSource,\n    startSampleDataset: projectResolver.startSampleDataset,\n    saveTables: projectResolver.saveTables,\n    saveRelations: projectResolver.saveRelations,\n    createModel: modelResolver.createModel,\n    updateModel: modelResolver.updateModel,\n    deleteModel: modelResolver.deleteModel,\n    previewModelData: modelResolver.previewModelData,\n    updateModelMetadata: modelResolver.updateModelMetadata,\n    triggerDataSourceDetection: projectResolver.triggerDataSourceDetection,\n    resolveSchemaChange: projectResolver.resolveSchemaChange,\n\n    // calculated field\n    createCalculatedField: modelResolver.createCalculatedField,\n    validateCalculatedField: modelResolver.validateCalculatedField,\n    updateCalculatedField: modelResolver.updateCalculatedField,\n    deleteCalculatedField: modelResolver.deleteCalculatedField,\n\n    // relation\n    createRelation: modelResolver.createRelation,\n    updateRelation: modelResolver.updateRelation,\n    deleteRelation: modelResolver.deleteRelation,\n\n    // Ask\n    createAskingTask: askingResolver.createAskingTask,\n    cancelAskingTask: askingResolver.cancelAskingTask,\n    createInstantRecommendedQuestions:\n      askingResolver.createInstantRecommendedQuestions,\n    rerunAskingTask: askingResolver.rerunAskingTask,\n\n    // Adjustment\n    adjustThreadResponse: askingResolver.adjustThreadResponse,\n    cancelAdjustmentTask: askingResolver.cancelAdjustThreadResponseAnswer,\n    rerunAdjustmentTask: askingResolver.rerunAdjustThreadResponseAnswer,\n\n    // Thread\n    createThread: askingResolver.createThread,\n    updateThread: askingResolver.updateThread,\n    deleteThread: askingResolver.deleteThread,\n    createThreadResponse: askingResolver.createThreadResponse,\n    updateThreadResponse: askingResolver.updateThreadResponse,\n    previewData: askingResolver.previewData,\n    previewBreakdownData: askingResolver.previewBreakdownData,\n\n    // Generate Thread Response Breakdown\n    generateThreadResponseBreakdown:\n      askingResolver.generateThreadResponseBreakdown,\n\n    // Generate Thread Response Answer\n    generateThreadResponseAnswer: askingResolver.generateThreadResponseAnswer,\n\n    // Generate Thread Response Chart\n    generateThreadResponseChart: askingResolver.generateThreadResponseChart,\n\n    // Adjust Thread Response Chart\n    adjustThreadResponseChart: askingResolver.adjustThreadResponseChart,\n\n    // Views\n    createView: modelResolver.createView,\n    deleteView: modelResolver.deleteView,\n    previewViewData: modelResolver.previewViewData,\n    validateView: modelResolver.validateView,\n    updateViewMetadata: modelResolver.updateViewMetadata,\n\n    // Settings\n    resetCurrentProject: projectResolver.resetCurrentProject,\n    updateCurrentProject: projectResolver.updateCurrentProject,\n    updateDataSource: projectResolver.updateDataSource,\n\n    // preview\n    previewSql: modelResolver.previewSql,\n\n    // Learning\n    saveLearningRecord: learningResolver.saveLearningRecord,\n\n    // Recommendation questions\n    generateThreadRecommendationQuestions:\n      askingResolver.generateThreadRecommendationQuestions,\n    generateProjectRecommendationQuestions:\n      askingResolver.generateProjectRecommendationQuestions,\n\n    // Dashboard\n    updateDashboardItemLayouts: dashboardResolver.updateDashboardItemLayouts,\n    createDashboardItem: dashboardResolver.createDashboardItem,\n    updateDashboardItem: dashboardResolver.updateDashboardItem,\n    deleteDashboardItem: dashboardResolver.deleteDashboardItem,\n    previewItemSQL: dashboardResolver.previewItemSQL,\n    setDashboardSchedule: dashboardResolver.setDashboardSchedule,\n\n    // SQL Pairs\n    createSqlPair: sqlPairResolver.createSqlPair,\n    updateSqlPair: sqlPairResolver.updateSqlPair,\n    deleteSqlPair: sqlPairResolver.deleteSqlPair,\n    generateQuestion: sqlPairResolver.generateQuestion,\n    modelSubstitute: sqlPairResolver.modelSubstitute,\n    // Instructions\n    createInstruction: instructionResolver.createInstruction,\n    updateInstruction: instructionResolver.updateInstruction,\n    deleteInstruction: instructionResolver.deleteInstruction,\n  },\n  ThreadResponse: askingResolver.getThreadResponseNestedResolver(),\n  DetailStep: askingResolver.getDetailStepNestedResolver(),\n  ResultCandidate: askingResolver.getResultCandidateNestedResolver(),\n\n  // Handle struct type to record for UI\n  DiagramModelField: { type: convertColumnType },\n  DiagramModelNestedField: { type: convertColumnType },\n  CompactColumn: { type: convertColumnType },\n  FieldInfo: { type: convertColumnType },\n  DetailedColumn: { type: convertColumnType },\n  DetailedNestedColumn: { type: convertColumnType },\n  DetailedChangeColumn: { type: convertColumnType },\n\n  // Add this line to include the SqlPair nested resolver\n  SqlPair: sqlPairResolver.getSqlPairNestedResolver(),\n\n  // Add ApiHistoryResponse nested resolvers\n  ApiHistoryResponse: apiHistoryResolver.getApiHistoryNestedResolver(),\n};\n\nexport default resolvers;\n"
  },
  {
    "path": "wren-ui/src/apollo/server/scalars.ts",
    "content": "import { GraphQLScalarType } from 'graphql';\nimport { DialectSQL } from '@server/models/adaptor';\n\nexport const DialectSQLScalar = new GraphQLScalarType({\n  name: 'DialectSQL',\n  description: 'A string representing a SQL query in a specific dialect',\n  serialize(value: unknown): string {\n    if (typeof value !== 'string') {\n      throw new Error('DialectSQL must be a string');\n    }\n    return value;\n  },\n  parseValue(value: unknown): DialectSQL {\n    if (typeof value !== 'string') {\n      throw new Error('DialectSQL must be a string');\n    }\n    return value as DialectSQL;\n  },\n  parseLiteral(ast: any): DialectSQL {\n    if (ast.kind !== 'StringValue') {\n      throw new Error('DialectSQL must be a string');\n    }\n    return ast.value as DialectSQL;\n  },\n});\n"
  },
  {
    "path": "wren-ui/src/apollo/server/schema.ts",
    "content": "import { gql } from 'apollo-server-micro';\n\nexport const typeDefs = gql`\n  scalar JSON\n  scalar DialectSQL\n\n  enum ApiType {\n    GENERATE_SQL\n    RUN_SQL\n    GENERATE_VEGA_CHART\n    GENERATE_SUMMARY\n    ASK\n    GET_INSTRUCTIONS\n    CREATE_INSTRUCTION\n    UPDATE_INSTRUCTION\n    DELETE_INSTRUCTION\n    CREATE_SQL_PAIR\n    UPDATE_SQL_PAIR\n    DELETE_SQL_PAIR\n    GET_SQL_PAIRS\n    GET_MODELS\n    STREAM_ASK\n    STREAM_GENERATE_SQL\n  }\n\n  input ApiHistoryFilterInput {\n    apiType: ApiType\n    statusCode: Int\n    threadId: String\n    projectId: Int\n    startDate: String\n    endDate: String\n  }\n\n  input ApiHistoryPaginationInput {\n    offset: Int!\n    limit: Int!\n  }\n\n  type ApiHistoryResponse {\n    id: String!\n    projectId: Int!\n    apiType: ApiType!\n    threadId: String\n    headers: JSON\n    requestPayload: JSON\n    responsePayload: JSON\n    statusCode: Int\n    durationMs: Int\n    createdAt: String!\n    updatedAt: String!\n  }\n\n  type ApiHistoryPaginatedResponse {\n    items: [ApiHistoryResponse!]!\n    total: Int!\n    hasMore: Boolean!\n  }\n\n  enum DataSourceName {\n    ATHENA\n    BIG_QUERY\n    DUCKDB\n    POSTGRES\n    MYSQL\n    ORACLE\n    MSSQL\n    CLICK_HOUSE\n    TRINO\n    SNOWFLAKE\n    REDSHIFT\n    DATABRICKS\n  }\n\n  enum RedshiftConnectionType {\n    redshift\n    redshift_iam\n  }\n\n  enum DatabricksConnectionType {\n    token\n    service_principal\n  }\n\n  enum ExpressionName {\n    ABS\n    AVG\n    COUNT\n    COUNT_IF\n    MAX\n    MIN\n    SUM\n    CBRT\n    CEIL\n    CEILING\n    EXP\n    FLOOR\n    LN\n    LOG10\n    ROUND\n    SIGN\n    LENGTH\n    REVERSE\n  }\n\n  enum SampleDatasetName {\n    HR\n    ECOMMERCE\n    NBA\n    MUSIC\n  }\n\n  enum SyncStatus {\n    IN_PROGRESS\n    SYNCRONIZED\n    UNSYNCRONIZED\n  }\n\n  enum SchemaChangeType {\n    DELETED_TABLES\n    DELETED_COLUMNS\n    MODIFIED_COLUMNS\n  }\n\n  enum ProjectLanguage {\n    EN\n    ES\n    FR\n    ZH_TW\n    ZH_CN\n    DE\n    PT\n    RU\n    JA\n    KO\n    IT\n    FA_IR\n    AR\n    NL\n    AZ_AZ\n    TR\n  }\n\n  type DataSource {\n    type: DataSourceName!\n    properties: JSON!\n    # Show the name if the data source setup comes from a sample\n    sampleDataset: SampleDatasetName\n  }\n\n  input WhereIdInput {\n    id: Int!\n  }\n\n  input DataSourceInput {\n    type: DataSourceName!\n    properties: JSON!\n  }\n\n  input SampleDatasetInput {\n    name: SampleDatasetName!\n  }\n\n  type CompactTable {\n    name: String!\n    columns: [CompactColumn!]!\n    properties: JSON\n  }\n\n  input MDLModelSubmitInput {\n    name: String!\n    columns: [String!]!\n  }\n\n  enum RelationType {\n    ONE_TO_ONE\n    ONE_TO_MANY\n    MANY_TO_ONE\n  }\n\n  enum OnboardingStatus {\n    NOT_STARTED\n    DATASOURCE_SAVED\n    ONBOARDING_FINISHED\n    WITH_SAMPLE_DATASET\n  }\n\n  enum NodeType {\n    MODEL\n    METRIC\n    VIEW\n    RELATION\n    FIELD\n    CALCULATED_FIELD\n  }\n\n  type Relation {\n    fromModelId: Int!\n    fromModelReferenceName: String!\n    fromColumnId: Int!\n    fromColumnReferenceName: String!\n    toModelId: Int!\n    toModelReferenceName: String!\n    toColumnId: Int!\n    toColumnReferenceName: String!\n    type: RelationType!\n    name: String!\n  }\n\n  type RecommendRelations {\n    id: Int!\n    displayName: String!\n    referenceName: String!\n    relations: [Relation]!\n  }\n\n  input RelationInput {\n    fromModelId: Int!\n    fromColumnId: Int!\n    toModelId: Int!\n    toColumnId: Int!\n    type: RelationType!\n  }\n\n  input UpdateRelationInput {\n    type: RelationType!\n  }\n\n  input SaveRelationInput {\n    relations: [RelationInput]!\n  }\n\n  input SaveTablesInput {\n    tables: [String!]!\n  }\n\n  type CompactColumn {\n    name: String!\n    type: String!\n    properties: JSON\n  }\n\n  input CustomFieldInput {\n    name: String!\n    expression: String!\n  }\n\n  input CalculatedFieldInput {\n    name: String!\n    expression: String!\n    lineage: [Int!]!\n    diagram: JSON\n  }\n\n  input CreateModelInput {\n    sourceTableName: String!\n    fields: [String!]!\n    primaryKey: String\n  }\n\n  input CreateCalculatedFieldInput {\n    modelId: Int!\n    name: String!\n    expression: ExpressionName!\n    lineage: [Int!]!\n  }\n\n  input UpdateCalculatedFieldInput {\n    name: String!\n    expression: ExpressionName!\n    lineage: [Int!]!\n  }\n\n  input UpdateCalculatedFieldWhere {\n    id: Int!\n  }\n\n  input ValidateCalculatedFieldInput {\n    name: String!\n    modelId: Int!\n    columnId: Int\n  }\n\n  type CalculatedFieldValidationResponse {\n    valid: Boolean!\n    message: String\n  }\n\n  input ModelWhereInput {\n    id: Int!\n  }\n\n  input UpdateModelInput {\n    fields: [String!]!\n    primaryKey: String\n  }\n\n  # Metadata related\n  input UpdateNestedColumnMetadataInput {\n    id: Int!\n    displayName: String\n    description: String\n  }\n\n  input UpdateColumnMetadataInput {\n    id: Int!\n    displayName: String\n    description: String\n  }\n\n  input UpdateCalculatedFieldMetadataInput {\n    id: Int!\n    description: String\n  }\n\n  input UpdateRelationshipMetadataInput {\n    id: Int!\n    description: String\n  }\n\n  input UpdateViewColumnMetadataInput {\n    referenceName: String!\n    description: String\n  }\n\n  input UpdateModelMetadataInput {\n    displayName: String # Model display name, i,e, the alias of the model\n    description: String # Model description\n    columns: [UpdateColumnMetadataInput!] # Update column metadata\n    nestedColumns: [UpdateNestedColumnMetadataInput!] # Update nested column metadata\n    calculatedFields: [UpdateCalculatedFieldMetadataInput!] # Update calculated field metadata\n    relationships: [UpdateRelationshipMetadataInput!] # Update relationship metadata\n  }\n\n  input UpdateViewMetadataInput {\n    displayName: String # View display name, i,e, the alias of the view\n    description: String # View description\n    columns: [UpdateViewColumnMetadataInput!]\n  }\n\n  type NestedFieldInfo {\n    id: Int!\n    displayName: String!\n    referenceName: String!\n    sourceColumnName: String!\n    columnPath: [String!]!\n    type: String!\n    properties: JSON!\n  }\n\n  type FieldInfo {\n    id: Int!\n    displayName: String!\n    referenceName: String!\n    sourceColumnName: String!\n    type: String\n    isCalculated: Boolean!\n    notNull: Boolean!\n    expression: String\n    properties: JSON\n    nestedColumns: [NestedFieldInfo!]\n  }\n\n  type ModelInfo {\n    id: Int!\n    displayName: String!\n    referenceName: String!\n    sourceTableName: String!\n    refSql: String\n    primaryKey: String\n    cached: Boolean!\n    refreshTime: String\n    description: String\n    fields: [FieldInfo]!\n    calculatedFields: [FieldInfo]!\n    properties: JSON\n  }\n\n  type DetailedNestedColumn {\n    id: Int!\n    displayName: String!\n    referenceName: String!\n    sourceColumnName: String!\n    columnPath: [String!]!\n    type: String\n    properties: JSON\n  }\n\n  type DetailedColumn {\n    displayName: String!\n    referenceName: String!\n    sourceColumnName: String!\n    type: String\n    isCalculated: Boolean!\n    notNull: Boolean!\n    properties: JSON!\n    nestedColumns: [DetailedNestedColumn!]\n  }\n\n  type DetailedRelation {\n    fromModelId: Int!\n    fromColumnId: Int!\n    toModelId: Int!\n    toColumnId: Int!\n    type: RelationType!\n    name: String!\n    properties: JSON!\n  }\n\n  type DetailedModel {\n    displayName: String!\n    referenceName: String!\n    sourceTableName: String!\n    refSql: String!\n    primaryKey: String\n    cached: Boolean!\n    refreshTime: String\n    description: String\n    fields: [DetailedColumn]\n    calculatedFields: [DetailedColumn]\n    relations: [DetailedRelation]\n    properties: JSON!\n  }\n\n  # View\n  type ViewInfo {\n    id: Int!\n    name: String!\n    statement: String!\n    displayName: String!\n  }\n\n  input ViewWhereUniqueInput {\n    id: Int!\n  }\n\n  input PreviewViewDataInput {\n    id: Int!\n    # It will return default 500 rows if not specified limit\n    # refer: DEFAULT_PREVIEW_LIMIT\n    limit: Int\n  }\n\n  input CreateViewInput {\n    name: String!\n    responseId: Int!\n    rephrasedQuestion: String!\n  }\n\n  input ValidateViewInput {\n    name: String!\n  }\n\n  type ViewValidationResponse {\n    valid: Boolean!\n    message: String\n  }\n\n  # onboarding\n  type OnboardingStatusResponse {\n    status: OnboardingStatus\n  }\n\n  type ModelSyncResponse {\n    status: SyncStatus!\n  }\n\n  type Diagram {\n    models: [DiagramModel]!\n    views: [DiagramView]!\n  }\n\n  type DiagramView {\n    id: String!\n    viewId: Int!\n    nodeType: NodeType!\n    statement: String!\n    displayName: String!\n    referenceName: String!\n    fields: [DiagramViewField]!\n    description: String\n  }\n\n  type DiagramViewField {\n    id: String!\n    displayName: String!\n    referenceName: String!\n    type: String!\n    nodeType: NodeType!\n    description: String\n  }\n\n  type DiagramModel {\n    id: String!\n    modelId: Int!\n    nodeType: NodeType!\n    displayName: String!\n    referenceName: String!\n    sourceTableName: String!\n    refSql: String\n    cached: Boolean!\n    refreshTime: String\n    description: String\n    fields: [DiagramModelField]!\n    calculatedFields: [DiagramModelField]!\n    relationFields: [DiagramModelRelationField]!\n  }\n\n  type DiagramModelNestedField {\n    id: String!\n    nestedColumnId: Int!\n    displayName: String!\n    referenceName: String!\n    columnPath: [String!]!\n    type: String!\n    description: String\n  }\n\n  type DiagramModelField {\n    id: String!\n    columnId: Int!\n    nodeType: NodeType!\n    type: String!\n    displayName: String!\n    referenceName: String!\n    description: String\n    isPrimaryKey: Boolean!\n    expression: String\n    aggregation: String\n    lineage: [Int!]\n    nestedFields: [DiagramModelNestedField!]\n  }\n\n  type DiagramModelRelationField {\n    id: String!\n    relationId: Int!\n    nodeType: NodeType!\n    type: RelationType!\n    displayName: String!\n    referenceName: String!\n    description: String\n    fromModelId: Int!\n    fromModelName: String!\n    fromModelDisplayName: String!\n    fromColumnId: Int!\n    fromColumnName: String!\n    fromColumnDisplayName: String!\n    toModelId: Int!\n    toModelName: String!\n    toModelDisplayName: String!\n    toColumnId: Int!\n    toColumnName: String!\n    toColumnDisplayName: String!\n  }\n\n  input SimpleMeasureInput {\n    name: String!\n    type: String!\n    isCalculated: Boolean!\n    notNull: Boolean!\n    properties: JSON!\n  }\n\n  input DimensionInput {\n    name: String!\n    type: String!\n    isCalculated: Boolean!\n    notNull: Boolean!\n    properties: JSON!\n  }\n\n  input TimeGrainInput {\n    name: String!\n    refColumn: String!\n    dateParts: [String!]!\n  }\n\n  input CreateSimpleMetricInput {\n    name: String!\n    displayName: String!\n    description: String\n    cached: Boolean!\n    refreshTime: String\n    model: String!\n    properties: JSON!\n    measure: [SimpleMeasureInput!]!\n    dimension: [DimensionInput!]!\n    timeGrain: [TimeGrainInput!]!\n  }\n\n  # Task\n  type Task {\n    id: String!\n  }\n\n  # Error\n  type Error {\n    code: String\n    shortMessage: String\n    message: String\n    stacktrace: [String]\n  }\n\n  # Asking Task\n  input AskingTaskInput {\n    question: String!\n    # Used for follow-up questions\n    threadId: Int\n  }\n\n  enum AskingTaskStatus {\n    UNDERSTANDING\n    SEARCHING\n    PLANNING\n    GENERATING\n    CORRECTING\n    FINISHED\n    FAILED\n    STOPPED\n  }\n\n  enum AskingTaskType {\n    GENERAL\n    TEXT_TO_SQL\n    MISLEADING_QUERY\n  }\n\n  enum ChartTaskStatus {\n    FETCHING\n    GENERATING\n    FINISHED\n    FAILED\n    STOPPED\n  }\n\n  enum ChartType {\n    BAR\n    PIE\n    LINE\n    MULTI_LINE\n    AREA\n    GROUPED_BAR\n    STACKED_BAR\n  }\n\n  enum ResultCandidateType {\n    VIEW # View type candidate is provided basd on a saved view\n    LLM # LLM type candidate is created by LLM\n    SQL_PAIR # SQL pair type candidate is created by SQL pair\n  }\n\n  type ResultCandidate {\n    type: ResultCandidateType!\n    sql: String!\n    view: ViewInfo\n    sqlPair: SqlPair\n  }\n\n  type AskingTask {\n    status: AskingTaskStatus!\n    type: AskingTaskType\n    error: Error\n    candidates: [ResultCandidate!]!\n    rephrasedQuestion: String\n    intentReasoning: String\n    sqlGenerationReasoning: String\n    retrievedTables: [String!]\n    invalidSql: String\n    traceId: String\n    queryId: String\n  }\n\n  input InstantRecommendedQuestionsInput {\n    previousQuestions: [String!]\n  }\n\n  enum RecommendedQuestionsTaskStatus {\n    NOT_STARTED\n    GENERATING\n    FINISHED\n    FAILED\n  }\n\n  type ResultQuestion {\n    question: String!\n    category: String!\n    sql: String!\n  }\n\n  type RecommendedQuestionsTask {\n    status: RecommendedQuestionsTaskStatus!\n    questions: [ResultQuestion!]!\n    error: Error\n  }\n\n  # Thread\n  input CreateThreadInput {\n    question: String\n    sql: String\n    taskId: String\n  }\n\n  input CreateThreadResponseInput {\n    question: String\n    sql: String\n    taskId: String\n  }\n\n  input ThreadUniqueWhereInput {\n    id: Int!\n  }\n\n  input UpdateThreadInput {\n    summary: String\n  }\n\n  input ThreadResponseUniqueWhereInput {\n    id: Int!\n  }\n\n  input UpdateThreadResponseInput {\n    sql: String\n  }\n\n  input AdjustThreadResponseChartInput {\n    chartType: ChartType!\n    xAxis: String\n    yAxis: String\n    xOffset: String\n    color: String\n    theta: String\n  }\n\n  input AdjustThreadResponseInput {\n    tables: [String!]\n    sqlGenerationReasoning: String\n    sql: String\n  }\n\n  input PreviewDataInput {\n    responseId: Int!\n    # Optional, only used for preview data of a single step\n    stepIndex: Int\n    # It will return default 500 rows if not specified limit\n    # refer: DEFAULT_PREVIEW_LIMIT\n    limit: Int\n  }\n\n  type DetailStep {\n    summary: String!\n    sql: String!\n    cteName: String\n  }\n\n  enum ThreadResponseAnswerStatus {\n    NOT_STARTED\n    FETCHING_DATA\n    PREPROCESSING\n    STREAMING\n    FINISHED\n    FAILED\n    INTERRUPTED\n  }\n\n  type ThreadResponseAnswerDetail {\n    queryId: String\n    status: ThreadResponseAnswerStatus\n    error: Error\n    numRowsUsedInLLM: Int\n    content: String\n  }\n\n  type ThreadResponseBreakdownDetail {\n    queryId: String\n    status: AskingTaskStatus!\n    error: Error\n    description: String\n    steps: [DetailStep!]\n  }\n\n  type ThreadResponseChartDetail {\n    queryId: String\n    status: ChartTaskStatus!\n    error: Error\n    description: String\n    chartType: ChartType\n    chartSchema: JSON\n    adjustment: Boolean\n  }\n\n  enum ThreadResponseAdjustmentType {\n    REASONING\n    APPLY_SQL\n  }\n\n  type ThreadResponseAdjustment {\n    type: ThreadResponseAdjustmentType!\n    payload: JSON\n  }\n\n  type AdjustmentTask {\n    queryId: String\n    status: AskingTaskStatus\n    error: Error\n    sql: String\n    traceId: String\n    invalidSql: String\n  }\n\n  type ThreadResponse {\n    id: Int!\n    threadId: Int!\n    question: String!\n    sql: String\n    view: ViewInfo\n    breakdownDetail: ThreadResponseBreakdownDetail\n    answerDetail: ThreadResponseAnswerDetail\n    chartDetail: ThreadResponseChartDetail\n    askingTask: AskingTask\n    adjustment: ThreadResponseAdjustment\n    adjustmentTask: AdjustmentTask\n  }\n\n  # Thread only consists of basic information of a thread\n  type Thread {\n    id: Int!\n    summary: String!\n  }\n\n  # Detailed thread consists of thread and thread responses\n  type DetailedThread {\n    id: Int!\n    responses: [ThreadResponse!]!\n  }\n\n  type SuggestedQuestion {\n    question: String!\n    label: String!\n  }\n  # Ask Questions Responses\n  type SuggestedQuestionResponse {\n    questions: [SuggestedQuestion]!\n  }\n\n  # Settings\n  input UpdateDataSourceInput {\n    properties: JSON!\n  }\n\n  input UpdateCurrentProjectInput {\n    language: ProjectLanguage!\n  }\n\n  type Settings {\n    productVersion: String!\n    dataSource: DataSource!\n    language: ProjectLanguage!\n  }\n\n  type GetMDLResult {\n    hash: String!\n    mdl: String\n  }\n\n  input PreviewSQLDataInput {\n    sql: String!\n    projectId: String\n    limit: Int\n    dryRun: Boolean\n  }\n\n  # Schema Change\n  type SchemaChange {\n    deletedTables: [DetailedChangeTable!]\n    deletedColumns: [DetailedChangeTable!]\n    modifiedColumns: [DetailedChangeTable!]\n    lastSchemaChangeTime: String\n  }\n\n  type DetailedChangeTable {\n    sourceTableName: String!\n    displayName: String!\n    columns: [DetailedChangeColumn!]!\n    calculatedFields: [DetailedAffectedCalculatedFields!]!\n    relationships: [DetailedAffectedRelationships!]!\n  }\n\n  type DetailedChangeColumn {\n    sourceColumnName: String!\n    displayName: String!\n    type: String!\n  }\n\n  type DetailedAffectedCalculatedFields {\n    displayName: String!\n    referenceName: String!\n    type: String!\n  }\n\n  type DetailedAffectedRelationships {\n    displayName: String!\n    referenceName: String!\n  }\n\n  input ResolveSchemaChangeWhereInput {\n    type: SchemaChangeType!\n  }\n\n  # Learning\n  type LearningRecord {\n    paths: [String!]!\n  }\n\n  input SaveLearningRecordInput {\n    path: String!\n  }\n\n  # Dashboard\n  enum DashboardItemType {\n    BAR\n    PIE\n    LINE\n    MULTI_LINE\n    AREA\n    GROUPED_BAR\n    STACKED_BAR\n    TABLE\n    NUMBER\n  }\n\n  input DashboardItemWhereInput {\n    id: Int!\n  }\n\n  input CreateDashboardItemInput {\n    itemType: DashboardItemType!\n    responseId: Int!\n  }\n\n  input UpdateDashboardItemInput {\n    displayName: String!\n  }\n\n  input ItemLayoutInput {\n    itemId: Int!\n    x: Int!\n    y: Int!\n    w: Int!\n    h: Int!\n  }\n\n  input UpdateDashboardItemLayoutsInput {\n    layouts: [ItemLayoutInput!]!\n  }\n\n  input DeleteDashboardItemInput {\n    itemId: Int!\n  }\n\n  input PreviewItemSQLInput {\n    itemId: Int!\n    limit: Int\n    refresh: Boolean = false\n  }\n\n  type PreviewItemResponse {\n    data: JSON!\n    cacheHit: Boolean!\n    cacheCreatedAt: String\n    cacheOverrodeAt: String\n    override: Boolean!\n  }\n\n  input SetDashboardScheduleInput {\n    cacheEnabled: Boolean!\n    schedule: SetDashboardScheduleData\n  }\n\n  type DashboardSchedule {\n    frequency: ScheduleFrequencyEnum\n    hour: Int\n    minute: Int\n    day: CacheScheduleDayEnum\n    timezone: String\n    cron: String\n  }\n\n  input SetDashboardScheduleData {\n    frequency: ScheduleFrequencyEnum!\n    hour: Int\n    minute: Int\n    day: CacheScheduleDayEnum\n    timezone: String\n    cron: String\n  }\n\n  enum ScheduleFrequencyEnum {\n    DAILY\n    WEEKLY\n    CUSTOM\n    NEVER\n  }\n\n  enum CacheScheduleDayEnum {\n    SUN\n    MON\n    TUE\n    WED\n    THU\n    FRI\n    SAT\n  }\n\n  type DashboardItemLayout {\n    x: Int!\n    y: Int!\n    w: Int!\n    h: Int!\n  }\n\n  type DashboardItemDetail {\n    sql: String!\n    chartSchema: JSON\n  }\n\n  type DashboardItem {\n    id: Int!\n    dashboardId: Int!\n    type: DashboardItemType!\n    layout: DashboardItemLayout!\n    detail: DashboardItemDetail!\n    displayName: String\n  }\n\n  type Dashboard {\n    id: Int!\n    projectId: Int!\n    name: String!\n    cacheEnabled: Boolean!\n    scheduleFrequency: ScheduleFrequencyEnum\n    scheduleTimezone: String\n    scheduleCron: String\n    nextScheduledAt: String\n  }\n\n  type DetailedDashboard {\n    id: Int!\n    name: String!\n    description: String\n    cacheEnabled: Boolean!\n    nextScheduledAt: String\n    schedule: DashboardSchedule\n    items: [DashboardItem!]!\n  }\n\n  type SqlPair {\n    id: Int!\n    projectId: Int!\n    sql: String!\n    question: String!\n    createdAt: String\n    updatedAt: String\n  }\n\n  input CreateSqlPairInput {\n    sql: String!\n    question: String!\n  }\n\n  input UpdateSqlPairInput {\n    sql: String\n    question: String\n  }\n\n  input SqlPairWhereUniqueInput {\n    id: Int!\n  }\n\n  input GenerateQuestionInput {\n    sql: String!\n  }\n\n  input ModelSubstituteInput {\n    sql: DialectSQL!\n  }\n\n  type Instruction {\n    id: Int!\n    projectId: Int!\n    instruction: String!\n    questions: [String!]!\n    isDefault: Boolean!\n    createdAt: String!\n    updatedAt: String!\n  }\n\n  input CreateInstructionInput {\n    instruction: String!\n    questions: [String!]!\n    isDefault: Boolean!\n  }\n\n  input UpdateInstructionInput {\n    instruction: String\n    questions: [String!]\n    isDefault: Boolean\n  }\n\n  input InstructionWhereInput {\n    id: Int!\n  }\n\n  # Query and Mutation\n  type Query {\n    # On Boarding Steps\n    listDataSourceTables: [CompactTable!]!\n    autoGenerateRelation: [RecommendRelations!]!\n    onboardingStatus: OnboardingStatusResponse!\n\n    # Modeling Page\n    listModels: [ModelInfo!]!\n    model(where: ModelWhereInput!): DetailedModel!\n    modelSync: ModelSyncResponse!\n    diagram: Diagram!\n    schemaChange: SchemaChange!\n\n    # View\n    listViews: [ViewInfo!]!\n    view(where: ViewWhereUniqueInput!): ViewInfo!\n\n    # Ask\n    askingTask(taskId: String!): AskingTask\n    suggestedQuestions: SuggestedQuestionResponse!\n    threads: [Thread!]!\n    thread(threadId: Int!): DetailedThread!\n    threadResponse(responseId: Int!): ThreadResponse!\n    nativeSql(responseId: Int!): String!\n\n    # Adjustment\n    adjustmentTask(taskId: String!): AdjustmentTask\n\n    # Settings\n    settings: Settings!\n\n    # System\n    getMDL(hash: String!): GetMDLResult!\n\n    # Learning\n    learningRecord: LearningRecord!\n\n    # Recommendation questions\n    getThreadRecommendationQuestions(threadId: Int!): RecommendedQuestionsTask!\n    getProjectRecommendationQuestions: RecommendedQuestionsTask!\n    instantRecommendedQuestions(taskId: String!): RecommendedQuestionsTask!\n\n    # Dashboard\n    dashboardItems: [DashboardItem!]!\n    dashboard: DetailedDashboard!\n\n    # SQL Pairs\n    sqlPairs: [SqlPair]!\n    # Instructions\n    instructions: [Instruction]!\n\n    # Api History\n    apiHistory(\n      filter: ApiHistoryFilterInput\n      pagination: ApiHistoryPaginationInput!\n    ): ApiHistoryPaginatedResponse!\n  }\n\n  type Mutation {\n    # On Boarding Steps\n    saveDataSource(data: DataSourceInput!): DataSource!\n    startSampleDataset(data: SampleDatasetInput!): JSON!\n    saveTables(data: SaveTablesInput!): JSON!\n    saveRelations(data: SaveRelationInput!): JSON!\n    deploy(force: Boolean): JSON!\n\n    # Modeling Page\n    createModel(data: CreateModelInput!): JSON!\n    updateModel(where: ModelWhereInput!, data: UpdateModelInput!): JSON!\n    deleteModel(where: ModelWhereInput!): Boolean!\n    previewModelData(where: WhereIdInput!): JSON!\n    triggerDataSourceDetection: Boolean!\n    resolveSchemaChange(where: ResolveSchemaChangeWhereInput!): Boolean!\n\n    # Metadata\n    updateModelMetadata(\n      where: ModelWhereInput!\n      data: UpdateModelMetadataInput!\n    ): Boolean!\n    updateViewMetadata(\n      where: ViewWhereUniqueInput!\n      data: UpdateViewMetadataInput!\n    ): Boolean!\n\n    # Relation\n    createRelation(data: RelationInput!): JSON!\n    updateRelation(data: UpdateRelationInput!, where: WhereIdInput!): JSON!\n    deleteRelation(where: WhereIdInput!): Boolean!\n\n    # Calculated field\n    createCalculatedField(data: CreateCalculatedFieldInput!): JSON!\n    updateCalculatedField(\n      where: UpdateCalculatedFieldWhere!\n      data: UpdateCalculatedFieldInput!\n    ): JSON!\n    deleteCalculatedField(where: UpdateCalculatedFieldWhere): Boolean!\n    validateCalculatedField(\n      data: ValidateCalculatedFieldInput!\n    ): CalculatedFieldValidationResponse!\n\n    # View\n    createView(data: CreateViewInput!): ViewInfo!\n    deleteView(where: ViewWhereUniqueInput!): Boolean!\n    previewViewData(where: PreviewViewDataInput!): JSON!\n    validateView(data: ValidateViewInput!): ViewValidationResponse!\n\n    # Ask\n    createAskingTask(data: AskingTaskInput!): Task!\n    cancelAskingTask(taskId: String!): Boolean!\n    rerunAskingTask(responseId: Int!): Task!\n\n    # Thread\n    createThread(data: CreateThreadInput!): Thread!\n    updateThread(\n      where: ThreadUniqueWhereInput!\n      data: UpdateThreadInput!\n    ): Thread!\n    deleteThread(where: ThreadUniqueWhereInput!): Boolean!\n\n    # Thread Response\n    createThreadResponse(\n      threadId: Int!\n      data: CreateThreadResponseInput!\n    ): ThreadResponse!\n    updateThreadResponse(\n      where: ThreadResponseUniqueWhereInput!\n      data: UpdateThreadResponseInput!\n    ): ThreadResponse!\n    previewData(where: PreviewDataInput!): JSON!\n    previewBreakdownData(where: PreviewDataInput!): JSON!\n\n    # Generate Thread Response Breakdown\n    generateThreadResponseBreakdown(responseId: Int!): ThreadResponse!\n\n    # Generate Thread Response Answer\n    generateThreadResponseAnswer(responseId: Int!): ThreadResponse!\n\n    # Generate Thread Response Chart\n    generateThreadResponseChart(responseId: Int!): ThreadResponse!\n\n    # Adjust Thread Response Chart\n    adjustThreadResponseChart(\n      responseId: Int!\n      data: AdjustThreadResponseChartInput!\n    ): ThreadResponse!\n\n    # Adjustment\n    adjustThreadResponse(\n      responseId: Int!\n      data: AdjustThreadResponseInput!\n    ): ThreadResponse!\n    cancelAdjustmentTask(taskId: String!): Boolean!\n    rerunAdjustmentTask(responseId: Int!): Boolean!\n\n    # Settings\n    resetCurrentProject: Boolean!\n    updateCurrentProject(data: UpdateCurrentProjectInput!): Boolean!\n    updateDataSource(data: UpdateDataSourceInput!): DataSource!\n\n    # preview\n    previewSql(data: PreviewSQLDataInput): JSON!\n\n    # Learning\n    saveLearningRecord(data: SaveLearningRecordInput!): LearningRecord!\n\n    # Recommendation questions\n    generateThreadRecommendationQuestions(threadId: Int!): Boolean!\n    generateProjectRecommendationQuestions: Boolean!\n    createInstantRecommendedQuestions(\n      data: InstantRecommendedQuestionsInput!\n    ): Task!\n\n    # Dashboard\n    updateDashboardItemLayouts(\n      data: UpdateDashboardItemLayoutsInput!\n    ): [DashboardItem!]!\n    createDashboardItem(data: CreateDashboardItemInput!): DashboardItem!\n    updateDashboardItem(\n      where: DashboardItemWhereInput!\n      data: UpdateDashboardItemInput!\n    ): DashboardItem!\n    deleteDashboardItem(where: DashboardItemWhereInput!): Boolean!\n    previewItemSQL(data: PreviewItemSQLInput!): PreviewItemResponse!\n    setDashboardSchedule(data: SetDashboardScheduleInput!): Dashboard!\n\n    # SQL Pairs\n    createSqlPair(data: CreateSqlPairInput!): SqlPair!\n    updateSqlPair(\n      where: SqlPairWhereUniqueInput!\n      data: UpdateSqlPairInput!\n    ): SqlPair!\n    deleteSqlPair(where: SqlPairWhereUniqueInput!): Boolean!\n    generateQuestion(data: GenerateQuestionInput!): String!\n    modelSubstitute(data: ModelSubstituteInput!): String!\n    # Instructions\n    createInstruction(data: CreateInstructionInput!): Instruction!\n    updateInstruction(\n      where: InstructionWhereInput!\n      data: UpdateInstructionInput!\n    ): Instruction!\n    deleteInstruction(where: InstructionWhereInput!): Boolean!\n  }\n`;\n"
  },
  {
    "path": "wren-ui/src/apollo/server/services/askingService.ts",
    "content": "import { IWrenAIAdaptor } from '@server/adaptors/wrenAIAdaptor';\nimport {\n  AskResultStatus,\n  RecommendationQuestionsResult,\n  RecommendationQuestionsInput,\n  RecommendationQuestion,\n  WrenAIError,\n  RecommendationQuestionStatus,\n  ChartStatus,\n  ChartAdjustmentOption,\n  WrenAILanguage,\n} from '@server/models/adaptor';\nimport { IDeployService } from './deployService';\nimport { IProjectService } from './projectService';\nimport { IThreadRepository, Thread } from '../repositories/threadRepository';\nimport {\n  IThreadResponseRepository,\n  ThreadResponse,\n  ThreadResponseAdjustmentType,\n} from '../repositories/threadResponseRepository';\nimport { getLogger } from '@server/utils';\nimport { isEmpty, isNil } from 'lodash';\nimport { safeFormatSQL } from '@server/utils/sqlFormat';\nimport {\n  PostHogTelemetry,\n  TelemetryEvent,\n  WrenService,\n} from '../telemetry/telemetry';\nimport {\n  IAskingTaskRepository,\n  IViewRepository,\n  Project,\n} from '../repositories';\nimport { IQueryService, PreviewDataResponse } from './queryService';\nimport { IMDLService } from './mdlService';\nimport {\n  ThreadRecommendQuestionBackgroundTracker,\n  ChartBackgroundTracker,\n  ChartAdjustmentBackgroundTracker,\n  AdjustmentBackgroundTaskTracker,\n  TrackedAdjustmentResult,\n} from '../backgrounds';\nimport { getConfig } from '@server/config';\nimport { TextBasedAnswerBackgroundTracker } from '../backgrounds/textBasedAnswerBackgroundTracker';\nimport { IAskingTaskTracker, TrackedAskingResult } from './askingTaskTracker';\n\nconst config = getConfig();\n\nconst logger = getLogger('AskingService');\nlogger.level = 'debug';\n\n// const QUERY_ID_PLACEHOLDER = '0';\n\nexport interface Task {\n  id: string;\n}\n\nexport interface AskingPayload {\n  threadId?: number;\n  language: string;\n}\n\nexport interface AskingTaskInput {\n  question: string;\n}\n\nexport interface AskingDetailTaskInput {\n  question?: string;\n  sql?: string;\n  trackedAskingResult?: TrackedAskingResult;\n}\n\nexport interface AskingDetailTaskUpdateInput {\n  summary?: string;\n}\n\nexport enum RecommendQuestionResultStatus {\n  NOT_STARTED = 'NOT_STARTED',\n  GENERATING = 'GENERATING',\n  FINISHED = 'FINISHED',\n  FAILED = 'FAILED',\n}\n\nexport interface ThreadRecommendQuestionResult {\n  status: RecommendQuestionResultStatus;\n  questions: RecommendationQuestion[];\n  error?: WrenAIError;\n}\n\nexport interface InstantRecommendedQuestionsInput {\n  previousQuestions?: string[];\n}\n\nexport enum ThreadResponseAnswerStatus {\n  NOT_STARTED = 'NOT_STARTED',\n  FETCHING_DATA = 'FETCHING_DATA',\n  PREPROCESSING = 'PREPROCESSING',\n  STREAMING = 'STREAMING',\n  FINISHED = 'FINISHED',\n  FAILED = 'FAILED',\n  INTERRUPTED = 'INTERRUPTED',\n}\n\n// adjustment input\nexport interface AdjustmentReasoningInput {\n  tables: string[];\n  sqlGenerationReasoning: string;\n  projectId: number;\n}\n\nexport interface AdjustmentSqlInput {\n  sql: string;\n}\n\nexport interface IAskingService {\n  /**\n   * Asking task.\n   */\n  createAskingTask(\n    input: AskingTaskInput,\n    payload: AskingPayload,\n    // if the asking task is rerun from a cancelled thread response\n    rerunFromCancelled?: boolean,\n    // if the asking task is rerun from a cancelled thread response,\n    // the previous task id is the task id of the cancelled thread response\n    previousTaskId?: number,\n    // if the asking task is rerun from a thread response\n    // the thread response id is the id of the cancelled thread response\n    threadResponseId?: number,\n  ): Promise<Task>;\n  rerunAskingTask(\n    threadResponseId: number,\n    payload: AskingPayload,\n  ): Promise<Task>;\n  cancelAskingTask(taskId: string): Promise<void>;\n  getAskingTask(taskId: string): Promise<TrackedAskingResult>;\n  getAskingTaskById(id: number): Promise<TrackedAskingResult>;\n\n  /**\n   * Asking detail task.\n   */\n  createThread(input: AskingDetailTaskInput): Promise<Thread>;\n  updateThread(\n    threadId: number,\n    input: Partial<AskingDetailTaskUpdateInput>,\n  ): Promise<Thread>;\n  deleteThread(threadId: number): Promise<void>;\n  listThreads(): Promise<Thread[]>;\n  createThreadResponse(\n    input: AskingDetailTaskInput,\n    threadId: number,\n  ): Promise<ThreadResponse>;\n  updateThreadResponse(\n    responseId: number,\n    data: { sql: string },\n  ): Promise<ThreadResponse>;\n  getResponsesWithThread(threadId: number): Promise<ThreadResponse[]>;\n  getResponse(responseId: number): Promise<ThreadResponse>;\n  generateThreadResponseBreakdown(\n    threadResponseId: number,\n    configurations: { language: string },\n  ): Promise<ThreadResponse>;\n  generateThreadResponseAnswer(\n    threadResponseId: number,\n    configurations: { language: string },\n  ): Promise<ThreadResponse>;\n  generateThreadResponseChart(\n    threadResponseId: number,\n    configurations: { language: string },\n  ): Promise<ThreadResponse>;\n  adjustThreadResponseChart(\n    threadResponseId: number,\n    input: ChartAdjustmentOption,\n    configurations: { language: string },\n  ): Promise<ThreadResponse>;\n  adjustThreadResponseWithSQL(\n    threadResponseId: number,\n    input: AdjustmentSqlInput,\n  ): Promise<ThreadResponse>;\n  adjustThreadResponseAnswer(\n    threadResponseId: number,\n    input: AdjustmentReasoningInput,\n    configurations: { language: string },\n  ): Promise<ThreadResponse>;\n  cancelAdjustThreadResponseAnswer(taskId: string): Promise<void>;\n  rerunAdjustThreadResponseAnswer(\n    threadResponseId: number,\n    projectId: number,\n    configurations: { language: string },\n  ): Promise<{ queryId: string }>;\n  getAdjustmentTask(taskId: string): Promise<TrackedAdjustmentResult>;\n  getAdjustmentTaskById(id: number): Promise<TrackedAdjustmentResult>;\n  changeThreadResponseAnswerDetailStatus(\n    responseId: number,\n    status: ThreadResponseAnswerStatus,\n    content?: string,\n  ): Promise<ThreadResponse>;\n  previewData(responseId: number, limit?: number): Promise<PreviewDataResponse>;\n  previewBreakdownData(\n    responseId: number,\n    stepIndex?: number,\n    limit?: number,\n  ): Promise<PreviewDataResponse>;\n\n  /**\n   * Recommendation questions\n   */\n  createInstantRecommendedQuestions(\n    input: InstantRecommendedQuestionsInput,\n  ): Promise<Task>;\n  getInstantRecommendedQuestions(\n    queryId: string,\n  ): Promise<RecommendationQuestionsResult>;\n  generateThreadRecommendationQuestions(threadId: number): Promise<void>;\n  getThreadRecommendationQuestions(\n    threadId: number,\n  ): Promise<ThreadRecommendQuestionResult>;\n\n  deleteAllByProjectId(projectId: number): Promise<void>;\n}\n\n/**\n * utility function to check if the status is finalized\n */\nconst isFinalized = (status: AskResultStatus) => {\n  return (\n    status === AskResultStatus.FAILED ||\n    status === AskResultStatus.FINISHED ||\n    status === AskResultStatus.STOPPED\n  );\n};\n\n/**\n * Given a list of steps, construct the SQL statement with CTEs\n * If stepIndex is provided, only construct the SQL from top to that step\n * @param steps\n * @param stepIndex\n * @returns string\n */\nexport const constructCteSql = (\n  steps: Array<{ cteName: string; summary: string; sql: string }>,\n  stepIndex?: number,\n): string => {\n  // validate stepIndex\n  if (!isNil(stepIndex) && (stepIndex < 0 || stepIndex >= steps.length)) {\n    throw new Error(`Invalid stepIndex: ${stepIndex}`);\n  }\n\n  const slicedSteps = isNil(stepIndex) ? steps : steps.slice(0, stepIndex + 1);\n\n  // if there's only one step, return the sql directly\n  if (slicedSteps.length === 1) {\n    return `-- ${slicedSteps[0].summary}\\n${slicedSteps[0].sql}`;\n  }\n\n  let sql = 'WITH ';\n  slicedSteps.forEach((step, index) => {\n    if (index === slicedSteps.length - 1) {\n      // if it's the last step, remove the trailing comma.\n      // no need to wrap with WITH\n      sql += `\\n-- ${step.summary}\\n`;\n      sql += `${step.sql}`;\n    } else if (index === slicedSteps.length - 2) {\n      // if it's the last two steps, remove the trailing comma.\n      // wrap with CTE\n      sql += `${step.cteName} AS`;\n      sql += `\\n-- ${step.summary}\\n`;\n      sql += `(${step.sql})`;\n    } else {\n      // if it's not the last step, wrap with CTE\n      sql += `${step.cteName} AS`;\n      sql += `\\n-- ${step.summary}\\n`;\n      sql += `(${step.sql}),`;\n    }\n  });\n\n  return sql;\n};\n\n/**\n * Background tracker to track the status of the asking breakdown task\n */\nclass BreakdownBackgroundTracker {\n  // tasks is a kv pair of task id and thread response\n  private tasks: Record<number, ThreadResponse> = {};\n  private intervalTime: number;\n  private wrenAIAdaptor: IWrenAIAdaptor;\n  private threadResponseRepository: IThreadResponseRepository;\n  private runningJobs = new Set();\n  private telemetry: PostHogTelemetry;\n\n  constructor({\n    telemetry,\n    wrenAIAdaptor,\n    threadResponseRepository,\n  }: {\n    telemetry: PostHogTelemetry;\n    wrenAIAdaptor: IWrenAIAdaptor;\n    threadResponseRepository: IThreadResponseRepository;\n  }) {\n    this.telemetry = telemetry;\n    this.wrenAIAdaptor = wrenAIAdaptor;\n    this.threadResponseRepository = threadResponseRepository;\n    this.intervalTime = 1000;\n    this.start();\n  }\n\n  public start() {\n    logger.info('Background tracker started');\n    setInterval(() => {\n      const jobs = Object.values(this.tasks).map(\n        (threadResponse) => async () => {\n          // check if same job is running\n          if (this.runningJobs.has(threadResponse.id)) {\n            return;\n          }\n\n          // mark the job as running\n          this.runningJobs.add(threadResponse.id);\n\n          // get the answer detail\n          const breakdownDetail = threadResponse.breakdownDetail;\n\n          // get the latest result from AI service\n          const result = await this.wrenAIAdaptor.getAskDetailResult(\n            breakdownDetail.queryId,\n          );\n\n          // check if status change\n          if (breakdownDetail.status === result.status) {\n            // mark the job as finished\n            logger.debug(\n              `Job ${threadResponse.id} status not changed, finished`,\n            );\n            this.runningJobs.delete(threadResponse.id);\n            return;\n          }\n\n          // update database\n          const updatedBreakdownDetail = {\n            queryId: breakdownDetail.queryId,\n            status: result?.status,\n            error: result?.error,\n            description: result?.response?.description,\n            steps: result?.response?.steps,\n          };\n          logger.debug(`Job ${threadResponse.id} status changed, updating`);\n          await this.threadResponseRepository.updateOne(threadResponse.id, {\n            breakdownDetail: updatedBreakdownDetail,\n          });\n\n          // remove the task from tracker if it is finalized\n          if (isFinalized(result.status)) {\n            const eventProperties = {\n              question: threadResponse.question,\n              error: result.error,\n            };\n            if (result.status === AskResultStatus.FINISHED) {\n              this.telemetry.sendEvent(\n                TelemetryEvent.HOME_ANSWER_BREAKDOWN,\n                eventProperties,\n              );\n            } else {\n              this.telemetry.sendEvent(\n                TelemetryEvent.HOME_ANSWER_BREAKDOWN,\n                eventProperties,\n                WrenService.AI,\n                false,\n              );\n            }\n            logger.debug(`Job ${threadResponse.id} is finalized, removing`);\n            delete this.tasks[threadResponse.id];\n          }\n\n          // mark the job as finished\n          this.runningJobs.delete(threadResponse.id);\n        },\n      );\n\n      // run the jobs\n      Promise.allSettled(jobs.map((job) => job())).then((results) => {\n        // show reason of rejection\n        results.forEach((result, index) => {\n          if (result.status === 'rejected') {\n            logger.error(`Job ${index} failed: ${result.reason}`);\n          }\n        });\n      });\n    }, this.intervalTime);\n  }\n\n  public addTask(threadResponse: ThreadResponse) {\n    this.tasks[threadResponse.id] = threadResponse;\n  }\n\n  public getTasks() {\n    return this.tasks;\n  }\n}\n\nexport class AskingService implements IAskingService {\n  private wrenAIAdaptor: IWrenAIAdaptor;\n  private deployService: IDeployService;\n  private projectService: IProjectService;\n  private viewRepository: IViewRepository;\n  private threadRepository: IThreadRepository;\n  private threadResponseRepository: IThreadResponseRepository;\n  private breakdownBackgroundTracker: BreakdownBackgroundTracker;\n  private textBasedAnswerBackgroundTracker: TextBasedAnswerBackgroundTracker;\n  private chartBackgroundTracker: ChartBackgroundTracker;\n  private chartAdjustmentBackgroundTracker: ChartAdjustmentBackgroundTracker;\n  private threadRecommendQuestionBackgroundTracker: ThreadRecommendQuestionBackgroundTracker;\n  private queryService: IQueryService;\n  private telemetry: PostHogTelemetry;\n  private mdlService: IMDLService;\n  private askingTaskTracker: IAskingTaskTracker;\n  private askingTaskRepository: IAskingTaskRepository;\n  private adjustmentBackgroundTracker: AdjustmentBackgroundTaskTracker;\n\n  constructor({\n    telemetry,\n    wrenAIAdaptor,\n    deployService,\n    projectService,\n    viewRepository,\n    threadRepository,\n    threadResponseRepository,\n    askingTaskRepository,\n    queryService,\n    mdlService,\n    askingTaskTracker,\n  }: {\n    telemetry: PostHogTelemetry;\n    wrenAIAdaptor: IWrenAIAdaptor;\n    deployService: IDeployService;\n    projectService: IProjectService;\n    viewRepository: IViewRepository;\n    threadRepository: IThreadRepository;\n    threadResponseRepository: IThreadResponseRepository;\n    askingTaskRepository: IAskingTaskRepository;\n    queryService: IQueryService;\n    mdlService: IMDLService;\n    askingTaskTracker: IAskingTaskTracker;\n  }) {\n    this.wrenAIAdaptor = wrenAIAdaptor;\n    this.deployService = deployService;\n    this.projectService = projectService;\n    this.viewRepository = viewRepository;\n    this.threadRepository = threadRepository;\n    this.threadResponseRepository = threadResponseRepository;\n    this.telemetry = telemetry;\n    this.queryService = queryService;\n    this.breakdownBackgroundTracker = new BreakdownBackgroundTracker({\n      telemetry,\n      wrenAIAdaptor,\n      threadResponseRepository,\n    });\n    this.textBasedAnswerBackgroundTracker =\n      new TextBasedAnswerBackgroundTracker({\n        wrenAIAdaptor,\n        threadResponseRepository,\n        projectService,\n        deployService,\n        queryService,\n      });\n    this.chartBackgroundTracker = new ChartBackgroundTracker({\n      telemetry,\n      wrenAIAdaptor,\n      threadResponseRepository,\n    });\n    this.chartAdjustmentBackgroundTracker =\n      new ChartAdjustmentBackgroundTracker({\n        telemetry,\n        wrenAIAdaptor,\n        threadResponseRepository,\n      });\n    this.threadRecommendQuestionBackgroundTracker =\n      new ThreadRecommendQuestionBackgroundTracker({\n        telemetry,\n        wrenAIAdaptor,\n        threadRepository,\n      });\n    this.adjustmentBackgroundTracker = new AdjustmentBackgroundTaskTracker({\n      telemetry,\n      wrenAIAdaptor,\n      askingTaskRepository,\n      threadResponseRepository,\n    });\n\n    this.askingTaskRepository = askingTaskRepository;\n    this.mdlService = mdlService;\n    this.askingTaskTracker = askingTaskTracker;\n  }\n\n  public async getThreadRecommendationQuestions(\n    threadId: number,\n  ): Promise<ThreadRecommendQuestionResult> {\n    const thread = await this.threadRepository.findOneBy({ id: threadId });\n    if (!thread) {\n      throw new Error(`Thread ${threadId} not found`);\n    }\n\n    // handle not started\n    const res: ThreadRecommendQuestionResult = {\n      status: RecommendQuestionResultStatus.NOT_STARTED,\n      questions: [],\n      error: null,\n    };\n    if (thread.queryId && thread.questionsStatus) {\n      res.status = RecommendQuestionResultStatus[thread.questionsStatus]\n        ? RecommendQuestionResultStatus[thread.questionsStatus]\n        : res.status;\n      res.questions = thread.questions || [];\n      res.error = thread.questionsError as WrenAIError;\n    }\n    return res;\n  }\n\n  public async generateThreadRecommendationQuestions(\n    threadId: number,\n  ): Promise<void> {\n    const thread = await this.threadRepository.findOneBy({ id: threadId });\n    if (!thread) {\n      throw new Error(`Thread ${threadId} not found`);\n    }\n\n    if (this.threadRecommendQuestionBackgroundTracker.isExist(thread)) {\n      logger.debug(\n        `thread \"${threadId}\" recommended questions are generating, skip the current request`,\n      );\n      return;\n    }\n\n    const project = await this.projectService.getCurrentProject();\n    const { manifest } = await this.mdlService.makeCurrentModelMDL();\n\n    const threadResponses = await this.threadResponseRepository.findAllBy({\n      threadId,\n    });\n    // descending order and get the latest 5\n    const slicedThreadResponses = threadResponses\n      .sort((a, b) => b.id - a.id)\n      .slice(0, 5);\n    const questions = slicedThreadResponses.map(({ question }) => question);\n    const recommendQuestionData: RecommendationQuestionsInput = {\n      manifest,\n      previousQuestions: questions,\n      ...this.getThreadRecommendationQuestionsConfig(project),\n    };\n\n    const result = await this.wrenAIAdaptor.generateRecommendationQuestions(\n      recommendQuestionData,\n    );\n    // reset thread recommended questions\n    const updatedThread = await this.threadRepository.updateOne(threadId, {\n      queryId: result.queryId,\n      questionsStatus: RecommendationQuestionStatus.GENERATING,\n      questions: [],\n      questionsError: null,\n    });\n    this.threadRecommendQuestionBackgroundTracker.addTask(updatedThread);\n    return;\n  }\n\n  public async initialize() {\n    // list thread responses from database\n    // filter status not finalized and put them into background tracker\n    const threadResponses = await this.threadResponseRepository.findAll();\n    const unfininshedBreakdownThreadResponses = threadResponses.filter(\n      (threadResponse) =>\n        threadResponse?.breakdownDetail?.status &&\n        !isFinalized(\n          threadResponse?.breakdownDetail?.status as AskResultStatus,\n        ),\n    );\n    logger.info(\n      `Initialization: adding unfininshed breakdown thread responses (total: ${unfininshedBreakdownThreadResponses.length}) to background tracker`,\n    );\n    for (const threadResponse of unfininshedBreakdownThreadResponses) {\n      this.breakdownBackgroundTracker.addTask(threadResponse);\n    }\n  }\n\n  /**\n   * Asking task.\n   */\n  public async createAskingTask(\n    input: AskingTaskInput,\n    payload: AskingPayload,\n    rerunFromCancelled?: boolean,\n    previousTaskId?: number,\n    threadResponseId?: number,\n  ): Promise<Task> {\n    const { threadId, language } = payload;\n    const deployId = await this.getDeployId();\n\n    // if it's a follow-up question, then the input will have a threadId\n    // then use the threadId to get the sql and get the steps of last thread response\n    // construct it into AskHistory and pass to ask\n    const histories = threadId\n      ? await this.getAskingHistory(threadId, threadResponseId)\n      : null;\n    const response = await this.askingTaskTracker.createAskingTask({\n      query: input.question,\n      histories,\n      deployId,\n      configurations: { language },\n      rerunFromCancelled,\n      previousTaskId,\n      threadResponseId,\n    });\n    return {\n      id: response.queryId,\n    };\n  }\n\n  public async rerunAskingTask(\n    threadResponseId: number,\n    payload: AskingPayload,\n  ): Promise<Task> {\n    const threadResponse = await this.threadResponseRepository.findOneBy({\n      id: threadResponseId,\n    });\n\n    if (!threadResponse) {\n      throw new Error(`Thread response ${threadResponseId} not found`);\n    }\n\n    // get the original question and ask again\n    const question = threadResponse.question;\n    const input = {\n      question,\n    };\n    const askingPayload = {\n      ...payload,\n      // it's possible that the threadId is not provided in the payload\n      // so we'll just use the threadId from the thread response\n      threadId: threadResponse.threadId,\n    };\n    const task = await this.createAskingTask(\n      input,\n      askingPayload,\n      true,\n      threadResponse.askingTaskId,\n      threadResponseId,\n    );\n    return task;\n  }\n\n  public async cancelAskingTask(taskId: string): Promise<void> {\n    const eventName = TelemetryEvent.HOME_CANCEL_ASK;\n    try {\n      await this.askingTaskTracker.cancelAskingTask(taskId);\n      this.telemetry.sendEvent(eventName, {});\n    } catch (err: any) {\n      this.telemetry.sendEvent(eventName, {}, err.extensions?.service, false);\n      throw err;\n    }\n  }\n\n  public async getAskingTask(\n    taskId: string,\n  ): Promise<TrackedAskingResult | null> {\n    return this.askingTaskTracker.getAskingResult(taskId);\n  }\n\n  public async getAskingTaskById(\n    id: number,\n  ): Promise<TrackedAskingResult | null> {\n    return this.askingTaskTracker.getAskingResultById(id);\n  }\n\n  /**\n   * Asking detail task.\n   * The process of creating a thread is as follows:\n   * 1. create a thread and the first thread response\n   * 2. create a task on AI service to generate the detail\n   * 3. update the thread response with the task id\n   */\n  public async createThread(input: AskingDetailTaskInput): Promise<Thread> {\n    // 1. create a thread and the first thread response\n    const { id } = await this.projectService.getCurrentProject();\n    const thread = await this.threadRepository.createOne({\n      projectId: id,\n      summary: input.question,\n    });\n\n    const threadResponse = await this.threadResponseRepository.createOne({\n      threadId: thread.id,\n      question: input.question,\n      sql: input.sql,\n      askingTaskId: input.trackedAskingResult?.taskId,\n    });\n\n    // if queryId is provided, update asking task\n    if (input.trackedAskingResult?.taskId) {\n      await this.askingTaskTracker.bindThreadResponse(\n        input.trackedAskingResult.taskId,\n        input.trackedAskingResult.queryId,\n        thread.id,\n        threadResponse.id,\n      );\n    }\n\n    // return the task id\n    return thread;\n  }\n\n  public async listThreads(): Promise<Thread[]> {\n    const { id } = await this.projectService.getCurrentProject();\n    return await this.threadRepository.listAllTimeDescOrder(id);\n  }\n\n  public async updateThread(\n    threadId: number,\n    input: Partial<AskingDetailTaskUpdateInput>,\n  ): Promise<Thread> {\n    // if input is empty, throw error\n    if (isEmpty(input)) {\n      throw new Error('Update thread input is empty');\n    }\n\n    return this.threadRepository.updateOne(threadId, {\n      summary: input.summary,\n    });\n  }\n\n  public async deleteThread(threadId: number): Promise<void> {\n    await this.threadRepository.deleteOne(threadId);\n  }\n\n  public async createThreadResponse(\n    input: AskingDetailTaskInput,\n    threadId: number,\n  ): Promise<ThreadResponse> {\n    const thread = await this.threadRepository.findOneBy({\n      id: threadId,\n    });\n\n    if (!thread) {\n      throw new Error(`Thread ${threadId} not found`);\n    }\n\n    const threadResponse = await this.threadResponseRepository.createOne({\n      threadId: thread.id,\n      question: input.question,\n      sql: input.sql,\n      askingTaskId: input.trackedAskingResult?.taskId,\n    });\n\n    // if queryId is provided, update asking task\n    if (input.trackedAskingResult?.taskId) {\n      await this.askingTaskTracker.bindThreadResponse(\n        input.trackedAskingResult.taskId,\n        input.trackedAskingResult.queryId,\n        thread.id,\n        threadResponse.id,\n      );\n    }\n\n    return threadResponse;\n  }\n\n  public async updateThreadResponse(\n    responseId: number,\n    data: { sql: string },\n  ): Promise<ThreadResponse> {\n    const threadResponse = await this.threadResponseRepository.findOneBy({\n      id: responseId,\n    });\n    if (!threadResponse) {\n      throw new Error(`Thread response ${responseId} not found`);\n    }\n\n    return await this.threadResponseRepository.updateOne(responseId, {\n      sql: data.sql,\n    });\n  }\n\n  public async generateThreadResponseBreakdown(\n    threadResponseId: number,\n    configurations: { language: string },\n  ): Promise<ThreadResponse> {\n    const { language } = configurations;\n    const threadResponse = await this.threadResponseRepository.findOneBy({\n      id: threadResponseId,\n    });\n\n    if (!threadResponse) {\n      throw new Error(`Thread response ${threadResponseId} not found`);\n    }\n\n    // 1. create a task on AI service to generate the detail\n    const response = await this.wrenAIAdaptor.generateAskDetail({\n      query: threadResponse.question,\n      sql: threadResponse.sql,\n      configurations: { language },\n    });\n\n    // 2. update the thread response with breakdown detail\n    const updatedThreadResponse = await this.threadResponseRepository.updateOne(\n      threadResponse.id,\n      {\n        breakdownDetail: {\n          queryId: response.queryId,\n          status: AskResultStatus.UNDERSTANDING,\n        },\n      },\n    );\n\n    // 3. put the task into background tracker\n    this.breakdownBackgroundTracker.addTask(updatedThreadResponse);\n\n    // return the task id\n    return updatedThreadResponse;\n  }\n\n  public async generateThreadResponseAnswer(\n    threadResponseId: number,\n  ): Promise<ThreadResponse> {\n    const threadResponse = await this.threadResponseRepository.findOneBy({\n      id: threadResponseId,\n    });\n\n    if (!threadResponse) {\n      throw new Error(`Thread response ${threadResponseId} not found`);\n    }\n\n    // update with initial status\n    const updatedThreadResponse = await this.threadResponseRepository.updateOne(\n      threadResponse.id,\n      {\n        answerDetail: {\n          status: ThreadResponseAnswerStatus.NOT_STARTED,\n        },\n      },\n    );\n\n    // put the task into background tracker\n    this.textBasedAnswerBackgroundTracker.addTask(updatedThreadResponse);\n\n    return updatedThreadResponse;\n  }\n\n  public async generateThreadResponseChart(\n    threadResponseId: number,\n    configurations: { language: string },\n  ): Promise<ThreadResponse> {\n    const threadResponse = await this.threadResponseRepository.findOneBy({\n      id: threadResponseId,\n    });\n\n    if (!threadResponse) {\n      throw new Error(`Thread response ${threadResponseId} not found`);\n    }\n\n    // 1. create a task on AI service to generate the chart\n    const response = await this.wrenAIAdaptor.generateChart({\n      query: threadResponse.question,\n      sql: threadResponse.sql,\n      configurations,\n    });\n\n    // 2. update the thread response with chart detail\n    const updatedThreadResponse = await this.threadResponseRepository.updateOne(\n      threadResponse.id,\n      {\n        chartDetail: {\n          queryId: response.queryId,\n          status: ChartStatus.FETCHING,\n        },\n      },\n    );\n\n    // 3. put the task into background tracker\n    this.chartBackgroundTracker.addTask(updatedThreadResponse);\n\n    return updatedThreadResponse;\n  }\n\n  public async adjustThreadResponseChart(\n    threadResponseId: number,\n    input: ChartAdjustmentOption,\n    configurations: { language: string },\n  ): Promise<ThreadResponse> {\n    const threadResponse = await this.threadResponseRepository.findOneBy({\n      id: threadResponseId,\n    });\n\n    if (!threadResponse) {\n      throw new Error(`Thread response ${threadResponseId} not found`);\n    }\n\n    // 1. create a task on AI service to adjust the chart\n    const response = await this.wrenAIAdaptor.adjustChart({\n      query: threadResponse.question,\n      sql: threadResponse.sql,\n      adjustmentOption: input,\n      chartSchema: threadResponse.chartDetail?.chartSchema,\n      configurations,\n    });\n\n    // 2. update the thread response with chart detail\n    const updatedThreadResponse = await this.threadResponseRepository.updateOne(\n      threadResponse.id,\n      {\n        chartDetail: {\n          queryId: response.queryId,\n          status: ChartStatus.FETCHING,\n          adjustment: true,\n        },\n      },\n    );\n\n    // 3. put the task into background tracker\n    this.chartAdjustmentBackgroundTracker.addTask(updatedThreadResponse);\n\n    return updatedThreadResponse;\n  }\n\n  public async getResponsesWithThread(threadId: number) {\n    return this.threadResponseRepository.getResponsesWithThread(threadId);\n  }\n\n  public async getResponse(responseId: number) {\n    return this.threadResponseRepository.findOneBy({ id: responseId });\n  }\n\n  public async previewData(responseId: number, limit?: number) {\n    const response = await this.getResponse(responseId);\n    if (!response) {\n      throw new Error(`Thread response ${responseId} not found`);\n    }\n    const project = await this.projectService.getCurrentProject();\n    const deployment = await this.deployService.getLastDeployment(project.id);\n    const mdl = deployment.manifest;\n    const eventName = TelemetryEvent.HOME_PREVIEW_ANSWER;\n    try {\n      const data = (await this.queryService.preview(response.sql, {\n        project,\n        manifest: mdl,\n        limit,\n      })) as PreviewDataResponse;\n      this.telemetry.sendEvent(eventName, { sql: response.sql });\n      return data;\n    } catch (err: any) {\n      this.telemetry.sendEvent(\n        eventName,\n        { sql: response.sql, error: err.message },\n        err.extensions?.service,\n        false,\n      );\n      throw err;\n    }\n  }\n\n  /**\n   * this function is used to preview the data of a thread response\n   * get the target thread response and get the steps\n   * construct the CTEs and get the data\n   * @param responseId: the id of the thread response\n   * @param stepIndex: the step in the response detail\n   * @returns Promise<QueryResponse>\n   */\n  public async previewBreakdownData(\n    responseId: number,\n    stepIndex?: number,\n    limit?: number,\n  ): Promise<PreviewDataResponse> {\n    const response = await this.getResponse(responseId);\n    if (!response) {\n      throw new Error(`Thread response ${responseId} not found`);\n    }\n    const project = await this.projectService.getCurrentProject();\n    const deployment = await this.deployService.getLastDeployment(project.id);\n    const mdl = deployment.manifest;\n    const steps = response?.breakdownDetail?.steps;\n    const sql = safeFormatSQL(constructCteSql(steps, stepIndex));\n    const eventName = TelemetryEvent.HOME_PREVIEW_ANSWER;\n    try {\n      const data = (await this.queryService.preview(sql, {\n        project,\n        manifest: mdl,\n        limit,\n      })) as PreviewDataResponse;\n      this.telemetry.sendEvent(eventName, { sql });\n      return data;\n    } catch (err: any) {\n      this.telemetry.sendEvent(\n        eventName,\n        { sql, error: err.message },\n        err.extensions?.service,\n        false,\n      );\n      throw err;\n    }\n  }\n\n  public async createInstantRecommendedQuestions(\n    input: InstantRecommendedQuestionsInput,\n  ): Promise<Task> {\n    const project = await this.projectService.getCurrentProject();\n    const { manifest } = await this.deployService.getLastDeployment(project.id);\n\n    const response = await this.wrenAIAdaptor.generateRecommendationQuestions({\n      manifest,\n      previousQuestions: input.previousQuestions,\n      ...this.getThreadRecommendationQuestionsConfig(project),\n    });\n    return { id: response.queryId };\n  }\n\n  public async getInstantRecommendedQuestions(\n    queryId: string,\n  ): Promise<RecommendationQuestionsResult> {\n    const response =\n      await this.wrenAIAdaptor.getRecommendationQuestionsResult(queryId);\n    return response;\n  }\n\n  public async deleteAllByProjectId(projectId: number): Promise<void> {\n    // delete all threads\n    await this.threadRepository.deleteAllBy({ projectId });\n  }\n\n  public async changeThreadResponseAnswerDetailStatus(\n    responseId: number,\n    status: ThreadResponseAnswerStatus,\n    content?: string,\n  ): Promise<ThreadResponse> {\n    const response = await this.threadResponseRepository.findOneBy({\n      id: responseId,\n    });\n    if (!response) {\n      throw new Error(`Thread response ${responseId} not found`);\n    }\n\n    if (response.answerDetail?.status === status) {\n      return;\n    }\n\n    const updatedResponse = await this.threadResponseRepository.updateOne(\n      responseId,\n      {\n        answerDetail: {\n          ...response.answerDetail,\n          status,\n          content,\n        },\n      },\n    );\n\n    return updatedResponse;\n  }\n\n  private async getDeployId() {\n    const { id } = await this.projectService.getCurrentProject();\n    const lastDeploy = await this.deployService.getLastDeployment(id);\n    return lastDeploy.hash;\n  }\n\n  public async adjustThreadResponseWithSQL(\n    threadResponseId: number,\n    input: AdjustmentSqlInput,\n  ): Promise<ThreadResponse> {\n    const response = await this.threadResponseRepository.findOneBy({\n      id: threadResponseId,\n    });\n    if (!response) {\n      throw new Error(`Thread response ${threadResponseId} not found`);\n    }\n\n    return await this.threadResponseRepository.createOne({\n      sql: input.sql,\n      threadId: response.threadId,\n      question: response.question,\n      adjustment: {\n        type: ThreadResponseAdjustmentType.APPLY_SQL,\n        payload: {\n          originalThreadResponseId: response.id,\n          sql: input.sql,\n        },\n      },\n    });\n  }\n\n  public async adjustThreadResponseAnswer(\n    threadResponseId: number,\n    input: AdjustmentReasoningInput,\n    configurations: { language: string },\n  ): Promise<ThreadResponse> {\n    const originalThreadResponse =\n      await this.threadResponseRepository.findOneBy({\n        id: threadResponseId,\n      });\n    if (!originalThreadResponse) {\n      throw new Error(`Thread response ${threadResponseId} not found`);\n    }\n\n    const { createdThreadResponse } =\n      await this.adjustmentBackgroundTracker.createAdjustmentTask({\n        threadId: originalThreadResponse.threadId,\n        tables: input.tables,\n        sqlGenerationReasoning: input.sqlGenerationReasoning,\n        sql: originalThreadResponse.sql,\n        projectId: input.projectId,\n        configurations,\n        question: originalThreadResponse.question,\n        originalThreadResponseId: originalThreadResponse.id,\n      });\n    return createdThreadResponse;\n  }\n\n  public async cancelAdjustThreadResponseAnswer(taskId: string): Promise<void> {\n    // call cancelAskFeedback on AI service\n    await this.adjustmentBackgroundTracker.cancelAdjustmentTask(taskId);\n  }\n\n  public async rerunAdjustThreadResponseAnswer(\n    threadResponseId: number,\n    projectId: number,\n    configurations: { language: string },\n  ): Promise<{ queryId: string }> {\n    const threadResponse = await this.threadResponseRepository.findOneBy({\n      id: threadResponseId,\n    });\n    if (!threadResponse) {\n      throw new Error(`Thread response ${threadResponseId} not found`);\n    }\n\n    const { queryId } =\n      await this.adjustmentBackgroundTracker.rerunAdjustmentTask({\n        threadId: threadResponse.threadId,\n        threadResponseId,\n        projectId,\n        configurations,\n      });\n    return { queryId };\n  }\n\n  public async getAdjustmentTask(\n    taskId: string,\n  ): Promise<TrackedAdjustmentResult | null> {\n    return this.adjustmentBackgroundTracker.getAdjustmentResult(taskId);\n  }\n\n  public async getAdjustmentTaskById(\n    id: number,\n  ): Promise<TrackedAdjustmentResult | null> {\n    return this.adjustmentBackgroundTracker.getAdjustmentResultById(id);\n  }\n\n  /**\n   * Get the thread response of a thread for asking\n   * @param threadId\n   * @returns Promise<ThreadResponse[]>\n   */\n  private async getAskingHistory(\n    threadId: number,\n    excludeThreadResponseId?: number,\n  ): Promise<ThreadResponse[]> {\n    if (!threadId) {\n      return [];\n    }\n    let responses = await this.threadResponseRepository.getResponsesWithThread(\n      threadId,\n      10,\n    );\n\n    // exclude the thread response if the excludeThreadResponseId is provided\n    // it's used when rerun the asking task, we don't want include the cancelled thread response\n    if (excludeThreadResponseId) {\n      responses = responses.filter(\n        (response) => response.id !== excludeThreadResponseId,\n      );\n    }\n\n    // filter out the thread response with empty sql\n    return responses.filter((response) => response.sql);\n  }\n\n  private getThreadRecommendationQuestionsConfig(project: Project) {\n    return {\n      maxCategories: config.threadRecommendationQuestionMaxCategories,\n      maxQuestions: config.threadRecommendationQuestionsMaxQuestions,\n      configuration: {\n        language: WrenAILanguage[project.language] || WrenAILanguage.EN,\n      },\n    };\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/services/askingTaskTracker.ts",
    "content": "import { getLogger } from '@server/utils';\nimport {\n  AskResult,\n  AskResultType,\n  AskResultStatus,\n  AskInput,\n} from '@server/models/adaptor';\nimport {\n  AskingTask,\n  IAskingTaskRepository,\n  IThreadResponseRepository,\n  IViewRepository,\n} from '@server/repositories';\nimport { IWrenAIAdaptor } from '../adaptors';\nimport * as Errors from '@server/utils/error';\n\nconst logger = getLogger('AskingTaskTracker');\nlogger.level = 'debug';\n\ninterface TrackedTask {\n  queryId: string;\n  taskId?: number;\n  lastPolled: number;\n  question?: string;\n  result?: AskResult;\n  isFinalized: boolean;\n  threadResponseId?: number;\n  rerunFromCancelled?: boolean;\n}\n\nexport type TrackedAskingResult = AskResult & {\n  taskId?: number;\n  queryId: string;\n  question: string;\n};\n\nexport type CreateAskingTaskInput = AskInput & {\n  rerunFromCancelled?: boolean;\n  previousTaskId?: number;\n  threadResponseId?: number;\n};\n\nexport interface IAskingTaskTracker {\n  createAskingTask(input: CreateAskingTaskInput): Promise<{ queryId: string }>;\n  getAskingResult(queryId: string): Promise<TrackedAskingResult | null>;\n  getAskingResultById(id: number): Promise<TrackedAskingResult | null>;\n  cancelAskingTask(queryId: string): Promise<void>;\n  bindThreadResponse(\n    id: number,\n    queryId: string,\n    threadId: number,\n    threadResponseId: number,\n  ): Promise<void>;\n}\n\nexport class AskingTaskTracker implements IAskingTaskTracker {\n  private wrenAIAdaptor: IWrenAIAdaptor;\n  private askingTaskRepository: IAskingTaskRepository;\n  private trackedTasks: Map<string, TrackedTask> = new Map();\n  private trackedTasksById: Map<number, TrackedTask> = new Map();\n  private pollingInterval: number;\n  private memoryRetentionTime: number;\n  private pollingIntervalId: NodeJS.Timeout;\n  private runningJobs = new Set<string>();\n  private threadResponseRepository: IThreadResponseRepository;\n  private viewRepository: IViewRepository;\n\n  constructor({\n    wrenAIAdaptor,\n    askingTaskRepository,\n    threadResponseRepository,\n    viewRepository,\n    pollingInterval = 1000, // 1 second\n    memoryRetentionTime = 5 * 60 * 1000, // 5 minutes\n  }: {\n    wrenAIAdaptor: IWrenAIAdaptor;\n    askingTaskRepository: IAskingTaskRepository;\n    threadResponseRepository: IThreadResponseRepository;\n    viewRepository: IViewRepository;\n    pollingInterval?: number;\n    memoryRetentionTime?: number;\n  }) {\n    this.wrenAIAdaptor = wrenAIAdaptor;\n    this.askingTaskRepository = askingTaskRepository;\n    this.threadResponseRepository = threadResponseRepository;\n    this.viewRepository = viewRepository;\n    this.pollingInterval = pollingInterval;\n    this.memoryRetentionTime = memoryRetentionTime;\n    this.startPolling();\n  }\n\n  public async createAskingTask(\n    input: CreateAskingTaskInput,\n  ): Promise<{ queryId: string }> {\n    try {\n      // Call the AI service to create a task\n      const response = await this.wrenAIAdaptor.ask(input);\n      const queryId = response.queryId;\n\n      // validate the input\n      if (\n        input.rerunFromCancelled &&\n        (!input.previousTaskId || !input.threadResponseId)\n      ) {\n        throw new Error(\n          'Previous task id and thread response id are required if rerun from cancelled',\n        );\n      }\n\n      // Start tracking this task\n      const task = {\n        queryId,\n        lastPolled: Date.now(),\n        question: input.query,\n        isFinalized: false,\n        rerunFromCancelled: input.rerunFromCancelled,\n      } as TrackedTask;\n      this.trackedTasks.set(queryId, task);\n\n      // if rerun from cancelled, we update the query id to the previous task\n      if (\n        input.rerunFromCancelled &&\n        input.previousTaskId &&\n        input.threadResponseId\n      ) {\n        // set the thread response id in memory to bind the task to the thread response\n        // we don't have to update to database here because the thread response id is already set in database\n        task.threadResponseId = input.threadResponseId;\n\n        // update the task id in memory\n        this.trackedTasksById.set(input.previousTaskId, task);\n\n        // get the latest result from the AI service\n        // we get the latest result first to make it more responsive to client-side\n        const result = await this.wrenAIAdaptor.getAskResult(queryId);\n\n        // update the result in memory\n        task.result = result;\n\n        // update the query id in database\n        await this.askingTaskRepository.updateOne(input.previousTaskId, {\n          queryId,\n        });\n      }\n\n      logger.info(`Created asking task with queryId: ${queryId}`);\n      return { queryId };\n    } catch (err) {\n      logger.error(`Failed to create asking task: ${err}`);\n      throw err;\n    }\n  }\n\n  public async getAskingResult(\n    queryId: string,\n  ): Promise<TrackedAskingResult | null> {\n    // Check if we're tracking this task in memory\n    const trackedTask = this.trackedTasks.get(queryId);\n\n    if (trackedTask && trackedTask.result) {\n      return {\n        ...trackedTask.result,\n        queryId,\n        question: trackedTask.question,\n        taskId: trackedTask.taskId,\n      };\n    }\n\n    // If not in memory or no result yet, check the database\n    return this.getAskingResultFromDB({ queryId });\n  }\n\n  public async getAskingResultById(\n    id: number,\n  ): Promise<TrackedAskingResult | null> {\n    const task = this.trackedTasksById.get(id);\n    if (task) {\n      return this.getAskingResult(task.queryId);\n    }\n\n    return this.getAskingResultFromDB({ taskId: id });\n  }\n\n  public async cancelAskingTask(queryId: string): Promise<void> {\n    await this.wrenAIAdaptor.cancelAsk(queryId);\n  }\n\n  public stopPolling(): void {\n    if (this.pollingIntervalId) {\n      clearInterval(this.pollingIntervalId);\n    }\n  }\n\n  public async bindThreadResponse(\n    id: number,\n    queryId: string,\n    threadId: number,\n    threadResponseId: number,\n  ): Promise<void> {\n    const task = this.trackedTasks.get(queryId);\n    if (!task) {\n      throw new Error(`Task ${queryId} not found`);\n    }\n\n    task.threadResponseId = threadResponseId;\n    this.trackedTasksById.set(id, task);\n    await this.askingTaskRepository.updateOne(id, {\n      threadId,\n      threadResponseId,\n    });\n\n    // check if the task is finalized and has a sql\n    if (task.isFinalized) {\n      await this.updateThreadResponseWhenTaskFinalized(task);\n    }\n  }\n\n  private startPolling(): void {\n    this.pollingIntervalId = setInterval(() => {\n      this.pollTasks();\n    }, this.pollingInterval);\n  }\n\n  private async pollTasks(): Promise<void> {\n    const now = Date.now();\n    const tasksToRemove: string[] = [];\n\n    // Create an array of job functions\n    const jobs = Array.from(this.trackedTasks.entries()).map(\n      ([queryId, task]) =>\n        async () => {\n          try {\n            // Skip if the job is already running\n            if (this.runningJobs.has(queryId)) {\n              return;\n            }\n\n            // Skip finalized tasks that have been in memory too long\n            if (\n              task.isFinalized &&\n              now - task.lastPolled > this.memoryRetentionTime\n            ) {\n              tasksToRemove.push(queryId);\n              return;\n            }\n\n            // Skip finalized tasks\n            if (task.isFinalized) {\n              return;\n            }\n\n            // Mark the job as running\n            this.runningJobs.add(queryId);\n\n            // Poll for updates\n            logger.info(`Polling for updates for task ${queryId}`);\n            const result = await this.wrenAIAdaptor.getAskResult(queryId);\n            task.lastPolled = now;\n\n            // if result is not changed, we don't need to update the database\n            if (!this.isResultChanged(task.result, result)) {\n              this.runningJobs.delete(queryId);\n              return;\n            }\n\n            // update task in memory if any change\n            task.result = result;\n\n            // if result is still understanding, we don't need to update the database\n            if (result.status === AskResultStatus.UNDERSTANDING) {\n              this.runningJobs.delete(queryId);\n              return;\n            }\n\n            // if it's identified as GENERAL or MISLEADING_QUER\n            // we don't need to update the database and finalize the task\n            if (\n              result.type === AskResultType.GENERAL ||\n              result.type === AskResultType.MISLEADING_QUERY\n            ) {\n              task.isFinalized = true;\n              // if it's rerun from cancelled, we need to update the task result to failed in db\n              if (task.rerunFromCancelled) {\n                const errorCode =\n                  result.type === AskResultType.GENERAL\n                    ? Errors.GeneralErrorCodes.IDENTIED_AS_GENERAL\n                    : Errors.GeneralErrorCodes.IDENTIED_AS_MISLEADING_QUERY;\n                const error = {\n                  code: errorCode,\n                  message: Errors.errorMessages[errorCode],\n                  shortMessage: Errors.shortMessages[errorCode],\n                };\n                await this.updateTaskInDatabase(\n                  { queryId },\n                  {\n                    ...task,\n                    // update the status to failed\n                    // and the error message should be \"IDENTIED_AS_GENERAL\" or \"IDENTIED_AS_MISLEADING_QUERY\"\n                    result: {\n                      ...task.result,\n                      status: AskResultStatus.FAILED,\n                      error,\n                    },\n                  },\n                );\n              }\n              this.runningJobs.delete(queryId);\n              return;\n            }\n\n            // update the database\n            // note: type could be null if it's still being understood or it's stopped\n            // we already filtered out the understanding status above\n            // so we update to database if it's stopped as well here.\n            logger.info(`Updating task ${queryId} in database`);\n            await this.updateTaskInDatabase({ queryId }, task);\n\n            // Check if task is now finalized\n            if (this.isTaskFinalized(result.status)) {\n              task.isFinalized = true;\n              // update thread response if threadResponseId is provided\n              if (task.threadResponseId) {\n                await this.updateThreadResponseWhenTaskFinalized(task);\n              }\n\n              logger.info(\n                `Task ${queryId} is finalized with status: ${result.status}`,\n              );\n            }\n\n            // Mark the job as finished\n            this.runningJobs.delete(queryId);\n          } catch (err) {\n            this.runningJobs.delete(queryId);\n            logger.error(err.stack);\n            throw err;\n          }\n        },\n    );\n\n    // Run all jobs in parallel\n    Promise.allSettled(jobs.map((job) => job())).then((results) => {\n      // Log any rejected promises\n      results.forEach((result, index) => {\n        if (result.status === 'rejected') {\n          logger.error(`Job ${index} failed: ${result.reason}`);\n        }\n      });\n\n      // Clean up tasks that have been in memory too long\n      if (tasksToRemove.length > 0) {\n        logger.info(\n          `Cleaning up tasks that have been in memory too long. Tasks: ${tasksToRemove.join(\n            ', ',\n          )}`,\n        );\n      }\n      for (const queryId of tasksToRemove) {\n        this.trackedTasks.delete(queryId);\n      }\n    });\n  }\n\n  private async updateThreadResponseWhenTaskFinalized(\n    task: TrackedTask,\n  ): Promise<void> {\n    const response = task?.result?.response?.[0];\n    if (!response) {\n      return;\n    }\n    // if the generated response of asking task is not null, update the thread response\n    if (response.viewId) {\n      // get sql from the view\n      const view = await this.viewRepository.findOneBy({\n        id: response.viewId,\n      });\n      await this.threadResponseRepository.updateOne(task.threadResponseId, {\n        sql: view.statement,\n        viewId: response.viewId,\n      });\n    } else {\n      await this.threadResponseRepository.updateOne(task.threadResponseId, {\n        sql: response?.sql,\n      });\n    }\n  }\n\n  private async getAskingResultFromDB({\n    queryId,\n    taskId,\n  }: {\n    queryId?: string;\n    taskId?: number;\n  }): Promise<TrackedAskingResult | null> {\n    let taskRecord: AskingTask | null = null;\n    if (queryId) {\n      taskRecord = await this.askingTaskRepository.findByQueryId(queryId);\n    } else if (taskId) {\n      taskRecord = await this.askingTaskRepository.findOneBy({ id: taskId });\n    }\n\n    if (!taskRecord) {\n      return null;\n    }\n\n    return {\n      ...(taskRecord?.detail as AskResult),\n      queryId: queryId || taskRecord?.queryId,\n      question: taskRecord?.question,\n      taskId: taskRecord?.id,\n    };\n  }\n\n  private async updateTaskInDatabase(\n    filter: { queryId?: string; taskId?: number },\n    trackedTask: TrackedTask,\n  ): Promise<void> {\n    const { queryId, taskId } = filter;\n    let taskRecord: AskingTask | null = null;\n    if (queryId) {\n      taskRecord = await this.askingTaskRepository.findByQueryId(queryId);\n    } else if (taskId) {\n      taskRecord = await this.askingTaskRepository.findOneBy({ id: taskId });\n    }\n\n    if (!taskRecord) {\n      // if record not found, create one\n      const task = await this.askingTaskRepository.createOne({\n        queryId,\n        question: trackedTask.question,\n        detail: trackedTask.result,\n      });\n      // update the task id in memory\n      let existingTask: TrackedTask;\n      if (queryId) {\n        existingTask = this.trackedTasks.get(queryId);\n      } else if (taskId) {\n        existingTask = this.trackedTasksById.get(taskId);\n      }\n      if (existingTask) {\n        existingTask.taskId = task.id;\n      }\n      return;\n    }\n\n    // update the task\n    await this.askingTaskRepository.updateOne(taskRecord.id, {\n      detail: trackedTask.result,\n    });\n  }\n\n  private isTaskFinalized(status: AskResultStatus): boolean {\n    return [\n      AskResultStatus.FINISHED,\n      AskResultStatus.FAILED,\n      AskResultStatus.STOPPED,\n    ].includes(status);\n  }\n\n  private isResultChanged(\n    previousResult: AskResult,\n    newResult: AskResult,\n  ): boolean {\n    // check status change\n    if (previousResult?.status !== newResult.status) {\n      return true;\n    }\n\n    return false;\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/services/dashboardService.ts",
    "content": "import {\n  IDashboardRepository,\n  IDashboardItemRepository,\n  Dashboard,\n  DashboardItem,\n  DashboardItemType,\n  DashboardItemDetail,\n  DashboardItemLayout,\n} from '@server/repositories';\nimport { getLogger } from '@server/utils';\nimport { getUTCOffsetMinutes } from '@server/utils/timezone';\nimport { IProjectService } from './projectService';\nimport {\n  SetDashboardCacheData,\n  ScheduleFrequencyEnum,\n  CacheScheduleDayEnum,\n  DashboardSchedule,\n  DAYS,\n} from '@server/models/dashboard';\nimport { CronExpressionParser } from 'cron-parser';\nconst logger = getLogger('DashboardService');\nlogger.level = 'debug';\n\nexport interface CreateDashboardItemInput {\n  dashboardId: number;\n  type: DashboardItemType;\n  sql: string;\n  chartSchema: DashboardItemDetail['chartSchema'];\n}\n\nexport interface UpdateDashboardItemInput {\n  displayName: string;\n}\n\nexport type UpdateDashboardItemLayouts = (DashboardItemLayout & {\n  itemId: number;\n})[];\n\nexport interface IDashboardService {\n  initDashboard(): Promise<Dashboard>;\n  getCurrentDashboard(): Promise<Dashboard>;\n  getDashboardItem(dashboardItemId: number): Promise<DashboardItem>;\n  getDashboardItems(dashboardId: number): Promise<DashboardItem[]>;\n  createDashboardItem(input: CreateDashboardItemInput): Promise<DashboardItem>;\n  updateDashboardItem(\n    dashboardItemId: number,\n    input: UpdateDashboardItemInput,\n  ): Promise<DashboardItem>;\n  deleteDashboardItem(dashboardItemId: number): Promise<boolean>;\n  updateDashboardItemLayouts(\n    layouts: UpdateDashboardItemLayouts,\n  ): Promise<DashboardItem[]>;\n  setDashboardSchedule(\n    dashboardId: number,\n    data: SetDashboardCacheData,\n  ): Promise<Dashboard>;\n  parseCronExpression(dashboard: Dashboard): DashboardSchedule;\n}\n\nexport class DashboardService implements IDashboardService {\n  private projectService: IProjectService;\n  private dashboardItemRepository: IDashboardItemRepository;\n  private dashboardRepository: IDashboardRepository;\n\n  constructor({\n    projectService,\n    dashboardItemRepository,\n    dashboardRepository,\n  }: {\n    projectService: IProjectService;\n    dashboardItemRepository: IDashboardItemRepository;\n    dashboardRepository: IDashboardRepository;\n  }) {\n    this.projectService = projectService;\n    this.dashboardItemRepository = dashboardItemRepository;\n    this.dashboardRepository = dashboardRepository;\n  }\n\n  public async setDashboardSchedule(\n    dashboardId: number,\n    data: SetDashboardCacheData,\n  ): Promise<Dashboard> {\n    try {\n      const { cacheEnabled, schedule } = data;\n      // Validate input\n      this.validateScheduleInput(data);\n\n      // Check if dashboard exists\n      const dashboard = await this.dashboardRepository.findOneBy({\n        id: dashboardId,\n      });\n      if (!dashboard) {\n        throw new Error(`Dashboard with id ${dashboardId} not found`);\n      }\n      if (!cacheEnabled) {\n        return await this.dashboardRepository.updateOne(dashboardId, {\n          cacheEnabled: false,\n          scheduleFrequency: null,\n          scheduleTimezone: null,\n          scheduleCron: null,\n          nextScheduledAt: null,\n        });\n      }\n      // Initialize schedule-related variables\n      let cronExpression: string | null = null;\n      let nextScheduledAt: Date | null = null;\n\n      // Process schedule if caching is enabled\n      if (cacheEnabled && schedule.frequency !== ScheduleFrequencyEnum.NEVER) {\n        cronExpression = this.generateCronExpression(schedule);\n        nextScheduledAt = this.calculateNextRunTime(cronExpression);\n      }\n\n      // Update dashboard with new schedule\n      return await this.dashboardRepository.updateOne(dashboardId, {\n        cacheEnabled,\n        scheduleFrequency: schedule.frequency,\n        scheduleTimezone: schedule.timezone,\n        scheduleCron: cronExpression,\n        nextScheduledAt,\n      });\n    } catch (error) {\n      logger.error(`Failed to set dashboard schedule: ${error.message}`);\n      throw error;\n    }\n  }\n\n  public async initDashboard(): Promise<Dashboard> {\n    const project = await this.projectService.getCurrentProject();\n    const existingDashboard = await this.dashboardRepository.findOneBy({\n      projectId: project.id,\n    });\n    if (existingDashboard) return existingDashboard;\n    // only support one dashboard for oss\n    return await this.dashboardRepository.createOne({\n      name: 'Dashboard',\n      projectId: project.id,\n    });\n  }\n\n  public async getCurrentDashboard(): Promise<Dashboard> {\n    const project = await this.projectService.getCurrentProject();\n    const dashboard = await this.dashboardRepository.findOneBy({\n      projectId: project.id,\n    });\n    return { ...dashboard };\n  }\n\n  public async getDashboardItem(\n    dashboardItemId: number,\n  ): Promise<DashboardItem> {\n    const item = await this.dashboardItemRepository.findOneBy({\n      id: dashboardItemId,\n    });\n    if (!item) {\n      throw new Error('Dashboard item not found.');\n    }\n    return item;\n  }\n\n  public async getDashboardItems(\n    dashboardId: number,\n  ): Promise<DashboardItem[]> {\n    return await this.dashboardItemRepository.findAllBy({\n      dashboardId,\n    });\n  }\n\n  public async createDashboardItem(\n    input: CreateDashboardItemInput,\n  ): Promise<DashboardItem> {\n    const layout = await this.calculateNewLayout(input.dashboardId);\n    return await this.dashboardItemRepository.createOne({\n      dashboardId: input.dashboardId,\n      type: input.type,\n      detail: {\n        sql: input.sql,\n        chartSchema: input.chartSchema,\n      },\n      layout,\n    });\n  }\n\n  public async updateDashboardItem(\n    dashboardItemId: number,\n    input: UpdateDashboardItemInput,\n  ): Promise<DashboardItem> {\n    return await this.dashboardItemRepository.updateOne(dashboardItemId, {\n      displayName: input.displayName,\n    });\n  }\n\n  public async updateDashboardItemLayouts(\n    layouts: UpdateDashboardItemLayouts,\n  ): Promise<DashboardItem[]> {\n    const updatedItems: DashboardItem[] = [];\n    const isValidLayouts = layouts.every(\n      (layout) =>\n        layout.itemId &&\n        layout.x >= 0 &&\n        layout.y >= 0 &&\n        layout.w > 0 &&\n        layout.h > 0,\n    );\n    if (!isValidLayouts) {\n      throw new Error('Invalid layouts boundaries.');\n    }\n    await Promise.all(\n      layouts.map(async (layout) => {\n        const updatedItem = await this.dashboardItemRepository.updateOne(\n          layout.itemId,\n          {\n            layout: {\n              x: layout.x,\n              y: layout.y,\n              w: layout.w,\n              h: layout.h,\n            },\n          },\n        );\n        updatedItems.push(updatedItem);\n      }),\n    );\n    return updatedItems;\n  }\n\n  public async deleteDashboardItem(dashboardItemId: number): Promise<boolean> {\n    await this.dashboardItemRepository.deleteOne(dashboardItemId);\n    return true;\n  }\n\n  private async calculateNewLayout(\n    dashboardId: number,\n  ): Promise<DashboardItemLayout> {\n    const dashboardItems = await this.dashboardItemRepository.findAllBy({\n      dashboardId,\n    });\n    const allLayouts = dashboardItems.map((item) => item.layout);\n    if (allLayouts.length === 0) return { x: 0, y: 0, w: 3, h: 2 };\n\n    const columnCount = 6;\n    const halfLayoutX = columnCount / 2;\n    // the current max y is the current row\n    const maxY = Math.max(...allLayouts.map((layout) => layout.y));\n\n    const latestLayout = allLayouts.filter((layout) => layout.y === maxY);\n    const isNextRow =\n      latestLayout.reduce((acc, layout) => acc + layout.x + layout.w, 0) >\n      halfLayoutX;\n\n    const x = isNextRow ? 0 : halfLayoutX;\n    const y = isNextRow ? maxY + 2 : maxY;\n    return { x, y, w: 3, h: 2 };\n  }\n\n  protected toUTC(schedule: DashboardSchedule): DashboardSchedule {\n    // If no timezone is specified or it's a custom schedule, return as is\n    if (\n      !schedule.timezone ||\n      schedule.frequency === ScheduleFrequencyEnum.CUSTOM\n    ) {\n      return schedule;\n    }\n\n    // Get timezone offset in minutes\n    const offsetMinutes = getUTCOffsetMinutes(schedule.timezone);\n\n    // Convert to UTC by subtracting the offset (if timezone is ahead of UTC)\n    // or adding the offset (if timezone is behind UTC)\n    let utcMinute = schedule.minute - offsetMinutes;\n    let carryOver = 0;\n\n    // Handle minute carry-over\n    if (utcMinute < 0) {\n      carryOver = Math.ceil(Math.abs(utcMinute) / 60);\n      utcMinute = (utcMinute + carryOver * 60) % 60;\n      carryOver = -carryOver;\n    } else if (utcMinute >= 60) {\n      carryOver = Math.floor(utcMinute / 60);\n      utcMinute = utcMinute % 60;\n    }\n\n    let utcHour = schedule.hour + carryOver;\n    let dayAdjustment = 0;\n\n    // Handle hour carry-over\n    if (utcHour < 0) {\n      dayAdjustment = Math.ceil(Math.abs(utcHour) / 24);\n      utcHour = (utcHour + dayAdjustment * 24) % 24;\n      dayAdjustment = -dayAdjustment;\n    } else if (utcHour >= 24) {\n      dayAdjustment = Math.floor(utcHour / 24);\n      utcHour = utcHour % 24;\n    }\n\n    // For weekly schedules, adjust the day if needed\n    if (\n      schedule.frequency === ScheduleFrequencyEnum.WEEKLY &&\n      dayAdjustment !== 0\n    ) {\n      const currentDayIndex = DAYS.indexOf(schedule.day);\n      const adjustedDayIndex = (currentDayIndex + dayAdjustment + 7) % 7;\n      return {\n        ...schedule,\n        hour: utcHour,\n        minute: utcMinute,\n        day: DAYS[adjustedDayIndex],\n      };\n    }\n\n    // Return a new schedule object with UTC hours and minutes\n    return {\n      ...schedule,\n      hour: utcHour,\n      minute: utcMinute,\n    };\n  }\n\n  protected toTimezone(schedule: DashboardSchedule): DashboardSchedule {\n    const { timezone } = schedule;\n    // If it's a custom schedule or no timezone is specified, return as is\n    if (\n      [ScheduleFrequencyEnum.CUSTOM, ScheduleFrequencyEnum.NEVER].includes(\n        schedule.frequency,\n      ) ||\n      !timezone\n    ) {\n      return schedule;\n    }\n\n    // Get timezone offset in minutes\n    const offsetMinutes = getUTCOffsetMinutes(timezone);\n\n    // Convert from UTC to timezone by adding the offset (if timezone is ahead of UTC)\n    // or subtracting the offset (if timezone is behind UTC)\n    let localMinute = schedule.minute + offsetMinutes;\n    let carryOver = 0;\n\n    // Handle minute carry-over\n    if (localMinute < 0) {\n      carryOver = Math.ceil(Math.abs(localMinute) / 60);\n      localMinute = (localMinute + carryOver * 60) % 60;\n      carryOver = -carryOver;\n    } else if (localMinute >= 60) {\n      carryOver = Math.floor(localMinute / 60);\n      localMinute = localMinute % 60;\n    }\n\n    let localHour = schedule.hour + carryOver;\n    let dayAdjustment = 0;\n\n    // Handle hour carry-over\n    if (localHour < 0) {\n      dayAdjustment = Math.ceil(Math.abs(localHour) / 24);\n      localHour = (localHour + dayAdjustment * 24) % 24;\n      dayAdjustment = -dayAdjustment;\n    } else if (localHour >= 24) {\n      dayAdjustment = Math.floor(localHour / 24);\n      localHour = localHour % 24;\n    }\n\n    // For weekly schedules, adjust the day if needed\n    if (\n      schedule.frequency === ScheduleFrequencyEnum.WEEKLY &&\n      dayAdjustment !== 0\n    ) {\n      const currentDayIndex = DAYS.indexOf(schedule.day);\n      const adjustedDayIndex = (currentDayIndex + dayAdjustment + 7) % 7;\n      return {\n        ...schedule,\n        hour: localHour,\n        minute: localMinute,\n        day: DAYS[adjustedDayIndex],\n        timezone,\n      };\n    }\n\n    // Return a new schedule object with local hours and minutes\n    return {\n      ...schedule,\n      hour: localHour,\n      minute: localMinute,\n      timezone,\n    };\n  }\n\n  protected generateCronExpression(schedule: DashboardSchedule): string | null {\n    const { frequency, day, hour, minute } = this.toUTC(schedule);\n\n    switch (frequency) {\n      case ScheduleFrequencyEnum.DAILY:\n        return `${minute} ${hour} * * *`;\n      case ScheduleFrequencyEnum.WEEKLY:\n        // e.g. 0 10 * * MON\n        return `${minute} ${hour} * * ${day}`;\n      case ScheduleFrequencyEnum.CUSTOM:\n        return schedule.cron;\n      case ScheduleFrequencyEnum.NEVER:\n        return null;\n      default:\n        logger.warn(`Unsupported schedule frequency: ${frequency}`);\n        return null;\n    }\n  }\n\n  protected calculateNextRunTime(cronExpression: string): Date | null {\n    try {\n      const interval = CronExpressionParser.parse(cronExpression, {\n        currentDate: new Date(),\n      });\n      return interval.next().toDate();\n    } catch (error) {\n      logger.error(`Failed to parse cron expression: ${error.message}`);\n      return null;\n    }\n  }\n\n  protected validateScheduleInput(data: SetDashboardCacheData): void {\n    const { schedule } = data;\n    if (!schedule) {\n      return;\n    }\n    if (schedule.frequency === ScheduleFrequencyEnum.WEEKLY && !schedule.day) {\n      throw new Error('Day of week is required for weekly schedule');\n    }\n\n    if (schedule.frequency === ScheduleFrequencyEnum.CUSTOM && !schedule.cron) {\n      throw new Error('Cron expression is required for custom schedule');\n    }\n\n    if (schedule.hour < 0 || schedule.hour > 23) {\n      throw new Error('Hour must be between 0 and 23');\n    }\n\n    if (schedule.minute < 0 || schedule.minute > 59) {\n      throw new Error('Minute must be between 0 and 59');\n    }\n\n    if (schedule.timezone) {\n      try {\n        new Date().toLocaleString('en-US', { timeZone: schedule.timezone });\n      } catch (_) {\n        throw new Error(`Invalid timezone: ${schedule.timezone}`);\n      }\n    }\n\n    if (schedule.frequency === ScheduleFrequencyEnum.CUSTOM) {\n      // can not less than 10 minutes, skip if is local\n      if (process.env.NODE_ENV === 'development') return;\n      const baseInterval = CronExpressionParser.parse(schedule.cron, {\n        currentDate: new Date(),\n      });\n      const baseDate = baseInterval.next().toDate();\n\n      const nextInterval = CronExpressionParser.parse(schedule.cron, {\n        currentDate: baseDate,\n      });\n      const nextDate = nextInterval.next().toDate();\n      const diff = nextDate.getTime() - baseDate.getTime();\n      if (diff < 10 * 60 * 1000) {\n        throw new Error(\n          'Custom cron expression must be at least 10 minutes apart',\n        );\n      }\n    }\n  }\n\n  public parseCronExpression(dashboard: Dashboard): DashboardSchedule {\n    if (!dashboard.scheduleCron) {\n      return {\n        frequency: dashboard.scheduleFrequency,\n        hour: 0,\n        minute: 0,\n        day: null,\n        timezone: dashboard.scheduleTimezone || '',\n        cron: '',\n      } as DashboardSchedule;\n    }\n    switch (dashboard.scheduleFrequency) {\n      case ScheduleFrequencyEnum.CUSTOM:\n        return {\n          frequency: ScheduleFrequencyEnum.CUSTOM,\n          hour: 0,\n          minute: 0,\n          day: null,\n          timezone: dashboard.scheduleTimezone || '',\n          cron: dashboard.scheduleCron,\n        };\n      case ScheduleFrequencyEnum.DAILY:\n      case ScheduleFrequencyEnum.WEEKLY: {\n        const parts = dashboard.scheduleCron.split(' ');\n        if (parts.length !== 5) {\n          throw new Error('Invalid cron expression format');\n        }\n        const [minute, hour, , , dayOfWeek] = parts;\n        return this.toTimezone({\n          frequency: dashboard.scheduleFrequency,\n          hour: parseInt(hour, 10),\n          minute: parseInt(minute, 10),\n          day:\n            dashboard.scheduleFrequency === ScheduleFrequencyEnum.WEEKLY\n              ? (dayOfWeek as CacheScheduleDayEnum)\n              : null,\n          timezone: dashboard.scheduleTimezone || '',\n          cron: null,\n        } as DashboardSchedule);\n      }\n      case ScheduleFrequencyEnum.NEVER: {\n        return {\n          frequency: ScheduleFrequencyEnum.NEVER,\n          hour: null,\n          minute: null,\n          day: null,\n          timezone: dashboard.scheduleTimezone || '',\n          cron: null,\n        } as DashboardSchedule;\n      }\n      default: {\n        throw new Error('Invalid schedule frequency');\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/services/deployService.ts",
    "content": "import { WrenAIDeployStatusEnum } from '@server/models/adaptor';\nimport { IWrenAIAdaptor } from '../adaptors/wrenAIAdaptor';\nimport {\n  Deploy,\n  DeployStatusEnum,\n  IDeployLogRepository,\n} from '../repositories/deployLogRepository';\nimport { Manifest } from '../mdl/type';\nimport { createHash } from 'node:crypto';\nimport { getLogger } from '@server/utils';\nimport {\n  PostHogTelemetry,\n  TelemetryEvent,\n  WrenService,\n} from '../telemetry/telemetry';\n\nconst logger = getLogger('DeployService');\nlogger.level = 'debug';\n\nexport interface DeployResponse {\n  status: DeployStatusEnum;\n  error?: string;\n}\n\nexport interface MDLSyncResponse {\n  isSyncronized: boolean;\n}\n\nexport interface IDeployService {\n  deploy(\n    manifest: Manifest,\n    projectId: number,\n    force?: boolean,\n  ): Promise<DeployResponse>;\n  getLastDeployment(projectId: number): Promise<Deploy>;\n  getInProgressDeployment(projectId: number): Promise<Deploy>;\n  createMDLHash(manifest: Manifest, projectId: number): string;\n  getMDLByHash(hash: string): Promise<string>;\n  deleteAllByProjectId(projectId: number): Promise<void>;\n}\n\nexport class DeployService implements IDeployService {\n  private wrenAIAdaptor: IWrenAIAdaptor;\n  private deployLogRepository: IDeployLogRepository;\n  private telemetry: PostHogTelemetry;\n\n  constructor({\n    wrenAIAdaptor,\n    deployLogRepository,\n    telemetry,\n  }: {\n    wrenAIAdaptor: IWrenAIAdaptor;\n    deployLogRepository: IDeployLogRepository;\n    telemetry: PostHogTelemetry;\n  }) {\n    this.wrenAIAdaptor = wrenAIAdaptor;\n    this.deployLogRepository = deployLogRepository;\n    this.telemetry = telemetry;\n  }\n\n  public async getLastDeployment(projectId) {\n    const lastDeploy =\n      await this.deployLogRepository.findLastProjectDeployLog(projectId);\n    if (!lastDeploy) {\n      return null;\n    }\n    return lastDeploy;\n  }\n\n  public async getInProgressDeployment(projectId) {\n    return await this.deployLogRepository.findInProgressProjectDeployLog(\n      projectId,\n    );\n  }\n\n  public async deploy(manifest, projectId, force = false) {\n    const eventName = TelemetryEvent.MODELING_DEPLOY_MDL;\n    try {\n      // generate hash of manifest\n      const hash = this.createMDLHash(manifest, projectId);\n      logger.debug(`Deploying model, hash: ${hash}`);\n\n      if (!force) {\n        // check if the model current deployment\n        const lastDeploy =\n          await this.deployLogRepository.findLastProjectDeployLog(projectId);\n        if (lastDeploy && lastDeploy.hash === hash) {\n          logger.log(`Model has been deployed, hash: ${hash}`);\n          return { status: DeployStatusEnum.SUCCESS };\n        }\n      }\n      const deployData = {\n        manifest,\n        hash,\n        projectId,\n        status: DeployStatusEnum.IN_PROGRESS,\n      } as Deploy;\n      const deploy = await this.deployLogRepository.createOne(deployData);\n\n      // deploy to AI-service\n      const { status: aiStatus, error: aiError } =\n        await this.wrenAIAdaptor.deploy({\n          manifest,\n          hash,\n        });\n\n      // update deploy status\n      const status =\n        aiStatus === WrenAIDeployStatusEnum.SUCCESS\n          ? DeployStatusEnum.SUCCESS\n          : DeployStatusEnum.FAILED;\n      await this.deployLogRepository.updateOne(deploy.id, {\n        status,\n        error: aiError,\n      });\n\n      // telemetry\n      if (status === DeployStatusEnum.SUCCESS) {\n        this.telemetry.sendEvent(eventName);\n      } else {\n        this.telemetry.sendEvent(\n          eventName,\n          { mdl: manifest, error: aiError },\n          WrenService.AI,\n          false,\n        );\n      }\n      return { status, error: aiError };\n    } catch (err: any) {\n      logger.error(`Error deploying model: ${err.message}`);\n      this.telemetry.sendEvent(\n        eventName,\n        { mdl: manifest, error: err.message },\n        err.extensions?.service,\n        false,\n      );\n      return { status: DeployStatusEnum.FAILED, error: err.message };\n    }\n  }\n\n  public createMDLHash(manifest: Manifest, projectId: number) {\n    const manifestStr = JSON.stringify(manifest);\n    const content = `${projectId} ${manifestStr}`;\n    const hash = createHash('sha1').update(content).digest('hex');\n    return hash;\n  }\n\n  public async getMDLByHash(hash: string) {\n    const deploy = await this.deployLogRepository.findOneBy({ hash });\n    if (!deploy) {\n      return null;\n    }\n    // return base64 encoded manifest\n    return Buffer.from(JSON.stringify(deploy.manifest)).toString('base64');\n  }\n\n  public async deleteAllByProjectId(projectId: number): Promise<void> {\n    // delete all deploy logs\n    await this.deployLogRepository.deleteAllBy({ projectId });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/services/index.ts",
    "content": "export * from './askingService';\nexport * from './deployService';\nexport * from './mdlService';\nexport * from './modelService';\nexport * from './projectService';\nexport * from './queryService';\nexport * from './metadataService';\nexport * from './dashboardService';\nexport * from './askingTaskTracker';\nexport * from './instructionService';\n"
  },
  {
    "path": "wren-ui/src/apollo/server/services/instructionService.ts",
    "content": "import { pick } from 'lodash';\nimport { IWrenAIAdaptor } from '@server/adaptors';\nimport { InstructionInput, UpdateInstructionInput } from '@server/models';\nimport {\n  InstructionResult,\n  InstructionStatus,\n  GenerateInstructionInput,\n} from '@server/models/adaptor';\nimport { IInstructionRepository, Instruction } from '@server/repositories';\nimport * as Errors from '@server/utils/error';\nimport { GeneralErrorCodes } from '@server/utils/error';\nexport interface IInstructionService {\n  getInstructions(projectId: number): Promise<Instruction[]>;\n  getInstruction(id: number): Promise<Instruction>;\n  createInstruction(instruction: InstructionInput): Promise<Instruction>;\n  createInstructions(instructions: InstructionInput[]): Promise<Instruction[]>;\n  updateInstruction(instruction: UpdateInstructionInput): Promise<Instruction>;\n  deleteInstruction(id: number, projectId: number): Promise<void>;\n}\n\nexport class InstructionService implements IInstructionService {\n  private readonly instructionRepository: IInstructionRepository;\n  private readonly wrenAIAdaptor: IWrenAIAdaptor;\n  constructor({\n    instructionRepository,\n    wrenAIAdaptor,\n  }: {\n    instructionRepository: IInstructionRepository;\n    wrenAIAdaptor: IWrenAIAdaptor;\n  }) {\n    this.instructionRepository = instructionRepository;\n    this.wrenAIAdaptor = wrenAIAdaptor;\n  }\n\n  public async getInstructions(projectId: number): Promise<Instruction[]> {\n    return this.instructionRepository.findAllBy({ projectId });\n  }\n\n  public async getInstruction(id: number): Promise<Instruction> {\n    return this.instructionRepository.findOneBy({ id });\n  }\n\n  public async createInstruction(\n    input: InstructionInput,\n  ): Promise<Instruction> {\n    const tx = await this.instructionRepository.transaction();\n    try {\n      this.validateInstructionInput(input);\n      const newInstruction = await this.instructionRepository.createOne(\n        {\n          ...input,\n          createdAt: new Date().toISOString(),\n          updatedAt: new Date().toISOString(),\n        },\n        {\n          tx,\n        },\n      );\n      const { queryId } = await this.wrenAIAdaptor.generateInstruction([\n        this.pickGenerateInstructionInput(newInstruction),\n      ]);\n      const res = await this.waitDeployInstruction(queryId);\n      if (res.error) {\n        await tx.rollback();\n        throw Errors.create(res.error.code, {\n          customMessage: res.error.message,\n        });\n      }\n      await tx.commit();\n      return newInstruction;\n    } catch (e: any) {\n      await tx.rollback();\n      throw new Error(`Failed to create instruction: ${e}`);\n    }\n  }\n\n  public async createInstructions(\n    inputs: InstructionInput[],\n  ): Promise<Instruction[]> {\n    const tx = await this.instructionRepository.transaction();\n    try {\n      inputs.forEach((input) => this.validateInstructionInput(input));\n      const newInstructions = await this.instructionRepository.createMany(\n        inputs.map((input) => ({\n          ...input,\n          createdAt: new Date().toISOString(),\n          updatedAt: new Date().toISOString(),\n        })),\n        {\n          tx,\n        },\n      );\n      const { queryId } = await this.wrenAIAdaptor.generateInstruction(\n        newInstructions.map(this.pickGenerateInstructionInput),\n      );\n      const res = await this.waitDeployInstruction(queryId);\n      if (res.error) {\n        await tx.rollback();\n        throw Errors.create(res.error.code, {\n          customMessage: res.error.message,\n        });\n      }\n      await tx.commit();\n      return newInstructions;\n    } catch (e: any) {\n      await tx.rollback();\n      throw new Error(`Failed to create instruction: ${e}`);\n    }\n  }\n\n  public async updateInstruction(\n    input: UpdateInstructionInput,\n  ): Promise<Instruction> {\n    const tx = await this.instructionRepository.transaction();\n    try {\n      this.validateInstructionInput(input);\n      const instruction = await this.instructionRepository.findOneBy(\n        { id: input.id, projectId: input.projectId },\n        {\n          tx,\n        },\n      );\n      if (!instruction) {\n        throw new Error('Instruction not found');\n      }\n      const instructionData = {\n        ...instruction,\n        ...input,\n        updatedAt: new Date().toISOString(),\n      };\n      const updatedInstruction = await this.instructionRepository.updateOne(\n        input.id,\n        instructionData,\n        { tx },\n      );\n      const { queryId } = await this.wrenAIAdaptor.generateInstruction([\n        this.pickGenerateInstructionInput(updatedInstruction),\n      ]);\n      const res = await this.waitDeployInstruction(queryId);\n      if (res.error) {\n        await tx.rollback();\n        throw Errors.create(res.error.code, {\n          customMessage: res.error.message,\n        });\n      }\n      await tx.commit();\n      return updatedInstruction;\n    } catch (e: any) {\n      await tx.rollback();\n      throw new Error(`Failed to update instruction: ${e}`);\n    }\n  }\n  async deleteInstruction(id: number, projectId: number): Promise<void> {\n    const tx = await this.instructionRepository.transaction();\n    try {\n      const instruction = await this.instructionRepository.findOneBy(\n        { id, projectId },\n        { tx },\n      );\n      if (!instruction) {\n        throw new Error('Instruction not found');\n      }\n      await this.instructionRepository.deleteOne(id, { tx });\n      await this.wrenAIAdaptor.deleteInstructions([id], instruction.projectId);\n      await tx.commit();\n    } catch (e: any) {\n      await tx.rollback();\n      throw new Error(`Failed to delete instruction: ${e}`);\n    }\n  }\n\n  private async waitDeployInstruction(\n    queryId: string,\n    maxRetries = 30, // Default 30 retries (30 seconds)\n  ): Promise<InstructionResult> {\n    const isFinalStatus = (status: InstructionStatus) =>\n      status === InstructionStatus.FINISHED ||\n      status === InstructionStatus.FAILED;\n\n    let res = await this.wrenAIAdaptor.getInstructionResult(queryId);\n    let retryCount = 0;\n\n    while (!isFinalStatus(res.status) && retryCount < maxRetries) {\n      await new Promise((resolve) => setTimeout(resolve, 1000));\n      res = await this.wrenAIAdaptor.getInstructionResult(queryId);\n      retryCount++;\n    }\n\n    if (!isFinalStatus(res.status)) {\n      throw Errors.create(GeneralErrorCodes.DEPLOY_TIMEOUT_ERROR, {\n        customMessage: `Instruction deployment timed out after ${maxRetries} seconds`,\n      });\n    }\n\n    return res;\n  }\n\n  private pickGenerateInstructionInput(\n    instruction: Instruction,\n  ): GenerateInstructionInput {\n    return pick(instruction, [\n      'id',\n      'projectId',\n      'instruction',\n      'questions',\n      'isDefault',\n    ]);\n  }\n\n  private validateInstructionInput(input: InstructionInput): void {\n    if (!input.instruction) {\n      throw new Error('Instruction is required');\n    }\n    if (input.instruction.length > 1000) {\n      throw new Error('Instruction is too long');\n    }\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/services/mdlService.ts",
    "content": "import { MDLBuilder } from '../mdl/mdlBuilder';\nimport {\n  IModelNestedColumnRepository,\n  IModelColumnRepository,\n  IModelRepository,\n  IProjectRepository,\n  IRelationRepository,\n  IViewRepository,\n} from '../repositories';\nimport { Manifest } from '../mdl/type';\n\nexport interface MakeCurrentModelMDLResult {\n  manifest: Manifest;\n  mdlBuilder: MDLBuilder;\n}\nexport interface IMDLService {\n  makeCurrentModelMDL(): Promise<MakeCurrentModelMDLResult>;\n}\n\nexport class MDLService implements IMDLService {\n  private projectRepository: IProjectRepository;\n  private modelRepository: IModelRepository;\n  private modelColumnRepository: IModelColumnRepository;\n  private modelNestedColumnRepository: IModelNestedColumnRepository;\n  private relationRepository: IRelationRepository;\n  private viewRepository: IViewRepository;\n\n  constructor({\n    projectRepository,\n    modelRepository,\n    modelColumnRepository,\n    modelNestedColumnRepository,\n    relationRepository,\n    viewRepository,\n  }: {\n    projectRepository: IProjectRepository;\n    modelRepository: IModelRepository;\n    modelColumnRepository: IModelColumnRepository;\n    modelNestedColumnRepository: IModelNestedColumnRepository;\n    relationRepository: IRelationRepository;\n    viewRepository: IViewRepository;\n  }) {\n    this.projectRepository = projectRepository;\n    this.modelRepository = modelRepository;\n    this.modelColumnRepository = modelColumnRepository;\n    this.modelNestedColumnRepository = modelNestedColumnRepository;\n    this.relationRepository = relationRepository;\n    this.viewRepository = viewRepository;\n  }\n\n  public async makeCurrentModelMDL() {\n    const project = await this.projectRepository.getCurrentProject();\n    const projectId = project.id;\n    const models = await this.modelRepository.findAllBy({ projectId });\n    const modelIds = models.map((m) => m.id);\n    const columns =\n      await this.modelColumnRepository.findColumnsByModelIds(modelIds);\n    const modelNestedColumns =\n      await this.modelNestedColumnRepository.findNestedColumnsByModelIds(\n        modelIds,\n      );\n    const relations = await this.relationRepository.findRelationInfoBy({\n      projectId,\n    });\n    const views = await this.viewRepository.findAllBy({ projectId });\n    const relatedModels = models;\n    const relatedColumns = columns;\n    const relatedRelations = relations;\n    const mdlBuilder = new MDLBuilder({\n      project,\n      models,\n      columns,\n      nestedColumns: modelNestedColumns,\n      relations,\n      views,\n      relatedModels,\n      relatedColumns,\n      relatedRelations,\n    });\n    return { manifest: mdlBuilder.build(), mdlBuilder };\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/services/metadataService.ts",
    "content": "/** \n    This class is responsible for handling the retrieval of metadata from the data source.\n    For DuckDB, we control the access logic and directly query the WrenEngine.\n    For PostgreSQL and BigQuery, we will use the Ibis server API.\n */\n\nimport { IIbisAdaptor } from '../adaptors/ibisAdaptor';\nimport { IWrenEngineAdaptor } from '../adaptors/wrenEngineAdaptor';\nimport { Project } from '../repositories';\nimport { DataSourceName } from '../types';\nimport { getLogger } from '@server/utils';\n\nconst logger = getLogger('MetadataService');\nlogger.level = 'debug';\n\nexport interface CompactColumn {\n  name: string;\n  type: string;\n  notNull: boolean;\n  description?: string;\n  properties?: Record<string, any>;\n  nestedColumns?: CompactColumn[];\n}\n\nexport enum ConstraintType {\n  PRIMARY_KEY = 'PRIMARY KEY',\n  FOREIGN_KEY = 'FOREIGN KEY',\n  UNIQUE = 'UNIQUE',\n}\n\nexport interface CompactTable {\n  name: string;\n  columns: CompactColumn[];\n  description?: string;\n  properties?: Record<string, any>;\n  primaryKey?: string;\n}\n\nexport interface RecommendConstraint {\n  constraintName: string;\n  constraintType: ConstraintType;\n  constraintTable: string;\n  constraintColumn: string;\n  constraintedTable: string;\n  constraintedColumn: string;\n}\n\nexport interface IDataSourceMetadataService {\n  listTables(project: Project): Promise<CompactTable[]>;\n  listConstraints(project: Project): Promise<RecommendConstraint[]>;\n  getVersion(project: Project): Promise<string>;\n}\n\nexport class DataSourceMetadataService implements IDataSourceMetadataService {\n  private readonly ibisAdaptor: IIbisAdaptor;\n  private readonly wrenEngineAdaptor: IWrenEngineAdaptor;\n\n  constructor({\n    ibisAdaptor,\n    wrenEngineAdaptor,\n  }: {\n    ibisAdaptor: IIbisAdaptor;\n    wrenEngineAdaptor: IWrenEngineAdaptor;\n  }) {\n    this.ibisAdaptor = ibisAdaptor;\n    this.wrenEngineAdaptor = wrenEngineAdaptor;\n  }\n\n  public async listTables(project): Promise<CompactTable[]> {\n    const { type: dataSource, connectionInfo } = project;\n    if (dataSource === DataSourceName.DUCKDB) {\n      const tables = await this.wrenEngineAdaptor.listTables();\n      return tables;\n    }\n    return await this.ibisAdaptor.getTables(dataSource, connectionInfo);\n  }\n\n  public async listConstraints(\n    project: Project,\n  ): Promise<RecommendConstraint[]> {\n    const { type: dataSource, connectionInfo } = project;\n    if (dataSource === DataSourceName.DUCKDB) {\n      return [];\n    }\n    return await this.ibisAdaptor.getConstraints(dataSource, connectionInfo);\n  }\n\n  public async getVersion(project: Project): Promise<string> {\n    const { type: dataSource, connectionInfo } = project;\n    return await this.ibisAdaptor.getVersion(dataSource, connectionInfo);\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/services/modelService.ts",
    "content": "import { SampleDatasetTable } from '@server/data';\nimport {\n  IModelColumnRepository,\n  IModelRepository,\n  IRelationRepository,\n  IViewRepository,\n  Model,\n  ModelColumn,\n  Relation,\n} from '@server/repositories';\nimport {\n  getLogger,\n  safeParseJson,\n  replaceAllowableSyntax,\n  validateDisplayName,\n} from '@server/utils';\nimport { RelationData, UpdateRelationData } from '@server/types';\nimport { IProjectService } from './projectService';\nimport {\n  CreateCalculatedFieldData,\n  ExpressionName,\n  UpdateCalculatedFieldData,\n  CheckCalculatedFieldCanQueryData,\n} from '@server/models';\nimport { IMDLService } from './mdlService';\nimport { IWrenEngineAdaptor } from '../adaptors/wrenEngineAdaptor';\nimport { ValidationRules } from '@server/adaptors/ibisAdaptor';\nimport { isEmpty, capitalize } from 'lodash';\nimport {} from '@server/utils/regex';\nimport * as Errors from '@server/utils/error';\nimport { DataSourceName } from '@server/types';\nimport { IQueryService } from './queryService';\n\nconst logger = getLogger('ModelService');\nlogger.level = 'debug';\n\nexport interface ValidateCalculatedFieldResponse {\n  valid: boolean;\n  message?: string;\n}\n\nexport interface IModelService {\n  updatePrimaryKeys(tables: SampleDatasetTable[]): Promise<void>;\n  batchUpdateModelProperties(tables: SampleDatasetTable[]): Promise<void>;\n  batchUpdateColumnProperties(tables: SampleDatasetTable[]): Promise<void>;\n  // saveRelations was used in the onboarding process, we assume there is not existing relation in the project\n  saveRelations(relations: RelationData[]): Promise<Relation[]>;\n  createRelation(relation: RelationData): Promise<Relation>;\n  updateRelation(relation: UpdateRelationData, id: number): Promise<Relation>;\n  deleteRelation(id: number): Promise<void>;\n  createCalculatedField(data: CreateCalculatedFieldData): Promise<ModelColumn>;\n  updateCalculatedField(\n    data: UpdateCalculatedFieldData,\n    id: number,\n  ): Promise<ModelColumn>;\n  generateReferenceName(data: any): string;\n  validateCalculatedFieldNaming(\n    name: string,\n    modelId: number,\n    columnId?: number,\n  ): Promise<ValidateCalculatedFieldResponse>;\n  deleteAllViewsByProjectId(projectId: number): Promise<void>;\n  deleteAllModelsByProjectId(projectId: number): Promise<void>;\n}\n\nexport interface GenerateReferenceNameData {\n  displayName: string;\n  sourceTableName: string;\n  existedReferenceNames: string[];\n}\n\nexport class ModelService implements IModelService {\n  private projectService: IProjectService;\n  private modelRepository: IModelRepository;\n  private modelColumnRepository: IModelColumnRepository;\n  private relationRepository: IRelationRepository;\n  private viewRepository: IViewRepository;\n  private mdlService: IMDLService;\n  private wrenEngineAdaptor: IWrenEngineAdaptor;\n  private queryService: IQueryService;\n\n  constructor({\n    projectService,\n    modelRepository,\n    modelColumnRepository,\n    relationRepository,\n    viewRepository,\n    mdlService,\n    wrenEngineAdaptor,\n    queryService,\n  }: {\n    projectService: IProjectService;\n    modelRepository: IModelRepository;\n    modelColumnRepository: IModelColumnRepository;\n    relationRepository: IRelationRepository;\n    viewRepository: IViewRepository;\n    mdlService: IMDLService;\n    wrenEngineAdaptor: IWrenEngineAdaptor;\n    queryService: IQueryService;\n  }) {\n    this.projectService = projectService;\n    this.modelRepository = modelRepository;\n    this.modelColumnRepository = modelColumnRepository;\n    this.relationRepository = relationRepository;\n    this.viewRepository = viewRepository;\n    this.mdlService = mdlService;\n    this.wrenEngineAdaptor = wrenEngineAdaptor;\n    this.queryService = queryService;\n  }\n\n  public async createCalculatedField(\n    data: CreateCalculatedFieldData,\n  ): Promise<ModelColumn> {\n    const { modelId, name: displayName, expression, lineage } = data;\n    const logTitle = `Create Calculated Field ${displayName}`;\n    const model = await this.modelRepository.findOneBy({\n      id: modelId,\n    });\n    if (!model) {\n      throw new Error('Model not found');\n    }\n    const { valid, message } = await this.validateCalculatedFieldNaming(\n      displayName,\n      modelId,\n    );\n    logger.debug(\n      `${logTitle} : validateCalculatedFieldNaming: ${valid}, ${message}`,\n    );\n    if (!valid) {\n      throw new Error(message);\n    }\n\n    // generate referenceName\n    const referenceName =\n      this.generateReferenceNameFromDisplayName(displayName);\n    logger.debug(`${logTitle} : generated referenceName: \"${referenceName}\"`);\n\n    // check this calculated field is valid for engine to query\n    const { valid: canQuery, message: errorMessage } =\n      await this.checkCalculatedFieldCanQuery(modelId, model.referenceName, {\n        referenceName,\n        expression,\n        lineage,\n      } as CheckCalculatedFieldCanQueryData);\n    logger.debug(`${logTitle} : checkCalculatedFieldCanQuery: ${canQuery}`);\n    if (!canQuery) {\n      const parsedErrorMessage = safeParseJson(errorMessage);\n      throw Errors.create(Errors.GeneralErrorCodes.INVALID_CALCULATED_FIELD, {\n        customMessage: parsedErrorMessage?.message || errorMessage,\n        originalError: parsedErrorMessage || null,\n      });\n    }\n    const inputFieldId = lineage[lineage.length - 1];\n    const dataType = await this.inferCalculatedFieldDataType(\n      expression,\n      inputFieldId,\n    );\n    logger.debug(`${logTitle} : inferCalculatedFieldDataType: ${dataType}`);\n\n    // create calculated field\n    const column = await this.modelColumnRepository.createOne({\n      modelId,\n      displayName: displayName,\n      sourceColumnName: referenceName,\n      referenceName,\n      type: dataType,\n      isCalculated: true,\n      isPk: false,\n      notNull: false,\n      aggregation: expression,\n      lineage: JSON.stringify(lineage),\n      properties: JSON.stringify({ description: '' }),\n    });\n    return column;\n  }\n\n  public async updateCalculatedField(\n    data: UpdateCalculatedFieldData,\n    id: number,\n  ): Promise<ModelColumn> {\n    const { name: displayName, expression, lineage } = data;\n    const logTitle = `Update Calculated Field ${id}`;\n    const column = await this.modelColumnRepository.findOneBy({ id });\n    if (!column) {\n      throw new Error('Column not found');\n    }\n    const model = await this.modelRepository.findOneBy({\n      id: column.modelId,\n    });\n    const { valid, message } = await this.validateCalculatedFieldNaming(\n      displayName,\n      column.modelId,\n      id,\n    );\n    logger.debug(\n      `${logTitle}: validateCalculatedFieldNaming: ${valid}, ${message}`,\n    );\n    if (!valid) {\n      throw new Error(message);\n    }\n    const referenceName =\n      this.generateReferenceNameFromDisplayName(displayName);\n    logger.debug(`${logTitle}: generated referenceName: \"${referenceName}\"`);\n\n    // check this calculated field is valid for engine to query\n    const { valid: canQuery, message: errorMessage } =\n      await this.checkCalculatedFieldCanQuery(model.id, model.referenceName, {\n        referenceName,\n        expression,\n        lineage,\n      } as CheckCalculatedFieldCanQueryData);\n    logger.debug(`${logTitle}: checkCalculatedFieldCanQuery: ${canQuery}`);\n    if (!canQuery) {\n      const error = JSON.parse(errorMessage);\n      throw Errors.create(Errors.GeneralErrorCodes.INVALID_CALCULATED_FIELD, {\n        customMessage: error?.message,\n        originalError: error,\n      });\n    }\n    const inputFieldId = lineage[lineage.length - 1];\n    const dataType = await this.inferCalculatedFieldDataType(\n      expression,\n      inputFieldId,\n    );\n    logger.debug(`${logTitle}: inferCalculatedFieldDataType: ${dataType}`);\n    const updatedColumn = await this.modelColumnRepository.updateOne(id, {\n      displayName: displayName,\n      sourceColumnName: referenceName,\n      referenceName,\n      type: dataType,\n      aggregation: expression,\n      lineage: JSON.stringify(lineage),\n    });\n    return updatedColumn;\n  }\n\n  public async updatePrimaryKeys(tables: SampleDatasetTable[]) {\n    logger.debug('start update primary keys');\n    const { id } = await this.projectService.getCurrentProject();\n    const models = await this.modelRepository.findAllBy({\n      projectId: id,\n    });\n    const tableToUpdate = tables.filter((t) => t.primaryKey);\n    for (const table of tableToUpdate) {\n      const model = models.find((m) => m.sourceTableName === table.tableName);\n      if (!model) {\n        logger.debug(`Model not found, table name: ${table.tableName}`);\n      }\n      await this.modelColumnRepository.setModelPrimaryKey(\n        model.id,\n        table.primaryKey,\n      );\n    }\n  }\n\n  public async batchUpdateModelProperties(tables: SampleDatasetTable[]) {\n    logger.debug('start batch update model description');\n    const { id } = await this.projectService.getCurrentProject();\n    const models = await this.modelRepository.findAllBy({\n      projectId: id,\n    });\n\n    await Promise.all([\n      tables.map(async (table) => {\n        const model = models.find((m) => m.sourceTableName === table.tableName);\n        if (!model) {\n          logger.debug(`Model not found, table name: ${table.tableName}`);\n          return;\n        }\n        const properties = model.properties\n          ? { ...JSON.parse(model.properties), ...table.properties }\n          : { ...table.properties };\n        await this.modelRepository.updateOne(model.id, {\n          displayName: table.properties?.displayName || model.displayName,\n          properties: JSON.stringify(properties),\n        });\n      }),\n    ]);\n  }\n\n  public async batchUpdateColumnProperties(tables: SampleDatasetTable[]) {\n    logger.debug('start batch update column description');\n    const { id } = await this.projectService.getCurrentProject();\n    const models = await this.modelRepository.findAllBy({\n      projectId: id,\n    });\n    const sourceColumns =\n      (await this.modelColumnRepository.findColumnsByModelIds(\n        models.map((m) => m.id),\n      )) as ModelColumn[];\n    const transformedColumns = tables.reduce((acc, table) => {\n      const columns = table.columns?.map((column) => {\n        return { ...column, tableName: table.tableName };\n      });\n      if (columns) {\n        acc.push(...columns);\n      }\n      return acc;\n    }, []);\n\n    await Promise.all([\n      transformedColumns.map(async (column) => {\n        if (!column.properties) {\n          return;\n        }\n        const model = models.find(\n          (m) => m.sourceTableName === column.tableName,\n        );\n        const sourceColumn = sourceColumns.find(\n          (sourceColumn) =>\n            sourceColumn.modelId === model.id &&\n            sourceColumn.sourceColumnName === column.name,\n        );\n        if (!sourceColumn) {\n          logger.debug(\n            `Column not found, table name: ${column.tableName}, column name: ${column.name}`,\n          );\n          return;\n        }\n        const properties = sourceColumn.properties\n          ? {\n              ...JSON.parse(sourceColumn.properties),\n              ...column.properties,\n            }\n          : { description: column.description };\n        await this.modelColumnRepository.updateOne(sourceColumn.id, {\n          properties: JSON.stringify(properties),\n        });\n      }),\n    ]);\n  }\n\n  public generateReferenceName(data: GenerateReferenceNameData): string {\n    const { sourceTableName, existedReferenceNames } = data;\n    if (!existedReferenceNames.includes(sourceTableName)) {\n      return sourceTableName;\n    }\n    return `${sourceTableName}_${existedReferenceNames.length + 1}`;\n  }\n\n  public async saveRelations(relations: RelationData[]) {\n    if (isEmpty(relations)) {\n      return [];\n    }\n    const { id } = await this.projectService.getCurrentProject();\n\n    const models = await this.modelRepository.findAllBy({\n      projectId: id,\n    });\n\n    const columnIds = relations\n      .map(({ fromColumnId, toColumnId }) => [fromColumnId, toColumnId])\n      .flat();\n    const columns =\n      await this.modelColumnRepository.findColumnsByIds(columnIds);\n    const relationValues = relations.map((relation) => {\n      const fromColumn = columns.find(\n        (column) => column.id === relation.fromColumnId,\n      );\n      if (!fromColumn) {\n        throw new Error(`Column not found, column Id ${relation.fromColumnId}`);\n      }\n      const toColumn = columns.find(\n        (column) => column.id === relation.toColumnId,\n      );\n      if (!toColumn) {\n        throw new Error(`Column not found, column Id  ${relation.toColumnId}`);\n      }\n      const relationName = this.generateRelationName(relation, models, columns);\n      return {\n        projectId: id,\n        name: relationName,\n        fromColumnId: relation.fromColumnId,\n        toColumnId: relation.toColumnId,\n        joinType: relation.type,\n        properties: relation.description\n          ? JSON.stringify({ description: relation.description })\n          : null,\n      } as Partial<Relation>;\n    });\n\n    const savedRelations =\n      await this.relationRepository.createMany(relationValues);\n\n    return savedRelations;\n  }\n\n  public async createRelation(relation: RelationData): Promise<Relation> {\n    const { id } = await this.projectService.getCurrentProject();\n    const modelIds = [relation.fromModelId, relation.toModelId];\n    const models = await this.modelRepository.findAllByIds(modelIds);\n    const columnIds = [relation.fromColumnId, relation.toColumnId];\n    const columns =\n      await this.modelColumnRepository.findColumnsByIds(columnIds);\n\n    const { valid, message } = await this.validateCreateRelation(\n      models,\n      columns,\n      relation,\n    );\n    if (!valid) {\n      throw new Error(message);\n    }\n    const relationName = this.generateRelationName(relation, models, columns);\n    const savedRelation = await this.relationRepository.createOne({\n      projectId: id,\n      name: relationName,\n      fromColumnId: relation.fromColumnId,\n      toColumnId: relation.toColumnId,\n      joinType: relation.type,\n    });\n    return savedRelation;\n  }\n\n  public async updateRelation(\n    relation: UpdateRelationData,\n    id: number,\n  ): Promise<Relation> {\n    const updatedRelation = await this.relationRepository.updateOne(id, {\n      joinType: relation.type,\n    });\n    return updatedRelation;\n  }\n\n  public async deleteRelation(id: number): Promise<void> {\n    const relation = await this.relationRepository.findOneBy({ id });\n    if (!relation) {\n      throw new Error('Relation not found');\n    }\n    const calculatedFields = await this.getCalculatedFieldByRelation(id);\n    if (calculatedFields.length > 0) {\n      // delete related calculated fields\n      await this.modelColumnRepository.deleteMany(\n        calculatedFields.map((f) => f.id),\n      );\n    }\n    await this.relationRepository.deleteOne(id);\n  }\n\n  public async getCalculatedFieldByRelation(\n    relationId: number,\n  ): Promise<ModelColumn[]> {\n    const calculatedFields = await this.modelColumnRepository.findAllBy({\n      isCalculated: true,\n    });\n    const relatedCalculatedFields = calculatedFields.reduce((acc, field) => {\n      const lineage = JSON.parse(field.lineage);\n      const relationIds = lineage.slice(0, lineage.length - 1);\n      if (relationIds.includes(relationId)) {\n        acc.push(field);\n      }\n      return acc;\n    }, []);\n    return relatedCalculatedFields;\n  }\n\n  public async validateCalculatedFieldNaming(\n    displayName: string,\n    modelId: number,\n    columnId?: number,\n  ): Promise<ValidateCalculatedFieldResponse> {\n    // only allow uppercase/lowercase english, numbers, syntaxes in the first raw of keyboard, {}, [], ', \", ,, .\n    const validationRes = validateDisplayName(displayName);\n    if (!validationRes.valid) {\n      return {\n        valid: false,\n        message: validationRes.message || 'Invalid Calculated field name',\n      };\n    }\n\n    // can not duplicated with existed column\n    const referenceName =\n      this.generateReferenceNameFromDisplayName(displayName);\n    let existedColumns = await this.modelColumnRepository.findColumnsByModelIds(\n      [modelId],\n    );\n    if (columnId) {\n      existedColumns = existedColumns.filter(\n        (column) => column.id !== columnId,\n      );\n    }\n    if (\n      existedColumns.find((column) => column.referenceName === referenceName)\n    ) {\n      return {\n        valid: false,\n        message: `The generated calculated field name \"${referenceName}\" is duplicated with existed column, please change the name and try again`,\n      };\n    }\n    return { valid: true };\n  }\n\n  public async deleteAllViewsByProjectId(projectId: number): Promise<void> {\n    // delete all views\n    await this.viewRepository.deleteAllBy({ projectId });\n  }\n\n  public async deleteAllModelsByProjectId(projectId: number): Promise<void> {\n    // delete all relations\n    await this.relationRepository.deleteAllBy({ projectId });\n\n    // delete all models\n    await this.modelRepository.deleteAllBy({ projectId });\n  }\n\n  private generateReferenceNameFromDisplayName(displayName: string) {\n    // replace all syntaxes that [in the first raw of keyboard, {}, [], ', \", ,, . ] with _\n    return replaceAllowableSyntax(displayName);\n  }\n\n  private generateRelationName(\n    relation: RelationData,\n    models: Model[],\n    columns: ModelColumn[],\n  ) {\n    const fromModel = models.find((m) => m.id === relation.fromModelId);\n    const toModel = models.find((m) => m.id === relation.toModelId);\n    if (!fromModel || !toModel) {\n      throw new Error('Model not found');\n    }\n\n    const fromColumn = columns.find(\n      (column) => column.id === relation.fromColumnId,\n    );\n    const toColumn = columns.find(\n      (column) => column.id === relation.toColumnId,\n    );\n\n    return (\n      capitalize(fromModel.sourceTableName) +\n      capitalize(fromColumn.referenceName) +\n      capitalize(toModel.sourceTableName) +\n      capitalize(toColumn.referenceName)\n    );\n  }\n\n  /** We currently support expression below, right side is the return type of the calculated field.\n  Aggregations\n    - **avg(***x***)** → double\n    - **count(***x***)** → bigint\n    - **max(***x***)** → [same as input]\n    - **min(***x***)** → [same as input]\n    - **sum(***x***)** → [same as input]\n  Math functions\n    - **abs(***x***)** → [same as input]\n    - **cbrt(***x***)** → double\n    - **ceil(***x***)** → [same as input]\n    - **exp(***x***)** → double\n    - **floor(***x***)** → [same as input]\n    - **ln(***x***)** → double\n    - **log10(***x***)** → double\n    - **round(***x***)** → [same as input]\n    - **sign(***x***)** → [same as input]\n\n  String functions\n    - **length(***string***)** → bigint\n    - **reverse(**string**)** → varbinary\n  */\n  private async inferCalculatedFieldDataType(\n    expression: ExpressionName,\n    inputFieldId: number,\n  ) {\n    let type = null;\n    switch (expression) {\n      case ExpressionName.CEIL:\n      case ExpressionName.FLOOR:\n      case ExpressionName.ROUND:\n      case ExpressionName.SIGN:\n      case ExpressionName.SUM:\n      case ExpressionName.MAX:\n      case ExpressionName.MIN:\n      case ExpressionName.ABS:\n        type = await this.getFieldDataType(inputFieldId);\n        break;\n      case ExpressionName.CBRT:\n      case ExpressionName.EXP:\n      case ExpressionName.AVG:\n      case ExpressionName.LN:\n      case ExpressionName.LOG10:\n        type = 'DOUBLE';\n        break;\n      case ExpressionName.COUNT:\n      case ExpressionName.LENGTH:\n        type = 'BIGINT';\n        break;\n      case ExpressionName.REVERSE:\n        type = 'VARBINARY';\n        break;\n      default:\n        throw new Error('Unsupported expression');\n    }\n    return type;\n  }\n\n  private async getFieldDataType(fieldId: number): Promise<string> {\n    const field = await this.modelColumnRepository.findOneBy({ id: fieldId });\n    if (!field) {\n      throw new Error('Field not found');\n    }\n    return field.type;\n  }\n\n  private async checkCalculatedFieldCanQuery(\n    modelId: number,\n    modelName: string,\n    data: CheckCalculatedFieldCanQueryData,\n  ) {\n    const project = await this.projectService.getCurrentProject();\n    const { mdlBuilder } = await this.mdlService.makeCurrentModelMDL();\n    const { referenceName, expression, lineage } = data;\n    const inputFieldId = lineage[lineage.length - 1];\n    const dataType = await this.inferCalculatedFieldDataType(\n      expression,\n      inputFieldId,\n    );\n\n    // add temporary calculated field\n    const modelColumn = {\n      id: 99999999,\n      modelId,\n      displayName: referenceName,\n      sourceColumnName: referenceName,\n      referenceName: referenceName,\n      type: dataType,\n      isCalculated: true,\n      isPk: false,\n      notNull: false,\n      aggregation: expression,\n      lineage: JSON.stringify(lineage),\n      properties: JSON.stringify({ description: '' }),\n    } as ModelColumn;\n    mdlBuilder.insertCalculatedField(modelName, modelColumn);\n    const manifest = mdlBuilder.getManifest();\n\n    // find the calculated field in manifest\n    const calculatedField = manifest.models\n      .find((m) => m.name === modelName)\n      ?.columns.find((c) => c.name === referenceName);\n\n    logger.debug(`Calculated field MDL: ${JSON.stringify(calculatedField)}`);\n\n    // validate calculated field can query\n    const dataSource = project.type;\n    if (dataSource === DataSourceName.DUCKDB) {\n      return await this.wrenEngineAdaptor.validateColumnIsValid(\n        manifest,\n        modelName,\n        referenceName,\n      );\n    } else {\n      const parameters = { modelName, columnName: referenceName };\n      return await this.queryService.validate(\n        project,\n        ValidationRules.COLUMN_IS_VALID,\n        manifest,\n        parameters,\n      );\n    }\n  }\n\n  private async validateCreateRelation(\n    models: Model[],\n    columns: ModelColumn[],\n    relation: RelationData,\n  ) {\n    const { fromModelId, fromColumnId, toModelId, toColumnId } = relation;\n    const fromModel = models.find((m) => m.id === fromModelId);\n    const toModel = models.find((m) => m.id === toModelId);\n    // model should exist\n    if (!fromModel) {\n      return {\n        valid: false,\n        message: `Model not found: fromModelId ${fromModelId}`,\n      };\n    }\n    if (!toModel) {\n      return {\n        valid: false,\n        message: `Model not found: toModelId ${toModelId}`,\n      };\n    }\n    // column should exist\n    const fromColumn = columns.find((column) => column.id === fromColumnId);\n    const toColumn = columns.find((column) => column.id === toColumnId);\n    if (!fromColumn) {\n      return {\n        valid: false,\n        message: `Column not found, column Id ${fromColumnId}`,\n      };\n    }\n    if (!toColumn) {\n      return {\n        valid: false,\n        message: `Column not found, column Id ${toColumnId}`,\n      };\n    }\n\n    // column should belong to the model\n    if (toColumn.modelId != toModelId) {\n      return {\n        valid: false,\n        message: `Column not belong to the model, column Id ${toColumnId}`,\n      };\n    }\n    if (fromColumn.modelId != fromModelId) {\n      return {\n        valid: false,\n        message: `Column not belong to the model, column Id ${fromColumnId}`,\n      };\n    }\n\n    const existedRelations =\n      await this.relationRepository.findExistedRelationBetweenModels(relation);\n\n    if (existedRelations.length > 0) {\n      return {\n        valid: false,\n        message: 'This relationship already exists.',\n      };\n    }\n\n    return { valid: true };\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/services/projectService.ts",
    "content": "import crypto from 'crypto';\nimport * as fs from 'fs';\nimport path from 'path';\nimport { getLogger } from '@server/utils';\nimport { IProjectRepository, WREN_AI_CONNECTION_INFO } from '../repositories';\nimport { Project } from '../repositories';\nimport {\n  CompactTable,\n  IDataSourceMetadataService,\n  RecommendConstraint,\n} from './metadataService';\nimport { DataSourceName } from '../types';\nimport {\n  RecommendationQuestion,\n  RecommendationQuestionStatus,\n  WrenAIError,\n  WrenAILanguage,\n} from '@server/models/adaptor';\nimport { encryptConnectionInfo } from '../dataSource';\nimport { IWrenAIAdaptor } from '../adaptors';\nimport { RecommendQuestionResultStatus } from './askingService';\nimport { IMDLService } from './mdlService';\nimport { ProjectRecommendQuestionBackgroundTracker } from '../backgrounds';\nimport { ITelemetry } from '../telemetry/telemetry';\nimport { getConfig } from '../config';\n\nconst config = getConfig();\n\nconst logger = getLogger('ProjectService');\nlogger.level = 'debug';\n\nconst SENSITIVE_PROPERTY_NAME = new Set([\n  'credentials',\n  'password',\n  'awsSecretKey',\n  'privateKey',\n  'accessToken',\n  'clientSecret',\n  'webIdentityToken',\n]);\nexport interface ProjectData {\n  displayName: string;\n  type: DataSourceName;\n  connectionInfo: WREN_AI_CONNECTION_INFO;\n}\n\nexport interface ProjectRecommendationQuestionsResult {\n  status: RecommendQuestionResultStatus;\n  questions: RecommendationQuestion[];\n  error: WrenAIError;\n}\nexport interface IProjectService {\n  createProject: (projectData: ProjectData) => Promise<Project>;\n  updateProject: (\n    projectId: number,\n    projectData: Partial<Project>,\n  ) => Promise<Project>;\n  getGeneralConnectionInfo: (project: Project) => Record<string, any>;\n  getProjectDataSourceTables: (\n    project?: Project,\n    projectId?: number,\n  ) => Promise<CompactTable[]>;\n  getProjectDataSourceVersion: (\n    project?: Project,\n    projectId?: number,\n  ) => Promise<string>;\n  getProjectSuggestedConstraint: (\n    project?: Project,\n    projectId?: number,\n  ) => Promise<RecommendConstraint[]>;\n\n  getCurrentProject: () => Promise<Project>;\n  getProjectById: (projectId: number) => Promise<Project>;\n  writeCredentialFile: (\n    credentials: JSON,\n    persistCredentialDir: string,\n  ) => string;\n  deleteProject: (projectId: number) => Promise<void>;\n  getProjectRecommendationQuestions: () => Promise<ProjectRecommendationQuestionsResult>;\n\n  // recommend questions\n  generateProjectRecommendationQuestions: () => Promise<void>;\n}\n\nexport class ProjectService implements IProjectService {\n  private projectRepository: IProjectRepository;\n  private metadataService: IDataSourceMetadataService;\n  private mdlService: IMDLService;\n  private wrenAIAdaptor: IWrenAIAdaptor;\n  private projectRecommendQuestionBackgroundTracker: ProjectRecommendQuestionBackgroundTracker;\n  constructor({\n    projectRepository,\n    metadataService,\n    mdlService,\n    wrenAIAdaptor,\n    telemetry,\n  }: {\n    projectRepository: IProjectRepository;\n    metadataService: IDataSourceMetadataService;\n    mdlService: IMDLService;\n    wrenAIAdaptor: IWrenAIAdaptor;\n    telemetry: ITelemetry;\n  }) {\n    this.projectRepository = projectRepository;\n    this.metadataService = metadataService;\n    this.mdlService = mdlService;\n    this.wrenAIAdaptor = wrenAIAdaptor;\n    this.projectRecommendQuestionBackgroundTracker =\n      new ProjectRecommendQuestionBackgroundTracker({\n        projectRepository,\n        telemetry,\n        wrenAIAdaptor,\n      });\n  }\n  public async updateProject(\n    projectId: number,\n    projectData: Partial<Project>,\n  ): Promise<Project> {\n    return await this.projectRepository.updateOne(projectId, projectData);\n  }\n\n  public async getProjectDataSourceVersion(\n    project?: Project,\n    projectId?: number,\n  ): Promise<string> {\n    const usedProject = project\n      ? project\n      : projectId\n        ? await this.getProjectById(projectId)\n        : await this.getCurrentProject();\n    return await this.metadataService.getVersion(usedProject);\n  }\n\n  public async generateProjectRecommendationQuestions(): Promise<void> {\n    const project = await this.getCurrentProject();\n    if (!project) {\n      throw new Error(`Project not found`);\n    }\n    const { manifest } = await this.mdlService.makeCurrentModelMDL();\n    const recommendQuestionResult =\n      await this.wrenAIAdaptor.generateRecommendationQuestions({\n        manifest,\n        ...this.getProjectRecommendationQuestionsConfig(project),\n      });\n\n    const updatedProject = await this.projectRepository.updateOne(project.id, {\n      queryId: recommendQuestionResult.queryId,\n      questionsStatus: RecommendationQuestionStatus.GENERATING,\n      questions: [],\n      questionsError: null,\n    });\n\n    if (\n      !this.projectRecommendQuestionBackgroundTracker.isExist(updatedProject)\n    ) {\n      this.projectRecommendQuestionBackgroundTracker.addTask(updatedProject);\n    } else {\n      logger.debug(\n        `Generate Project Recommendation Questions Task ${updatedProject.id} already exists, skip adding`,\n      );\n    }\n  }\n\n  public async getProjectRecommendationQuestions() {\n    const project = await this.projectRepository.getCurrentProject();\n    if (!project) {\n      throw new Error(`Project not found`);\n    }\n    const result: ProjectRecommendationQuestionsResult = {\n      status: RecommendQuestionResultStatus.NOT_STARTED,\n      questions: [],\n      error: null,\n    };\n    if (project.queryId) {\n      result.status = project.questionsStatus\n        ? RecommendQuestionResultStatus[project.questionsStatus]\n        : result.status;\n      result.questions = project.questions || [];\n      result.error = project.questionsError as WrenAIError;\n    }\n    return result;\n  }\n\n  public async getCurrentProject() {\n    return await this.projectRepository.getCurrentProject();\n  }\n\n  public async getProjectById(projectId: number) {\n    return await this.projectRepository.findOneBy({ id: projectId });\n  }\n\n  public async getProjectDataSourceTables(\n    project?: Project,\n    projectId?: number,\n  ) {\n    const usedProject = project\n      ? project\n      : projectId\n        ? await this.getProjectById(projectId)\n        : await this.getCurrentProject();\n    return await this.metadataService.listTables(usedProject);\n  }\n\n  public async getProjectSuggestedConstraint(\n    project?: Project,\n    projectId?: number,\n  ) {\n    const usedProject = project\n      ? project\n      : projectId\n        ? await this.getProjectById(projectId)\n        : await this.getCurrentProject();\n    return await this.metadataService.listConstraints(usedProject);\n  }\n\n  public async createProject(projectData: ProjectData) {\n    const projectValue = {\n      displayName: projectData.displayName,\n      type: projectData.type,\n      catalog: 'wrenai',\n      schema: 'public',\n      connectionInfo: encryptConnectionInfo(\n        projectData.type,\n        projectData.connectionInfo,\n      ),\n    };\n    logger.debug('Creating project...');\n    const project = await this.projectRepository.createOne(projectValue);\n    return project;\n  }\n\n  public writeCredentialFile(credentials: JSON, persistCredentialDir: string) {\n    // create persist_credential_dir if not exists\n    if (!fs.existsSync(persistCredentialDir)) {\n      fs.mkdirSync(persistCredentialDir, { recursive: true });\n    }\n    // file name will be the hash of the credentials, file path is current working directory\n    // convert credentials from base64 to string and replace all the matched \"\\n\" with \"\\\\n\",  there are many \\n in the \"private_key\" property\n    const credentialString = JSON.stringify(credentials);\n    const fileName = crypto\n      .createHash('md5')\n      .update(credentialString)\n      .digest('hex');\n\n    const filePath = path.join(persistCredentialDir, `${fileName}.json`);\n    // check if file exists\n    if (fs.existsSync(filePath)) {\n      logger.debug(`File ${filePath} already exists`);\n      return filePath;\n    }\n    fs.writeFileSync(filePath, credentialString);\n    logger.debug(`Wrote credentials to file`);\n    return filePath;\n  }\n\n  public async deleteProject(projectId: number): Promise<void> {\n    await this.projectRepository.deleteOne(projectId);\n  }\n\n  public getGeneralConnectionInfo(project) {\n    return Object.entries(project.connectionInfo).reduce(\n      (acc, [key, value]) => {\n        if (!SENSITIVE_PROPERTY_NAME.has(key)) {\n          acc[key] = value;\n        }\n        return acc;\n      },\n      {},\n    );\n  }\n\n  private getProjectRecommendationQuestionsConfig(project: Project) {\n    return {\n      maxCategories: config.projectRecommendationQuestionMaxCategories,\n      maxQuestions: config.projectRecommendationQuestionsMaxQuestions,\n      regenerate: true,\n      configuration: {\n        language: WrenAILanguage[project.language] || WrenAILanguage.EN,\n      },\n    };\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/services/queryService.ts",
    "content": "import { DataSourceName } from '@server/types';\nimport { Manifest } from '@server/mdl/type';\nimport { IWrenEngineAdaptor } from '../adaptors/wrenEngineAdaptor';\nimport {\n  SupportedDataSource,\n  IIbisAdaptor,\n  IbisQueryResponse,\n  ValidationRules,\n  IbisResponse,\n} from '../adaptors/ibisAdaptor';\nimport { getLogger } from '@server/utils';\nimport { Project } from '../repositories';\nimport { PostHogTelemetry, TelemetryEvent } from '../telemetry/telemetry';\n\nconst logger = getLogger('QueryService');\nlogger.level = 'debug';\n\nexport const DEFAULT_PREVIEW_LIMIT = 500;\n\nexport interface ColumnMetadata {\n  name: string;\n  type: string;\n}\n\nexport interface PreviewDataResponse extends IbisResponse {\n  columns: ColumnMetadata[];\n  data: any[][];\n  cacheHit?: boolean;\n  cacheCreatedAt?: string;\n  cacheOverrodeAt?: string;\n  override?: boolean;\n}\n\nexport interface DescribeStatementResponse {\n  columns: ColumnMetadata[];\n}\n\nexport interface PreviewOptions {\n  project: Project;\n  modelingOnly?: boolean;\n  // if not given, will use the deployed manifest\n  manifest: Manifest;\n  limit?: number;\n  dryRun?: boolean;\n  refresh?: boolean;\n  cacheEnabled?: boolean;\n}\n\nexport interface SqlValidateOptions {\n  project: Project;\n  mdl: Manifest;\n  modelingOnly?: boolean;\n}\n\nexport interface ValidateResponse {\n  valid: boolean;\n  message?: string;\n}\n\nexport interface IQueryService {\n  preview(\n    sql: string,\n    options: PreviewOptions,\n  ): Promise<IbisResponse | PreviewDataResponse | boolean>;\n\n  describeStatement(\n    sql: string,\n    options: PreviewOptions,\n  ): Promise<DescribeStatementResponse>;\n\n  validate(\n    project: Project,\n    rule: ValidationRules,\n    manifest: Manifest,\n    parameters: Record<string, any>,\n  ): Promise<ValidateResponse>;\n}\n\nexport class QueryService implements IQueryService {\n  private readonly ibisAdaptor: IIbisAdaptor;\n  private readonly wrenEngineAdaptor: IWrenEngineAdaptor;\n  private readonly telemetry: PostHogTelemetry;\n\n  constructor({\n    ibisAdaptor,\n    wrenEngineAdaptor,\n    telemetry,\n  }: {\n    ibisAdaptor: IIbisAdaptor;\n    wrenEngineAdaptor: IWrenEngineAdaptor;\n    telemetry: PostHogTelemetry;\n  }) {\n    this.ibisAdaptor = ibisAdaptor;\n    this.wrenEngineAdaptor = wrenEngineAdaptor;\n    this.telemetry = telemetry;\n  }\n\n  public async preview(\n    sql: string,\n    options: PreviewOptions,\n  ): Promise<IbisResponse | PreviewDataResponse | boolean> {\n    const {\n      project,\n      manifest: mdl,\n      limit,\n      dryRun,\n      refresh,\n      cacheEnabled,\n    } = options;\n    const { type: dataSource, connectionInfo } = project;\n    if (this.useEngine(dataSource)) {\n      if (dryRun) {\n        logger.debug('Using wren engine to dry run');\n        await this.wrenEngineAdaptor.dryRun(sql, {\n          manifest: mdl,\n          limit,\n        });\n        return true;\n      } else {\n        logger.debug('Using wren engine to preview');\n        const data = await this.wrenEngineAdaptor.previewData(sql, mdl, limit);\n        return data as PreviewDataResponse;\n      }\n    } else {\n      this.checkDataSourceIsSupported(dataSource);\n      logger.debug('Use ibis adaptor to preview');\n      if (dryRun) {\n        return await this.ibisDryRun(sql, dataSource, connectionInfo, mdl);\n      } else {\n        return await this.ibisQuery(\n          sql,\n          dataSource,\n          connectionInfo,\n          mdl,\n          limit,\n          refresh,\n          cacheEnabled,\n        );\n      }\n    }\n  }\n\n  public async describeStatement(\n    sql: string,\n    options: PreviewOptions,\n  ): Promise<DescribeStatementResponse> {\n    try {\n      // preview data with limit 1 to get column metadata\n      options.limit = 1;\n      const res = (await this.preview(sql, options)) as PreviewDataResponse;\n      return { columns: res.columns };\n    } catch (err: any) {\n      logger.debug(`Got error when describing statement: ${err.message}`);\n      throw err;\n    }\n  }\n\n  public async validate(\n    project,\n    rule: ValidationRules,\n    manifest: Manifest,\n    parameters: Record<string, any>,\n  ): Promise<ValidateResponse> {\n    const { type: dataSource, connectionInfo } = project;\n    const res = await this.ibisAdaptor.validate(\n      dataSource,\n      rule,\n      connectionInfo,\n      manifest,\n      parameters,\n    );\n    return res;\n  }\n\n  private useEngine(dataSource: DataSourceName): boolean {\n    if (dataSource === DataSourceName.DUCKDB) {\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  private checkDataSourceIsSupported(dataSource: DataSourceName) {\n    if (\n      !Object.prototype.hasOwnProperty.call(SupportedDataSource, dataSource)\n    ) {\n      throw new Error(`Unsupported datasource for ibis: \"${dataSource}\"`);\n    }\n  }\n\n  private async ibisDryRun(\n    sql: string,\n    dataSource: DataSourceName,\n    connectionInfo: any,\n    mdl: Manifest,\n  ): Promise<IbisResponse> {\n    const event = TelemetryEvent.IBIS_DRY_RUN;\n    try {\n      const res = await this.ibisAdaptor.dryRun(sql, {\n        dataSource,\n        connectionInfo,\n        mdl,\n      });\n      this.sendIbisEvent(event, res, { dataSource, sql });\n      return {\n        correlationId: res.correlationId,\n      };\n    } catch (err: any) {\n      this.sendIbisFailedEvent(event, err, { dataSource, sql });\n      throw err;\n    }\n  }\n\n  private async ibisQuery(\n    sql: string,\n    dataSource: DataSourceName,\n    connectionInfo: any,\n    mdl: Manifest,\n    limit: number,\n    refresh?: boolean,\n    cacheEnabled?: boolean,\n  ): Promise<PreviewDataResponse> {\n    const event = TelemetryEvent.IBIS_QUERY;\n    try {\n      const res = await this.ibisAdaptor.query(sql, {\n        dataSource,\n        connectionInfo,\n        mdl,\n        limit,\n        refresh,\n        cacheEnabled,\n      });\n      this.sendIbisEvent(event, res, { dataSource, sql });\n      const data = this.transformDataType(res);\n      return {\n        correlationId: res.correlationId,\n        cacheHit: res.cacheHit,\n        cacheCreatedAt: res.cacheCreatedAt,\n        cacheOverrodeAt: res.cacheOverrodeAt,\n        override: res.override,\n        ...data,\n      };\n    } catch (err: any) {\n      this.sendIbisFailedEvent(event, err, { dataSource, sql });\n      throw err;\n    }\n  }\n\n  private transformDataType(data: IbisQueryResponse): PreviewDataResponse {\n    const columns = data.columns;\n    const dtypes = data.dtypes;\n    const transformedColumns = columns.map((column) => {\n      let type = 'unknown';\n      if (dtypes && dtypes[column]) {\n        type = dtypes[column] === 'object' ? 'string' : dtypes[column];\n      }\n      if (type === 'unknown') {\n        logger.debug(`Did not find type mapping for \"${column}\"`);\n        logger.debug(\n          `dtypes mapping: ${dtypes ? JSON.stringify(dtypes, null, 2) : 'undefined'} `,\n        );\n      }\n      return {\n        name: column,\n        type,\n      } as ColumnMetadata;\n    });\n    return {\n      columns: transformedColumns,\n      data: data.data,\n    } as PreviewDataResponse;\n  }\n\n  private sendIbisEvent(\n    event: TelemetryEvent,\n    res: IbisResponse,\n    others: Record<string, any>,\n  ) {\n    this.telemetry.sendEvent(event, {\n      correlationId: res.correlationId,\n      processTime: res.processTime,\n      ...others,\n    });\n  }\n\n  private sendIbisFailedEvent(\n    event: TelemetryEvent,\n    err: any,\n    others: Record<string, any>,\n  ) {\n    this.telemetry.sendEvent(\n      event,\n      {\n        correlationId: err.extensions?.other?.correlationId,\n        processTime: err.extensions?.other?.processTime,\n        error: err.message,\n        ...others,\n      },\n      err.extensions?.service,\n      false,\n    );\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/services/sqlPairService.ts",
    "content": "import { SqlPair } from '@server/repositories';\nimport { IWrenAIAdaptor } from '@server/adaptors/wrenAIAdaptor';\nimport { ISqlPairRepository } from '@server/repositories/sqlPairRepository';\nimport { getLogger } from '@server/utils';\nimport { chunk } from 'lodash';\nimport * as Errors from '@server/utils/error';\nimport { Project } from '../repositories';\nimport { IIbisAdaptor } from '../adaptors/ibisAdaptor';\nimport {\n  DialectSQL,\n  WrenSQL,\n  WrenAILanguage,\n  SqlPairResult,\n  SqlPairStatus,\n  QuestionsResult,\n  QuestionsStatus,\n} from '../models/adaptor';\nimport { Manifest } from '@server/mdl/type';\nimport { DataSourceName } from '@server/types';\n\nconst logger = getLogger('SqlPairService');\n\nexport interface CreateSqlPair {\n  sql: string;\n  question: string;\n}\n\nexport interface EditSqlPair {\n  sql?: string;\n  question?: string;\n}\n\nexport interface ModelSubstituteOptions {\n  project: Project;\n  // if not given, will use the deployed manifest\n  manifest: Manifest;\n}\n\nexport interface ISqlPairService {\n  getProjectSqlPairs(projectId: number): Promise<SqlPair[]>;\n  createSqlPair(projectId: number, sqlPair: CreateSqlPair): Promise<SqlPair>;\n  createSqlPairs(\n    projectId: number,\n    sqlPairs: CreateSqlPair[],\n  ): Promise<SqlPair[]>;\n  editSqlPair(\n    projectId: number,\n    sqlPairId: number,\n    sqlPair: EditSqlPair,\n  ): Promise<SqlPair>;\n  deleteSqlPair(projectId: number, sqlPairId: number): Promise<boolean>;\n  generateQuestions(project: Project, sqls: string[]): Promise<string[]>;\n  modelSubstitute(\n    sql: DialectSQL,\n    options: ModelSubstituteOptions,\n  ): Promise<WrenSQL>;\n}\n\nexport class SqlPairService implements ISqlPairService {\n  private sqlPairRepository: ISqlPairRepository;\n  private wrenAIAdaptor: IWrenAIAdaptor;\n  private ibisAdaptor: IIbisAdaptor;\n\n  constructor({\n    sqlPairRepository,\n    wrenAIAdaptor,\n    ibisAdaptor,\n  }: {\n    sqlPairRepository: ISqlPairRepository;\n    wrenAIAdaptor: IWrenAIAdaptor;\n    ibisAdaptor: IIbisAdaptor;\n  }) {\n    this.sqlPairRepository = sqlPairRepository;\n    this.wrenAIAdaptor = wrenAIAdaptor;\n    this.ibisAdaptor = ibisAdaptor;\n  }\n\n  public async modelSubstitute(\n    sql: DialectSQL,\n    options: ModelSubstituteOptions,\n  ): Promise<WrenSQL> {\n    const { manifest: mdl, project } = options;\n    const { type: dataSource, connectionInfo } = project;\n    if (dataSource === DataSourceName.DUCKDB) {\n      // engine does not implement model substitute.\n      throw Errors.create(Errors.GeneralErrorCodes.IBIS_SERVER_ERROR, {\n        customMessage: 'DuckDB data source does not support model substitute.',\n      });\n    }\n    // use the first model's table reference as default catalog and schema\n    const firstModel = mdl.models?.[0];\n    const catalog = firstModel?.tableReference?.catalog;\n    const schema = firstModel?.tableReference?.schema;\n    return await this.ibisAdaptor.modelSubstitute(sql, {\n      dataSource,\n      connectionInfo,\n      mdl,\n      catalog,\n      schema,\n    });\n  }\n\n  public async generateQuestions(\n    project: Project,\n    sqls: string[],\n  ): Promise<string[]> {\n    try {\n      const configurations = {\n        language: WrenAILanguage[project.language] || WrenAILanguage.EN,\n      };\n\n      const { queryId } = await this.wrenAIAdaptor.generateQuestions({\n        projectId: project.id,\n        configurations,\n        sqls,\n      });\n      const result = await this.waitQuestionGenerateResult(queryId);\n      if (result.error) {\n        throw Errors.create(Errors.GeneralErrorCodes.GENERATE_QUESTIONS_ERROR, {\n          customMessage: result.error.message,\n        });\n      }\n      return result.questions;\n    } catch (err) {\n      throw Errors.create(Errors.GeneralErrorCodes.GENERATE_QUESTIONS_ERROR, {\n        customMessage: err.message,\n      });\n    }\n  }\n\n  public async getProjectSqlPairs(projectId: number): Promise<SqlPair[]> {\n    return this.sqlPairRepository.findAllBy({ projectId });\n  }\n\n  public async createSqlPair(\n    projectId: number,\n    sqlPair: CreateSqlPair,\n  ): Promise<SqlPair> {\n    const tx = await this.sqlPairRepository.transaction();\n    try {\n      const newPair = await this.sqlPairRepository.createOne(\n        {\n          ...sqlPair,\n          projectId,\n        },\n        { tx },\n      );\n      const { queryId } = await this.wrenAIAdaptor.deploySqlPair(\n        projectId,\n        newPair,\n      );\n      const deployResult = await this.waitUntilSqlPairResult(queryId);\n      if (deployResult.error) {\n        throw Errors.create(deployResult.error.code, {\n          customMessage: deployResult.error.message,\n        });\n      }\n      await tx.commit();\n      return newPair;\n    } catch (error) {\n      await tx.rollback();\n      throw error;\n    }\n  }\n\n  public async createSqlPairs(\n    projectId: number,\n    sqlPairs: CreateSqlPair[],\n  ): Promise<SqlPair[]> {\n    const tx = await this.sqlPairRepository.transaction();\n    const newPairs = await this.sqlPairRepository.createMany(\n      sqlPairs.map((pair) => ({\n        ...pair,\n        projectId,\n      })),\n      { tx },\n    );\n    // batch parall process with size of 10\n    const successPairs = [];\n    const errorPairs = [];\n    const chunks = chunk(newPairs, 10);\n    for (const pairs of chunks) {\n      await Promise.allSettled(\n        pairs.map(async (pair) => {\n          const { queryId } = await this.wrenAIAdaptor.deploySqlPair(\n            projectId,\n            pair,\n          );\n          const deployResult = await this.waitUntilSqlPairResult(queryId);\n          if (deployResult.error) {\n            errorPairs.push(deployResult.error);\n          }\n          successPairs.push(deployResult);\n        }),\n      ).then(async (_result) => {\n        if (errorPairs.length > 0) {\n          logger.debug(\n            `deploy sql pair failed. ${errorPairs.map((pair) => pair.question).join(', ')}`,\n          );\n          await tx.rollback();\n          await this.wrenAIAdaptor.deleteSqlPairs(\n            projectId,\n            successPairs.map((pair) => pair.id),\n          );\n          throw Errors.create(Errors.GeneralErrorCodes.DEPLOY_SQL_PAIR_ERROR, {\n            customMessage: errorPairs.map((pair) => pair.message).join(', '),\n          });\n        }\n      });\n    }\n    await tx.commit();\n    return newPairs;\n  }\n\n  async editSqlPair(\n    projectId: number,\n    sqlPairId: number,\n    sqlPair: EditSqlPair,\n  ): Promise<SqlPair> {\n    // First verify the SQL pair exists and belongs to the project\n    const existingPair = await this.sqlPairRepository.findOneBy({\n      id: sqlPairId,\n      projectId,\n    });\n    if (!existingPair) {\n      throw new Error(\n        `SQL pair with ID ${sqlPairId} not found in project ${projectId}`,\n      );\n    }\n\n    // Update only the provided fields\n    const updatedData: Partial<SqlPair> = {\n      sql: existingPair.sql,\n      question: existingPair.question,\n      updatedAt: new Date().toISOString(),\n    };\n\n    if (sqlPair.sql !== undefined) {\n      updatedData.sql = sqlPair.sql;\n    }\n\n    if (sqlPair.question !== undefined) {\n      updatedData.question = sqlPair.question;\n    }\n    const tx = await this.sqlPairRepository.transaction();\n    try {\n      const updatedSqlPair = await this.sqlPairRepository.updateOne(\n        sqlPairId,\n        updatedData,\n        { tx },\n      );\n      const { queryId } = await this.wrenAIAdaptor.deploySqlPair(\n        projectId,\n        updatedSqlPair,\n      );\n      const deployResult = await this.waitUntilSqlPairResult(queryId);\n      if (deployResult.error) {\n        throw Errors.create(Errors.GeneralErrorCodes.DEPLOY_SQL_PAIR_ERROR, {\n          customMessage: deployResult.error.message,\n        });\n      }\n      await tx.commit();\n      return updatedSqlPair;\n    } catch (error) {\n      logger.error(`edit sql pair failed. ${error}`);\n      await tx.rollback();\n      throw Errors.create(Errors.GeneralErrorCodes.DEPLOY_SQL_PAIR_ERROR, {\n        customMessage: error.message,\n      });\n    }\n  }\n\n  async deleteSqlPair(projectId: number, sqlPairId: number): Promise<boolean> {\n    // First verify the SQL pair exists and belongs to the project\n    const existingPair = await this.sqlPairRepository.findOneBy({\n      id: sqlPairId,\n      projectId,\n    });\n\n    if (!existingPair) {\n      throw new Error(\n        `SQL pair with ID ${sqlPairId} not found in project ${projectId}`,\n      );\n    }\n    const tx = await this.sqlPairRepository.transaction();\n    try {\n      await this.sqlPairRepository.deleteOne(sqlPairId, { tx });\n      await this.wrenAIAdaptor.deleteSqlPairs(projectId, [sqlPairId]);\n      await tx.commit();\n      return true;\n    } catch (error) {\n      logger.error(`delete sql pair failed. ${error}`);\n      await tx.rollback();\n      throw Errors.create(Errors.GeneralErrorCodes.DEPLOY_SQL_PAIR_ERROR, {\n        customMessage: error.message,\n      });\n    }\n  }\n\n  private async waitUntilSqlPairResult(\n    queryId: string,\n  ): Promise<SqlPairResult> {\n    let result = await this.wrenAIAdaptor.getSqlPairResult(queryId);\n    while (!this.isFinishedState(result.status)) {\n      await new Promise((resolve) => setTimeout(resolve, 500));\n      result = await this.wrenAIAdaptor.getSqlPairResult(queryId);\n    }\n    return result;\n  }\n\n  private async waitQuestionGenerateResult(\n    queryId: string,\n  ): Promise<Partial<QuestionsResult>> {\n    let result = await this.wrenAIAdaptor.getQuestionsResult(queryId);\n    while (\n      ![QuestionsStatus.SUCCEEDED, QuestionsStatus.FAILED].includes(\n        result.status,\n      )\n    ) {\n      await new Promise((resolve) => setTimeout(resolve, 500));\n      result = await this.wrenAIAdaptor.getQuestionsResult(queryId);\n    }\n    return result;\n  }\n\n  private isFinishedState(status: SqlPairStatus) {\n    return [SqlPairStatus.FINISHED, SqlPairStatus.FAILED].includes(status);\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/services/tests/askingService.test.ts",
    "content": "import { constructCteSql } from '../askingService';\n\ndescribe('AskingService', () => {\n  describe('utility: constructCteSql', () => {\n    test('oneline sql', () => {\n      const sql = 'SELECT * FROM test';\n      const steps = [{ sql, summary: 'test', cteName: '' }];\n      const result = constructCteSql(steps);\n      expect(result).toBe(`-- test\\nSELECT * FROM test`);\n    });\n\n    test('2 steps of sql', () => {\n      const steps = [\n        {\n          sql: 'SELECT * FROM test',\n          summary: 'test1 summary',\n          cteName: 'test1',\n        },\n        { sql: 'SELECT * FROM test2', summary: 'test2', cteName: '' },\n      ];\n      const result = constructCteSql(steps);\n      expect(result).toBe(\n        `WITH test1 AS\\n-- test1 summary\\n(SELECT * FROM test)\\n-- test2\\nSELECT * FROM test2`,\n      );\n    });\n\n    test('3 steps of sql', () => {\n      const steps = [\n        {\n          sql: 'SELECT * FROM test',\n          summary: 'test1 summary',\n          cteName: 'test1',\n        },\n        {\n          sql: 'SELECT * FROM test2',\n          summary: 'test2 summary',\n          cteName: 'test2',\n        },\n        { sql: 'SELECT * FROM test3', summary: 'test3', cteName: '' },\n      ];\n      const result = constructCteSql(steps);\n      expect(result).toBe(\n        `WITH test1 AS\\n-- test1 summary\\n(SELECT * FROM test),` +\n          `test2 AS\\n-- test2 summary\\n(SELECT * FROM test2)\\n-- test3\\nSELECT * FROM test3`,\n      );\n    });\n\n    test('2 steps of sql with stepIndex=0', () => {\n      const steps = [\n        {\n          sql: 'SELECT * FROM test',\n          summary: 'test1 summary',\n          cteName: 'test1',\n        },\n        { sql: 'SELECT * FROM test2', summary: 'test2', cteName: '' },\n      ];\n      const result = constructCteSql(steps, 0);\n      expect(result).toBe(`-- test1 summary\\nSELECT * FROM test`);\n    });\n\n    test('2 steps of sql with stepIndex=1', () => {\n      const steps = [\n        {\n          sql: 'SELECT * FROM test',\n          summary: 'test1 summary',\n          cteName: 'test1',\n        },\n        { sql: 'SELECT * FROM test2', summary: 'test2', cteName: '' },\n      ];\n      const result = constructCteSql(steps, 1);\n      expect(result).toBe(\n        `WITH test1 AS\\n-- test1 summary\\n(SELECT * FROM test)\\n-- test2\\nSELECT * FROM test2`,\n      );\n    });\n\n    test('3 steps of sql with stepIndex=1', () => {\n      const steps = [\n        {\n          sql: 'SELECT * FROM test',\n          summary: 'test1 summary',\n          cteName: 'test1',\n        },\n        {\n          sql: 'SELECT * FROM test2',\n          summary: 'test2 summary',\n          cteName: 'test2',\n        },\n        { sql: 'SELECT * FROM test3', summary: 'test3', cteName: '' },\n      ];\n      const result = constructCteSql(steps, 1);\n      expect(result).toBe(\n        `WITH test1 AS\\n-- test1 summary\\n(SELECT * FROM test)` +\n          `\\n-- test2 summary\\nSELECT * FROM test2`,\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "wren-ui/src/apollo/server/services/tests/dashboardService.test.ts",
    "content": "import { DashboardService } from '../dashboardService';\nimport { ScheduleFrequencyEnum } from '@server/models/dashboard';\nimport { CacheScheduleDayEnum } from '@server/models/dashboard';\nimport {\n  SetDashboardCacheData,\n  DashboardSchedule,\n} from '@server/models/dashboard';\n\n// Create a test class that extends DashboardService to access protected methods\nclass TestDashboardService extends DashboardService {\n  public testGenerateCronExpression(\n    schedule: DashboardSchedule,\n  ): string | null {\n    return this.generateCronExpression(schedule);\n  }\n\n  public testCalculateNextRunTime(cronExpression: string): Date | null {\n    return this.calculateNextRunTime(cronExpression);\n  }\n\n  public testToUTC(schedule: DashboardSchedule): DashboardSchedule {\n    return this.toUTC(schedule);\n  }\n\n  public testToTimezone(schedule: DashboardSchedule): DashboardSchedule {\n    return this.toTimezone(schedule);\n  }\n\n  public testValidateScheduleInput(data: SetDashboardCacheData): void {\n    return this.validateScheduleInput(data);\n  }\n}\n\ndescribe('DashboardService', () => {\n  let dashboardService: TestDashboardService;\n  let mockProjectService;\n  let mockDashboardItemRepository;\n  let mockDashboardRepository;\n\n  const createScheduleData = (\n    frequency: ScheduleFrequencyEnum,\n    options: {\n      hour?: number;\n      minute?: number;\n      day?: CacheScheduleDayEnum;\n      timezone?: string;\n      cron?: string;\n      cacheEnabled?: boolean;\n    } = {},\n  ): SetDashboardCacheData => {\n    return {\n      cacheEnabled: options.cacheEnabled ?? true,\n      schedule: {\n        frequency,\n        hour: options.hour ?? 0,\n        minute: options.minute ?? 0,\n        day: options.day ?? CacheScheduleDayEnum.MON,\n        timezone: options.timezone ?? '',\n        cron: options.cron ?? '',\n      },\n    };\n  };\n\n  beforeEach(() => {\n    mockProjectService = {\n      getCurrentProject: jest.fn(),\n    };\n    mockDashboardItemRepository = {\n      findOneBy: jest.fn(),\n      findAllBy: jest.fn(),\n      createOne: jest.fn(),\n      updateOne: jest.fn(),\n      deleteOne: jest.fn(),\n    };\n    mockDashboardRepository = {\n      findOneBy: jest.fn(),\n      createOne: jest.fn(),\n      updateOne: jest.fn(),\n    };\n\n    dashboardService = new TestDashboardService({\n      projectService: mockProjectService,\n      dashboardItemRepository: mockDashboardItemRepository,\n      dashboardRepository: mockDashboardRepository,\n    });\n  });\n\n  describe('generateCronExpression', () => {\n    it('should generate correct cron expression for daily schedule', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.DAILY,\n        hour: 14,\n        minute: 30,\n        timezone: '',\n        day: null,\n        cron: null,\n      };\n\n      const result = dashboardService.testGenerateCronExpression(schedule);\n      expect(result).toBe('30 14 * * *');\n    });\n\n    it('should generate correct cron expression for weekly schedule', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.WEEKLY,\n        day: CacheScheduleDayEnum.MON,\n        hour: 9,\n        minute: 0,\n        timezone: '',\n        cron: null,\n      };\n\n      const result = dashboardService.testGenerateCronExpression(schedule);\n      expect(result).toBe('0 9 * * MON');\n    });\n\n    it('should return custom cron expression for custom schedule', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.CUSTOM,\n        cron: '0 0 * * *',\n        timezone: '',\n        day: null,\n        hour: 0,\n        minute: 0,\n      };\n\n      const result = dashboardService.testGenerateCronExpression(schedule);\n      expect(result).toBe('0 0 * * *');\n    });\n\n    it('should return null for never schedule', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.NEVER,\n        timezone: '',\n        day: null,\n        hour: 0,\n        minute: 0,\n        cron: null,\n      };\n\n      const result = dashboardService.testGenerateCronExpression(schedule);\n      expect(result).toBeNull();\n    });\n  });\n\n  describe('calculateNextRunTime', () => {\n    it('should return null for invalid cron expression', () => {\n      const result = dashboardService.testCalculateNextRunTime('invalid-cron');\n      expect(result).toBeNull();\n    });\n\n    it('should calculate next run time for daily schedule', () => {\n      const cronExpression = '0 12 * * *'; // Every day at 12:00 PM\n      const result = dashboardService.testCalculateNextRunTime(cronExpression);\n\n      const now = Date.now();\n      expect(result).toBeInstanceOf(Date);\n      expect(result!.getTime()).toBeGreaterThan(now);\n\n      // Verify the time is correct (within 1 minute of expected time)\n      const expectedTime = new Date();\n      expectedTime.setHours(12, 0, 0, 0);\n      if (expectedTime < new Date()) {\n        expectedTime.setDate(expectedTime.getDate() + 1);\n      }\n      expect(\n        Math.abs((result?.getTime() ?? 0) - expectedTime.getTime()),\n      ).toBeLessThan(60000);\n    });\n\n    it('should calculate next run time for weekly schedule', () => {\n      const cronExpression = '0 12 * * 1'; // Every Monday at 12:00 PM\n      const result = dashboardService.testCalculateNextRunTime(cronExpression);\n\n      expect(result).toBeInstanceOf(Date);\n      const now = Date.now();\n      expect(result!.getTime()).toBeGreaterThan(now);\n\n      // Verify it's a Monday\n      expect(result?.getDay()).toBe(1); // 1 represents Monday\n    });\n\n    it('should calculate next run time for custom schedule', () => {\n      const cronExpression = '0 */2 * * *'; // Every 2 hours\n      const result = dashboardService.testCalculateNextRunTime(cronExpression);\n\n      expect(result).toBeInstanceOf(Date);\n      const now = Date.now();\n      expect(result!.getTime()).toBeGreaterThan(now);\n\n      // Verify the time is in 2-hour intervals\n      const hours = result?.getHours() ?? 0;\n      expect(hours % 2).toBe(0);\n    });\n\n    it('should handle timezone conversion correctly', () => {\n      // Test with a schedule that would be affected by timezone conversion\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.DAILY,\n        timezone: 'America/New_York',\n        hour: 12,\n        minute: 0,\n        day: CacheScheduleDayEnum.MON,\n        cron: '',\n      };\n\n      const cronExpression =\n        dashboardService.testGenerateCronExpression(schedule);\n      const result = dashboardService.testCalculateNextRunTime(\n        cronExpression ?? '',\n      );\n\n      expect(result).toBeInstanceOf(Date);\n      const now = Date.now();\n      expect(result!.getTime()).toBeGreaterThan(now);\n    });\n  });\n\n  describe('toUTC', () => {\n    beforeEach(() => {\n      // Mock the current date to a fixed value for consistent testing\n      jest.useFakeTimers().setSystemTime(new Date('2024-04-22T10:00:00Z'));\n    });\n\n    afterEach(() => {\n      jest.useRealTimers();\n    });\n\n    it('should return original schedule if no timezone is specified', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.DAILY,\n        hour: 14,\n        minute: 30,\n        timezone: '',\n        day: null,\n        cron: null,\n      };\n\n      const result = dashboardService.testToUTC(schedule);\n      expect(result).toEqual(schedule);\n    });\n\n    it('should convert daily schedule from local time to UTC', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.DAILY,\n        hour: 14,\n        minute: 30,\n        timezone: 'America/New_York', // UTC-4\n        day: null,\n        cron: null,\n      };\n      const result = dashboardService.testToUTC(schedule);\n      expect(result).toEqual({\n        ...schedule,\n        hour: 18, // 14 + 4 = 18 UTC\n        minute: 30,\n      });\n    });\n\n    it('should convert weekly schedule from local time to UTC without day change', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.WEEKLY,\n        day: CacheScheduleDayEnum.MON,\n        hour: 14,\n        minute: 30,\n        timezone: 'America/New_York', // UTC-4\n        cron: null,\n      };\n\n      const result = dashboardService.testToUTC(schedule);\n      expect(result).toEqual({\n        ...schedule,\n        hour: 18, // 14 + 4 = 18 UTC\n        minute: 30,\n        day: CacheScheduleDayEnum.MON, // Same day because 18:30 UTC is still Monday\n      });\n    });\n\n    it('should adjust day forward for weekly schedule when UTC time crosses midnight', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.WEEKLY,\n        day: CacheScheduleDayEnum.MON,\n        hour: 23,\n        minute: 30,\n        timezone: 'America/New_York', // UTC-4\n        cron: null,\n      };\n\n      const result = dashboardService.testToUTC(schedule);\n      expect(result).toEqual({\n        ...schedule,\n        hour: 3, // 23 + 4 = 3 UTC (next day)\n        minute: 30,\n        day: CacheScheduleDayEnum.TUE, // Day changes to Tuesday\n      });\n    });\n\n    it('should adjust day forward from Saturday to Sunday when UTC time crosses midnight', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.WEEKLY,\n        day: CacheScheduleDayEnum.SAT,\n        hour: 23,\n        minute: 30,\n        timezone: 'America/New_York', // UTC-4\n        cron: null,\n      };\n\n      const result = dashboardService.testToUTC(schedule);\n      expect(result).toEqual({\n        ...schedule,\n        hour: 3, // 23 + 4 = 3 UTC (next day)\n        minute: 30,\n        day: CacheScheduleDayEnum.SUN, // Day wraps around from Saturday to Sunday\n      });\n    });\n\n    it('should adjust day backward for weekly schedule when UTC time is on previous day', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.WEEKLY,\n        day: CacheScheduleDayEnum.MON,\n        hour: 1,\n        minute: 30,\n        timezone: 'Asia/Tokyo', // UTC+9\n        cron: null,\n      };\n\n      const result = dashboardService.testToUTC(schedule);\n      expect(result).toEqual({\n        ...schedule,\n        hour: 16, // 1 - 9 = 16 UTC (previous day)\n        minute: 30,\n        day: CacheScheduleDayEnum.SUN, // Day changes to Sunday\n      });\n    });\n\n    it('should adjust day backward from Sunday to Saturday when UTC time crosses midnight', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.WEEKLY,\n        day: CacheScheduleDayEnum.SUN,\n        hour: 1,\n        minute: 30,\n        timezone: 'Asia/Tokyo', // UTC+9\n        cron: null,\n      };\n\n      const result = dashboardService.testToUTC(schedule);\n      expect(result).toEqual({\n        ...schedule,\n        hour: 16, // 1 - 9 = 16 UTC (previous day)\n        minute: 30,\n        day: CacheScheduleDayEnum.SAT, // Day wraps around from Sunday to Saturday\n      });\n    });\n\n    it('should handle custom schedule without timezone conversion', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.CUSTOM,\n        cron: '0 0 * * *',\n        timezone: 'America/New_York',\n        day: null,\n        hour: 0,\n        minute: 0,\n      };\n\n      const result = dashboardService.testToUTC(schedule);\n      expect(result).toEqual(schedule);\n    });\n\n    it('should handle timezone with non-hour offset (UTC+2:15)', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.DAILY,\n        hour: 14,\n        minute: 30,\n        timezone: 'Asia/Kolkata', // UTC+5:30\n        day: null,\n        cron: null,\n      };\n\n      const result = dashboardService.testToUTC(schedule);\n      expect(result).toEqual({\n        ...schedule,\n        hour: 9, // 14 - 5 = 9 UTC\n        minute: 0, // 30 - 30 = 0 UTC\n      });\n    });\n\n    it('should handle timezone with non-hour offset crossing midnight', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.WEEKLY,\n        day: CacheScheduleDayEnum.MON,\n        hour: 23,\n        minute: 45,\n        timezone: 'Asia/Kolkata', // UTC+5:30\n        cron: null,\n      };\n\n      const result = dashboardService.testToUTC(schedule);\n      expect(result).toEqual({\n        ...schedule,\n        hour: 18, // 23 - 5 = 18 UTC\n        minute: 15, // 45 - 30 = 15 UTC\n        day: CacheScheduleDayEnum.MON, // Same day because 18:15 UTC is still Monday\n      });\n    });\n  });\n\n  describe('toTimezone', () => {\n    beforeEach(() => {\n      // Mock the current date to a fixed value for consistent testing\n      jest.useFakeTimers().setSystemTime(new Date('2024-04-22T10:00:00Z'));\n    });\n\n    afterEach(() => {\n      jest.useRealTimers();\n    });\n\n    it('should return original schedule if no timezone is specified', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.DAILY,\n        hour: 14,\n        minute: 30,\n        day: null,\n        timezone: '',\n        cron: null,\n      };\n\n      const result = dashboardService.testToTimezone(schedule);\n      expect(result).toEqual(schedule);\n    });\n\n    it('should convert daily schedule from UTC to local time', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.DAILY,\n        hour: 18,\n        minute: 30,\n        day: null,\n        timezone: 'America/New_York', // UTC-4\n        cron: null,\n      };\n      const result = dashboardService.testToTimezone(schedule);\n      expect(result).toEqual({\n        ...schedule,\n        hour: 14, // 18 - 4 = 14 local time\n        minute: 30,\n      });\n    });\n\n    it('should convert weekly schedule from UTC to local time without day change', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.WEEKLY,\n        day: CacheScheduleDayEnum.MON,\n        hour: 18,\n        minute: 30,\n        timezone: 'America/New_York', // UTC-4\n        cron: null,\n      };\n\n      const result = dashboardService.testToTimezone(schedule);\n      expect(result).toEqual({\n        ...schedule,\n        hour: 14, // 18 - 4 = 14 local time\n        minute: 30,\n        day: CacheScheduleDayEnum.MON, // Same day because 14:30 local is still Monday\n      });\n    });\n\n    it('should adjust day forward for weekly schedule when local time crosses midnight', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.WEEKLY,\n        day: CacheScheduleDayEnum.MON,\n        hour: 3,\n        minute: 30,\n        timezone: 'America/New_York', // UTC-4\n        cron: null,\n      };\n\n      const result = dashboardService.testToTimezone(schedule);\n      expect(result).toEqual({\n        ...schedule,\n        hour: 23, // 3 + 4 = 23 local time (previous day)\n        minute: 30,\n        day: CacheScheduleDayEnum.SUN, // Day changes to Sunday\n      });\n    });\n\n    it('should adjust day forward from Saturday to Sunday when local time crosses midnight', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.WEEKLY,\n        day: CacheScheduleDayEnum.SAT,\n        hour: 3,\n        minute: 30,\n        timezone: 'America/New_York', // UTC-4\n        cron: null,\n      };\n\n      const result = dashboardService.testToTimezone(schedule);\n      expect(result).toEqual({\n        ...schedule,\n        hour: 23, // 3 + 4 = 23 local time (previous day)\n        minute: 30,\n        day: CacheScheduleDayEnum.FRI, // Day wraps around from Saturday to Friday\n      });\n    });\n\n    it('should adjust day backward for weekly schedule when local time is on next day', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.WEEKLY,\n        day: CacheScheduleDayEnum.MON,\n        hour: 16,\n        minute: 30,\n        timezone: 'Asia/Tokyo', // UTC+9\n        cron: null,\n      };\n\n      const result = dashboardService.testToTimezone(schedule);\n      expect(result).toEqual({\n        ...schedule,\n        hour: 1, // 16 - 9 = 1 local time (next day)\n        minute: 30,\n        day: CacheScheduleDayEnum.TUE, // Day changes to Tuesday\n      });\n    });\n\n    it('should adjust day backward from Sunday to Monday when local time crosses midnight', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.WEEKLY,\n        day: CacheScheduleDayEnum.SUN,\n        hour: 16,\n        minute: 30,\n        timezone: 'Asia/Tokyo', // UTC+9\n        cron: null,\n      };\n\n      const result = dashboardService.testToTimezone(schedule);\n      expect(result).toEqual({\n        ...schedule,\n        hour: 1, // 16 - 9 = 1 local time (next day)\n        minute: 30,\n        day: CacheScheduleDayEnum.MON, // Day wraps around from Sunday to Monday\n      });\n    });\n\n    it('should handle custom schedule without timezone conversion', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.CUSTOM,\n        minute: null,\n        hour: null,\n        day: null,\n        cron: '0 0 * * *',\n        timezone: 'America/New_York',\n      };\n\n      const result = dashboardService.testToTimezone(schedule);\n      expect(result).toEqual(schedule);\n    });\n\n    it('should handle timezone with non-hour offset (UTC+2:15)', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.DAILY,\n        hour: 9,\n        minute: 0,\n        day: null,\n        timezone: 'Asia/Kolkata', // UTC+5:30\n        cron: null,\n      };\n\n      const result = dashboardService.testToTimezone(schedule);\n      expect(result).toEqual({\n        ...schedule,\n        hour: 14, // 9 + 5 = 14 local time\n        minute: 30, // 0 + 30 = 30 local time\n      });\n    });\n\n    it('should handle timezone with non-hour offset crossing midnight', () => {\n      const schedule = {\n        frequency: ScheduleFrequencyEnum.WEEKLY,\n        day: CacheScheduleDayEnum.MON,\n        hour: 18,\n        minute: 15,\n        timezone: 'Asia/Kolkata', // UTC+5:30\n        cron: null,\n      };\n\n      const result = dashboardService.testToTimezone(schedule);\n      expect(result).toEqual({\n        ...schedule,\n        hour: 23, // 18 + 5 = 23 local time\n        minute: 45, // 15 + 30 = 45 local time\n        day: CacheScheduleDayEnum.MON, // Same day because 23:45 local is still Monday\n      });\n    });\n  });\n\n  describe('validateScheduleInput', () => {\n    it('should throw error for weekly schedule without day', () => {\n      const data = {\n        cacheEnabled: true,\n        schedule: {\n          frequency: ScheduleFrequencyEnum.WEEKLY,\n          hour: 12,\n          minute: 0,\n          timezone: '',\n          day: null,\n          cron: null,\n        },\n      };\n\n      expect(() => {\n        dashboardService.testValidateScheduleInput(data);\n      }).toThrow('Day of week is required for weekly schedule');\n    });\n\n    it('should throw error for custom schedule without cron expression', () => {\n      const data = {\n        cacheEnabled: true,\n        schedule: {\n          frequency: ScheduleFrequencyEnum.CUSTOM,\n          hour: 12,\n          minute: 0,\n          timezone: '',\n          day: null,\n          cron: null,\n        },\n      };\n\n      expect(() => {\n        dashboardService.testValidateScheduleInput(data);\n      }).toThrow('Cron expression is required for custom schedule');\n    });\n\n    it('should throw error for invalid hour', () => {\n      const data = {\n        cacheEnabled: true,\n        schedule: {\n          frequency: ScheduleFrequencyEnum.DAILY,\n          hour: 24,\n          minute: 0,\n          timezone: '',\n          day: null,\n          cron: null,\n        },\n      };\n\n      expect(() => {\n        dashboardService.testValidateScheduleInput(data);\n      }).toThrow('Hour must be between 0 and 23');\n    });\n\n    it('should throw error for invalid minute', () => {\n      const data = {\n        cacheEnabled: true,\n        schedule: {\n          frequency: ScheduleFrequencyEnum.DAILY,\n          hour: 12,\n          minute: 60,\n          timezone: '',\n          day: null,\n          cron: null,\n        },\n      };\n\n      expect(() => {\n        dashboardService.testValidateScheduleInput(data);\n      }).toThrow('Minute must be between 0 and 59');\n    });\n\n    it('should throw error for invalid timezone', () => {\n      const data = {\n        cacheEnabled: true,\n        schedule: {\n          frequency: ScheduleFrequencyEnum.DAILY,\n          hour: 12,\n          minute: 0,\n          timezone: 'Invalid/Timezone',\n          day: null,\n          cron: null,\n        },\n      };\n\n      expect(() => {\n        dashboardService.testValidateScheduleInput(data);\n      }).toThrow('Invalid timezone: Invalid/Timezone');\n    });\n\n    it('should throw error for custom schedule with interval less than 10 minutes', () => {\n      const data = {\n        cacheEnabled: true,\n        schedule: {\n          frequency: ScheduleFrequencyEnum.CUSTOM,\n          cron: '*/5 * * * *', // Every 5 minutes\n          timezone: '',\n          day: null,\n          hour: 0,\n          minute: 0,\n        },\n      };\n\n      expect(() => {\n        dashboardService.testValidateScheduleInput(data);\n      }).toThrow('Custom cron expression must be at least 10 minutes apart');\n    });\n\n    it('should not throw error for valid daily schedule', () => {\n      const data = {\n        cacheEnabled: true,\n        schedule: {\n          frequency: ScheduleFrequencyEnum.DAILY,\n          hour: 12,\n          minute: 0,\n          timezone: '',\n          day: CacheScheduleDayEnum.MON,\n          cron: '',\n        },\n      };\n\n      expect(() => {\n        dashboardService.testValidateScheduleInput(data);\n      }).not.toThrow();\n    });\n\n    it('should not throw error for valid weekly schedule', () => {\n      const data = {\n        cacheEnabled: true,\n        schedule: {\n          frequency: ScheduleFrequencyEnum.WEEKLY,\n          day: CacheScheduleDayEnum.MON,\n          hour: 12,\n          minute: 0,\n          timezone: '',\n          cron: null,\n        },\n      };\n\n      expect(() => {\n        dashboardService.testValidateScheduleInput(data);\n      }).not.toThrow();\n    });\n\n    it('should not throw error for valid custom schedule', () => {\n      const data = {\n        cacheEnabled: true,\n        schedule: {\n          frequency: ScheduleFrequencyEnum.CUSTOM,\n          cron: '0 */15 * * *', // Every 15 minutes\n          timezone: '',\n          day: null,\n          hour: 0,\n          minute: 0,\n        },\n      };\n\n      expect(() => {\n        dashboardService.testValidateScheduleInput(data);\n      }).not.toThrow();\n    });\n\n    it('should not throw error for valid schedule with timezone', () => {\n      const data = {\n        cacheEnabled: true,\n        schedule: {\n          frequency: ScheduleFrequencyEnum.DAILY,\n          hour: 12,\n          minute: 0,\n          timezone: 'America/New_York',\n          day: null,\n          cron: null,\n        },\n      };\n\n      expect(() => {\n        dashboardService.testValidateScheduleInput(data);\n      }).not.toThrow();\n    });\n  });\n\n  describe('setDashboardSchedule', () => {\n    beforeEach(() => {\n      mockDashboardRepository.findOneBy.mockReset();\n      mockDashboardRepository.updateOne.mockReset();\n    });\n\n    it('should throw error if dashboard not found', async () => {\n      mockDashboardRepository.findOneBy.mockResolvedValue(null);\n\n      const data = createScheduleData(ScheduleFrequencyEnum.DAILY, {\n        hour: 12,\n        minute: 0,\n      });\n\n      await expect(\n        dashboardService.setDashboardSchedule(1, data),\n      ).rejects.toThrow('Dashboard with id 1 not found');\n    });\n\n    it('should update dashboard with daily schedule', async () => {\n      const mockDashboard = {\n        id: 1,\n        projectId: 1,\n        name: 'Test Dashboard',\n      };\n      mockDashboardRepository.findOneBy.mockResolvedValue(mockDashboard);\n      mockDashboardRepository.updateOne.mockResolvedValue({\n        ...mockDashboard,\n        cacheEnabled: true,\n        scheduleFrequency: ScheduleFrequencyEnum.DAILY,\n        scheduleCron: '0 12 * * *',\n        nextScheduledAt: expect.any(Date),\n        scheduleTimezone: '',\n      });\n\n      const data = createScheduleData(ScheduleFrequencyEnum.DAILY, {\n        hour: 12,\n        minute: 0,\n      });\n\n      await dashboardService.setDashboardSchedule(1, data);\n\n      expect(mockDashboardRepository.updateOne).toHaveBeenCalledWith(1, {\n        cacheEnabled: true,\n        scheduleFrequency: ScheduleFrequencyEnum.DAILY,\n        scheduleCron: '0 12 * * *',\n        nextScheduledAt: expect.any(Date),\n        scheduleTimezone: '',\n      });\n    });\n\n    it('should update dashboard with weekly schedule', async () => {\n      const mockDashboard = {\n        id: 1,\n        projectId: 1,\n        name: 'Test Dashboard',\n      };\n      mockDashboardRepository.findOneBy.mockResolvedValue(mockDashboard);\n      mockDashboardRepository.updateOne.mockResolvedValue({\n        ...mockDashboard,\n        cacheEnabled: true,\n        scheduleFrequency: ScheduleFrequencyEnum.WEEKLY,\n        scheduleCron: '0 12 * * MON',\n        nextScheduledAt: expect.any(Date),\n        scheduleTimezone: '',\n      });\n\n      const data = createScheduleData(ScheduleFrequencyEnum.WEEKLY, {\n        day: CacheScheduleDayEnum.MON,\n        hour: 12,\n        minute: 0,\n      });\n\n      await dashboardService.setDashboardSchedule(1, data);\n\n      expect(mockDashboardRepository.updateOne).toHaveBeenCalledWith(1, {\n        cacheEnabled: true,\n        scheduleFrequency: ScheduleFrequencyEnum.WEEKLY,\n        scheduleCron: '0 12 * * MON',\n        nextScheduledAt: expect.any(Date),\n        scheduleTimezone: '',\n      });\n    });\n\n    it('should update dashboard with custom schedule', async () => {\n      const mockDashboard = {\n        id: 1,\n        projectId: 1,\n        name: 'Test Dashboard',\n      };\n      mockDashboardRepository.findOneBy.mockResolvedValue(mockDashboard);\n      mockDashboardRepository.updateOne.mockResolvedValue({\n        ...mockDashboard,\n        cacheEnabled: true,\n        scheduleFrequency: ScheduleFrequencyEnum.CUSTOM,\n        scheduleCron: '0 */15 * * *',\n        nextScheduledAt: expect.any(Date),\n        scheduleTimezone: '',\n      });\n\n      const data = createScheduleData(ScheduleFrequencyEnum.CUSTOM, {\n        cron: '0 */15 * * *',\n      });\n\n      await dashboardService.setDashboardSchedule(1, data);\n\n      expect(mockDashboardRepository.updateOne).toHaveBeenCalledWith(1, {\n        cacheEnabled: true,\n        scheduleFrequency: ScheduleFrequencyEnum.CUSTOM,\n        scheduleCron: '0 */15 * * *',\n        nextScheduledAt: expect.any(Date),\n        scheduleTimezone: '',\n      });\n    });\n\n    it('should update dashboard with disabled cache', async () => {\n      const mockDashboard = {\n        id: 1,\n        projectId: 1,\n        name: 'Test Dashboard',\n      };\n      mockDashboardRepository.findOneBy.mockResolvedValue(mockDashboard);\n      mockDashboardRepository.updateOne.mockResolvedValue({\n        ...mockDashboard,\n        cacheEnabled: false,\n        scheduleFrequency: null,\n        scheduleCron: null,\n        nextScheduledAt: null,\n        scheduleTimezone: null,\n      });\n\n      const data = createScheduleData(ScheduleFrequencyEnum.NEVER, {\n        cacheEnabled: false,\n      });\n\n      await dashboardService.setDashboardSchedule(1, data);\n\n      expect(mockDashboardRepository.updateOne).toHaveBeenCalledWith(1, {\n        cacheEnabled: false,\n        scheduleFrequency: null,\n        scheduleCron: null,\n        nextScheduledAt: null,\n        scheduleTimezone: null,\n      });\n    });\n\n    it('should handle timezone conversion in schedule', async () => {\n      const mockDashboard = {\n        id: 1,\n        projectId: 1,\n        name: 'Test Dashboard',\n      };\n      mockDashboardRepository.findOneBy.mockResolvedValue(mockDashboard);\n      mockDashboardRepository.updateOne.mockResolvedValue({\n        ...mockDashboard,\n        cacheEnabled: true,\n        scheduleFrequency: ScheduleFrequencyEnum.DAILY,\n        scheduleCron: '0 16 * * *', // 12:00 PM EST = 16:00 UTC\n        nextScheduledAt: expect.any(Date),\n        scheduleTimezone: 'America/New_York',\n      });\n\n      const data = createScheduleData(ScheduleFrequencyEnum.DAILY, {\n        hour: 12,\n        minute: 0,\n        timezone: 'America/New_York',\n      });\n\n      await dashboardService.setDashboardSchedule(1, data);\n\n      expect(mockDashboardRepository.updateOne).toHaveBeenCalledWith(1, {\n        cacheEnabled: true,\n        scheduleFrequency: ScheduleFrequencyEnum.DAILY,\n        scheduleCron: '0 16 * * *',\n        nextScheduledAt: expect.any(Date),\n        scheduleTimezone: 'America/New_York',\n      });\n    });\n\n    it('should handle error during update', async () => {\n      const mockDashboard = {\n        id: 1,\n        projectId: 1,\n        name: 'Test Dashboard',\n      };\n      mockDashboardRepository.findOneBy.mockResolvedValue(mockDashboard);\n      mockDashboardRepository.updateOne.mockRejectedValue(\n        new Error('Update failed'),\n      );\n\n      const data = createScheduleData(ScheduleFrequencyEnum.DAILY, {\n        hour: 12,\n        minute: 0,\n      });\n\n      await expect(\n        dashboardService.setDashboardSchedule(1, data),\n      ).rejects.toThrow('Update failed');\n    });\n  });\n});\n"
  },
  {
    "path": "wren-ui/src/apollo/server/services/tests/deployService.test.ts",
    "content": "import { DeployService } from '../deployService';\nimport { DeployStatusEnum } from '@server/repositories/deployLogRepository';\n\ndescribe('DeployService', () => {\n  let mockWrenAIAdaptor;\n\n  let mockDeployLogRepository;\n  let deployService;\n  let mockTelemetry;\n\n  beforeEach(() => {\n    mockTelemetry = { sendEvent: jest.fn() };\n    mockWrenAIAdaptor = { deploy: jest.fn() };\n    mockDeployLogRepository = {\n      findLastProjectDeployLog: jest.fn(),\n      createOne: jest.fn(),\n      updateOne: jest.fn(),\n    };\n\n    deployService = new DeployService({\n      telemetry: mockTelemetry,\n      wrenAIAdaptor: mockWrenAIAdaptor,\n      deployLogRepository: mockDeployLogRepository,\n    });\n  });\n\n  it('should successfully deploy when there is no existing deployment with the same hash', async () => {\n    const manifest = { key: 'value' };\n    const projectId = 1;\n\n    mockDeployLogRepository.findLastProjectDeployLog.mockResolvedValue(null);\n    mockWrenAIAdaptor.deploy.mockResolvedValue({ status: 'SUCCESS' });\n    mockDeployLogRepository.createOne.mockResolvedValue({ id: 123 });\n\n    const response = await deployService.deploy(manifest, projectId);\n\n    expect(response.status).toEqual(DeployStatusEnum.SUCCESS);\n    expect(mockDeployLogRepository.updateOne).toHaveBeenCalledWith(123, {\n      status: DeployStatusEnum.SUCCESS,\n      error: undefined,\n    });\n  });\n\n  it('should return failed status if ai-service deployment fails', async () => {\n    const manifest = { key: 'value' };\n    const projectId = 1;\n\n    mockDeployLogRepository.findLastProjectDeployLog.mockResolvedValue(null);\n    mockWrenAIAdaptor.deploy.mockResolvedValue({\n      status: 'FAILED',\n      error: 'AI error',\n    });\n    mockDeployLogRepository.createOne.mockResolvedValue({ id: 123 });\n\n    const response = await deployService.deploy(manifest, projectId);\n\n    expect(response.status).toEqual(DeployStatusEnum.FAILED);\n    expect(response.error).toEqual('AI error');\n  });\n\n  it('should skip deployment if an existing deployment with the same hash exists', async () => {\n    const manifest = { key: 'value' };\n    const projectId = 1;\n\n    mockDeployLogRepository.findLastProjectDeployLog.mockResolvedValue({\n      hash: deployService.createMDLHash(manifest, 1),\n    });\n\n    const response = await deployService.deploy(manifest, projectId);\n\n    expect(response.status).toEqual(DeployStatusEnum.SUCCESS);\n    expect(mockWrenAIAdaptor.deploy).not.toHaveBeenCalled();\n  });\n\n  // Add more tests here to cover other scenarios and error handling\n});\n"
  },
  {
    "path": "wren-ui/src/apollo/server/services/tests/queryService.test.ts",
    "content": "import { TelemetryEvent } from '../../telemetry/telemetry';\nimport { DataSourceName } from '../../types';\nimport { QueryService } from '../queryService';\n\ndescribe('QueryService', () => {\n  let mockIbisAdaptor;\n  let mockWrenEngineAdaptor;\n  let mockTelemetry;\n  let queryService;\n\n  beforeEach(() => {\n    mockIbisAdaptor = {\n      query: jest.fn(),\n      dryRun: jest.fn(),\n    };\n    mockWrenEngineAdaptor = {};\n    mockTelemetry = new MockTelemetry();\n\n    queryService = new QueryService({\n      ibisAdaptor: mockIbisAdaptor,\n      wrenEngineAdaptor: mockWrenEngineAdaptor,\n      telemetry: mockTelemetry,\n    });\n  });\n\n  afterEach(() => {\n    mockTelemetry.records = [];\n    jest.clearAllMocks();\n  });\n\n  it('should return true and send event when previewing via ibis dry run succeeds', async () => {\n    mockIbisAdaptor.dryRun.mockResolvedValue({\n      correlationId: '123',\n      processTime: '1s',\n    });\n\n    const res = await queryService.preview('SELECT * FROM test', {\n      project: { type: DataSourceName.POSTGRES, connectionInfo: {} },\n      manifest: {},\n      dryRun: true,\n    });\n\n    expect(res).toEqual({ correlationId: '123' });\n    expect(mockTelemetry.records).toHaveLength(1);\n    expect(mockTelemetry.records[0]).toEqual({\n      event: TelemetryEvent.IBIS_DRY_RUN,\n      properties: {\n        correlationId: '123',\n        processTime: '1s',\n        sql: 'SELECT * FROM test',\n        dataSource: DataSourceName.POSTGRES,\n      },\n      actionSuccess: true,\n    });\n  });\n\n  it('should send event when previewing via ibis dry run fails', async () => {\n    mockIbisAdaptor.dryRun.mockRejectedValue({\n      message: 'Error message',\n      extensions: {\n        other: {\n          correlationId: '123',\n          processTime: '1s',\n        },\n      },\n    });\n\n    try {\n      await queryService.preview('SELECT * FROM test', {\n        project: { type: DataSourceName.POSTGRES, connectionInfo: {} },\n        manifest: {},\n        dryRun: true,\n      });\n    } catch (e) {\n      expect(e.message).toEqual('Error message');\n      expect(e.extensions.other.correlationId).toEqual('123');\n      expect(e.extensions.other.processTime).toEqual('1s');\n    }\n\n    expect(mockTelemetry.records).toHaveLength(1);\n    expect(mockTelemetry.records[0]).toEqual({\n      event: TelemetryEvent.IBIS_DRY_RUN,\n      properties: {\n        correlationId: '123',\n        processTime: '1s',\n        sql: 'SELECT * FROM test',\n        dataSource: DataSourceName.POSTGRES,\n        error: 'Error message',\n      },\n      actionSuccess: false,\n      service: undefined,\n    });\n  });\n\n  it('should return data and send event when previewing via ibis query succeeds', async () => {\n    mockIbisAdaptor.query.mockResolvedValue({\n      data: [],\n      columns: [],\n      dtypes: [],\n      correlationId: '123',\n      processTime: '1s',\n    });\n\n    const res = await queryService.preview('SELECT * FROM test', {\n      project: { type: DataSourceName.POSTGRES, connectionInfo: {} },\n      manifest: {},\n      limit: 10,\n    });\n\n    expect(res.data).toEqual([]);\n    expect(mockTelemetry.records).toHaveLength(1);\n    expect(mockTelemetry.records[0]).toEqual({\n      event: TelemetryEvent.IBIS_QUERY,\n      properties: {\n        correlationId: '123',\n        processTime: '1s',\n        sql: 'SELECT * FROM test',\n        dataSource: DataSourceName.POSTGRES,\n      },\n      actionSuccess: true,\n    });\n  });\n\n  it('should send event when previewing via ibis query fails', async () => {\n    mockIbisAdaptor.query.mockRejectedValue({\n      message: 'Error message',\n      extensions: {\n        other: {\n          correlationId: '123',\n          processTime: '1s',\n        },\n      },\n    });\n\n    await expect(\n      queryService.preview('SELECT * FROM test', {\n        project: { type: DataSourceName.POSTGRES, connectionInfo: {} },\n        manifest: {},\n      }),\n    ).rejects.toMatchObject({\n      message: 'Error message',\n      extensions: {\n        other: {\n          correlationId: '123',\n          processTime: '1s',\n        },\n      },\n    });\n\n    expect(mockTelemetry.records).toHaveLength(1);\n    expect(mockTelemetry.records[0]).toEqual({\n      event: TelemetryEvent.IBIS_QUERY,\n      properties: {\n        correlationId: '123',\n        processTime: '1s',\n        sql: 'SELECT * FROM test',\n        dataSource: DataSourceName.POSTGRES,\n        error: 'Error message',\n      },\n      actionSuccess: false,\n      service: undefined,\n    });\n  });\n});\n\nclass MockTelemetry {\n  records: any[] = [];\n  sendEvent(\n    event: TelemetryEvent,\n    properties: Record<string, any> = {},\n    service: any,\n    actionSuccess: boolean = true,\n  ) {\n    this.records.push({ event, properties, service, actionSuccess });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/telemetry/telemetry.ts",
    "content": "import { getConfig } from '../config';\nimport { PostHog } from 'posthog-node';\nimport { v4 as uuidv4 } from 'uuid';\nimport { getLogger } from '@server/utils';\nimport { IContext } from '../types';\n\nconst logger = getLogger('TELEMETRY');\nlogger.level = 'debug';\n\nconst config = getConfig();\n\nconst {\n  userUUID,\n  telemetryEnabled,\n  wrenAIVersion,\n  generationModel,\n  wrenEngineVersion,\n  wrenUIVersion,\n  posthogApiKey,\n  posthogHost,\n} = config;\n\nexport enum TelemetryEvent {\n  // onboarding\n  CONNECTION_START_SAMPLE_DATASET = 'connection_start_sample_dataset',\n  CONNECTION_SAVE_DATA_SOURCE = 'connection_save_data_source',\n  CONNECTION_SAVE_TABLES = 'connection_save_tables',\n  CONNECTION_SAVE_RELATION = 'connection_save_relation',\n\n  // modeling page\n  MODELING_DEPLOY_MDL = 'modeling_deploy_mdl',\n  MODELING_CREATE_MODEL = 'modeling_create_model',\n  MODELING_UPDATE_MODEL = 'modeling_update_model',\n  MODELING_CREATE_CF = 'modeling_create_cf',\n  MODELING_UPDATE_CF = 'modeling_update_cf',\n  MODELING_UPDATE_MODEL_METADATA = 'modeling_update_model_metadata',\n  MODELING_UPDATE_VIEW_METADATA = 'modeling_update_view_metadata',\n  MODELING_CREATE_RELATION = 'modeling_create_relation',\n  MODELING_UPDATE_RELATION = 'modeling_update_relation',\n  // schema change\n  MODELING_DETECT_SCHEMA_CHANGE = 'modeling_detect_schema_change',\n  MODELING_RESOLVE_SCHEMA_CHANGE = 'modeling_resolve_schema_change',\n\n  HOME_UPDATE_THREAD_SUMMARY = 'update_thread_summary',\n  // ask question\n  HOME_ASK_CANDIDATE = 'home_ask_candidate',\n  HOME_CREATE_THREAD = 'home_create_thread',\n  HOME_ANSWER_QUESTION = 'home_answer_question',\n  HOME_ANSWER_QUESTION_INTERRUPTED = 'home_answer_question_interrupted',\n  HOME_ANSWER_BREAKDOWN = 'home_answer_breakdown',\n  HOME_ANSWER_CHART = 'home_answer_chart',\n  HOME_ANSWER_ADJUST_CHART = 'home_answer_adjust_chart',\n  HOME_ASK_FOLLOWUP_QUESTION = 'home_ask_followup_question',\n  HOME_CANCEL_ASK = 'home_cancel_ask',\n  HOME_RERUN_ASKING_TASK = 'home_rerun_asking_task',\n  HOME_GENERATE_PROJECT_RECOMMENDATION_QUESTIONS = 'home_generate_project_recommendation_questions',\n  HOME_GENERATE_THREAD_RECOMMENDATION_QUESTIONS = 'home_generate_thread_recommendation_questions',\n\n  // adjustment\n  HOME_ADJUST_THREAD_RESPONSE = 'home_adjust_thread_response',\n  HOME_ADJUST_THREAD_RESPONSE_CANCEL = 'home_adjust_thread_response_cancel',\n  HOME_ADJUST_THREAD_RESPONSE_RERUN = 'home_adjust_thread_response_rerun',\n  HOME_ADJUST_THREAD_RESPONSE_WITH_SQL = 'home_adjust_thread_response_with_sql',\n\n  // event after ask\n  HOME_CREATE_VIEW = 'home_create_view',\n  HOME_PREVIEW_ANSWER = 'home_preview_answer',\n\n  // settings event\n  SETTING_RESET_PROJECT = 'setting_reset_project',\n\n  // ibis event\n  IBIS_DRY_RUN = 'ibis_dry_run',\n  IBIS_QUERY = 'ibis_query',\n\n  // Default error\n  GRAPHQL_ERROR = 'graphql_error',\n\n  // Knowledge\n  KNOWLEDGE_CREATE_INSTRUCTION = 'knowledge_create_instruction',\n  KNOWLEDGE_UPDATE_INSTRUCTION = 'knowledge_update_instruction',\n  KNOWLEDGE_DELETE_INSTRUCTION = 'knowledge_delete_instruction',\n  KNOWLEDGE_CREATE_SQL_PAIR = 'knowledge_create_sql_pair',\n  KNOWLEDGE_UPDATE_SQL_PAIR = 'knowledge_update_sql_pair',\n  KNOWLEDGE_DELETE_SQL_PAIR = 'knowledge_delete_sql_pair',\n}\n\nexport enum WrenService {\n  BE = 'BE',\n  AI = 'AI',\n  ENGINE = 'ENGINE',\n  UNKNOWN = 'UNKNOWN',\n}\n\nexport interface ITelemetry {\n  sendEvent: (\n    event: TelemetryEvent,\n    properties: Record<string, any>,\n    service?: WrenService | any,\n    actionSuccess?: boolean,\n  ) => void;\n}\n\nexport class PostHogTelemetry {\n  private readonly posthog: any;\n  private readonly userId: string;\n\n  constructor() {\n    if (telemetryEnabled) {\n      if (!posthogApiKey) {\n        logger.debug('Telemetry enabled but posthogApiKey not provided.');\n        return;\n      }\n      const client = new PostHog(posthogApiKey, {\n        host: posthogHost || 'https://us.posthog.com',\n      });\n      this.posthog = client;\n      this.userId = userUUID || uuidv4();\n      logger.info(`Telemetry initialized: ${this.userId}`);\n      return;\n    }\n    logger.info('Telemetry not enabled.');\n  }\n\n  public async sendEvent(\n    event: TelemetryEvent,\n    properties: Record<string, any> = {},\n    service: WrenService | any = WrenService.UNKNOWN,\n    actionSuccess: boolean = true,\n  ) {\n    if (!this.posthog) {\n      return;\n    }\n    const eventName = actionSuccess ? `${event}_success` : `${event}_failed`;\n    try {\n      console.log('sendEvent', eventName, properties, service, actionSuccess);\n      const systemInfo = this.collectSystemInfo();\n      this.posthog.capture({\n        distinctId: this.userId,\n        event: eventName,\n        properties: {\n          ...systemInfo,\n          ...properties,\n          wren_service: service,\n        },\n      });\n    } catch (e) {\n      logger.error(e);\n    }\n  }\n\n  private collectSystemInfo(): Record<string, any> {\n    return {\n      // collect services version\n      'wren-ui-version': wrenUIVersion || null,\n      'wren-engine-version': wrenEngineVersion || null,\n      'wren-ai-service-version': wrenAIVersion || null,\n\n      // collect AI model info\n      'generation-model': generationModel || null,\n\n      // collect some system info from process module\n      node_version: process.version,\n      node_platform: process.platform,\n      node_arch: process.arch,\n      memory_usage: process.memoryUsage(),\n      cpu_usage: process.cpuUsage(),\n    };\n  }\n\n  public stop() {\n    if (this.posthog) {\n      this.posthog.shutdown();\n    }\n  }\n}\n\nexport const withTelemetry = async <T>(\n  eventName: TelemetryEvent,\n  data: any,\n  operation: () => Promise<T>,\n  ctx: IContext,\n): Promise<T> => {\n  try {\n    const result = await operation();\n    ctx.telemetry.sendEvent(eventName, { data });\n    return result;\n  } catch (err: any) {\n    ctx.telemetry.sendEvent(\n      eventName,\n      { data, error: err.message },\n      err.extensions?.service,\n      false,\n    );\n    throw err;\n  }\n};\n\nexport function TrackTelemetry(eventName: TelemetryEvent) {\n  return function (\n    _target: any,\n    _propertyKey: string,\n    descriptor: PropertyDescriptor,\n  ) {\n    const originalMethod = descriptor.value;\n\n    descriptor.value = async function (...args: [any, any, IContext]) {\n      // The last argument is typically the context in GraphQL resolvers\n      const [, , ctx] = args;\n      // Extract data using the provided extractor or use a default approach\n      const data = args[1]?.data || args[1];\n\n      try {\n        const result = await originalMethod.apply(this, args);\n        ctx.telemetry.sendEvent(eventName, { data });\n        return result;\n      } catch (err: any) {\n        ctx.telemetry.sendEvent(\n          eventName,\n          { data, error: err.message },\n          err.extensions?.service,\n          false,\n        );\n        throw err;\n      }\n    };\n\n    return descriptor;\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/types/context.ts",
    "content": "import { IConfig } from '@server/config';\nimport {\n  IIbisAdaptor,\n  IWrenAIAdaptor,\n  IWrenEngineAdaptor,\n} from '@server/adaptors';\nimport {\n  IModelColumnRepository,\n  IModelNestedColumnRepository,\n  IModelRepository,\n  IProjectRepository,\n  IRelationRepository,\n  IViewRepository,\n  ILearningRepository,\n  ISchemaChangeRepository,\n  IDeployLogRepository,\n  IDashboardRepository,\n  IDashboardItemRepository,\n  ISqlPairRepository,\n  IInstructionRepository,\n  IApiHistoryRepository,\n  IDashboardItemRefreshJobRepository,\n} from '@server/repositories';\nimport {\n  IQueryService,\n  IAskingService,\n  IDeployService,\n  IModelService,\n  IMDLService,\n  IProjectService,\n  IDashboardService,\n  IInstructionService,\n} from '@server/services';\nimport { ITelemetry } from '@server/telemetry/telemetry';\nimport {\n  ProjectRecommendQuestionBackgroundTracker,\n  ThreadRecommendQuestionBackgroundTracker,\n  DashboardCacheBackgroundTracker,\n} from '@server/backgrounds';\nimport { ISqlPairService } from '../services/sqlPairService';\n\nexport interface IContext {\n  config: IConfig;\n  // telemetry\n  telemetry: ITelemetry;\n\n  // adaptor\n  wrenEngineAdaptor: IWrenEngineAdaptor;\n  ibisServerAdaptor: IIbisAdaptor;\n  wrenAIAdaptor: IWrenAIAdaptor;\n\n  // services\n  projectService: IProjectService;\n  modelService: IModelService;\n  mdlService: IMDLService;\n  deployService: IDeployService;\n  askingService: IAskingService;\n  queryService: IQueryService;\n  dashboardService: IDashboardService;\n  sqlPairService: ISqlPairService;\n  instructionService: IInstructionService;\n\n  // repository\n  projectRepository: IProjectRepository;\n  modelRepository: IModelRepository;\n  modelColumnRepository: IModelColumnRepository;\n  modelNestedColumnRepository: IModelNestedColumnRepository;\n  relationRepository: IRelationRepository;\n  viewRepository: IViewRepository;\n  deployRepository: IDeployLogRepository;\n  schemaChangeRepository: ISchemaChangeRepository;\n  learningRepository: ILearningRepository;\n  dashboardRepository: IDashboardRepository;\n  dashboardItemRepository: IDashboardItemRepository;\n  sqlPairRepository: ISqlPairRepository;\n  instructionRepository: IInstructionRepository;\n  apiHistoryRepository: IApiHistoryRepository;\n  dashboardItemRefreshJobRepository: IDashboardItemRefreshJobRepository;\n\n  // background trackers\n  projectRecommendQuestionBackgroundTracker: ProjectRecommendQuestionBackgroundTracker;\n  threadRecommendQuestionBackgroundTracker: ThreadRecommendQuestionBackgroundTracker;\n  dashboardCacheBackgroundTracker: DashboardCacheBackgroundTracker;\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/types/dataSource.ts",
    "content": "export enum DataSourceName {\n  BIG_QUERY = 'BIG_QUERY',\n  DUCKDB = 'DUCKDB',\n  POSTGRES = 'POSTGRES',\n  MYSQL = 'MYSQL',\n  ORACLE = 'ORACLE',\n  MSSQL = 'MSSQL',\n  CLICK_HOUSE = 'CLICK_HOUSE',\n  TRINO = 'TRINO',\n  SNOWFLAKE = 'SNOWFLAKE',\n  ATHENA = 'ATHENA',\n  REDSHIFT = 'REDSHIFT',\n  DATABRICKS = 'DATABRICKS',\n}\n\nexport interface DataSource {\n  type: DataSourceName;\n  properties: DataSourceProperties;\n  sampleDataset?: string;\n}\n\nexport interface SampleDatasetData {\n  name: string;\n}\n\nexport type DataSourceProperties = { displayName: string } & Partial<\n  BigQueryDataSourceProperties &\n    DuckDBDataSourceProperties &\n    PGDataSourceProperties\n>;\n\nexport interface BigQueryDataSourceProperties {\n  displayName: string;\n  projectId: string;\n  datasetId: string;\n  credentials: JSON;\n}\n\nexport interface DuckDBDataSourceProperties {\n  displayName: string;\n  initSql: string;\n  extensions: string[];\n  configurations: Record<string, any>;\n}\n\nexport interface PGDataSourceProperties {\n  displayName: string;\n  host: string;\n  port: number;\n  database: string;\n  user: string;\n  password: string;\n  ssl?: boolean;\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/types/diagram.ts",
    "content": "import { RelationType } from '@server/types';\n\nexport enum NodeType {\n  MODEL = 'MODEL',\n  VIEW = 'VIEW',\n  RELATION = 'RELATION',\n  FIELD = 'FIELD',\n  CALCULATED_FIELD = 'CALCULATED_FIELD',\n}\n\nexport interface Diagram {\n  models: DiagramModel[];\n  views: DiagramView[];\n}\n\nexport interface DiagramView {\n  id: string;\n  viewId: number;\n  nodeType: NodeType;\n  statement: string;\n  displayName: string;\n  referenceName: string;\n  fields: DiagramViewField[];\n  description: string;\n}\n\nexport interface DiagramViewField {\n  id: string;\n  displayName: string;\n  referenceName: string;\n  type: string;\n  nodeType: NodeType;\n  description: string;\n}\n\nexport interface DiagramModel {\n  id: string;\n  modelId: number;\n  nodeType: NodeType;\n  displayName: string;\n  referenceName: string;\n  sourceTableName: string;\n  refSql?: string;\n  cached: boolean;\n  refreshTime: string;\n  description: string;\n  fields: DiagramModelField[];\n  calculatedFields: DiagramModelField[];\n  relationFields: DiagramModelRelationField[];\n}\n\nexport interface DiagramModelNestedField {\n  id: string;\n  nestedColumnId: number;\n  type: string;\n  displayName: string;\n  referenceName: string;\n  description: string;\n}\n\nexport interface DiagramModelField {\n  id: string;\n  columnId: number;\n  type: string;\n  nodeType: NodeType;\n  displayName: string;\n  referenceName: string;\n  description: string;\n  isPrimaryKey?: boolean;\n  expression?: string;\n  lineage?: string;\n  aggregation?: string;\n  nestedFields?: DiagramModelNestedField[];\n}\n\nexport interface DiagramModelRelationField {\n  id: string;\n  relationId: number;\n  type: RelationType;\n  nodeType: NodeType;\n  displayName: string;\n  referenceName: string;\n  fromModelId: number;\n  fromModelName: string;\n  fromModelDisplayName: string;\n  fromColumnId: number;\n  fromColumnName: string;\n  fromColumnDisplayName: string;\n  toModelId: number;\n  toModelName: string;\n  toModelDisplayName: string;\n  toColumnId: number;\n  toColumnName: string;\n  toColumnDisplayName: string;\n  description: string;\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/types/index.ts",
    "content": "export * from './dataSource';\nexport * from './relationship';\nexport * from './manifest';\nexport * from './diagram';\nexport * from './metric';\nexport * from './context';\n"
  },
  {
    "path": "wren-ui/src/apollo/server/types/manifest.ts",
    "content": "export interface Manifest {\n  catalog: string;\n  schema: string;\n  models: Model[];\n  relationships: Relationship[];\n  enumDefinitions: EnumDefinition[];\n  metrics: Metric[];\n  cumulativeMetrics: CumulativeMetric[];\n  views: EnumDefinition[];\n  macros: Macro[];\n  dateSpine: DateSpine;\n}\n\nexport interface CumulativeMetric {\n  name: string;\n  baseObject: string;\n  measure: Measure;\n  window: Window;\n  cached: boolean;\n  description?: string;\n  properties: CumulativeMetricProperties;\n}\n\nexport interface Measure {\n  name: string;\n  type: string;\n  operator: string;\n  refColumn: string;\n  properties?: CumulativeMetricProperties;\n}\n\nexport interface CumulativeMetricProperties {\n  description?: string;\n}\n\nexport interface Window {\n  name: string;\n  refColumn: string;\n  timeUnit: string;\n  start: Date;\n  end: Date;\n  properties: CumulativeMetricProperties;\n}\n\nexport interface DateSpine {\n  unit: string;\n  start: Date;\n  end: Date;\n  properties: CumulativeMetricProperties;\n}\n\nexport interface EnumDefinition {\n  name: string;\n  values?: Value[];\n  description: string;\n  properties: CumulativeMetricProperties;\n  statement?: string;\n}\n\nexport interface Value {\n  name: string;\n  value: string;\n  properties: CumulativeMetricProperties;\n}\n\nexport interface Macro {\n  name: string;\n  definition: string;\n  properties: CumulativeMetricProperties;\n}\n\nexport interface Metric {\n  name: string;\n  baseObject: string;\n  dimension: Dimension[];\n  measure: Dimension[];\n  timeGrain: TimeGrain[];\n  cached: boolean;\n  refreshTime: string;\n  description: string;\n  properties: CumulativeMetricProperties;\n}\n\nexport interface Dimension {\n  name: string;\n  type: string;\n  isCalculated: boolean;\n  notNull: boolean;\n  properties: DimensionProperties;\n}\n\nexport interface DimensionProperties {}\n\nexport interface TimeGrain {\n  name: string;\n  refColumn: string;\n  dateParts: string[];\n}\n\nexport interface Model {\n  name: string;\n  refSql: string;\n  columns: Column[];\n  primaryKey?: string;\n  cached: boolean;\n  refreshTime: string;\n  description?: string;\n  properties: CumulativeMetricProperties;\n}\n\nexport interface createColumnInput {\n  name: string;\n}\n\nexport interface Column {\n  name: string;\n  type: string;\n  isCalculated: boolean;\n  notNull: boolean;\n  description?: string;\n  properties: CumulativeMetricProperties;\n  relationship?: string;\n  expression?: string;\n}\n\nexport interface Relationship {\n  name: string;\n  models: string[];\n  joinType: string;\n  condition: string;\n  manySideSortKeys: ManySideSortKey[];\n  description: string;\n  properties: CumulativeMetricProperties;\n}\n\nexport interface ManySideSortKey {\n  name: string;\n  descending: boolean;\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/types/metric.ts",
    "content": "enum ModelType {\n  TABLE = 'TABLE',\n  METRIC = 'METRIC',\n}\n\nexport type CreateSimpleMetricPayload = BaseMetricPaylod & {\n  measure: SimpleMeasure[];\n  dimension: Dimension[];\n  timeGrain: TimeGrain[];\n};\n\nexport type CreateCumulativeMetricPayload = BaseMetricPaylod & {\n  measure: CumulativeMeasure[];\n  window: Window;\n};\n\ninterface BaseMetricPaylod {\n  name: string;\n  displayName: string;\n  description: string;\n  cached: boolean;\n  refreshTime?: string;\n  model: string;\n  modelType: ModelType;\n  properties: Properties;\n}\n\ninterface SimpleMeasure {\n  name: string;\n  type: string;\n  isCalculated: boolean;\n  notNull: boolean;\n  properties: Properties;\n}\n\ninterface CumulativeMeasure {\n  name: string;\n  type: string;\n  operator: string;\n  refColumn: string;\n  properties: Properties;\n}\n\ninterface Dimension {\n  name: string;\n  type: string;\n  isCalculated: boolean;\n  notNull: boolean;\n  properties: Properties;\n}\n\ninterface TimeGrain {\n  name: string;\n  refColumn: string;\n  dateParts: string[];\n}\n\ninterface Window {\n  name: string;\n  refColumn: string;\n  timeUnit: string;\n  start: string;\n  end: string;\n  properties: Properties;\n}\n\nexport interface Properties {}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/types/relationship.ts",
    "content": "export interface RelationData {\n  fromModelId: number;\n  fromColumnId: number;\n  toModelId: number;\n  toColumnId: number;\n  type: RelationType;\n  description?: string;\n}\n\nexport interface UpdateRelationData {\n  type: RelationType;\n}\n\nexport interface AnalysisRelationInfo {\n  name: string;\n  fromModelId: number;\n  fromModelReferenceName: string;\n  fromColumnId: number;\n  fromColumnReferenceName: string;\n  toModelId: number;\n  toModelReferenceName: string;\n  toColumnId: number;\n  toColumnReferenceName: string;\n  type: RelationType;\n}\n\nexport enum RelationType {\n  ONE_TO_ONE = 'ONE_TO_ONE',\n  ONE_TO_MANY = 'ONE_TO_MANY',\n  MANY_TO_ONE = 'MANY_TO_ONE',\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/apiUtils.ts",
    "content": "import { NextApiResponse } from 'next';\nimport { v4 as uuidv4 } from 'uuid';\nimport { ApiType, ApiHistory } from '@server/repositories/apiHistoryRepository';\nimport * as Errors from '@server/utils/error';\nimport { components } from '@/common';\nimport {\n  AskResult,\n  AskResultStatus,\n  AskResultType,\n  WrenAIError,\n  TextBasedAnswerResult,\n  TextBasedAnswerStatus,\n} from '@/apollo/server/models/adaptor';\n\nconst { apiHistoryRepository } = components;\n\nexport const MAX_WAIT_TIME = 1000 * 60 * 3; // 3 minutes\n\nexport const isAskResultFinished = (result: AskResult) => {\n  return (\n    result.status === AskResultStatus.FINISHED ||\n    result.status === AskResultStatus.FAILED ||\n    result.status === AskResultStatus.STOPPED ||\n    result.error\n  );\n};\n\n/**\n * Validates the AI result and throws appropriate errors for different failure cases\n * @param result The AI result to validate\n * @param taskQueryId The query ID of the task (used for explanation queries)\n * @throws ApiError if result contains errors or is of an invalid type\n */\nexport const validateAskResult = (\n  result: AskResult,\n  taskQueryId: string,\n): void => {\n  // Check for error in result\n  if (result.error) {\n    const errorMessage =\n      (result.error as WrenAIError).message || 'Unknown error';\n    const additionalData: Record<string, any> = {};\n\n    // Include invalid SQL if available\n    if (result.invalidSql) {\n      additionalData.invalidSql = result.invalidSql;\n    }\n\n    throw new ApiError(errorMessage, 400, result.error.code, additionalData);\n  }\n\n  // Check for misleading query type\n  if (result.type === AskResultType.MISLEADING_QUERY) {\n    throw new ApiError(\n      result.intentReasoning ||\n        Errors.errorMessages[Errors.GeneralErrorCodes.NON_SQL_QUERY],\n      400,\n      Errors.GeneralErrorCodes.NON_SQL_QUERY,\n    );\n  }\n\n  // Check for general type response\n  if (result.type === AskResultType.GENERAL) {\n    throw new ApiError(\n      result.intentReasoning ||\n        Errors.errorMessages[Errors.GeneralErrorCodes.NON_SQL_QUERY],\n      400,\n      Errors.GeneralErrorCodes.NON_SQL_QUERY,\n      { explanationQueryId: taskQueryId },\n    );\n  }\n};\n\n/**\n * Validates the summary generation result and checks for errors\n * @param result The summary result to validate\n * @throws ApiError if the result has errors or is in a failed state\n */\nexport const validateSummaryResult = (result: TextBasedAnswerResult): void => {\n  // Check for errors or failed status\n  if (result.status === TextBasedAnswerStatus.FAILED || result.error) {\n    throw new ApiError(\n      result.error?.message || 'Failed to generate summary',\n      400,\n      Errors.GeneralErrorCodes.INTERNAL_SERVER_ERROR,\n    );\n  }\n\n  // Verify that the status is succeeded\n  if (result.status !== TextBasedAnswerStatus.SUCCEEDED) {\n    throw new ApiError('Summary generation is still in progress', 500);\n  }\n};\n\nexport const transformHistoryInput = (histories: ApiHistory[]) => {\n  if (!histories) {\n    return [];\n  }\n\n  const validApiTypes = [\n    ApiType.GENERATE_SQL,\n    ApiType.ASK,\n    ApiType.STREAM_GENERATE_SQL,\n    ApiType.STREAM_ASK,\n  ];\n\n  return histories\n    .filter(\n      (history) =>\n        validApiTypes.includes(history.apiType) &&\n        history.responsePayload?.sql &&\n        history.requestPayload?.question,\n    )\n    .map((history) => ({\n      question: history.requestPayload?.question,\n      sql: history.responsePayload?.sql,\n    }));\n};\n\n/**\n * Validates SQL syntax and compatibility with the project's manifest.\n * Throws an ApiError if the SQL is invalid or cannot be previewed.\n * @param sql The SQL string to validate\n * @param project The project object (must have id)\n * @param deployService The deployment service instance\n * @param queryService The query service instance\n */\nexport const validateSql = async (\n  sql: string,\n  project: any,\n  deployService: any,\n  queryService: any,\n) => {\n  const lastDeployment = await deployService.getLastDeployment(project.id);\n  const manifest = lastDeployment.manifest;\n  try {\n    await queryService.preview(sql, {\n      manifest,\n      project,\n      dryRun: true,\n    });\n  } catch (err: any) {\n    throw new ApiError(\n      err.message || 'Invalid SQL',\n      400,\n      Errors.GeneralErrorCodes.INVALID_SQL_ERROR,\n    );\n  }\n};\n\n/**\n * Common error class for API endpoints\n */\nexport class ApiError extends Error {\n  statusCode: number;\n  code?: Errors.GeneralErrorCodes;\n  additionalData?: Record<string, any>;\n\n  constructor(\n    message: string,\n    statusCode: number,\n    code?: Errors.GeneralErrorCodes,\n    additionalData?: Record<string, any>,\n  ) {\n    super(message);\n    this.statusCode = statusCode;\n    this.code = code;\n    this.additionalData = additionalData;\n  }\n}\n\n/**\n * Common response handler for API endpoints that also logs to API history\n */\nexport const respondWith = async ({\n  res,\n  statusCode,\n  responsePayload,\n  projectId,\n  apiType,\n  threadId,\n  headers,\n  requestPayload,\n  startTime,\n}: {\n  res: NextApiResponse;\n  statusCode: number;\n  responsePayload: any;\n  projectId: number;\n  apiType: ApiType;\n  startTime: number;\n  requestPayload?: Record<string, any>;\n  threadId?: string;\n  headers?: Record<string, string>;\n}) => {\n  const durationMs = startTime ? Date.now() - startTime : undefined;\n  const responseId = uuidv4();\n  await apiHistoryRepository.createOne({\n    id: responseId,\n    projectId,\n    apiType,\n    threadId,\n    headers,\n    requestPayload,\n    responsePayload,\n    statusCode,\n    durationMs,\n  });\n\n  return res.status(statusCode).json({\n    id: responseId,\n    ...responsePayload,\n  });\n};\n\n/**\n * Simple response handler for API endpoints that don't need responseId or threadId\n * Used for simple CRUD operations like instructions\n */\nexport const respondWithSimple = async ({\n  res,\n  statusCode,\n  responsePayload,\n  projectId,\n  apiType,\n  headers,\n  requestPayload,\n  startTime,\n}: {\n  res: NextApiResponse;\n  statusCode: number;\n  responsePayload: any;\n  projectId: number;\n  apiType: ApiType;\n  startTime: number;\n  requestPayload?: Record<string, any>;\n  headers?: Record<string, string>;\n}) => {\n  const durationMs = startTime ? Date.now() - startTime : undefined;\n  const responseId = uuidv4();\n  await apiHistoryRepository.createOne({\n    id: responseId,\n    projectId,\n    apiType,\n    headers,\n    requestPayload,\n    responsePayload,\n    statusCode,\n    durationMs,\n  });\n\n  return res.status(statusCode).json(responsePayload);\n};\n\n/**\n * Common error handler for API endpoints\n */\nexport const handleApiError = async ({\n  error,\n  res,\n  projectId,\n  apiType,\n  requestPayload,\n  threadId,\n  headers,\n  startTime,\n  logger,\n}: {\n  error: any;\n  res: NextApiResponse;\n  projectId?: number;\n  apiType: ApiType;\n  requestPayload?: Record<string, any>;\n  threadId?: string;\n  headers?: Record<string, string>;\n  startTime: number;\n  logger?: any;\n}) => {\n  if (logger) {\n    logger.error(`Error in ${apiType} API:`, error);\n  }\n\n  const statusCode = error instanceof ApiError ? error.statusCode : 500;\n  let responsePayload: Record<string, any>;\n\n  if (error instanceof ApiError && error.code) {\n    responsePayload = {\n      code: error.code,\n      error: error.message,\n    };\n\n    // Include any additional data associated with the error\n    if (error.additionalData) {\n      Object.assign(responsePayload, error.additionalData);\n    }\n  } else {\n    responsePayload = { error: error.message };\n  }\n\n  await respondWith({\n    res,\n    statusCode,\n    responsePayload,\n    projectId: projectId || 0,\n    apiType,\n    startTime,\n    requestPayload,\n    threadId,\n    headers,\n  });\n};\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/dataUtils.ts",
    "content": "import { ColumnMetadata } from '@server/services/queryService';\n\n/**\n * Transform raw data (columns + rows) into an array of objects\n * @param columns Column metadata (name, type)\n * @param rows Raw data rows\n * @returns Array of objects with column names as keys\n */\nexport const transformToObjects = (\n  columns: ColumnMetadata[],\n  rows: any[][],\n): Record<string, any>[] => {\n  if (!rows || !columns || rows.length === 0 || columns.length === 0) {\n    return [];\n  }\n\n  // throw an error if the number of columns in the rows does not match the number of columns in the columns array\n  if (rows[0].length !== columns.length) {\n    throw new Error(\n      'Number of columns in the rows does not match the number of columns in the columns array',\n    );\n  }\n\n  return rows.map((row) => {\n    const obj: Record<string, any> = {};\n    columns.forEach((col, index) => {\n      obj[col.name] = row[index];\n    });\n    return obj;\n  });\n};\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/docker.ts",
    "content": "export const toDockerHost = (host: string) => {\n  // if host is localhost or 127.0.0.1, rewrite it to docker.for.{platform}.localhost\n  if (host === 'localhost' || host === '127.0.0.1') {\n    const platform = process.platform;\n    switch (platform) {\n      case 'darwin':\n        return 'docker.for.mac.localhost';\n      case 'linux':\n        return 'docker.for.linux.localhost';\n      default:\n        // windows and others...\n        return 'host.docker.internal';\n    }\n  }\n  return host;\n};\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/encode.ts",
    "content": "export function toBase64(str: string): string {\n  return Buffer.from(str).toString('base64');\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/encryptor.ts",
    "content": "import crypto from 'crypto';\n\nexport interface encryptOptions {\n  password: string;\n  salt: string;\n  iteration?: number;\n  keyLength?: number;\n  algorithm?: string;\n  separator?: string;\n}\n\nexport class Encryptor {\n  private readonly ENCRYPTION_PASSWORD: string;\n  private readonly ENCRYPTION_SALT: string;\n  private ENCRYPTION_ITERATION = 1000;\n  private ENCRYPTION_KEY_LENGTH = 256 / 8; // in bytes\n  private ENCRYPTION_ALGORITHM = 'aes-256-cbc';\n  private ENCRYPTION_SEPARATOR = ':';\n\n  constructor({\n    encryptionPassword,\n    encryptionSalt,\n  }: {\n    encryptionPassword: string;\n    encryptionSalt: string;\n  }) {\n    this.ENCRYPTION_PASSWORD = encryptionPassword;\n    this.ENCRYPTION_SALT = encryptionSalt;\n  }\n\n  public encrypt(credentials: JSON) {\n    const credentialsString = JSON.stringify(credentials);\n    const key = this.createSecretKey();\n    const iv = crypto.randomBytes(16); // AES block size\n    const cipher = crypto.createCipheriv(this.ENCRYPTION_ALGORITHM, key, iv);\n    const encrypted = Buffer.concat([\n      cipher.update(credentialsString, 'utf8'),\n      cipher.final(),\n    ]);\n    return (\n      iv.toString('base64') +\n      this.ENCRYPTION_SEPARATOR +\n      encrypted.toString('base64')\n    );\n  }\n\n  public decrypt(encryptedText: string) {\n    const [ivBase64, encryptedBase64] = encryptedText.split(\n      this.ENCRYPTION_SEPARATOR,\n    );\n    const iv = Buffer.from(ivBase64, 'base64');\n    const encrypted = Buffer.from(encryptedBase64, 'base64');\n    const key = this.createSecretKey();\n    const decipher = crypto.createDecipheriv(\n      this.ENCRYPTION_ALGORITHM,\n      key,\n      iv,\n    );\n    const decrypted = Buffer.concat([\n      decipher.update(encrypted),\n      decipher.final(),\n    ]);\n    return decrypted.toString('utf8');\n  }\n\n  private createSecretKey() {\n    return crypto.pbkdf2Sync(\n      this.ENCRYPTION_PASSWORD,\n      this.ENCRYPTION_SALT,\n      this.ENCRYPTION_ITERATION,\n      this.ENCRYPTION_KEY_LENGTH,\n      'sha512',\n    );\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/error.ts",
    "content": "import { GraphQLError } from 'graphql';\nimport { WrenService } from '../telemetry/telemetry';\n\nexport enum GeneralErrorCodes {\n  INTERNAL_SERVER_ERROR = 'INTERNAL_SERVER_ERROR',\n  // AI service errors\n  NO_RELEVANT_DATA = 'NO_RELEVANT_DATA',\n  NO_RELEVANT_SQL = 'NO_RELEVANT_SQL',\n  RESOURCE_NOT_FOUND = 'RESOURCE_NOT_FOUND',\n  MDL_PARSE_ERROR = 'MDL_PARSE_ERROR',\n  NO_CHART = 'NO_CHART',\n\n  // Exception error for AI service (e.g., network connection error)\n  AI_SERVICE_UNDEFINED_ERROR = 'OTHERS',\n\n  // IBIS Error\n  IBIS_SERVER_ERROR = 'IBIS_SERVER_ERROR',\n\n  // Connector errors\n  CONNECTION_ERROR = 'CONNECTION_ERROR',\n  // duckdb\n  INIT_SQL_ERROR = 'INIT_SQL_ERROR',\n  SESSION_PROPS_ERROR = 'SESSION_PROPS_ERROR',\n  // postgres\n  CONNECTION_REFUSED = 'CONNECTION_REFUSED',\n\n  // calculated field validation\n  DUPLICATED_FIELD_NAME = 'DUPLICATED_FIELD_NAME',\n  INVALID_EXPRESSION = 'INVALID_EXPRESSION',\n  INVALID_CALCULATED_FIELD = 'INVALID_CALCULATED_FIELD',\n\n  // when createing views\n  INVALID_VIEW_CREATION = 'INVALID_VIEW_CREATION',\n\n  // dry run error\n  DRY_RUN_ERROR = 'DRY_RUN_ERROR',\n  DRY_PLAN_ERROR = 'DRY_PLAN_ERROR',\n\n  // deploy sql pair error\n  DEPLOY_SQL_PAIR_ERROR = 'DEPLOY_SQL_PAIR_ERROR',\n  GENERATE_QUESTIONS_ERROR = 'GENERATE_QUESTIONS_ERROR',\n  INVALID_SQL_ERROR = 'INVALID_SQL_ERROR',\n\n  // wren engine error\n  WREN_ENGINE_ERROR = 'WREN_ENGINE_ERROR',\n\n  // asking task error\n  // when rerun from cancelled, the task is identified as general or misleading query\n  IDENTIED_AS_GENERAL = 'IDENTIED_AS_GENERAL',\n  IDENTIED_AS_MISLEADING_QUERY = 'IDENTIED_AS_MISLEADING_QUERY',\n  DEPLOY_TIMEOUT_ERROR = 'DEPLOY_TIMEOUT_ERROR',\n\n  // api error\n  NON_SQL_QUERY = 'NON_SQL_QUERY',\n  NO_DEPLOYMENT_FOUND = 'NO_DEPLOYMENT_FOUND',\n\n  // vega schema error\n  FAILED_TO_GENERATE_VEGA_SCHEMA = 'FAILED_TO_GENERATE_VEGA_SCHEMA',\n  POLLING_TIMEOUT = 'POLLING_TIMEOUT',\n\n  // sql execution error\n  SQL_EXECUTION_ERROR = 'SQL_EXECUTION_ERROR',\n}\n\nexport const errorMessages = {\n  [GeneralErrorCodes.INTERNAL_SERVER_ERROR]: 'Internal server error',\n\n  // AI service errors\n  [GeneralErrorCodes.NO_RELEVANT_DATA]:\n    \"I can't find the exact data you're looking for, but feel free to ask about other available topics.\",\n  [GeneralErrorCodes.NO_RELEVANT_SQL]:\n    \"Could you please provide more details or specify the information you're seeking?\",\n  [GeneralErrorCodes.NO_CHART]:\n    \"The chart couldn't be generated this time. Please try regenerating the chart or rephrasing your question for better results.\",\n\n  // Connector errors\n  [GeneralErrorCodes.CONNECTION_ERROR]: 'Can not connect to data source',\n  // duckdb\n  [GeneralErrorCodes.INIT_SQL_ERROR]:\n    'The initializing SQL seems to be invalid, Please check your SQL and try again.',\n  [GeneralErrorCodes.SESSION_PROPS_ERROR]:\n    'The session properties seem to be invalid, Please check your session properties and try again.',\n  // postgres\n  [GeneralErrorCodes.CONNECTION_REFUSED]:\n    'Connection refused by the server, Please check your connection settings and try again.',\n\n  // ibis service errors\n  [GeneralErrorCodes.IBIS_SERVER_ERROR]:\n    'Error occurred while querying ibis server, please try again later.',\n\n  // calculated field validation\n  [GeneralErrorCodes.DUPLICATED_FIELD_NAME]: 'This field name already exists',\n  [GeneralErrorCodes.INVALID_EXPRESSION]:\n    'Invalid expression, please check your expression and try again.',\n  [GeneralErrorCodes.INVALID_CALCULATED_FIELD]:\n    'Can not execute a query when using this calculated field',\n\n  // when createing views\n  [GeneralErrorCodes.INVALID_VIEW_CREATION]: 'Invalid view creation',\n\n  // dry run error\n  [GeneralErrorCodes.DRY_RUN_ERROR]: 'Dry run sql statement error',\n  [GeneralErrorCodes.DRY_PLAN_ERROR]: 'Dry plan error',\n\n  // deploy sql pair error\n  [GeneralErrorCodes.DEPLOY_SQL_PAIR_ERROR]: 'Deploy sql pair error',\n  [GeneralErrorCodes.GENERATE_QUESTIONS_ERROR]: 'Generate questions error',\n  [GeneralErrorCodes.INVALID_SQL_ERROR]:\n    'Invalid SQL, please check your SQL syntax',\n\n  // asking task error\n  [GeneralErrorCodes.IDENTIED_AS_GENERAL]:\n    'The question is identified as a general question, please follow-up ask with more specific questions.',\n  [GeneralErrorCodes.IDENTIED_AS_MISLEADING_QUERY]:\n    'The question is identified as a misleading query, please follow-up ask with more specific questions.',\n  [GeneralErrorCodes.DEPLOY_TIMEOUT_ERROR]:\n    'LLM deployment timed out after 30 seconds',\n\n  // api error\n  [GeneralErrorCodes.NON_SQL_QUERY]: 'Cannot generate SQL from this question.',\n  [GeneralErrorCodes.NO_DEPLOYMENT_FOUND]:\n    'No deployment found, please deploy your project first',\n\n  // vega schema error\n  [GeneralErrorCodes.FAILED_TO_GENERATE_VEGA_SCHEMA]:\n    'Failed to generate Vega spec',\n  [GeneralErrorCodes.POLLING_TIMEOUT]: 'Polling timeout',\n\n  // sql execution error\n  [GeneralErrorCodes.SQL_EXECUTION_ERROR]: 'SQL execution error',\n};\n\nexport const shortMessages = {\n  [GeneralErrorCodes.INTERNAL_SERVER_ERROR]: 'Internal server error',\n  [GeneralErrorCodes.NO_RELEVANT_DATA]: 'Try a different query',\n  [GeneralErrorCodes.NO_RELEVANT_SQL]: 'Clarification needed',\n  [GeneralErrorCodes.NO_CHART]: 'Chart not available',\n  [GeneralErrorCodes.CONNECTION_ERROR]: 'Failed to connect',\n  [GeneralErrorCodes.IBIS_SERVER_ERROR]: 'Data connection error',\n  [GeneralErrorCodes.INIT_SQL_ERROR]: 'Invalid initializing SQL',\n  [GeneralErrorCodes.SESSION_PROPS_ERROR]: 'Invalid session properties',\n  [GeneralErrorCodes.CONNECTION_REFUSED]: 'Connection refused',\n  [GeneralErrorCodes.DUPLICATED_FIELD_NAME]: 'Duplicated field name',\n  [GeneralErrorCodes.INVALID_EXPRESSION]: 'Invalid expression',\n  [GeneralErrorCodes.INVALID_CALCULATED_FIELD]: 'Invalid calculated field',\n  [GeneralErrorCodes.INVALID_VIEW_CREATION]: 'Invalid view creation',\n  [GeneralErrorCodes.DRY_RUN_ERROR]: 'Dry run sql statement error',\n  [GeneralErrorCodes.DRY_PLAN_ERROR]: 'Dry plan error',\n  [GeneralErrorCodes.DEPLOY_SQL_PAIR_ERROR]: 'Deploy sql pair error',\n  [GeneralErrorCodes.GENERATE_QUESTIONS_ERROR]: 'Generate questions error',\n  [GeneralErrorCodes.INVALID_SQL_ERROR]:\n    'Invalid SQL, please check your SQL syntax',\n  [GeneralErrorCodes.IDENTIED_AS_GENERAL]: 'Identified as general question',\n  [GeneralErrorCodes.IDENTIED_AS_MISLEADING_QUERY]:\n    'Identified as misleading query',\n  [GeneralErrorCodes.DEPLOY_TIMEOUT_ERROR]: 'LLM deployment timed out',\n  [GeneralErrorCodes.NON_SQL_QUERY]: 'Cannot generate SQL from this question.',\n  [GeneralErrorCodes.NO_DEPLOYMENT_FOUND]:\n    'No deployment found, please deploy your project first',\n  [GeneralErrorCodes.FAILED_TO_GENERATE_VEGA_SCHEMA]:\n    'Failed to generate Vega spec',\n  [GeneralErrorCodes.POLLING_TIMEOUT]: 'Polling timeout',\n  [GeneralErrorCodes.SQL_EXECUTION_ERROR]: 'SQL execution error',\n};\n\nexport const create = (\n  code?: GeneralErrorCodes,\n  options?: {\n    customMessage?: string;\n    originalError?: Error;\n    service?: WrenService;\n    other?: any;\n  },\n): GraphQLError => {\n  const { customMessage, originalError, service } = options || {};\n  // Default to INTERNAL_SERVER_ERROR if no code is provided\n  code = code || GeneralErrorCodes.INTERNAL_SERVER_ERROR;\n\n  // Get the error message based on the code\n  const message =\n    customMessage ||\n    originalError?.message ||\n    errorMessages[code] ||\n    errorMessages[GeneralErrorCodes.INTERNAL_SERVER_ERROR];\n\n  // Return the GraphQLError\n  const err = new GraphQLError(message, {\n    extensions: {\n      originalError,\n      code,\n      message,\n      service,\n      shortMessage:\n        shortMessages[code] ||\n        shortMessages[GeneralErrorCodes.INTERNAL_SERVER_ERROR],\n      other: options?.other,\n    },\n  });\n\n  return err;\n};\n\n/**\n * Default error handler for Apollo Server\n * For error like this:\n * [GraphQLError: connect ECONNREFUSED 127.0.0.1:8080] {\n *   locations: [ { line: 2, column: 3 } ],\n *   path: [ 'previewData' ],\n *   extensions: {\n *     code: 'INTERNAL_SERVER_ERROR',\n *     exception: {\n *       port: 8080,\n *       address: '127.0.0.1',\n *       syscall: 'connect',\n *       code: 'ECONNREFUSED',\n *       errno: -61,\n *       message: 'connect ECONNREFUSED 127.0.0.1:8080',\n *       stack: 'Error: connect ECONNREFUSED 127.0.0.1:8080\\n' +\n *         '    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1278:16)',\n *       name: 'Error',\n *       config: [Object],\n *       request: [Writable],\n *       stacktrace: [Array]\n *     }\n *   }\n * }\n * it will easily cause `Converting circular structure to JSON` error.\n * Thus, we only pick required fields to reformat the error.\n */\nexport const defaultApolloErrorHandler = (error: GraphQLError) => {\n  if (error instanceof GraphQLError) {\n    const code = (error.extensions?.code ||\n      GeneralErrorCodes.INTERNAL_SERVER_ERROR) as GeneralErrorCodes;\n    return {\n      locations: error.locations,\n      path: error.path,\n      message: error.message,\n      extensions: {\n        code,\n        message: error.message,\n        shortMessage: shortMessages[code],\n        stacktrace: error.extensions?.exception?.stacktrace,\n        other: error.extensions?.other,\n      },\n    };\n  }\n\n  // Return the original error if it's not a GraphQLError\n  return error;\n};\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/helper.ts",
    "content": "/**\n * @function\n * @description Retrieve json without error\n */\nexport const safeParseJson = (data) => {\n  try {\n    return JSON.parse(data);\n  } catch (_e) {\n    return false;\n  }\n};\n\nexport const safeStringify = (data) => {\n  if (typeof data === 'string') {\n    return data;\n  }\n  try {\n    return JSON.stringify(data);\n  } catch (_e) {\n    return data;\n  }\n};\n\nexport const convertColumnType = (parent: { type: string }) => {\n  return parent.type.includes('STRUCT') ? 'RECORD' : parent.type;\n};\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/index.ts",
    "content": "export * from './logger';\nexport * from './encryptor';\nexport * from './encode';\nexport * from './string';\nexport * from './docker';\nexport * from './model';\nexport * from './helper';\nexport * from './regex';\nexport * from './sseTypes';\nexport * from './sseUtils';\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/knex.ts",
    "content": "interface KnexOptions {\n  dbType: string;\n  pgUrl?: string;\n  debug?: boolean;\n  sqliteFile?: string;\n}\n\nexport const bootstrapKnex = (options: KnexOptions) => {\n  if (options.dbType === 'pg') {\n    const { pgUrl, debug } = options;\n    console.log('using pg');\n    /* eslint-disable @typescript-eslint/no-var-requires */\n    return require('knex')({\n      client: 'pg',\n      connection: pgUrl,\n      debug,\n      pool: { min: 2, max: 10 },\n    });\n  } else {\n    console.log('using sqlite');\n    /* eslint-disable @typescript-eslint/no-var-requires */\n    return require('knex')({\n      client: 'better-sqlite3',\n      connection: {\n        filename: options.sqliteFile,\n      },\n      useNullAsDefault: true,\n    });\n  }\n};\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/logger.ts",
    "content": "export { getLogger } from 'log4js';\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/model.ts",
    "content": "import {\n  IModelColumnRepository,\n  ModelColumn,\n  ModelNestedColumn,\n} from '@server/repositories';\nimport { replaceAllowableSyntax } from './regex';\nimport { CompactColumn } from '@server/services/metadataService';\n\nexport function getPreviewColumnsStr(modelColumns: ModelColumn[]) {\n  if (modelColumns.length === 0) return '*';\n  const columns = modelColumns.map((column) => `\"${column.referenceName}\"`);\n  return columns.join(',');\n}\n\nexport function transformInvalidColumnName(columnName: string) {\n  let referenceName = replaceAllowableSyntax(columnName);\n  // If the reference name does not start with a letter, add a prefix\n  const startWithLetterRegex = /^[A-Za-z]/;\n  if (!startWithLetterRegex.test(referenceName)) {\n    referenceName = `col_${referenceName}`;\n  }\n  return referenceName;\n}\n\nexport function replaceInvalidReferenceName(referenceName: string) {\n  // replace dot with underscore\n  return referenceName.replace(/\\./g, '_');\n}\n\nexport function findColumnsToUpdate(\n  columns: string[],\n  existingColumns: ModelColumn[],\n  sourceTableColumns: CompactColumn[],\n): {\n  toDeleteColumnIds: number[];\n  toCreateColumns: string[];\n  toUpdateColumns: Array<{\n    id: number;\n    sourceColumnName: string;\n    type: string;\n  }>;\n} {\n  const toDeleteColumnIds = existingColumns\n    .map(({ id, sourceColumnName }) => {\n      const shouldKeep = columns.includes(sourceColumnName);\n      return shouldKeep ? undefined : id;\n    })\n    .filter((id) => id);\n  const existColumnNames = existingColumns.map(\n    ({ sourceColumnName }) => sourceColumnName,\n  );\n  const toCreateColumns = columns.filter(\n    (columnName) => !existColumnNames.includes(columnName),\n  );\n\n  const toUpdateColumns = sourceTableColumns.reduce((acc, sourceColumn) => {\n    const existingColumn = existingColumns.find(\n      (col) => col.sourceColumnName === sourceColumn.name,\n    );\n    if (!existingColumn) return acc;\n\n    const columnName = columns.find((col) => col === sourceColumn.name);\n    if (!columnName) return acc;\n\n    if (sourceColumn.type === existingColumn.type) return acc;\n\n    return [\n      ...acc,\n      {\n        id: existingColumn.id,\n        sourceColumnName: sourceColumn.name,\n        type: sourceColumn.type || 'string',\n      },\n    ];\n  }, []);\n\n  return {\n    toDeleteColumnIds,\n    toCreateColumns,\n    toUpdateColumns,\n  };\n}\n\nexport async function updateModelPrimaryKey(\n  repository: IModelColumnRepository,\n  modelId: number,\n  primaryKey: string,\n) {\n  await repository.resetModelPrimaryKey(modelId);\n  if (primaryKey) {\n    await repository.setModelPrimaryKey(modelId, primaryKey);\n  }\n}\n\nexport function handleNestedColumns(\n  column: CompactColumn,\n  parent: {\n    modelId: number;\n    columnId: number;\n    sourceColumnName: string;\n    columnPath?: string[];\n  },\n): Partial<ModelNestedColumn>[] {\n  if (!column.nestedColumns) return [];\n\n  const nestedColumnValues = [];\n  for (const nestedColumn of column.nestedColumns) {\n    const parentColumnPath = (parent as Partial<ModelNestedColumn>)\n      .columnPath || [parent.sourceColumnName];\n    const name = nestedColumn.name.split(`${parent.sourceColumnName}.`)[1];\n    const columnPath = [...parentColumnPath, name];\n    const nestedColumnValue = {\n      modelId: parent.modelId,\n      columnId: parent.columnId,\n      columnPath,\n      displayName: nestedColumn.name,\n      sourceColumnName: nestedColumn.name,\n      referenceName: columnPath.map(transformInvalidColumnName).join('.'),\n      type: nestedColumn.type || 'string',\n      properties: nestedColumn.properties,\n    } as Partial<ModelNestedColumn>;\n    nestedColumnValues.push(nestedColumnValue);\n    nestedColumnValues.push(\n      ...handleNestedColumns(nestedColumn, {\n        modelId: parent.modelId,\n        columnId: parent.columnId,\n        sourceColumnName: nestedColumn.name,\n        columnPath,\n      }),\n    );\n  }\n  return nestedColumnValues;\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/regex.ts",
    "content": "export interface ValidationResult {\n  valid: boolean;\n  message: string | null;\n}\n\nexport function validateDisplayName(displayName: string): ValidationResult {\n  let message = null;\n  let valid = true;\n\n  const allowableSyntaxRegex = /^[A-Za-z0-9 !@#$%^&*()_+{}[\\],.'\"-]*$/;\n  const syntaxValid = allowableSyntaxRegex.test(displayName);\n  if (!syntaxValid) {\n    valid = false;\n    message =\n      'Only space & [  a-z, A-Z, 0-9, _, -, !@#$%^&*()-+{}[]\\'\".,  ] are allowed.';\n  }\n  const startWithLetterRegex = /^[A-Za-z]/;\n  const startWithLetterValid = startWithLetterRegex.test(displayName);\n  if (!startWithLetterValid) {\n    valid = false;\n    message = 'Must start with a letter.';\n  }\n\n  return {\n    valid,\n    message,\n  };\n}\n\nexport function replaceAllowableSyntax(str: string) {\n  const replacedStr = str.replace(/[!@#$%^&*()+{}[\\]'\",. -]/g, '_');\n  return replacedStr;\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/sqlFormat.ts",
    "content": "import { format, FormatOptionsWithLanguage } from 'sql-formatter';\nimport { getLogger } from './logger';\n\nconst logger = getLogger('SQL Format');\n\nexport function safeFormatSQL(\n  sql: string,\n  options?: FormatOptionsWithLanguage,\n): string {\n  try {\n    return format(sql, options);\n  } catch (err) {\n    try {\n      logger.debug(`Fallback to Trino dialect for SQL formatting...`);\n      // Try using Trino as the fallback dialect\n      return format(sql, { ...options, language: 'trino' });\n    } catch (_fallbackError) {\n      logger.error(`Failed to format SQL: ${err.message}`);\n      return sql;\n    }\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/sseTypes.ts",
    "content": "// Server-Sent Events (SSE) types for real-time streaming APIs\nexport enum EventType {\n  MESSAGE_START = 'message_start',\n  MESSAGE_STOP = 'message_stop',\n  STATE = 'state',\n  CONTENT_BLOCK_START = 'content_block_start',\n  CONTENT_BLOCK_DELTA = 'content_block_delta',\n  CONTENT_BLOCK_STOP = 'content_block_stop',\n  ERROR = 'error',\n}\n\nexport enum StateType {\n  SQL_GENERATION_START = 'sql_generation_start',\n  SQL_GENERATION_UNDERSTANDING = 'sql_generation_understanding',\n  SQL_GENERATION_SEARCHING = 'sql_generation_searching',\n  SQL_GENERATION_PLANNING = 'sql_generation_planning',\n  SQL_GENERATION_GENERATING = 'sql_generation_generating',\n  SQL_GENERATION_CORRECTING = 'sql_generation_correcting',\n  SQL_GENERATION_FINISHED = 'sql_generation_finished',\n  SQL_GENERATION_FAILED = 'sql_generation_failed',\n  SQL_GENERATION_STOPPED = 'sql_generation_stopped',\n  SQL_GENERATION_SUCCESS = 'sql_generation_success',\n  SQL_EXECUTION_START = 'sql_execution_start',\n  SQL_EXECUTION_END = 'sql_execution_end',\n}\n\nexport enum ContentBlockContentType {\n  SUMMARY_GENERATION = 'summary_generation',\n  EXPLANATION = 'explanation',\n}\n\n// Interfaces for request and events\nexport interface AsyncAskRequest {\n  question: string;\n  sampleSize?: number;\n  language?: string;\n  threadId?: string;\n}\n\nexport interface BaseEvent {\n  timestamp: number;\n}\n\nexport interface MessageStartEvent extends BaseEvent {\n  type: EventType.MESSAGE_START;\n}\n\nexport interface MessageStopEvent extends BaseEvent {\n  type: EventType.MESSAGE_STOP;\n  data: {\n    threadId: string;\n    duration: number;\n  };\n}\n\nexport interface StateEvent extends BaseEvent {\n  type: EventType.STATE;\n  data: {\n    state: StateType;\n    [key: string]: any;\n  };\n}\n\nexport interface ContentBlockStartEvent extends BaseEvent {\n  type: EventType.CONTENT_BLOCK_START;\n  content_block: {\n    type: 'text';\n    name: ContentBlockContentType;\n  };\n}\n\nexport interface ContentBlockDeltaEvent extends BaseEvent {\n  type: EventType.CONTENT_BLOCK_DELTA;\n  delta: {\n    type: 'text_delta';\n    text: string;\n  };\n}\n\nexport interface ContentBlockStopEvent extends BaseEvent {\n  type: EventType.CONTENT_BLOCK_STOP;\n}\n\nexport interface ErrorEvent extends BaseEvent {\n  type: EventType.ERROR;\n  data: {\n    error: string;\n    code?: string;\n  };\n}\n\nexport type StreamEvent =\n  | MessageStartEvent\n  | MessageStopEvent\n  | StateEvent\n  | ContentBlockStartEvent\n  | ContentBlockDeltaEvent\n  | ContentBlockStopEvent\n  | ErrorEvent;\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/sseUtils.ts",
    "content": "import { NextApiResponse } from 'next';\nimport { AskResultStatus } from '@/apollo/server/models/adaptor';\nimport {\n  EventType,\n  StateType,\n  StreamEvent,\n  StateEvent,\n  ErrorEvent,\n  MessageStartEvent,\n  MessageStopEvent,\n} from './sseTypes';\n\n/**\n * Send SSE event to client\n */\nexport const sendSSEEvent = (res: NextApiResponse, event: StreamEvent) => {\n  const eventData = `data: ${JSON.stringify(event)}\\n\\n`;\n  res.write(eventData);\n};\n\n/**\n * Send message start event to client\n */\nexport const sendMessageStart = (res: NextApiResponse) => {\n  const messageStartEvent: MessageStartEvent = {\n    type: EventType.MESSAGE_START,\n    timestamp: Date.now(),\n  };\n  sendSSEEvent(res, messageStartEvent);\n};\n\n/**\n * Send message stop event to client\n */\nexport const sendMessageStop = (\n  res: NextApiResponse,\n  threadId: string,\n  duration: number,\n) => {\n  const messageStopEvent: MessageStopEvent = {\n    type: EventType.MESSAGE_STOP,\n    data: {\n      threadId,\n      duration,\n    },\n    timestamp: Date.now(),\n  };\n  sendSSEEvent(res, messageStopEvent);\n};\n\n/**\n * Send state update to client\n */\nexport const sendStateUpdate = (\n  res: NextApiResponse,\n  state: StateType,\n  data?: any,\n) => {\n  const stateEvent: StateEvent = {\n    type: EventType.STATE,\n    data: {\n      state,\n      ...data,\n    },\n    timestamp: Date.now(),\n  };\n  sendSSEEvent(res, stateEvent);\n};\n\n/**\n * Send error to client\n */\nexport const sendError = (\n  res: NextApiResponse,\n  error: string,\n  code?: string,\n  additionalData?: Record<string, any>,\n) => {\n  const errorEvent: ErrorEvent = {\n    type: EventType.ERROR,\n    data: {\n      error,\n      code,\n      ...additionalData,\n    },\n    timestamp: Date.now(),\n  };\n  sendSSEEvent(res, errorEvent);\n};\n\n/**\n * Transform AskResultStatus to descriptive SQL generation state\n */\nexport const getSqlGenerationState = (status: AskResultStatus): StateType => {\n  switch (status) {\n    case AskResultStatus.UNDERSTANDING:\n      return StateType.SQL_GENERATION_UNDERSTANDING;\n    case AskResultStatus.SEARCHING:\n      return StateType.SQL_GENERATION_SEARCHING;\n    case AskResultStatus.PLANNING:\n      return StateType.SQL_GENERATION_PLANNING;\n    case AskResultStatus.GENERATING:\n      return StateType.SQL_GENERATION_GENERATING;\n    case AskResultStatus.CORRECTING:\n      return StateType.SQL_GENERATION_CORRECTING;\n    case AskResultStatus.FINISHED:\n      return StateType.SQL_GENERATION_FINISHED;\n    case AskResultStatus.FAILED:\n      return StateType.SQL_GENERATION_FAILED;\n    case AskResultStatus.STOPPED:\n      return StateType.SQL_GENERATION_STOPPED;\n    default:\n      return StateType.SQL_GENERATION_UNDERSTANDING;\n  }\n};\n\n/**\n * End the SSE stream with message stop event\n */\nexport const endStream = (\n  res: NextApiResponse,\n  threadId: string,\n  startTime: number,\n) => {\n  // Send message stop event\n  sendMessageStop(res, threadId, Date.now() - startTime);\n  res.end();\n};\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/string.ts",
    "content": "export const trim = (str: string) => str.replace(/^\\s+|\\s+$/g, '');\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/tests/dataSource.test.ts",
    "content": "import { encryptConnectionInfo } from '../../dataSource';\nimport { DataSourceName } from '../../types';\nimport {\n  BIG_QUERY_CONNECTION_INFO,\n  DUCKDB_CONNECTION_INFO,\n  MYSQL_CONNECTION_INFO,\n  POSTGRES_CONNECTION_INFO,\n} from '../../repositories';\nimport { Encryptor } from '@server/utils/encryptor';\n\njest.mock('@server/utils/encryptor');\n\nconst mockedEncryptor = Encryptor as jest.MockedClass<typeof Encryptor>;\n\ndescribe('Encryptor', () => {\n  beforeEach(() => {\n    mockedEncryptor.prototype.decrypt.mockReturnValue('decrypted string');\n    mockedEncryptor.prototype.encrypt.mockReturnValue('encrypted string');\n  });\n\n  it('should encrypt sensitive connection info for BigQuery connection info', async () => {\n    const connectionInfo = {\n      credentials: 'some-credentials',\n      datasetId: 'my-bq-dataset-id',\n      projectId: 'my-bq-project-id',\n    } as BIG_QUERY_CONNECTION_INFO;\n\n    const encryptedConnectionInfo = await encryptConnectionInfo(\n      DataSourceName.BIG_QUERY,\n      connectionInfo,\n    );\n\n    expect(encryptedConnectionInfo).toEqual({\n      credentials: 'encrypted string',\n      datasetId: 'my-bq-dataset-id',\n      projectId: 'my-bq-project-id',\n    });\n  });\n\n  it('should encrypt sensitive connection info for Postgres connection info', async () => {\n    const connectionInfo = {\n      host: 'localhost',\n      port: 5432,\n      database: 'my-database',\n      user: 'my-user',\n      password: 'my-password',\n      ssl: false,\n    } as POSTGRES_CONNECTION_INFO;\n\n    const encryptedConnectionInfo = await encryptConnectionInfo(\n      DataSourceName.POSTGRES,\n      connectionInfo,\n    );\n\n    expect(encryptedConnectionInfo).toEqual({\n      host: 'localhost',\n      port: 5432,\n      database: 'my-database',\n      user: 'my-user',\n      password: 'encrypted string',\n      ssl: false,\n    });\n  });\n\n  it('should encrypt sensitive connection info for MySQL connection info', async () => {\n    const connectionInfo = {\n      host: 'localhost',\n      port: 5432,\n      database: 'my-database',\n      user: 'my-user',\n      password: 'my-password',\n    } as MYSQL_CONNECTION_INFO;\n\n    const encryptedConnectionInfo = await encryptConnectionInfo(\n      DataSourceName.MYSQL,\n      connectionInfo,\n    );\n\n    expect(encryptedConnectionInfo).toEqual({\n      host: 'localhost',\n      port: 5432,\n      database: 'my-database',\n      user: 'my-user',\n      password: 'encrypted string',\n    });\n  });\n\n  it('should encrypt sensitive connection info for DuckDB connection info', async () => {\n    const connectionInfo = {\n      initSql: 'some-sql',\n      extensions: ['extension1', 'extension2'],\n      configurations: { key: 'value' },\n    } as DUCKDB_CONNECTION_INFO;\n\n    const encryptedConnectionInfo = await encryptConnectionInfo(\n      DataSourceName.DUCKDB,\n      connectionInfo,\n    );\n\n    expect(encryptedConnectionInfo).toEqual({\n      initSql: 'some-sql',\n      extensions: ['extension1', 'extension2'],\n      configurations: { key: 'value' },\n    });\n  });\n});\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/tests/encryptor.test.ts",
    "content": "import { Encryptor } from '../encryptor';\nimport crypto from 'crypto';\n\njest.mock('crypto', () => ({\n  randomBytes: jest.fn(),\n  createCipheriv: jest.fn(),\n  createDecipheriv: jest.fn(),\n  pbkdf2Sync: jest.fn(),\n}));\n\nconst credentials = { username: 'user', password: 'pass' };\n\ndescribe('Encryptor', () => {\n  const mockConfig = {\n    encryptionPassword: 'testPassword',\n    encryptionSalt: 'testSalt',\n  };\n\n  let encryptor: Encryptor;\n  beforeEach(() => {\n    encryptor = new Encryptor(mockConfig);\n  });\n\n  it('should encrypt data correctly', async () => {\n    // Arrange\n    const testData = JSON.parse(JSON.stringify(credentials));\n    const mockIV = Buffer.from('mockIV');\n    (crypto.randomBytes as jest.Mock).mockReturnValue(mockIV);\n    const mockCipher = {\n      update: jest.fn().mockReturnValue(Buffer.from('ciphered')),\n      final: jest.fn().mockReturnValue(Buffer.from('finalCiphered')),\n    };\n    (crypto.createCipheriv as jest.Mock).mockReturnValue(mockCipher);\n\n    // Act\n    const encryptedData = await encryptor.encrypt(testData);\n\n    // Assert\n    expect(encryptedData).toContain(Buffer.from('mockIV').toString('base64')); // Basic check, more sophisticated assertions can be made\n    expect(encryptedData).toContain(':'); // contain seperator\n    expect(encryptedData).toContain(\n      Buffer.concat([\n        Buffer.from('ciphered'),\n        Buffer.from('finalCiphered'),\n      ]).toString('base64'),\n    ); // contain ciphered data\n    expect(crypto.createCipheriv).toHaveBeenCalled();\n  });\n\n  it('should decrypt data correctly', async () => {\n    // Setup\n    const encryptedData = 'mockIV:encryptedData';\n    const mockDecrypted = Buffer.from(JSON.stringify(credentials));\n    const mockDecipher = {\n      update: jest.fn().mockReturnValue(mockDecrypted),\n      final: jest.fn().mockReturnValue(Buffer.from('')),\n    };\n    (crypto.createDecipheriv as jest.Mock).mockReturnValue(mockDecipher);\n\n    // Act\n    const decryptedData = await encryptor.decrypt(encryptedData);\n\n    // Assert\n    expect(decryptedData).toEqual(JSON.stringify(credentials));\n    expect(crypto.createDecipheriv).toHaveBeenCalled();\n  });\n\n  it('should return original data after encrypt and decrypt', async () => {\n    // Setup\n    const testData = JSON.parse('{\"username\":\"user\",\"password\":\"pass\"}');\n    const mockIV = Buffer.from('mockIV');\n    (crypto.randomBytes as jest.Mock).mockReturnValue(mockIV);\n    const mockCipher = {\n      update: jest.fn().mockReturnValue(Buffer.from('ciphered')),\n      final: jest.fn().mockReturnValue(Buffer.from('finalCiphered')),\n    };\n    (crypto.createCipheriv as jest.Mock).mockReturnValue(mockCipher);\n\n    const mockDecipher = {\n      update: jest.fn().mockReturnValue(Buffer.from(JSON.stringify(testData))),\n      final: jest.fn().mockReturnValue(Buffer.from('')),\n    };\n    (crypto.createDecipheriv as jest.Mock).mockReturnValue(mockDecipher);\n\n    // Act\n    const encryptedData = await encryptor.encrypt(testData);\n    const decryptedData = await encryptor.decrypt(encryptedData);\n\n    // Assert\n    expect(JSON.parse(decryptedData)).toEqual(testData);\n  });\n});\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/tests/regex.test.ts",
    "content": "import { validateDisplayName, replaceAllowableSyntax } from '../regex';\n\ndescribe('validateDisplayName', () => {\n  it('should return valid when displayName contains only allowable syntax and start with a letter', () => {\n    // Arrange\n    const displayName = 'Valid Display Name !@#$%^&*()_+{}[].,\"\\'';\n\n    // Act\n    const result = validateDisplayName(displayName);\n\n    // Assert\n    expect(result.valid).toBe(true);\n    expect(result.message).toBeNull();\n  });\n\n  it.each([['~'], ['<'], ['\\\\'], ['>'], ['?']])(\n    'should return invalid when displayName contains invalid syntax: %s',\n    ([invalidSyntax]) => {\n      // Arrange\n      const displayName = `Invalid Display Name ${invalidSyntax}`;\n\n      // Act\n      const result = validateDisplayName(displayName);\n\n      // Assert\n      expect(result.valid).toBe(false);\n      expect(result.message).toBe(\n        'Only space & [  a-z, A-Z, 0-9, _, -, !@#$%^&*()-+{}[]\\'\".,  ] are allowed.',\n      );\n    },\n  );\n  it.each([['@'], ['1'], [' ']])(\n    'should return invalid when displayName does not start with a letter',\n    ([invalidSyntax]) => {\n      // Arrange\n      const displayName = `${invalidSyntax}Display Name`;\n\n      // Act\n      const result = validateDisplayName(displayName);\n\n      // Assert\n      expect(result.valid).toBe(false);\n      expect(result.message).toBe('Must start with a letter.');\n    },\n  );\n});\n\ndescribe('replaceAllowableSyntax', () => {\n  it('should replace allowable syntax characters with underscores', () => {\n    // Arrange\n    const str = 'Replace   !@#$%^&*() -+{}[],\\'\".';\n\n    // Act\n    const result = replaceAllowableSyntax(str);\n\n    // Assert\n    expect(result).toBe('Replace________________________');\n    expect(result.length).toBe(str.length);\n  });\n});\n"
  },
  {
    "path": "wren-ui/src/apollo/server/utils/timezone.ts",
    "content": "export function getUTCOffsetMinutes(timeZone: string) {\n  const date = new Date();\n  const utcDate = new Date(\n    date.toLocaleString('en-US', { timeZone: 'UTC' }),\n  ) as any;\n  const tzDate = new Date(date.toLocaleString('en-US', { timeZone })) as any;\n\n  return (tzDate - utcDate) / 60000; // Convert to minutes\n}\n\nexport function formatUTCOffset(offsetMinutes: number) {\n  const sign = offsetMinutes >= 0 ? '+' : '-';\n  const absOffset = Math.abs(offsetMinutes);\n  const hours = Math.floor(absOffset / 60)\n    .toString()\n    .padStart(2, '0');\n  const minutes = (absOffset % 60).toString().padStart(2, '0');\n  return `UTC${sign}${hours}:${minutes}`;\n}\n"
  },
  {
    "path": "wren-ui/src/common.ts",
    "content": "import { getConfig } from '@server/config';\nimport { bootstrapKnex } from './apollo/server/utils/knex';\nimport {\n  ProjectRepository,\n  ViewRepository,\n  DeployLogRepository,\n  ThreadRepository,\n  ThreadResponseRepository,\n  ModelRepository,\n  ModelColumnRepository,\n  RelationRepository,\n  SchemaChangeRepository,\n  ModelNestedColumnRepository,\n  LearningRepository,\n  DashboardItemRepository,\n  DashboardRepository,\n  SqlPairRepository,\n  AskingTaskRepository,\n  InstructionRepository,\n  ApiHistoryRepository,\n  DashboardItemRefreshJobRepository,\n} from '@server/repositories';\nimport {\n  WrenEngineAdaptor,\n  WrenAIAdaptor,\n  IbisAdaptor,\n} from '@server/adaptors';\nimport {\n  DataSourceMetadataService,\n  QueryService,\n  ProjectService,\n  DeployService,\n  AskingService,\n  MDLService,\n  DashboardService,\n  AskingTaskTracker,\n  InstructionService,\n} from '@server/services';\nimport { PostHogTelemetry } from './apollo/server/telemetry/telemetry';\nimport {\n  ProjectRecommendQuestionBackgroundTracker,\n  ThreadRecommendQuestionBackgroundTracker,\n  DashboardCacheBackgroundTracker,\n} from './apollo/server/backgrounds';\nimport { SqlPairService } from './apollo/server/services/sqlPairService';\n\nexport const serverConfig = getConfig();\n\nexport const initComponents = () => {\n  const telemetry = new PostHogTelemetry();\n  const knex = bootstrapKnex({\n    dbType: serverConfig.dbType,\n    pgUrl: serverConfig.pgUrl,\n    debug: serverConfig.debug,\n    sqliteFile: serverConfig.sqliteFile,\n  });\n\n  // repositories\n  const projectRepository = new ProjectRepository(knex);\n  const deployLogRepository = new DeployLogRepository(knex);\n  const threadRepository = new ThreadRepository(knex);\n  const threadResponseRepository = new ThreadResponseRepository(knex);\n  const viewRepository = new ViewRepository(knex);\n  const modelRepository = new ModelRepository(knex);\n  const modelColumnRepository = new ModelColumnRepository(knex);\n  const modelNestedColumnRepository = new ModelNestedColumnRepository(knex);\n  const relationRepository = new RelationRepository(knex);\n  const schemaChangeRepository = new SchemaChangeRepository(knex);\n  const learningRepository = new LearningRepository(knex);\n  const dashboardRepository = new DashboardRepository(knex);\n  const dashboardItemRepository = new DashboardItemRepository(knex);\n  const sqlPairRepository = new SqlPairRepository(knex);\n  const askingTaskRepository = new AskingTaskRepository(knex);\n  const instructionRepository = new InstructionRepository(knex);\n  const apiHistoryRepository = new ApiHistoryRepository(knex);\n  const dashboardItemRefreshJobRepository =\n    new DashboardItemRefreshJobRepository(knex);\n\n  // adaptors\n  const wrenEngineAdaptor = new WrenEngineAdaptor({\n    wrenEngineEndpoint: serverConfig.wrenEngineEndpoint,\n  });\n  const wrenAIAdaptor = new WrenAIAdaptor({\n    wrenAIBaseEndpoint: serverConfig.wrenAIEndpoint,\n  });\n  const ibisAdaptor = new IbisAdaptor({\n    ibisServerEndpoint: serverConfig.ibisServerEndpoint,\n  });\n\n  // services\n  const metadataService = new DataSourceMetadataService({\n    ibisAdaptor,\n    wrenEngineAdaptor,\n  });\n  const queryService = new QueryService({\n    ibisAdaptor,\n    wrenEngineAdaptor,\n    telemetry,\n  });\n  const deployService = new DeployService({\n    wrenAIAdaptor,\n    deployLogRepository,\n    telemetry,\n  });\n  const mdlService = new MDLService({\n    projectRepository,\n    modelRepository,\n    modelColumnRepository,\n    modelNestedColumnRepository,\n    relationRepository,\n    viewRepository,\n  });\n  const projectService = new ProjectService({\n    projectRepository,\n    metadataService,\n    mdlService,\n    wrenAIAdaptor,\n    telemetry,\n  });\n  const askingTaskTracker = new AskingTaskTracker({\n    wrenAIAdaptor,\n    askingTaskRepository,\n    threadResponseRepository,\n    viewRepository,\n  });\n  const askingService = new AskingService({\n    telemetry,\n    wrenAIAdaptor,\n    deployService,\n    projectService,\n    viewRepository,\n    threadRepository,\n    threadResponseRepository,\n    queryService,\n    mdlService,\n    askingTaskTracker,\n    askingTaskRepository,\n  });\n  const dashboardService = new DashboardService({\n    projectService,\n    dashboardItemRepository,\n    dashboardRepository,\n  });\n  const sqlPairService = new SqlPairService({\n    sqlPairRepository,\n    wrenAIAdaptor,\n    ibisAdaptor,\n  });\n  const instructionService = new InstructionService({\n    instructionRepository,\n    wrenAIAdaptor,\n  });\n\n  // background trackers\n  const projectRecommendQuestionBackgroundTracker =\n    new ProjectRecommendQuestionBackgroundTracker({\n      telemetry,\n      wrenAIAdaptor,\n      projectRepository,\n    });\n  const threadRecommendQuestionBackgroundTracker =\n    new ThreadRecommendQuestionBackgroundTracker({\n      telemetry,\n      wrenAIAdaptor,\n      threadRepository,\n    });\n  const dashboardCacheBackgroundTracker = new DashboardCacheBackgroundTracker({\n    dashboardRepository,\n    dashboardItemRepository,\n    dashboardItemRefreshJobRepository,\n    projectService,\n    deployService,\n    queryService,\n  });\n\n  return {\n    knex,\n    telemetry,\n\n    // repositories\n    projectRepository,\n    deployLogRepository,\n    threadRepository,\n    threadResponseRepository,\n    viewRepository,\n    modelRepository,\n    modelColumnRepository,\n    relationRepository,\n    schemaChangeRepository,\n    learningRepository,\n    modelNestedColumnRepository,\n    dashboardRepository,\n    dashboardItemRepository,\n    sqlPairRepository,\n    askingTaskRepository,\n    apiHistoryRepository,\n    instructionRepository,\n    dashboardItemRefreshJobRepository,\n\n    // adaptors\n    wrenEngineAdaptor,\n    wrenAIAdaptor,\n    ibisAdaptor,\n\n    // services\n    metadataService,\n    projectService,\n    queryService,\n    deployService,\n    askingService,\n    mdlService,\n    dashboardService,\n    sqlPairService,\n    instructionService,\n    askingTaskTracker,\n\n    // background trackers\n    projectRecommendQuestionBackgroundTracker,\n    threadRecommendQuestionBackgroundTracker,\n    dashboardCacheBackgroundTracker,\n  };\n};\n\n// singleton components\nexport const components = initComponents();\n"
  },
  {
    "path": "wren-ui/src/components/ActionButton.tsx",
    "content": "import { Button } from 'antd';\nimport PlusSquareOutlined from '@ant-design/icons/PlusSquareOutlined';\nimport { MoreIcon } from '@/utils/icons';\n\ninterface Props {\n  onClick?: (event: React.MouseEvent) => void;\n  onMouseEnter?: (event: React.MouseEvent) => void;\n  onMouseLeave?: (event: React.MouseEvent) => void;\n  className?: string;\n  marginLeft?: number;\n  marginRight?: number;\n}\n\nconst makeActionButton = (icon: React.ReactNode) => (props: Props) => {\n  const {\n    onClick,\n    onMouseEnter,\n    onMouseLeave,\n    className,\n    marginLeft,\n    marginRight,\n    ...restProps\n  } = props;\n  const click = (event) => {\n    onClick && onClick(event);\n    event.stopPropagation();\n  };\n  const mouseEnter = (event) => {\n    onMouseEnter && onMouseEnter(event);\n    event.stopPropagation();\n  };\n  const mouseLeave = (event) => {\n    onMouseLeave && onMouseLeave(event);\n    event.stopPropagation();\n  };\n  return (\n    <Button\n      className={className}\n      style={{ marginLeft, marginRight }}\n      icon={icon}\n      onClick={click}\n      onMouseEnter={mouseEnter}\n      onMouseLeave={mouseLeave}\n      type=\"text\"\n      size=\"small\"\n      {...restProps}\n    />\n  );\n};\n\nexport const AddButton = makeActionButton(<PlusSquareOutlined />);\nexport const MoreButton = makeActionButton(<MoreIcon />);\n"
  },
  {
    "path": "wren-ui/src/components/EditableWrapper.tsx",
    "content": "import { createContext, useContext, useEffect, useRef, useState } from 'react';\nimport { Input, InputRef, Form, FormInstance } from 'antd';\nimport styled from 'styled-components';\nimport { get } from 'lodash';\nimport EllipsisWrapper from '@/components/EllipsisWrapper';\n\ninterface Props {\n  children: React.ReactNode;\n  dataIndex: string;\n  record: any;\n  rules?: any[];\n  handleSave: (id: string | number, value: { [key: string]: string }) => void;\n}\n\nconst EditableStyle = styled.div`\n  line-height: 24px;\n  min-height: 25px;\n\n  .editable-cell-value-wrap {\n    padding: 0 7px;\n    border: 1px var(--gray-4) solid;\n    border-radius: 4px;\n    cursor: pointer;\n\n    &:hover {\n      border-color: var(--gray-5);\n    }\n  }\n  .ant-form-item-control-input {\n    min-height: 24px;\n    .ant-input {\n      line-height: 24px;\n    }\n  }\n`;\n\nexport const EditableContext = createContext<FormInstance<any> | null>(null);\n\nexport default function EditableWrapper(props: Props) {\n  const { children, dataIndex, record, rules, handleSave } = props;\n\n  const [editing, setEditing] = useState(false);\n  const textRef = useRef<HTMLDivElement>(null);\n  const inputWidth = useRef(0);\n  const inputRef = useRef<InputRef>(null);\n  const form = useContext(EditableContext);\n  const dataIndexKey = Array.isArray(dataIndex)\n    ? dataIndex.join('.')\n    : dataIndex;\n\n  useEffect(() => {\n    if (editing) inputRef.current!.focus();\n  }, [editing]);\n\n  const toggleEdit = () => {\n    if (textRef.current) inputWidth.current = textRef.current.clientWidth;\n    setEditing(!editing);\n    const value = get(record, dataIndexKey);\n    form.setFieldsValue({ [dataIndexKey]: value });\n  };\n\n  const save = async () => {\n    try {\n      const values = await form.validateFields();\n\n      toggleEdit();\n      handleSave(record.id, values);\n    } catch (errInfo) {\n      console.log('Save failed:', errInfo);\n    }\n  };\n\n  const childNode = editing ? (\n    <Form.Item style={{ margin: 0 }} name={dataIndexKey} rules={rules}>\n      <Input\n        size=\"small\"\n        ref={inputRef}\n        onPressEnter={save}\n        onBlur={save}\n        style={{ width: inputWidth.current }}\n      />\n    </Form.Item>\n  ) : (\n    <div\n      ref={textRef}\n      className=\"editable-cell-value-wrap\"\n      style={{ paddingRight: 24 }}\n      onClick={toggleEdit}\n    >\n      <EllipsisWrapper text={children as string} />\n    </div>\n  );\n\n  return <EditableStyle>{childNode}</EditableStyle>;\n}\n"
  },
  {
    "path": "wren-ui/src/components/EllipsisWrapper.tsx",
    "content": "import { ReactNode, useEffect, useRef, useState } from 'react';\nimport styled from 'styled-components';\n\ninterface Props {\n  text?: string;\n  children?: ReactNode;\n  multipleLine?: number;\n  minHeight?: number;\n  showMoreCount?: boolean;\n}\n\nconst Wrapper = styled.div<{ multipleLine?: number }>`\n  overflow: hidden;\n  text-overflow: ellipsis;\n  ${(props) =>\n    props.multipleLine\n      ? `\n  display: -webkit-box;\n  -webkit-line-clamp: ${props.multipleLine};\n  -webkit-box-orient: vertical;\n`\n      : `\n  white-space: nowrap;\n`}\n`;\n\nexport default function EllipsisWrapper(props: Props) {\n  const { text, multipleLine, minHeight, children, showMoreCount } = props;\n  const ref = useRef<HTMLDivElement | null>(null);\n  const stageRef = useRef<HTMLDivElement | null>(null);\n  const [width, setWidth] = useState(undefined);\n  const hasWidth = width !== undefined;\n  // Stage for counting the children that will be shown\n  const [stage, setStage] = useState([]);\n\n  const isStageEnd = useRef(false);\n  const calculateStageShow = () => {\n    if (isStageEnd.current) return;\n    const remainSpace = 60; // remain space for showing more tip\n    const stageWidth = stageRef.current?.clientWidth;\n    const canPrintNext = stageWidth < width - remainSpace;\n\n    if (canPrintNext) {\n      const hasMoreChildren = (children as ReactNode[]).length > stage.length;\n      hasMoreChildren && setStage([...stage, children[stage.length]]);\n    } else {\n      setStage(stage.slice(0, stage.length - 1));\n      isStageEnd.current = true;\n    }\n  };\n\n  // Auto setup client width itself\n  useEffect(() => {\n    if (ref.current && !hasWidth) {\n      const cellWidth = ref.current.clientWidth;\n      cellWidth === 0 ? setWidth('auto') : setWidth(cellWidth);\n    }\n\n    // Reset state when unmount\n    return () => {\n      isStageEnd.current = false;\n      setStage([]);\n      setWidth(undefined);\n    };\n  }, []);\n\n  // Only work when showMoreCount is provided\n  useEffect(() => {\n    if (!showMoreCount) return;\n    // Run only once when showMoreCount is true\n    if (stage.length === 0) {\n      setStage([children[0]]);\n      return;\n    }\n    calculateStageShow();\n  }, [showMoreCount, stage]);\n\n  const renderContent = () => {\n    if (!children) return text || '-';\n\n    // Turn another template if showMoreCount is provided\n    if (showMoreCount) {\n      const moreCount = (children as ReactNode[]).length - stage.length;\n      return (\n        <span className=\"d-inline-block\" ref={stageRef}>\n          {stage}\n          {moreCount > 0 && <span className=\"gray-7\">...{moreCount} more</span>}\n        </span>\n      );\n    }\n\n    return children;\n  };\n\n  // Convert to string if React pass its children as array type to props\n  const title = Array.isArray(text) ? text.join('') : text;\n\n  return (\n    <Wrapper\n      ref={ref}\n      title={title}\n      multipleLine={multipleLine}\n      style={{ width, minHeight }}\n    >\n      {hasWidth ? renderContent() : null}\n    </Wrapper>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/ErrorCollapse.tsx",
    "content": "import { useState } from 'react';\nimport { Collapse } from 'antd';\nimport styled from 'styled-components';\nimport CaretRightOutlined from '@ant-design/icons/CaretRightOutlined';\n\nconst StyledCollapse = styled(Collapse)`\n  .ant-collapse-item {\n    > .ant-collapse-header {\n      user-select: none;\n      color: var(--gray-7);\n      padding-left: 0;\n      padding-right: 0;\n      padding-top: 0;\n      padding-bottom: 0;\n\n      .ant-collapse-arrow {\n        margin-right: 8px;\n      }\n    }\n    > .ant-collapse-content .ant-collapse-content-box {\n      color: var(--gray-7);\n      padding: 4px 0 0 0;\n    }\n  }\n`;\n\ninterface Props {\n  message: string;\n  className?: string;\n  defaultActive?: boolean;\n}\n\nexport default function ErrorCollapse(props: Props) {\n  const { message, className, defaultActive } = props;\n  const [activeKey, setActiveKey] = useState<string[]>(\n    defaultActive ? ['1'] : [],\n  );\n\n  return (\n    <StyledCollapse\n      className={className}\n      ghost\n      activeKey={activeKey}\n      onChange={(key) => setActiveKey(key as string[])}\n      expandIcon={({ isActive }) => (\n        <CaretRightOutlined rotate={isActive ? 90 : 0} />\n      )}\n    >\n      <Collapse.Panel key=\"1\" header=\"Show error messages\">\n        <pre className=\"text-sm mb-0 pl-5\" style={{ whiteSpace: 'pre-wrap' }}>\n          {message}\n        </pre>\n      </Collapse.Panel>\n    </StyledCollapse>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/HeaderBar.tsx",
    "content": "import { useRouter } from 'next/router';\nimport { Button, Layout, Space } from 'antd';\nimport styled from 'styled-components';\nimport LogoBar from '@/components/LogoBar';\nimport { Path } from '@/utils/enum';\nimport Deploy from '@/components/deploy/Deploy';\n\nconst { Header } = Layout;\n\nconst StyledButton = styled(Button)<{ $isHighlight: boolean }>`\n  background: ${(props) =>\n    props.$isHighlight ? 'rgba(255, 255, 255, 0.20)' : 'transparent'};\n  font-weight: ${(props) => (props.$isHighlight ? '700' : 'normal')};\n  border: none;\n  color: var(--gray-1);\n\n  &:hover,\n  &:focus {\n    background: ${(props) =>\n      props.$isHighlight\n        ? 'rgba(255, 255, 255, 0.20)'\n        : 'rgba(255, 255, 255, 0.05)'};\n    color: var(--gray-1);\n  }\n`;\n\nconst StyledHeader = styled(Header)`\n  height: 48px;\n  border-bottom: 1px solid var(--gray-5);\n  background: var(--gray-10);\n  padding: 10px 16px;\n`;\n\nexport default function HeaderBar() {\n  const router = useRouter();\n  const { pathname } = router;\n  const showNav = !pathname.startsWith(Path.Onboarding);\n  const isModeling = pathname.startsWith(Path.Modeling);\n\n  return (\n    <StyledHeader>\n      <div\n        className=\"d-flex justify-space-between align-center\"\n        style={{ marginTop: -2 }}\n      >\n        <Space size={[48, 0]}>\n          <LogoBar />\n          {showNav && (\n            <Space size={[16, 0]}>\n              <StyledButton\n                shape=\"round\"\n                size=\"small\"\n                $isHighlight={pathname.startsWith(Path.Home)}\n                onClick={() => router.push(Path.Home)}\n              >\n                Home\n              </StyledButton>\n              <StyledButton\n                shape=\"round\"\n                size=\"small\"\n                $isHighlight={pathname.startsWith(Path.Modeling)}\n                onClick={() => router.push(Path.Modeling)}\n              >\n                Modeling\n              </StyledButton>\n              <StyledButton\n                shape=\"round\"\n                size=\"small\"\n                $isHighlight={pathname.startsWith(Path.Knowledge)}\n                onClick={() => router.push(Path.KnowledgeQuestionSQLPairs)}\n              >\n                Knowledge\n              </StyledButton>\n              <StyledButton\n                shape=\"round\"\n                size=\"small\"\n                $isHighlight={pathname.startsWith(Path.APIManagement)}\n                onClick={() => router.push(Path.APIManagementHistory)}\n              >\n                API\n              </StyledButton>\n            </Space>\n          )}\n        </Space>\n        {isModeling && (\n          <Space size={[16, 0]}>\n            <Deploy />\n          </Space>\n        )}\n      </div>\n    </StyledHeader>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/Logo.tsx",
    "content": "interface Props {\n  size?: number;\n  color?: string;\n}\n\nexport const Logo = (props: Props) => {\n  const { color = 'var(--gray-9)', size = 30 } = props;\n  return (\n    <svg\n      style={{ width: size, height: 'auto' }}\n      viewBox=\"0 0 30 30\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      shapeRendering=\"geometricPrecision\"\n    >\n      <path\n        d=\"M15.8023 7.82981C16.2779 8.98701 16.0102 10.1784 15.2043 10.491C14.3983 10.8035 13.3594 10.1187 12.8838 8.96153C12.4082 7.80433 12.676 6.61289 13.4819 6.30038C14.2878 5.98786 15.3267 6.67261 15.8023 7.82981Z\"\n        fill={color}\n      />\n      <path\n        d=\"M29.2498 21.952C29.6972 22.4662 30.06 23.0215 29.9917 23.685C29.9234 24.3486 29.3086 24.614 28.8987 24.6804C28.4888 24.7467 20.4276 25.8084 19.5396 25.8748C18.7537 25.9335 18.6097 25.8363 18.303 25.6293C18.1647 25.5398 15.0158 22.5446 13.4586 21.0582C12.69 20.502 11.9941 20.0605 11.5031 19.8762C11.0511 19.7065 10.8708 19.0927 11.2918 18.7366L12.3395 17.8503C12.6148 17.6175 13.0379 17.6319 13.2922 17.9027C13.5897 18.1624 14.5664 19.2307 15.0176 19.7324C16.4453 21.0988 18.1849 22.7674 19.1297 23.685C19.8811 23.9504 21.6801 23.6187 22.0672 23.486C22.0672 23.486 19.4312 20.2141 18.8919 19.8065C18.3525 19.3989 17.8676 19.0849 17.4905 18.9339C16.7022 18.5185 17.059 17.9764 17.336 17.7573L18.4758 16.9463C18.7522 16.7496 19.1457 16.7781 19.3852 17.0359C20.803 18.8099 23.7888 22.4906 24.3899 23.0215C25.1414 23.2869 26.8948 22.9994 27.3274 22.8224L21.8995 16.0762C21.0284 15.3386 20.2227 14.7346 19.6677 14.5037C19.2263 14.3201 19.0551 13.6941 19.5023 13.3497L20.6563 12.4606C20.8517 12.3422 21.3174 12.1979 21.6163 12.5686L22.4088 13.5326L29.2498 21.952Z\"\n        fill={color}\n      />\n      <path\n        d=\"M11.8478 1.99067C10.5707 1.99067 9.16387 2.29138 7.65774 3.03904C4.50493 4.60413 2.85603 7.82981 2.33475 10.202C1.60286 13.5326 2.02008 17.0359 3.22442 19.2504C4.07463 20.8137 4.76646 21.6232 6.14326 22.773C8.22894 24.5149 9.81294 25.2866 12.5342 25.6205C13.3997 25.7267 14.7668 25.6858 14.7668 25.6858C15.0555 25.6943 15.3305 25.807 15.5383 26.0018L16.946 27.322L18.5323 28.7087C18.8115 28.9528 18.6338 29.4028 18.2581 29.4028H16.4788C16.1959 29.4028 15.9415 29.1595 15.8496 29.0378C15.2849 28.4856 14.3617 27.6654 14.3617 27.6654L12.5949 27.6134L12.0702 29.601C12.0082 29.8358 11.7904 30 11.5408 30H10.8359C10.4826 30 10.2222 29.6793 10.3044 29.3456L10.7754 27.4341C10.4111 27.3614 10.0218 27.2603 9.62389 27.1204L8.89011 29.615C8.82307 29.8429 8.60863 30 8.36462 30H7.57716C7.21754 30 6.95595 29.6684 7.04944 29.3312L7.88561 26.3144C6.21075 25.5469 4.73704 24.2212 4.73704 24.2212C3.61206 23.3518 2.40208 21.6625 1.93772 20.9265C0.758197 18.9403 0.394862 17.7438 0.0906286 15.4688C-0.12877 13.8281 0.0906362 11.06 0.319969 9.83744C1.19531 6.30038 2.88436 3.2418 6.58906 1.34044C8.46832 0.375947 10.2771 0 11.8478 0C13.447 0 15.5446 0.508003 17.1081 1.30947C18.6578 2.10386 19.4247 2.82829 20.4677 3.84627C20.795 4.1666 21.6271 4.79496 22.3369 4.74577C22.7866 4.80486 24.0471 4.75887 25.4919 4.10215C26.2394 3.83912 26.7594 4.35638 26.9213 4.63196C27.103 4.91761 27.3006 5.6137 26.6372 6.11287L21.7843 9.76476C21.5609 10.1265 21.3962 10.4625 21.3325 10.7478C21.1055 11.6585 20.3487 11.25 20.057 11.06C19.7653 10.87 19.0996 9.90218 19.0996 9.90218C18.8562 9.60785 18.9128 9.17176 19.2335 8.94832C19.5878 8.70146 20.7613 7.88917 21.6518 7.34629L22.4617 6.73683C21.868 6.78175 20.3598 6.55944 19.0768 5.3108C19.0768 5.3108 17.441 3.72084 16.1516 3.07001C14.6097 2.29178 13.0964 1.99067 11.8478 1.99067Z\"\n        fill={color}\n      />\n    </svg>\n  );\n};\n"
  },
  {
    "path": "wren-ui/src/components/LogoBar.tsx",
    "content": "import Image from 'next/image';\n\nexport default function LogoBar() {\n  return (\n    <Image\n      src=\"/images/logo-white-with-text.svg\"\n      alt=\"Wren AI\"\n      width={125}\n      height={30}\n    />\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/PageLoading.tsx",
    "content": "import { Spin } from 'antd';\nimport styled from 'styled-components';\nimport LoadingOutlined from '@ant-design/icons/LoadingOutlined';\n\nconst Wrapper = styled.div`\n  position: absolute;\n  top: 48px;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  z-index: 9999;\n  background-color: white;\n  display: none;\n\n  &.isShow {\n    display: flex;\n  }\n`;\n\ninterface Props {\n  visible?: boolean;\n}\n\ninterface LoadingProps {\n  children?: React.ReactNode | null;\n  spinning?: boolean;\n  loading?: boolean;\n  tip?: string;\n  size?: number;\n  width?: number;\n  height?: number;\n  className?: string;\n}\n\nexport const defaultIndicator = (\n  <LoadingOutlined style={{ fontSize: 36 }} spin />\n);\n\nexport const Spinner = ({ className = '', size = 36 }) => (\n  <LoadingOutlined className={className} style={{ fontSize: size }} spin />\n);\n\nexport default function PageLoading(props: Props) {\n  const { visible } = props;\n  return (\n    <Wrapper\n      className={`align-center justify-center${visible ? ' isShow' : ''}`}\n    >\n      <div className=\"text-center\">\n        <Spin indicator={defaultIndicator} />\n        <div className=\"mt-2 geekblue-6\">Loading...</div>\n      </div>\n    </Wrapper>\n  );\n}\n\nexport const FlexLoading = (props) => {\n  const { height, tip } = props;\n  return (\n    <div\n      className=\"d-flex align-center justify-center flex-column geekblue-6\"\n      style={{ height: height || '100%' }}\n    >\n      {defaultIndicator}\n      {tip && <span className=\"mt-2\">{tip}</span>}\n    </div>\n  );\n};\n\nexport const Loading = ({\n  children = null,\n  spinning = false,\n  loading = false,\n  tip,\n}: LoadingProps) => (\n  <Spin indicator={defaultIndicator} spinning={spinning || loading} tip={tip}>\n    {children}\n  </Spin>\n);\n\ninterface LoadingWrapperProps {\n  loading: boolean;\n  tip?: string;\n  children: React.ReactElement;\n}\n\nexport const LoadingWrapper = (props: LoadingWrapperProps) => {\n  const { loading, tip, children } = props;\n  if (loading) return <FlexLoading tip={tip} />;\n  return children;\n};\n"
  },
  {
    "path": "wren-ui/src/components/chart/handler.ts",
    "content": "import {\n  ChartType,\n  ThreadResponseChartDetail,\n} from '@/apollo/client/graphql/__types__';\nimport { isNil, cloneDeep, uniq, sortBy, omit, isNumber } from 'lodash';\nimport { Config, TopLevelSpec } from 'vega-lite';\n\nenum MarkType {\n  ARC = 'arc',\n  AREA = 'area',\n  BAR = 'bar',\n  BOXPLOT = 'boxplot',\n  CIRCLE = 'circle',\n  ERRORBAND = 'errorband',\n  ERRORBAR = 'errorbar',\n  IMAGE = 'image',\n  LINE = 'line',\n  POINT = 'point',\n  RECT = 'rect',\n  RULE = 'rule',\n  SQUARE = 'square',\n  TEXT = 'text',\n  TICK = 'tick',\n  TRAIL = 'trail',\n}\n\nconst COLOR = {\n  GRAY_10: '#262626',\n  GRAY_9: '#434343',\n  GRAY_8: '#65676c',\n  GRAY_5: '#d9d9d9',\n};\n\n// Default color scheme\nconst colorScheme = [\n  '#7763CF',\n  '#444CE7',\n  '#1570EF',\n  '#0086C9',\n  '#3E4784',\n  '#E31B54',\n  '#EC4A0A',\n  '#EF8D0C',\n  '#EBC405',\n  '#5381AD',\n];\n\n// high contrast color scheme\nconst pickedColorScheme = [\n  colorScheme[4],\n  colorScheme[5],\n  colorScheme[8],\n  colorScheme[3],\n  colorScheme[0],\n];\n\nconst DEFAULT_COLOR = colorScheme[2];\n\n// type EncodingFieldType = 'quantitative' | 'nominal' | 'temporal';\ntype DataSpec = { values: Record<string, any>[] };\ntype EncodingSpec = Extract<TopLevelSpec, { encoding?: any }>['encoding'] & {\n  x: { type: string; field: string };\n  y: { type: string; field: string };\n};\ntype MarkSpec = Extract<TopLevelSpec, { mark?: any }>['mark'] extends\n  | string\n  | infer M\n  ? M\n  : never;\ntype AutosizeSpec = Extract<TopLevelSpec, { autosize?: any }>['autosize'];\ntype ParamsSpec = {\n  name: string;\n  select: {\n    type: string;\n    fields?: string[];\n    on: string;\n    clear: string;\n  };\n  value?: any;\n}[];\ntype TransformSpec = Extract<TopLevelSpec, { transform?: any }>['transform'];\n\ntype ChartOptions = {\n  width?: number | string;\n  height?: number | string;\n  stack?: 'zero' | 'normalize';\n  point?: boolean;\n  donutInner?: number | false;\n  categoriesLimit?: number;\n  isShowTopCategories?: boolean;\n  isHideLegend?: boolean;\n  isHideTitle?: boolean;\n};\n\nconst config: Config = {\n  mark: { tooltip: true },\n  font: 'Roboto, Arial, Noto Sans, sans-serif',\n  padding: {\n    top: 30,\n    bottom: 20,\n    left: 0,\n    right: 0,\n  },\n  title: {\n    color: COLOR.GRAY_10,\n    fontSize: 14,\n  },\n  axis: {\n    labelPadding: 0,\n    labelOffset: 0,\n    labelFontSize: 10,\n    gridColor: COLOR.GRAY_5,\n    titleColor: COLOR.GRAY_9,\n    labelColor: COLOR.GRAY_8,\n    labelFont: ' Roboto, Arial, Noto Sans, sans-serif',\n  },\n  axisX: { labelAngle: -45 },\n  line: {\n    color: DEFAULT_COLOR,\n  },\n  bar: {\n    color: DEFAULT_COLOR,\n  },\n  legend: {\n    symbolLimit: 15,\n    columns: 1,\n    labelFontSize: 10,\n    labelColor: COLOR.GRAY_8,\n    titleColor: COLOR.GRAY_9,\n    titleFontSize: 14,\n  },\n  range: {\n    category: colorScheme,\n    ordinal: colorScheme,\n    diverging: colorScheme,\n    symbol: colorScheme,\n    heatmap: colorScheme,\n    ramp: colorScheme,\n  },\n  point: { size: 60, color: DEFAULT_COLOR },\n};\n\nexport default class ChartSpecHandler {\n  public config: Config;\n  public options: ChartOptions;\n  public $schema: string;\n  public title: string;\n  public data: DataSpec;\n  public encoding: EncodingSpec;\n  public mark: MarkSpec;\n  public autosize: AutosizeSpec;\n  public params: ParamsSpec;\n  public transform: TransformSpec;\n\n  constructor(spec: TopLevelSpec, options?: ChartOptions) {\n    this.config = config;\n    this.data = spec.data as DataSpec;\n    this.autosize = { type: 'fit', contains: 'padding' };\n    this.params = [\n      {\n        name: 'hover',\n        select: {\n          type: 'point',\n          on: 'mouseover',\n          clear: 'mouseout',\n        },\n      },\n    ];\n    // default options\n    this.options = {\n      width: isNil(options?.width) ? 'container' : options.width,\n      height: isNil(options?.height) ? 'container' : options.height,\n      stack: isNil(options?.stack) ? 'zero' : options.stack,\n      point: isNil(options?.point) ? true : options.point,\n      donutInner: isNil(options?.donutInner) ? 60 : options.donutInner,\n      categoriesLimit: isNil(options?.categoriesLimit)\n        ? 25\n        : options.categoriesLimit,\n      isShowTopCategories: isNil(options?.isShowTopCategories)\n        ? false\n        : options?.isShowTopCategories,\n      isHideLegend: isNil(options?.isHideLegend) ? false : options.isHideLegend,\n      isHideTitle: isNil(options?.isHideTitle) ? false : options.isHideTitle,\n    };\n\n    // avoid mutating the original spec\n    const clonedSpec = cloneDeep(spec);\n    this.parseSpec(clonedSpec);\n  }\n\n  public getChartSpec() {\n    const categories = this.getAllCategories(this.encoding);\n    // chart not support if categories more than the categories limit\n    if (categories.length > this.options.categoriesLimit) {\n      return null;\n    }\n\n    // if categories less or equal 5, use the picked color\n    if (categories.length <= 5) {\n      // Set the contrast color range on the color encoding instead of x/xOffset\n      this.encoding.color = {\n        ...this.encoding.color,\n        scale: {\n          range: pickedColorScheme,\n        },\n      } as any;\n    }\n\n    if (this.options.isHideLegend) {\n      this.encoding.color = {\n        ...this.encoding.color,\n        legend: null,\n      } as any;\n    }\n\n    if (this.options.isHideTitle) {\n      this.title = null;\n    }\n\n    // transform values\n    this.data = this.transformDataValues(this.data, this.encoding);\n\n    return {\n      $schema: this.$schema,\n      title: this.title,\n      data: this.data,\n      mark: this.mark,\n      width: this.options.width,\n      height: this.options.height,\n      autosize: this.autosize,\n      encoding: this.encoding,\n      params: this.params,\n      transform: this.transform,\n    } as TopLevelSpec;\n  }\n\n  private parseSpec(spec: TopLevelSpec) {\n    this.$schema = spec.$schema;\n    this.title = spec.title as string;\n    this.transform = spec.transform;\n\n    if ('mark' in spec) {\n      const mark =\n        typeof spec.mark === 'string' ? { type: spec.mark } : spec.mark;\n      this.addMark(mark);\n    }\n\n    if ('encoding' in spec) {\n      // filter top categories before encoding scale calculation\n      if (this.options?.isShowTopCategories) {\n        const filteredData = this.filterTopCategories(\n          spec.encoding as EncodingSpec,\n        );\n        if (filteredData) this.data = filteredData;\n      }\n\n      this.addEncoding(spec.encoding as EncodingSpec);\n    }\n  }\n\n  private addMark(mark: MarkSpec) {\n    let additionalProps = {};\n\n    if (mark.type === MarkType.LINE) {\n      additionalProps = { point: this.options.point, tooltip: true };\n    } else if (mark.type === MarkType.ARC) {\n      additionalProps = { innerRadius: this.options.donutInner };\n    }\n    this.mark = { type: mark.type, ...additionalProps };\n  }\n\n  private addEncoding(encoding: EncodingSpec) {\n    this.encoding = encoding;\n\n    // fill color by x field if AI not provide color(category) field\n    if (isNil(this.encoding.color)) {\n      // find the nominal axis\n      const nominalAxis = ['x', 'y'].find(\n        (axis) => encoding[axis]?.type === 'nominal',\n      );\n      if (nominalAxis) {\n        const category = encoding[nominalAxis] as any;\n        this.encoding.color = {\n          field: category.field,\n          type: category.type,\n        };\n      }\n    }\n\n    // handle scale on bar chart\n    if (this.mark.type === MarkType.BAR) {\n      if ('stack' in this.encoding.y) {\n        this.encoding.y.stack = this.options.stack;\n      }\n\n      if ('xOffset' in this.encoding) {\n        const xOffset = this.encoding.xOffset as any;\n        let title = xOffset?.title;\n        // find xOffset title if not provided\n        if (!title) {\n          title = this.findFieldTitleInEncoding(this.encoding, xOffset?.field);\n        }\n        this.encoding.xOffset = { ...xOffset, title };\n      }\n    }\n\n    this.addHoverHighlight(this.encoding);\n  }\n\n  private addHoverHighlight(encoding: EncodingSpec) {\n    const category = (\n      encoding.color?.condition ? encoding.color.condition : encoding.color\n    ) as { type: any; field: string; title?: string };\n    if (!category?.field || !category?.type) return;\n\n    // Define the hover parameter correctly\n    if (this.params && category?.field) {\n      this.params[0].select.fields = [category.field];\n    }\n\n    this.encoding.opacity = {\n      condition: {\n        param: 'hover',\n        value: 1,\n      },\n      value: 0.3,\n    };\n\n    let title = category?.title;\n    // find color title if not provided\n    if (!title) {\n      title = this.findFieldTitleInEncoding(this.encoding, category?.field);\n    }\n\n    // basic color properties\n    const colorProperties = {\n      title,\n      field: category?.field,\n      type: category?.type,\n      scale: {\n        range: colorScheme,\n      },\n    } as any;\n\n    this.encoding.color = {\n      ...colorProperties,\n      condition: {\n        param: 'hover',\n        ...omit(colorProperties, 'scale'),\n      } as any,\n    };\n  }\n\n  private filterTopCategories(encoding: EncodingSpec) {\n    const nominalKeys = ['xOffset', 'color', 'x', 'y'].filter(\n      (axis) => encoding[axis]?.type === 'nominal',\n    );\n    const quantitativeKeys = ['theta', 'x', 'y'].filter(\n      (axis) => encoding[axis]?.type === 'quantitative',\n    );\n    if (!nominalKeys.length || !quantitativeKeys.length) return;\n\n    const clonedValues = cloneDeep((this.data as any).values);\n\n    const quantitativeAxis = quantitativeKeys[0];\n    const quanAxis = encoding[quantitativeAxis] as any;\n    const sortedValues = sortBy(clonedValues, (val) => {\n      const value = val[quanAxis.field];\n      return isNumber(value) ? -value : 0;\n    });\n\n    // nominal values probably have different length, so we need to filter them\n    const filteredNominals = [];\n    for (const nominalKey of nominalKeys) {\n      const nomiAxis = encoding[nominalKey] as any;\n      if (filteredNominals.some((val) => val.field === nomiAxis.field)) {\n        continue;\n      }\n      const nominalValues = sortedValues.map((val) => val[nomiAxis.field]);\n      const uniqueNominalValues = uniq(nominalValues);\n      const topNominalValues = uniqueNominalValues.slice(\n        0,\n        this.options.categoriesLimit,\n      );\n      filteredNominals.push({\n        field: nomiAxis.field,\n        values: topNominalValues,\n      });\n    }\n    const values = clonedValues.filter((val) =>\n      filteredNominals.every((nominal) =>\n        nominal.values.includes(val[nominal.field]),\n      ),\n    );\n    return { values };\n  }\n\n  private getAllCategories(encoding: EncodingSpec) {\n    const nominalAxis = ['xOffset', 'color', 'x', 'y'].find(\n      (axis) => encoding[axis]?.type === 'nominal',\n    );\n    if (!nominalAxis) return [];\n    const axisKey = encoding[nominalAxis] as any;\n    const values = (this.data as any).values;\n    const categoryValues = values.map((val) => val[axisKey.field]);\n    const uniqueCategoryValues = uniq(categoryValues);\n\n    return uniqueCategoryValues;\n  }\n\n  private findFieldTitleInEncoding(encoding: EncodingSpec, field: string) {\n    const axis = ['x', 'y', 'xOffset', 'color'].find(\n      (axis) => encoding[axis]?.field === field && encoding[axis]?.title,\n    ) as any;\n    return encoding[axis]?.title || undefined;\n  }\n\n  private transformDataValues(\n    data: DataSpec,\n    encoding: {\n      x?: { type?: string; field?: string };\n      y?: { type?: string; field?: string };\n    },\n  ) {\n    // If axis x is temporal\n    if (encoding?.x?.type === 'temporal') {\n      const transformedValues = data.values.map((val) => ({\n        ...val,\n        [encoding.x.field]: this.transformTemporalValue(val[encoding.x.field]),\n      }));\n      return { ...data, values: transformedValues };\n    }\n    // If axis y is temporal\n    if (encoding?.y?.type === 'temporal') {\n      const transformedValues = data.values.map((val) => ({\n        ...val,\n        [encoding.y.field]: this.transformTemporalValue(val[encoding.y.field]),\n      }));\n      return { ...data, values: transformedValues };\n    }\n    return data;\n  }\n\n  private transformTemporalValue(value: string | any) {\n    if (value === null || value === undefined) {\n      return value;\n    }\n    const strValue = typeof value === 'string' ? value : String(value);\n    // Safari not support if containing \"YYYY-MM-DD HH:mm:ss.SSS UTC+00:00\"\n    // so we remove the UTC+00:00 for compatibility\n    if (strValue.includes('UTC')) {\n      return strValue.replace(/\\s+UTC([+-][0-9]+)?(:[0-9]+)?/, '');\n    }\n    return strValue;\n  }\n}\n\nexport const convertToChartType = (\n  markType: string,\n  encoding: EncodingSpec,\n) => {\n  if (markType === MarkType.BAR) {\n    if (encoding?.xOffset) {\n      return ChartType.GROUPED_BAR;\n    } else if (\n      !isNil((encoding?.y as any)?.stack) ||\n      !isNil((encoding?.x as any)?.stack)\n    ) {\n      return ChartType.STACKED_BAR;\n    }\n  } else if (markType === MarkType.ARC) {\n    return ChartType.PIE;\n  }\n  return markType ? (markType.toUpperCase() as ChartType) : null;\n};\n\nexport const getChartSpecOptionValues = (\n  chartDetail: ThreadResponseChartDetail,\n) => {\n  const spec = chartDetail?.chartSchema;\n  let chartType: string | null = chartDetail?.chartType || null;\n  let xAxis: string | null = null;\n  let yAxis: string | null = null;\n  let color: string | null = null;\n  let xOffset: string | null = null;\n  let theta: string | null = null;\n\n  if (spec && 'encoding' in spec) {\n    const encoding = spec.encoding as EncodingSpec;\n    xAxis = (encoding?.x as any)?.field || null;\n    yAxis = (encoding?.y as any)?.field || null;\n    color = (encoding?.color as any)?.field || null;\n    xOffset = (encoding?.xOffset as any)?.field || null;\n    theta = (encoding?.theta as any)?.field || null;\n    if (chartType === null) {\n      chartType = convertToChartType(\n        typeof spec.mark === 'string' ? spec.mark : spec.mark.type,\n        encoding,\n      );\n    }\n  }\n  return {\n    chartType,\n    xAxis,\n    yAxis,\n    color,\n    xOffset,\n    theta,\n  };\n};\n\nexport const getChartSpecFieldTitleMap = (encoding: EncodingSpec) => {\n  if (!encoding) return {};\n  const allFields = ['x', 'y', 'xOffset', 'color'].reduce((result, key) => {\n    const axis = encoding[key] as any;\n    if (axis?.field && axis?.title) {\n      result[axis?.field] = axis?.title;\n    }\n    return result;\n  }, {});\n  return allFields;\n};\n"
  },
  {
    "path": "wren-ui/src/components/chart/index.tsx",
    "content": "import { useEffect, useRef, useState } from 'react';\nimport clsx from 'clsx';\nimport { isEmpty } from 'lodash';\nimport { Alert, Button, Tooltip } from 'antd';\nimport { TopLevelSpec, compile } from 'vega-lite';\nimport embed, { EmbedOptions, Result } from 'vega-embed';\nimport ChartSpecHandler from './handler';\nimport ReloadOutlined from '@ant-design/icons/ReloadOutlined';\nimport EditOutlined from '@ant-design/icons/EditOutlined';\nimport EyeOutlined from '@ant-design/icons/EyeOutlined';\nimport PushPinOutlined from '@ant-design/icons/PushpinOutlined';\nimport ErrorCollapse from '@/components/ErrorCollapse';\n\nconst embedOptions: EmbedOptions = {\n  mode: 'vega-lite',\n  renderer: 'svg',\n  tooltip: { theme: 'custom' },\n  actions: {\n    export: true,\n    editor: false,\n  },\n};\n\ninterface VegaLiteProps {\n  className?: string;\n  width?: number | string;\n  height?: number | string;\n  spec?: TopLevelSpec;\n  values?: Record<string, any>[];\n  autoFilter?: boolean;\n  hideActions?: boolean;\n  hideTitle?: boolean;\n  hideLegend?: boolean;\n  forceUpdate?: number;\n  isPinned?: boolean;\n  onReload?: () => void;\n  onEdit?: () => void;\n  onPin?: () => void;\n}\n\nexport default function Chart(props: VegaLiteProps) {\n  const {\n    className,\n    spec,\n    values,\n    width = 600,\n    height = 320,\n    autoFilter,\n    hideActions,\n    hideTitle,\n    hideLegend,\n    forceUpdate,\n    isPinned,\n    onReload,\n    onEdit,\n    onPin,\n  } = props;\n\n  const [donutInner, setDonutInner] = useState(null);\n  const [parsedSpec, setParsedSpec] =\n    useState<ReturnType<typeof compile>['spec']>(null);\n  const [parsedError, setParsedError] = useState<Record<string, any>>(null);\n  const [isShowTopCategories, setIsShowTopCategories] = useState(false);\n  const $view = useRef<Result>(null);\n  const $container = useRef<HTMLDivElement>(null);\n\n  useEffect(() => {\n    if (!spec || !values) return;\n    try {\n      const specHandler = new ChartSpecHandler(\n        {\n          ...spec,\n          data: { values },\n        },\n        {\n          donutInner,\n          isShowTopCategories: autoFilter || isShowTopCategories,\n          isHideLegend: hideLegend,\n          isHideTitle: hideTitle,\n        },\n      );\n      const chartSpec = specHandler.getChartSpec();\n      const isDataEmpty = isEmpty((chartSpec?.data as any)?.values);\n      if (isDataEmpty) {\n        setParsedSpec(null);\n      } else {\n        const compiled = compile(chartSpec, { config: specHandler.config });\n        setParsedSpec(compiled.spec);\n      }\n    } catch (error) {\n      console.error(error);\n      setParsedError({\n        code: 'CLIENT_PARSE_ERROR',\n        shortMessage: 'Failed to render chart visualization',\n        message: error?.message,\n        stacktrace: error?.stack?.split('\\n') || [],\n      });\n    }\n    return () => {\n      setParsedSpec(null);\n      setParsedError(null);\n    };\n  }, [spec, values, isShowTopCategories, donutInner, forceUpdate]);\n\n  // initial vega view\n  useEffect(() => {\n    if ($container.current && parsedSpec) {\n      embed($container.current, parsedSpec, embedOptions).then((view) => {\n        $view.current = view;\n      });\n    }\n    return () => {\n      if ($view.current) $view.current.finalize();\n    };\n  }, [parsedSpec, forceUpdate]);\n\n  useEffect(() => {\n    if ($container.current) {\n      setDonutInner($container.current.clientHeight * 0.15);\n    }\n  }, [forceUpdate]);\n\n  const onShowTopCategories = () => {\n    setIsShowTopCategories(!isShowTopCategories);\n  };\n\n  const getChartContent = () => {\n    if (values.length === 0) return <div>No available data</div>;\n\n    if (parsedError) {\n      return (\n        <div\n          className={clsx({ 'mx-4 mt-12': !isPinned })}\n          onMouseDown={(e) => e.stopPropagation()}\n        >\n          <Alert\n            showIcon\n            type=\"error\"\n            message={parsedError.shortMessage}\n            description={\n              <ErrorCollapse message={parsedError.message} defaultActive />\n            }\n          />\n        </div>\n      );\n    }\n\n    if (parsedSpec === null) {\n      return (\n        <Alert\n          className=\"mt-12 mb-4 mx-4\"\n          message={\n            <div className=\"d-flex align-center justify-space-between\">\n              <div>\n                There are too many categories to display effectively. Click\n                'Show top 25' to view the top results, or ask a follow-up\n                question to focus on a specific group or filter results.\n              </div>\n              <Button\n                size=\"small\"\n                icon={<EyeOutlined />}\n                onClick={onShowTopCategories}\n              >\n                Show top 25\n              </Button>\n            </div>\n          }\n          type=\"warning\"\n        />\n      );\n    }\n\n    return <div style={{ width, height }} ref={$container} />;\n  };\n\n  const isAdditionalShow = !!onReload || !!onEdit || !!onPin;\n\n  return (\n    <div\n      className={clsx(\n        'adm-chart',\n        { 'adm-chart--no-actions': hideActions },\n        className,\n      )}\n      style={{ width }}\n    >\n      {isAdditionalShow && (\n        <div className=\"adm-chart-additional d-flex justify-content-between align-center\">\n          {!!onReload && (\n            <Tooltip title=\"Regenerate chart\">\n              <button onClick={onReload}>\n                <ReloadOutlined />\n              </button>\n            </Tooltip>\n          )}\n          {!!onEdit && (\n            <Tooltip title=\"Edit chart\">\n              <button onClick={onEdit}>\n                <EditOutlined />\n              </button>\n            </Tooltip>\n          )}\n          {!!onPin && (\n            <Tooltip title=\"Pin chart to dashboard\">\n              <button onClick={onPin}>\n                <PushPinOutlined />\n              </button>\n            </Tooltip>\n          )}\n        </div>\n      )}\n      {getChartContent()}\n    </div>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/chart/properties/BasicProperties.tsx",
    "content": "import { capitalize } from 'lodash';\nimport { Form, Row, Col, Select } from 'antd';\nimport { ChartType } from '@/apollo/client/graphql/__types__';\n\nexport const getChartTypeOptions = () => {\n  return Object.entries(ChartType).map(([key, value]) => ({\n    label: capitalize(value.replace('_', ' ')),\n    value: key,\n  }));\n};\n\nexport const getColumnOptions = (\n  columns: { name: string; type: string }[],\n  titleMap?: Record<string, string>,\n) => {\n  return (columns || []).map((column) => ({\n    label: titleMap?.[column.name] || column.name,\n    value: column.name,\n  }));\n};\n\nexport function ChartTypeProperty(props: {\n  options: { label: string; value: string }[];\n}) {\n  const { options } = props;\n  return (\n    <Form.Item className=\"mb-0\" label=\"Chart type\" name=\"chartType\">\n      <Select size=\"small\" options={options} placeholder=\"Select chart type\" />\n    </Form.Item>\n  );\n}\n\nexport function AxisProperty(props: {\n  options: { label: string; value: string }[];\n}) {\n  const { options } = props;\n  return (\n    <Row gutter={16}>\n      <Col span={12}>\n        <Form.Item className=\"mb-0\" label=\"X-axis\" name=\"xAxis\">\n          <Select size=\"small\" options={options} placeholder=\"Select x-axis\" />\n        </Form.Item>\n      </Col>\n      <Col span={12}>\n        <Form.Item className=\"mb-0\" label=\"Y-axis\" name=\"yAxis\">\n          <Select size=\"small\" options={options} placeholder=\"Select y-axis\" />\n        </Form.Item>\n      </Col>\n    </Row>\n  );\n}\n\nexport interface PropertiesProps {\n  columns: { name: string; type: string }[];\n  titleMap: Record<string, string>;\n  onChartTypeChange: (chartType: ChartType) => void;\n}\n\nexport default function BasicProperties(props: PropertiesProps) {\n  const { columns, titleMap } = props;\n  const chartTypeOptions = getChartTypeOptions();\n  const columnOptions = getColumnOptions(columns, titleMap);\n  return (\n    <>\n      <Row className=\"mb-2\" gutter={16}>\n        <Col span={12}>\n          <ChartTypeProperty options={chartTypeOptions} />\n        </Col>\n        <Col span={12}></Col>\n      </Row>\n      <AxisProperty options={columnOptions} />\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/chart/properties/DonutProperties.tsx",
    "content": "import { Form, Row, Col, Select } from 'antd';\nimport {\n  PropertiesProps,\n  getColumnOptions,\n  getChartTypeOptions,\n  ChartTypeProperty,\n} from './BasicProperties';\n\nexport default function DonutProperties(props: PropertiesProps) {\n  const { columns, titleMap } = props;\n  const chartTypeOptions = getChartTypeOptions();\n  const columnOptions = getColumnOptions(columns, titleMap);\n  return (\n    <>\n      <Row gutter={16} className=\"mb-2\">\n        <Col span={12}>\n          <ChartTypeProperty options={chartTypeOptions} />\n        </Col>\n        <Col span={12}>\n          <Form.Item className=\"mb-0\" label=\"Category\" name=\"color\">\n            <Select\n              size=\"small\"\n              options={columnOptions}\n              placeholder=\"Select category\"\n            />\n          </Form.Item>\n        </Col>\n      </Row>\n      <Row gutter={16}>\n        <Col span={12}>\n          <Form.Item className=\"mb-0\" label=\"Value\" name=\"theta\">\n            <Select\n              size=\"small\"\n              options={columnOptions}\n              placeholder=\"Select value\"\n            />\n          </Form.Item>\n        </Col>\n        <Col span={12}></Col>\n      </Row>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/chart/properties/GroupedBarProperties.tsx",
    "content": "import { Form, Row, Col, Select } from 'antd';\nimport {\n  PropertiesProps,\n  getChartTypeOptions,\n  getColumnOptions,\n  ChartTypeProperty,\n  AxisProperty,\n} from './BasicProperties';\n\nexport default function GroupedBarProperties(props: PropertiesProps) {\n  const { columns, titleMap } = props;\n  const chartTypeOptions = getChartTypeOptions();\n  const columnOptions = getColumnOptions(columns, titleMap);\n  return (\n    <>\n      <Row className=\"mb-2\" gutter={16}>\n        <Col span={12}>\n          <ChartTypeProperty options={chartTypeOptions} />\n        </Col>\n        <Col span={12}>\n          <Form.Item className=\"mb-0\" label=\"Sub-category\" name=\"xOffset\">\n            <Select\n              size=\"small\"\n              options={columnOptions}\n              placeholder=\"Select sub-category\"\n            />\n          </Form.Item>\n        </Col>\n      </Row>\n      <AxisProperty options={columnOptions} />\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/chart/properties/LineProperties.tsx",
    "content": "import { Form, Row, Col, Select } from 'antd';\nimport {\n  PropertiesProps,\n  getChartTypeOptions,\n  getColumnOptions,\n  ChartTypeProperty,\n  AxisProperty,\n} from './BasicProperties';\n\nexport default function LineProperties(props: PropertiesProps) {\n  const { columns, titleMap } = props;\n  const chartTypeOptions = getChartTypeOptions();\n  const columnOptions = getColumnOptions(columns, titleMap);\n  return (\n    <>\n      <Row className=\"mb-2\" gutter={16}>\n        <Col span={12}>\n          <ChartTypeProperty options={chartTypeOptions} />\n        </Col>\n        <Col span={12}>\n          <Form.Item className=\"mb-0\" label=\"Line groups\" name=\"color\">\n            <Select\n              size=\"small\"\n              options={columnOptions}\n              placeholder=\"Select line groups\"\n            />\n          </Form.Item>\n        </Col>\n      </Row>\n      <AxisProperty options={columnOptions} />\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/chart/properties/StackedBarProperties.tsx",
    "content": "import { Form, Row, Col, Select } from 'antd';\nimport {\n  PropertiesProps,\n  getChartTypeOptions,\n  getColumnOptions,\n  ChartTypeProperty,\n  AxisProperty,\n} from './BasicProperties';\n\nexport default function StackedBarProperties(props: PropertiesProps) {\n  const { columns, titleMap } = props;\n  const chartTypeOptions = getChartTypeOptions();\n  const columnOptions = getColumnOptions(columns, titleMap);\n  return (\n    <>\n      <Row className=\"mb-2\" gutter={16}>\n        <Col span={12}>\n          <ChartTypeProperty options={chartTypeOptions} />\n        </Col>\n        <Col span={12}>\n          <Form.Item className=\"mb-0\" label=\"Stack groups\" name=\"color\">\n            <Select\n              size=\"small\"\n              options={columnOptions}\n              placeholder=\"Select stack groups\"\n            />\n          </Form.Item>\n        </Col>\n      </Row>\n      <AxisProperty options={columnOptions} />\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/code/BaseCodeBlock.tsx",
    "content": "import { useEffect, useRef, useState } from 'react';\nimport styled from 'styled-components';\nimport { Button, Typography } from 'antd';\nimport CheckOutlined from '@ant-design/icons/CheckOutlined';\nimport CopyOutlined from '@ant-design/icons/CopyOutlined';\nimport { Loading } from '@/components/PageLoading';\nimport '@/components/editor/AceEditor';\n\nexport interface BaseProps {\n  code: string;\n  copyable?: boolean;\n  inline?: boolean;\n  loading?: boolean;\n  maxHeight?: string;\n  showLineNumbers?: boolean;\n  backgroundColor?: string;\n  onCopy?: () => void;\n}\n\nconst getBlockStyles = (props: {\n  inline?: boolean;\n  backgroundColor?: string;\n}) => {\n  if (props.inline) {\n    return `\n      display: inline;\n      border: none;\n      background: transparent !important;\n      padding: 0;\n      * { display: inline !important; }\n    `;\n  }\n  return `\n    background: ${props.backgroundColor || 'var(--gray-1)'} !important;\n    padding: 8px;\n  `;\n};\n\nexport const Block = styled.div<{\n  maxHeight?: string;\n  inline?: boolean;\n  backgroundColor?: string;\n}>`\n  position: relative;\n  white-space: pre;\n  font-size: 13px;\n  border: 1px var(--gray-4) solid;\n  border-radius: 4px;\n  font-family: 'Source Code Pro', monospace;\n  user-select: text;\n  cursor: text;\n  &:focus {\n    outline: none;\n  }\n  ${getBlockStyles}\n\n  .adm-code-wrap {\n    ${(props) => (props.inline ? '' : 'overflow: auto;')}\n    ${(props) => (props.maxHeight ? `max-height: ${props.maxHeight}px;` : ``)}\n    user-select: text;\n  }\n\n  .adm-code-line {\n    display: block;\n    user-select: text;\n    &-number {\n      user-select: none;\n      display: inline-block;\n      min-width: 14px;\n      text-align: right;\n      margin-right: 1em;\n      color: var(--gray-6);\n      font-weight: 700;\n      font-size: 12px;\n    }\n  }\n`;\n\nexport const CopyText = styled(Typography.Text)<{ $hasVScrollbar: boolean }>`\n  position: absolute;\n  top: 0;\n  right: ${(props) => (props.$hasVScrollbar ? '20px' : '0')};\n  font-size: 0;\n  button {\n    background: var(--gray-1) !important;\n  }\n\n  .ant-typography-copy {\n    font-size: 12px;\n  }\n\n  .ant-btn:not(:hover) {\n    color: var(--gray-8);\n  }\n`;\n\nexport const addThemeStyleManually = (cssText: string) => {\n  const id = 'ace-tomorrow';\n  const themeElement = document.getElementById(id);\n  if (!themeElement) {\n    const styleElement = document.createElement('style');\n    styleElement.id = id;\n    document.head.appendChild(styleElement);\n    styleElement.appendChild(document.createTextNode(cssText));\n  }\n};\n\nexport const createCodeBlock = (HighlightRules: any) => {\n  return function CodeBlock(props: BaseProps) {\n    const {\n      code,\n      copyable,\n      maxHeight,\n      inline,\n      loading,\n      showLineNumbers,\n      backgroundColor,\n      onCopy,\n    } = props;\n    const { ace } = window as any;\n    const { Tokenizer } = ace.require('ace/tokenizer');\n    const rules = new HighlightRules();\n    const tokenizer = new Tokenizer(rules.getRules());\n\n    const codeWrapRef = useRef<HTMLDivElement>(null);\n    const [hasVerticalScrollbar, setHasVerticalScrollbar] =\n      useState<boolean>(false);\n\n    useEffect(() => {\n      const { cssText } = ace.require('ace/theme/tomorrow');\n      addThemeStyleManually(cssText);\n    }, []);\n\n    useEffect(() => {\n      const el = codeWrapRef.current;\n      if (!el) return;\n\n      const hasScroll = el.scrollHeight > el.clientHeight;\n      setHasVerticalScrollbar(hasScroll);\n    }, [code]);\n\n    const lines = (code || '').split('\\n').map((line, index) => {\n      const tokens = tokenizer.getLineTokens(line).tokens;\n      const children = tokens.map((token, index) => {\n        const classNames = token.type.split('.').map((name) => `ace_${name}`);\n        return (\n          <span key={index} className={classNames.join(' ')}>\n            {token.value}\n          </span>\n        );\n      });\n\n      return (\n        <span className=\"adm-code-line ace_line\" key={`${line}-${index}`}>\n          {showLineNumbers && (\n            <span className=\"adm-code-line-number\">{index + 1}</span>\n          )}\n          {children}\n        </span>\n      );\n    });\n\n    const handleKeyDown = (e: React.KeyboardEvent) => {\n      if ((e.metaKey || e.ctrlKey) && e.key === 'a') {\n        e.preventDefault();\n        const selection = window.getSelection();\n        const range = document.createRange();\n        range.selectNodeContents(\n          e.currentTarget.querySelector('.adm-code-wrap') || e.currentTarget,\n        );\n        selection?.removeAllRanges();\n        selection?.addRange(range);\n      }\n    };\n\n    return (\n      <Block\n        className=\"ace_editor ace-tomorrow adm_code-block\"\n        maxHeight={maxHeight}\n        inline={inline}\n        backgroundColor={backgroundColor}\n        tabIndex={0}\n        onKeyDown={handleKeyDown}\n      >\n        <Loading spinning={loading}>\n          <div className=\"adm-code-wrap\" ref={codeWrapRef}>\n            {lines}\n            {copyable && (\n              <CopyText\n                $hasVScrollbar={hasVerticalScrollbar}\n                copyable={{\n                  onCopy,\n                  icon: [\n                    <Button\n                      key=\"copy-icon\"\n                      icon={<CopyOutlined />}\n                      size=\"small\"\n                      style={{ backgroundColor: 'transparent' }}\n                    />,\n                    <Button\n                      key=\"copied-icon\"\n                      icon={<CheckOutlined className=\"green-6\" />}\n                      size=\"small\"\n                    />,\n                  ],\n                  text: code,\n                }}\n              >\n                {code}\n              </CopyText>\n            )}\n          </div>\n        </Loading>\n      </Block>\n    );\n  };\n};\n"
  },
  {
    "path": "wren-ui/src/components/code/JsonCodeBlock.tsx",
    "content": "import { createCodeBlock, BaseProps } from './BaseCodeBlock';\n\nconst JsonCodeBlock = (props: BaseProps) => {\n  const { code, ...rest } = props;\n  const { ace } = window as any;\n  let formattedJson;\n  try {\n    formattedJson =\n      typeof code === 'string' ? code : JSON.stringify(code, null, 2);\n  } catch {\n    console.warn('Failed to format JSON', code);\n    formattedJson = code;\n  }\n\n  const { JsonHighlightRules } = ace.require('ace/mode/json_highlight_rules');\n  const BaseCodeBlock = createCodeBlock(JsonHighlightRules);\n  return <BaseCodeBlock code={formattedJson} {...rest} />;\n};\n\nexport default JsonCodeBlock;\n"
  },
  {
    "path": "wren-ui/src/components/code/SQLCodeBlock.tsx",
    "content": "import { createCodeBlock, BaseProps } from './BaseCodeBlock';\n\nconst SQLCodeBlock = (props: BaseProps) => {\n  const { ace } = window as any;\n  const { SqlHighlightRules } = ace.require('ace/mode/sql_highlight_rules');\n  const BaseCodeBlock = createCodeBlock(SqlHighlightRules);\n  return <BaseCodeBlock {...props} />;\n};\n\nexport default SQLCodeBlock;\n"
  },
  {
    "path": "wren-ui/src/components/dataPreview/PreviewData.tsx",
    "content": "import { memo, useMemo } from 'react';\nimport { Alert, Typography, Button } from 'antd';\nimport { ApolloError } from '@apollo/client';\nimport styled from 'styled-components';\nimport { getColumnTypeIcon } from '@/utils/columnType';\nimport PreviewDataContent from '@/components/dataPreview/PreviewDataContent';\nimport { parseGraphQLError } from '@/utils/errorHandler';\n\nconst { Text } = Typography;\n\nconst StyledCell = styled.div`\n  position: relative;\n\n  .copy-icon {\n    position: absolute;\n    top: 50%;\n    right: 0;\n    transform: translateY(-50%);\n    opacity: 0;\n    transition: opacity 0.3s;\n  }\n\n  .ant-typography-copy {\n    margin: -4px;\n  }\n\n  &:hover .copy-icon {\n    opacity: 1;\n  }\n`;\n\nconst ColumnTitle = memo((props: { name: string; type: any }) => {\n  const { name, type } = props;\n  const columnTypeIcon = getColumnTypeIcon({ type }, { title: type });\n\n  return (\n    <>\n      {columnTypeIcon}\n      <Text title={name} className=\"ml-1\">\n        {name}\n      </Text>\n    </>\n  );\n});\n\nconst ColumnContext = memo((props: { text: string; copyable: boolean }) => {\n  const { text, copyable } = props;\n  return (\n    <StyledCell className=\"text-truncate\">\n      <span title={text} className=\"text text-container\">\n        {text}\n      </span>\n      {copyable && (\n        <Button size=\"small\" className=\"copy-icon\">\n          <Text copyable={{ text, tooltips: false }} className=\"gray-8\" />\n        </Button>\n      )}\n    </StyledCell>\n  );\n});\n\nconst getPreviewColumns = (cols, { copyable }) =>\n  cols.map(({ name, type }: Record<string, any>) => {\n    return {\n      dataIndex: name,\n      titleText: name,\n      key: name,\n      ellipsis: true,\n      title: <ColumnTitle name={name} type={type} />,\n      render: (text) => <ColumnContext text={text} copyable={copyable} />,\n      onCell: () => ({ style: { lineHeight: '24px' } }),\n    };\n  });\n\ninterface Props {\n  previewData?: {\n    data: Array<Array<any>>;\n    columns: Array<{\n      name: string;\n      type: string;\n    }>;\n  };\n  loading: boolean;\n  error?: ApolloError;\n  locale?: { emptyText: React.ReactNode };\n  copyable?: boolean;\n}\n\nexport default function PreviewData(props: Props) {\n  const { previewData, loading, error, locale, copyable = true } = props;\n\n  const columns = useMemo(\n    () =>\n      previewData?.columns &&\n      getPreviewColumns(previewData.columns, { copyable }),\n    [previewData?.columns, copyable],\n  );\n\n  const hasErrorMessage = error && error.message;\n  if (!loading && hasErrorMessage) {\n    const { message, shortMessage } = parseGraphQLError(error);\n\n    return (\n      <Alert\n        message={shortMessage}\n        description={message}\n        type=\"error\"\n        showIcon\n      />\n    );\n  }\n\n  return (\n    <PreviewDataContent\n      columns={columns}\n      data={previewData?.data || []}\n      loading={loading}\n      locale={locale}\n    />\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/dataPreview/PreviewDataContent.tsx",
    "content": "import { useMemo } from 'react';\nimport { Table, TableColumnProps } from 'antd';\nimport { isString } from 'lodash';\n\nconst FONT_SIZE = 16;\nconst BASIC_COLUMN_WIDTH = 100;\n\ntype TableColumn = TableColumnProps<any> & { titleText?: string };\n\ninterface Props {\n  columns: TableColumn[];\n  data: Array<any[]>;\n  loading: boolean;\n  locale?: { emptyText: React.ReactNode };\n}\n\nconst getValueByValueType = (value: any) =>\n  ['boolean', 'object'].includes(typeof value) ? JSON.stringify(value) : value;\n\nconst convertResultData = (data: Array<any>, columns) => {\n  return data.map((datum: Array<any>, index: number) => {\n    const obj = {};\n    // should have a unique \"key\" prop.\n    obj['key'] = index;\n\n    datum.forEach((value, index) => {\n      const columnName = columns[index].dataIndex;\n      obj[columnName] = getValueByValueType(value);\n    });\n\n    return obj;\n  });\n};\n\nexport default function PreviewDataContent(props: Props) {\n  const { columns = [], data = [], loading, locale } = props;\n  const hasColumns = !!columns.length;\n\n  const dynamicWidth = useMemo(() => {\n    return columns.reduce((result, column) => {\n      const width = isString(column.titleText || column.title)\n        ? (column.titleText || (column.title as string)).length * FONT_SIZE\n        : BASIC_COLUMN_WIDTH;\n      return result + width;\n    }, 0);\n  }, [columns]);\n\n  const tableColumns = useMemo(() => {\n    return columns.map((column) => ({\n      ...column,\n      ellipsis: true,\n    }));\n  }, [columns]);\n\n  const dataSource = useMemo(() => convertResultData(data, columns), [data]);\n\n  // https://posthog.com/docs/session-replay/privacy#other-elements\n  return (\n    <Table\n      className={`ph-no-capture ${hasColumns ? 'ant-table-has-header' : ''}`}\n      showHeader={hasColumns}\n      dataSource={dataSource}\n      columns={tableColumns}\n      pagination={false}\n      size=\"small\"\n      scroll={{ y: 280, x: dynamicWidth }}\n      loading={loading}\n      locale={locale}\n    />\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/deploy/Context.ts",
    "content": "import { createContext, useContext } from 'react';\nimport { DeployStatusQueryHookResult } from '@/apollo/client/graphql/deploy.generated';\n\ntype ContextProps = DeployStatusQueryHookResult;\n\nexport const DeployStatusContext = createContext<ContextProps>(\n  {} as ContextProps,\n);\n\nexport function useDeployStatusContext() {\n  return useContext(DeployStatusContext);\n}\n"
  },
  {
    "path": "wren-ui/src/components/deploy/Deploy.tsx",
    "content": "import { useEffect } from 'react';\nimport { Button, Space, Typography, message } from 'antd';\nimport CheckCircleOutlined from '@ant-design/icons/CheckCircleOutlined';\nimport LoadingOutlined from '@ant-design/icons/LoadingOutlined';\nimport WarningOutlined from '@ant-design/icons/WarningOutlined';\nimport { SyncStatus } from '@/apollo/client/graphql/__types__';\nimport { useDeployMutation } from '@/apollo/client/graphql/deploy.generated';\nimport { useDeployStatusContext } from '@/components/deploy/Context';\n\nconst { Text } = Typography;\n\nconst getDeployStatus = (deploying: boolean, status: SyncStatus) => {\n  const syncStatus = deploying ? SyncStatus.IN_PROGRESS : status;\n\n  return (\n    {\n      [SyncStatus.IN_PROGRESS]: (\n        <Space size={[4, 0]}>\n          <LoadingOutlined className=\"mr-1 gray-1\" />\n          <Text className=\"gray-1\">Deploying...</Text>\n        </Space>\n      ),\n      [SyncStatus.SYNCRONIZED]: (\n        <Space size={[4, 0]}>\n          <CheckCircleOutlined className=\"mr-1 green-7\" />\n          <Text className=\"gray-1\">Synced</Text>\n        </Space>\n      ),\n      [SyncStatus.UNSYNCRONIZED]: (\n        <Space size={[4, 0]}>\n          <WarningOutlined className=\"mr-1 gold-6\" />\n          <Text className=\"gray-1\">Undeployed changes</Text>\n        </Space>\n      ),\n    }[syncStatus] || ''\n  );\n};\n\nexport default function Deploy() {\n  const deployContext = useDeployStatusContext();\n  const { data, loading, startPolling, stopPolling } = deployContext;\n\n  const [deployMutation, { data: deployResult, loading: deploying }] =\n    useDeployMutation({\n      onError: (error) => console.error(error),\n      onCompleted: (data) => {\n        if (data.deploy?.status === 'FAILED') {\n          console.error('Failed to deploy - ', data.deploy?.error);\n          message.error(\n            'Failed to deploy. Please check the log for more details.',\n          );\n        }\n      },\n    });\n\n  useEffect(() => {\n    // Stop polling deploy status if deploy failed\n    if (\n      deployResult?.deploy?.status === 'FAILED' &&\n      data?.modelSync.status === SyncStatus.UNSYNCRONIZED\n    ) {\n      stopPolling();\n    }\n  }, [deployResult, data]);\n\n  const syncStatus = data?.modelSync.status;\n\n  const onDeploy = () => {\n    deployMutation();\n    startPolling(1000);\n  };\n\n  useEffect(() => {\n    if (syncStatus === SyncStatus.SYNCRONIZED) stopPolling();\n  }, [syncStatus]);\n\n  const disabled =\n    deploying ||\n    loading ||\n    [SyncStatus.SYNCRONIZED, SyncStatus.IN_PROGRESS].includes(syncStatus);\n\n  return (\n    <Space size={[8, 0]}>\n      {getDeployStatus(deploying, syncStatus)}\n      <Button\n        className={`adm-modeling-header-btn ${disabled ? '' : 'gray-10'}`}\n        disabled={disabled}\n        onClick={() => onDeploy()}\n        size=\"small\"\n        data-guideid=\"deploy-model\"\n      >\n        Deploy\n      </Button>\n    </Space>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/diagram/Context.ts",
    "content": "import { createContext } from 'react';\nimport { ComposeDiagram } from '@/utils/data';\n\nexport interface ClickPayload {\n  [key: string]: any;\n  data: ComposeDiagram;\n}\n\ntype ContextProps = {\n  onMoreClick: (data: ClickPayload) => void;\n  onNodeClick: (data: ClickPayload) => void;\n  onAddClick: (data: ClickPayload) => void;\n} | null;\n\nexport const DiagramContext = createContext<ContextProps>({\n  onMoreClick: () => {},\n  onNodeClick: () => {},\n  onAddClick: () => {},\n});\n"
  },
  {
    "path": "wren-ui/src/components/diagram/CustomDropdown.tsx",
    "content": "import React from 'react';\nimport styled from 'styled-components';\nimport { Dropdown, Menu } from 'antd';\nimport { ItemType } from 'antd/lib/menu/hooks/useItems';\nimport { MORE_ACTION, NODE_TYPE } from '@/utils/enum';\nimport EditOutlined from '@ant-design/icons/EditOutlined';\nimport ReloadOutlined from '@ant-design/icons/ReloadOutlined';\nimport EyeInvisibleOutlined from '@ant-design/icons/EyeInvisibleOutlined';\nimport EyeOutlined from '@ant-design/icons/EyeOutlined';\nimport CodeFilled from '@ant-design/icons/CodeFilled';\nimport DatabaseOutlined from '@ant-design/icons/DatabaseOutlined';\nimport { EditSVG } from '@/utils/svgs';\nimport {\n  DeleteCalculatedFieldModal,\n  DeleteRelationshipModal,\n  DeleteModelModal,\n  DeleteViewModal,\n  DeleteDashboardItemModal,\n  DeleteQuestionSQLPairModal,\n  DeleteInstructionModal,\n} from '@/components/modals/DeleteModal';\n\nconst StyledMenu = styled(Menu)`\n  .ant-dropdown-menu-item:not(.ant-dropdown-menu-item-disabled) {\n    color: var(--gray-8);\n  }\n`;\n\ninterface Props {\n  [key: string]: any;\n  onMoreClick: (type: MORE_ACTION | { type: MORE_ACTION; data: any }) => void;\n  onMenuEnter?: (event: React.MouseEvent) => void;\n  children: React.ReactNode;\n  onDropdownVisibleChange?: (visible: boolean) => void;\n}\n\nconst makeDropdown =\n  (getItems: (props: Props) => ItemType[]) => (props: Props) => {\n    const { children, onMenuEnter, onDropdownVisibleChange } = props;\n\n    const items = getItems(props);\n\n    return (\n      <Dropdown\n        trigger={['click']}\n        overlayStyle={{ minWidth: 100, userSelect: 'none' }}\n        overlay={\n          <StyledMenu\n            onClick={(e) => e.domEvent.stopPropagation()}\n            items={items}\n            onMouseEnter={onMenuEnter}\n          />\n        }\n        onVisibleChange={onDropdownVisibleChange}\n      >\n        {children}\n      </Dropdown>\n    );\n  };\n\nexport const ModelDropdown = makeDropdown((props: Props) => {\n  const { onMoreClick } = props;\n\n  const items: ItemType[] = [\n    {\n      label: (\n        <>\n          <EditOutlined className=\"mr-2\" />\n          Update Columns\n        </>\n      ),\n      key: MORE_ACTION.UPDATE_COLUMNS,\n      onClick: () => onMoreClick(MORE_ACTION.UPDATE_COLUMNS),\n    },\n    {\n      label: (\n        <DeleteModelModal onConfirm={() => onMoreClick(MORE_ACTION.DELETE)} />\n      ),\n      className: 'red-5',\n      key: MORE_ACTION.DELETE,\n      onClick: ({ domEvent }) => domEvent.stopPropagation(),\n    },\n  ];\n\n  return items;\n});\n\nexport const ViewDropdown = makeDropdown((props: Props) => {\n  const { onMoreClick } = props;\n  const items: ItemType[] = [\n    {\n      label: (\n        <DeleteViewModal onConfirm={() => onMoreClick(MORE_ACTION.DELETE)} />\n      ),\n      className: 'red-5',\n      key: MORE_ACTION.DELETE,\n      onClick: ({ domEvent }) => domEvent.stopPropagation(),\n    },\n  ];\n  return items;\n});\n\nexport const ColumnDropdown = makeDropdown((props: Props) => {\n  const { onMoreClick, data } = props;\n  const { nodeType } = data;\n\n  const DeleteColumnModal =\n    {\n      [NODE_TYPE.CALCULATED_FIELD]: DeleteCalculatedFieldModal,\n      [NODE_TYPE.RELATION]: DeleteRelationshipModal,\n    }[nodeType] || DeleteCalculatedFieldModal;\n\n  const items: ItemType[] = [\n    {\n      label: (\n        <>\n          <EditOutlined className=\"mr-2\" />\n          Edit\n        </>\n      ),\n      key: MORE_ACTION.EDIT,\n      onClick: () => onMoreClick(MORE_ACTION.EDIT),\n    },\n    {\n      label: (\n        <DeleteColumnModal onConfirm={() => onMoreClick(MORE_ACTION.DELETE)} />\n      ),\n      className: 'red-5',\n      key: MORE_ACTION.DELETE,\n      onClick: ({ domEvent }) => domEvent.stopPropagation(),\n    },\n  ];\n\n  return items;\n});\n\nexport const DashboardDropdown = makeDropdown((props: Props) => {\n  const { onMoreClick, isSupportCached } = props;\n  const items: ItemType[] = [\n    isSupportCached && {\n      label: (\n        <>\n          <DatabaseOutlined className=\"mr-2\" />\n          Cache settings\n        </>\n      ),\n      key: MORE_ACTION.CACHE_SETTINGS,\n      onClick: () => onMoreClick(MORE_ACTION.CACHE_SETTINGS),\n    },\n    {\n      label: (\n        <>\n          <ReloadOutlined className=\"mr-2\" />\n          {isSupportCached ? 'Refresh all caches' : 'Refresh all'}\n        </>\n      ),\n      key: MORE_ACTION.REFRESH,\n      onClick: () => onMoreClick(MORE_ACTION.REFRESH),\n    },\n  ].filter(Boolean);\n  return items;\n});\n\nexport const DashboardItemDropdown = makeDropdown((props: Props) => {\n  const { onMoreClick, isHideLegend, isSupportCached } = props;\n  const items: ItemType[] = [\n    {\n      label: isHideLegend ? (\n        <>\n          <EyeOutlined className=\"mr-2\" />\n          Show categories\n        </>\n      ) : (\n        <>\n          {<EyeInvisibleOutlined className=\"mr-2\" />}\n          Hide categories\n        </>\n      ),\n      key: MORE_ACTION.HIDE_CATEGORY,\n      onClick: () => onMoreClick(MORE_ACTION.HIDE_CATEGORY),\n    },\n    {\n      label: (\n        <>\n          <ReloadOutlined className=\"mr-2\" />\n          {isSupportCached ? 'Refresh cache' : 'Refresh'}\n        </>\n      ),\n      key: MORE_ACTION.REFRESH,\n      onClick: () => onMoreClick(MORE_ACTION.REFRESH),\n    },\n    {\n      label: (\n        <DeleteDashboardItemModal\n          onConfirm={() => onMoreClick(MORE_ACTION.DELETE)}\n        />\n      ),\n      className: 'red-5',\n      key: MORE_ACTION.DELETE,\n      onClick: ({ domEvent }) => domEvent.stopPropagation(),\n    },\n  ];\n  return items;\n});\n\nexport const SQLPairDropdown = makeDropdown(\n  (\n    props: Props & {\n      onMoreClick: (payload: { type: MORE_ACTION; data: any }) => void;\n    },\n  ) => {\n    const { onMoreClick, data } = props;\n    const items: ItemType[] = [\n      {\n        label: (\n          <>\n            <EyeOutlined className=\"mr-2\" />\n            View\n          </>\n        ),\n        key: MORE_ACTION.VIEW_SQL_PAIR,\n        onClick: () =>\n          onMoreClick({\n            type: MORE_ACTION.VIEW_SQL_PAIR,\n            data,\n          }),\n      },\n      {\n        label: (\n          <>\n            <EditOutlined className=\"mr-2\" />\n            Edit\n          </>\n        ),\n        key: MORE_ACTION.EDIT,\n        onClick: () =>\n          onMoreClick({\n            type: MORE_ACTION.EDIT,\n            data,\n          }),\n      },\n      {\n        label: (\n          <DeleteQuestionSQLPairModal\n            onConfirm={() =>\n              onMoreClick({\n                type: MORE_ACTION.DELETE,\n                data,\n              })\n            }\n            modalProps={{\n              cancelButtonProps: { autoFocus: true },\n            }}\n          />\n        ),\n        className: 'red-5',\n        key: MORE_ACTION.DELETE,\n        onClick: ({ domEvent }) => domEvent.stopPropagation(),\n      },\n    ];\n    return items;\n  },\n);\n\nexport const InstructionDropdown = makeDropdown(\n  (\n    props: Props & {\n      onMoreClick: (payload: { type: MORE_ACTION; data: any }) => void;\n    },\n  ) => {\n    const { onMoreClick, data } = props;\n    const items: ItemType[] = [\n      {\n        label: (\n          <>\n            <EyeOutlined className=\"mr-2\" />\n            View\n          </>\n        ),\n        key: MORE_ACTION.VIEW_INSTRUCTION,\n        onClick: () =>\n          onMoreClick({\n            type: MORE_ACTION.VIEW_INSTRUCTION,\n            data,\n          }),\n      },\n      {\n        label: (\n          <>\n            <EditOutlined className=\"mr-2\" />\n            Edit\n          </>\n        ),\n        key: MORE_ACTION.EDIT,\n        onClick: () =>\n          onMoreClick({\n            type: MORE_ACTION.EDIT,\n            data,\n          }),\n      },\n      {\n        label: (\n          <DeleteInstructionModal\n            onConfirm={() =>\n              onMoreClick({\n                type: MORE_ACTION.DELETE,\n                data,\n              })\n            }\n            modalProps={{\n              cancelButtonProps: { autoFocus: true },\n            }}\n          />\n        ),\n        className: 'red-5',\n        key: MORE_ACTION.DELETE,\n        onClick: ({ domEvent }) => domEvent.stopPropagation(),\n      },\n    ];\n    return items;\n  },\n);\n\nexport const AdjustAnswerDropdown = makeDropdown(\n  (\n    props: Props & {\n      onMoreClick: (payload: { type: MORE_ACTION; data: any }) => void;\n    },\n  ) => {\n    const { onMoreClick, data } = props;\n    const items: ItemType[] = [\n      {\n        label: 'Adjust steps',\n        icon: <EditSVG />,\n        disabled: !data.sqlGenerationReasoning,\n        key: 'adjust-steps',\n        onClick: () =>\n          onMoreClick({\n            type: MORE_ACTION.ADJUST_STEPS,\n            data,\n          }),\n      },\n      {\n        label: 'Adjust SQL',\n        icon: <CodeFilled className=\"text-base\" />,\n        disabled: !data.sql,\n        key: 'adjust-sql',\n        onClick: () =>\n          onMoreClick({\n            type: MORE_ACTION.ADJUST_SQL,\n            data,\n          }),\n      },\n    ];\n    return items;\n  },\n);\n"
  },
  {
    "path": "wren-ui/src/components/diagram/CustomPopover.tsx",
    "content": "import { Popover, PopoverProps, Row, Col, Typography } from 'antd';\n\ntype Props = PopoverProps;\n\nexport default function CustomPopover(props: Props) {\n  const { children } = props;\n\n  return (\n    <Popover {...props} mouseLeaveDelay={0} overlayStyle={{ maxWidth: 520 }}>\n      {children}\n    </Popover>\n  );\n}\n\nconst CustomPopoverCol = (props: {\n  title: string;\n  children: React.ReactNode;\n  code?: boolean;\n  span?: number;\n  marginBottom?: number;\n}) => {\n  const { title, children, code, span = 24, marginBottom = 8 } = props;\n  return (\n    <Col span={span}>\n      <div className=\"gray-7 mb-0\">{title}</div>\n      <div style={{ marginBottom }}>\n        <Typography.Text code={code}>{children}</Typography.Text>\n      </div>\n    </Col>\n  );\n};\n\nCustomPopover.Row = Row;\nCustomPopover.Col = CustomPopoverCol;\n"
  },
  {
    "path": "wren-ui/src/components/diagram/Marker.tsx",
    "content": "export default function Marker() {\n  // This is only used to embed definitions which can reused inside an svg image.\n  return (\n    <svg\n      style={{\n        position: 'absolute',\n        top: 0,\n        left: 0,\n        width: 0,\n        height: 0,\n        zIndex: -1,\n      }}\n    >\n      <defs>\n        <marker\n          id=\"many_right\"\n          viewBox=\"0 0 14 22\"\n          markerHeight={14}\n          markerWidth={14}\n          refX={0}\n          refY={11}\n        >\n          <path\n            fillRule=\"evenodd\"\n            clipRule=\"evenodd\"\n            d=\"M9.28866 10L6.49577e-06 2.33206L1.4329e-05 -1.18499e-06L13.5547 11L2.869e-06 22L3.07287e-06 19.668L9.28864 12L5.65057e-06 12L5.82542e-06 10L9.28866 10Z\"\n            fill=\"#b1b1b7\"\n          />\n        </marker>\n        <marker\n          id=\"many_left\"\n          viewBox=\"0 0 14 22\"\n          markerHeight={14}\n          markerWidth={14}\n          refX={14}\n          refY={11}\n        >\n          <path\n            fillRule=\"evenodd\"\n            clipRule=\"evenodd\"\n            d=\"M4.26603 12L13.5547 19.6679L13.5547 22L0 11L13.5547 0V2.33204L4.26605 10L13.5547 10V12L4.26603 12Z\"\n            fill=\"#b1b1b7\"\n          />\n        </marker>\n        <marker\n          id=\"one_right\"\n          viewBox=\"0 0 14 22\"\n          markerHeight={14}\n          markerWidth={14}\n          refX={-4}\n          refY={11}\n        >\n          <rect\n            width=\"1400\"\n            height=\"993\"\n            transform=\"translate(-407 -263)\"\n            fill=\"none\"\n          />\n          <rect x=\"6\" width=\"2\" height=\"22\" fill=\"#b1b1b7\" />\n        </marker>\n        <marker\n          id=\"one_left\"\n          viewBox=\"0 0 14 22\"\n          markerHeight={14}\n          markerWidth={14}\n          refX={18}\n          refY={11}\n        >\n          <rect\n            width=\"1400\"\n            height=\"993\"\n            transform=\"translate(-407 -263)\"\n            fill=\"none\"\n          />\n          <rect x=\"6\" width=\"2\" height=\"22\" fill=\"#b1b1b7\" />\n        </marker>\n\n        {/* seleceted */}\n        <marker\n          id=\"many_right_selected\"\n          viewBox=\"0 0 18 32\"\n          markerHeight={18}\n          markerWidth={18}\n          refX={0}\n          refY={16}\n        >\n          <path\n            fillRule=\"evenodd\"\n            clipRule=\"evenodd\"\n            d=\"M13.4161 4.94444L13.2993 8H14.7007L14.5839 4.94444L17.2993 6.58333L18 5.41667L15.1387 4L18 2.58333L17.2993 1.41667L14.5839 3.05556L14.7007 0H13.2993L13.4161 3.05556L10.7007 1.41667L10 2.58333L12.8613 4L10 5.41667L10.7007 6.58333L13.4161 4.94444ZM3.63475e-06 7.33206L9.28865 15L2.9644e-06 15L2.78955e-06 17L9.28863 17L0 24.668V27L13.5547 16L1.1468e-05 5L3.63475e-06 7.33206Z\"\n            fill=\"#2F54EB\"\n          />\n        </marker>\n        <marker\n          id=\"many_left_selected\"\n          viewBox=\"0 0 18 32\"\n          markerHeight={18}\n          markerWidth={18}\n          refX={18}\n          refY={16}\n        >\n          <path\n            fillRule=\"evenodd\"\n            clipRule=\"evenodd\"\n            d=\"M3.41606 4.94444L3.29927 8H4.70073L4.58394 4.94444L7.29927 6.58333L8 5.41667L5.13869 4L8 2.58333L7.29927 1.41667L4.58394 3.05556L4.70073 0H3.29927L3.41606 3.05556L0.70073 1.41667L0 2.58333L2.86131 4L0 5.41667L0.70073 6.58333L3.41606 4.94444ZM17.8899 24.6679L8.60127 17H17.8899V15H8.60129L17.8899 7.33204V5L4.33524 16L17.8899 27L17.8899 24.6679Z\"\n            fill=\"#2F54EB\"\n          />\n        </marker>\n        <marker\n          id=\"one_right_selected\"\n          viewBox=\"0 0 16 32\"\n          markerHeight={16}\n          markerWidth={16}\n          refX={0}\n          refY={16}\n        >\n          <path\n            fillRule=\"evenodd\"\n            clipRule=\"evenodd\"\n            d=\"M16 8V0H15.0211L13 1.32812V2.3125L14.9737 1.01563H15.0211V8H16ZM8.63351 5H6.63351V27H8.63351V5Z\"\n            fill=\"#2F54EB\"\n          />\n        </marker>\n        <marker\n          id=\"one_left_selected\"\n          viewBox=\"0 0 16 32\"\n          markerHeight={16}\n          markerWidth={16}\n          refX={18}\n          refY={16}\n        >\n          <path\n            fillRule=\"evenodd\"\n            clipRule=\"evenodd\"\n            d=\"M3 8V0H2.02105L0 1.32812V2.3125L1.97368 1.01563H2.02105V8H3ZM9 5H7V27H9V5Z\"\n            fill=\"#2F54EB\"\n          />\n        </marker>\n      </defs>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/diagram/customEdge/ModelEdge.tsx",
    "content": "import { memo, useMemo } from 'react';\nimport {\n  BaseEdge,\n  EdgeLabelRenderer,\n  EdgeProps,\n  getSmoothStepPath,\n} from 'reactflow';\nimport styled from 'styled-components';\nimport CustomPopover from '../CustomPopover';\nimport { getJoinTypeText } from '@/utils/data';\n\nconst Joint = styled.div`\n  position: absolute;\n  width: 30px;\n  height: 30px;\n  opacity: 0;\n`;\n\nconst ModelEdge = ({\n  sourceX,\n  sourceY,\n  targetX,\n  targetY,\n  sourcePosition,\n  targetPosition,\n  markerStart,\n  markerEnd,\n  data,\n}: EdgeProps) => {\n  const [edgePath, labelX, labelY] = getSmoothStepPath({\n    sourceX,\n    sourceY,\n    sourcePosition,\n    targetX,\n    targetY,\n    targetPosition,\n  });\n\n  const isPopoverShow = data.highlight;\n  const style = isPopoverShow\n    ? {\n        stroke: 'var(--geekblue-6)',\n        strokeWidth: 1.5,\n      }\n    : { stroke: 'var(--gray-5)' };\n\n  const relation = useMemo(() => {\n    const fromField = `${data.relation.fromModelName}.${data.relation.fromColumnName}`;\n    const toField = `${data.relation.toModelName}.${data.relation.toColumnName}`;\n    return {\n      name: data.relation.name,\n      joinType: getJoinTypeText(data.relation.type),\n      description: data.relation?.description || '-',\n      fromField,\n      toField,\n    };\n  }, [data.relation]);\n\n  return (\n    <>\n      <BaseEdge\n        path={edgePath}\n        markerStart={markerStart}\n        markerEnd={markerEnd}\n        style={style}\n      />\n      <EdgeLabelRenderer>\n        <CustomPopover\n          visible={isPopoverShow}\n          title=\"Relationship\"\n          content={\n            <CustomPopover.Row gutter={16}>\n              <CustomPopover.Col title=\"From\" span={12}>\n                {relation.fromField}\n              </CustomPopover.Col>\n              <CustomPopover.Col title=\"To\" span={12}>\n                {relation.toField}\n              </CustomPopover.Col>\n              <CustomPopover.Col title=\"Type\" span={12}>\n                {relation.joinType}\n              </CustomPopover.Col>\n              <CustomPopover.Col title=\"Description\">\n                {relation.description}\n              </CustomPopover.Col>\n            </CustomPopover.Row>\n          }\n        >\n          <Joint\n            style={{\n              transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,\n            }}\n          />\n        </CustomPopover>\n      </EdgeLabelRenderer>\n    </>\n  );\n};\n\nexport default memo(ModelEdge);\n"
  },
  {
    "path": "wren-ui/src/components/diagram/customEdge/index.ts",
    "content": "export { default as ModelEdge } from './ModelEdge';\n"
  },
  {
    "path": "wren-ui/src/components/diagram/customNode/Column.tsx",
    "content": "import React from 'react';\nimport styled from 'styled-components';\nimport MarkerHandle from '@/components/diagram/customNode/MarkerHandle';\n\nconst NodeColumn = styled.div`\n  position: relative;\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding: 4px 8px;\n  color: var(--gray-9);\n  line-height: 24px;\n\n  &:hover {\n    background-color: var(--gray-3);\n  }\n\n  svg {\n    flex-shrink: 0;\n  }\n\n  .adm-column-title {\n    display: flex;\n    align-items: center;\n    min-width: 1px;\n    svg {\n      margin-right: 6px;\n    }\n    > span {\n      white-space: nowrap;\n      overflow: hidden;\n      text-overflow: ellipsis;\n    }\n  }\n`;\n\nconst Title = styled.div`\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  color: var(--gray-8);\n  padding: 4px 12px;\n  cursor: default;\n`;\n\ntype ColumnProps = {\n  id: number | string;\n  type: string;\n  displayName: string;\n  style?: React.CSSProperties;\n  icon: React.ReactNode;\n  extra?: React.ReactNode;\n  onMouseEnter?: (event: React.MouseEvent) => void;\n  onMouseLeave?: (event: React.MouseEvent) => void;\n};\n\ntype ColumnTitleProps = {\n  show: boolean;\n  extra?: React.ReactNode;\n  children: React.ReactNode;\n};\n\nexport default function Column(props: ColumnProps) {\n  const {\n    id,\n    type,\n    onMouseEnter,\n    onMouseLeave,\n    displayName,\n    style = {},\n    icon,\n    extra,\n  } = props;\n\n  const nodeColumn = (\n    <NodeColumn\n      style={style}\n      onMouseEnter={onMouseEnter}\n      onMouseLeave={onMouseLeave}\n    >\n      <div className=\"adm-column-title\">\n        <span className=\"d-inline-flex flex-shrink-0\" title={type}>\n          {icon}\n        </span>\n        <span title={displayName}>{displayName}</span>\n      </div>\n      {extra}\n      <MarkerHandle id={id.toString()} />\n    </NodeColumn>\n  );\n\n  return nodeColumn;\n}\n\nconst MoreColumnTip = (props: { count: number }) => {\n  return <div className=\"text-sm gray-7 px-3 py-1\">and {props.count} more</div>;\n};\n\nconst ColumnTitle = (props: ColumnTitleProps) => {\n  const { show, extra, children } = props;\n  if (!show) return null;\n\n  return (\n    <Title>\n      {children}\n      <span>{extra}</span>\n    </Title>\n  );\n};\n\nColumn.Title = ColumnTitle;\nColumn.MoreTip = MoreColumnTip;\n"
  },
  {
    "path": "wren-ui/src/components/diagram/customNode/MarkerHandle.tsx",
    "content": "import { Handle, Position } from 'reactflow';\n\n// parent should be position relative\nexport default function MarkerHandle({ id }: { id: string }) {\n  return (\n    <>\n      {/* all handlers */}\n      <Handle\n        type=\"source\"\n        position={Position.Left}\n        id={`${id}_${Position.Left}`}\n      />\n      <Handle\n        type=\"source\"\n        position={Position.Right}\n        id={`${id}_${Position.Right}`}\n      />\n      <Handle\n        type=\"target\"\n        position={Position.Left}\n        id={`${id}_${Position.Left}`}\n      />\n      <Handle\n        type=\"target\"\n        position={Position.Right}\n        id={`${id}_${Position.Right}`}\n      />\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/diagram/customNode/ModelNode.tsx",
    "content": "import { memo, useCallback, useContext } from 'react';\nimport { Typography } from 'antd';\nimport { useReactFlow } from 'reactflow';\nimport {\n  highlightEdges,\n  highlightNodes,\n  trimId,\n} from '@/components/diagram/utils';\nimport {\n  CachedIcon,\n  CustomNodeProps,\n  NodeBody,\n  NodeHeader,\n  StyledNode,\n} from '@/components/diagram/customNode/utils';\nimport MarkerHandle from '@/components/diagram/customNode/MarkerHandle';\nimport { DiagramContext } from '@/components/diagram/Context';\nimport Column from '@/components/diagram/customNode/Column';\nimport { PrimaryKeyIcon, ModelIcon } from '@/utils/icons';\nimport {\n  ComposeDiagram,\n  ComposeDiagramField,\n  DiagramModel,\n} from '@/utils/data';\nimport { getColumnTypeIcon } from '@/utils/columnType';\nimport { makeIterable } from '@/utils/iteration';\nimport { Config } from '@/utils/diagram';\nimport { MORE_ACTION, NODE_TYPE } from '@/utils/enum';\nimport {\n  ModelDropdown,\n  ColumnDropdown,\n} from '@/components/diagram/CustomDropdown';\nimport { AddButton, MoreButton } from '@/components/ActionButton';\n\nconst { Text } = Typography;\n\nexport const ModelNode = ({ data }: CustomNodeProps<DiagramModel>) => {\n  const context = useContext(DiagramContext);\n  const onMoreClick = (type: MORE_ACTION) => {\n    context?.onMoreClick({\n      type,\n      data: data.originalData,\n    });\n  };\n  const onNodeClick = () => {\n    context?.onNodeClick({\n      data: data.originalData,\n    });\n  };\n  const onAddClick = (targetNodeType: NODE_TYPE) => {\n    context?.onAddClick({\n      targetNodeType,\n      data: data.originalData,\n    });\n  };\n\n  const renderColumns = useCallback(\n    (columns: ComposeDiagramField[]) =>\n      getColumns(columns, data, { limit: Config.columnsLimit }),\n    [data.highlight],\n  );\n\n  return (\n    <StyledNode\n      onClick={onNodeClick}\n      data-testid={`diagram__model-node__${data.originalData.displayName}`}\n      data-guideid={`model-${data.index}`}\n    >\n      <NodeHeader className=\"dragHandle\">\n        <span className=\"adm-model-header\">\n          <ModelIcon />\n          <Text ellipsis title={data.originalData.displayName}>\n            {data.originalData.displayName}\n          </Text>\n        </span>\n        <span>\n          <CachedIcon originalData={data.originalData} />\n          <ModelDropdown data={data.originalData} onMoreClick={onMoreClick}>\n            <MoreButton\n              className=\"gray-1\"\n              marginRight={-4}\n              data-guideid={`edit-model-${data.index}`}\n            />\n          </ModelDropdown>\n        </span>\n\n        <MarkerHandle id={data.originalData.id.toString()} />\n      </NodeHeader>\n      <NodeBody draggable={false}>\n        <Column.Title show={true}>Columns</Column.Title>\n        {renderColumns(data.originalData.fields)}\n        <Column.Title\n          show={true}\n          extra={\n            <AddButton\n              className=\"gray-8\"\n              marginRight={-8}\n              onClick={() => onAddClick(NODE_TYPE.CALCULATED_FIELD)}\n            />\n          }\n        >\n          Calculated Fields\n        </Column.Title>\n        {renderColumns(data.originalData.calculatedFields)}\n        <Column.Title\n          show={true}\n          extra={\n            <AddButton\n              className=\"gray-8\"\n              marginRight={-8}\n              onClick={() => onAddClick(NODE_TYPE.RELATION)}\n            />\n          }\n        >\n          Relationships\n        </Column.Title>\n        {renderColumns(data.originalData.relationFields)}\n      </NodeBody>\n    </StyledNode>\n  );\n};\n\nexport default memo(ModelNode);\n\nconst ColumnTemplate = (props) => {\n  const { nodeType, id, type, isPrimaryKey, highlight } = props;\n  const isRelationship = nodeType === NODE_TYPE.RELATION;\n  const isCalculatedField = nodeType === NODE_TYPE.CALCULATED_FIELD;\n  const isMoreButtonShow = isCalculatedField || isRelationship;\n  const reactflowInstance = useReactFlow();\n\n  const context = useContext(DiagramContext);\n  const onMoreClick = (type: MORE_ACTION) => {\n    context?.onMoreClick({\n      type,\n      data: props,\n    });\n  };\n\n  const onMouseEnter = useCallback(\n    (_event: React.MouseEvent) => {\n      if (!isRelationship) return;\n      const { getEdges, setEdges, setNodes } = reactflowInstance;\n      const edges = getEdges();\n      const relatedEdge = edges.find(\n        (edge: any) =>\n          trimId(edge.sourceHandle) === id || trimId(edge.targetHandle) === id,\n      );\n\n      // skip to highlight & open relationship popup if no related edge\n      if (!relatedEdge) return;\n\n      setEdges(highlightEdges([relatedEdge?.id], true));\n      setNodes(\n        highlightNodes(\n          [relatedEdge.source, relatedEdge.target],\n          [trimId(relatedEdge.sourceHandle), trimId(relatedEdge.targetHandle)],\n        ),\n      );\n    },\n    [reactflowInstance],\n  );\n  const onMouseLeave = useCallback(\n    (_event: React.MouseEvent) => {\n      if (!isRelationship) return;\n      const { setEdges, setNodes } = reactflowInstance;\n      setEdges(highlightEdges([], false));\n      setNodes(highlightNodes([], []));\n    },\n    [reactflowInstance],\n  );\n\n  const onMoreMouseEnter = useCallback(\n    (event: React.MouseEvent) => {\n      onMouseLeave(event);\n    },\n    [reactflowInstance],\n  );\n\n  const onMoreMouseLeave = useCallback(\n    (event: React.MouseEvent) => {\n      onMouseEnter(event);\n    },\n    [reactflowInstance],\n  );\n\n  const onMenuEnter = useCallback(\n    (event: React.MouseEvent) => {\n      onMouseLeave(event);\n    },\n    [reactflowInstance],\n  );\n\n  return (\n    <Column\n      {...props}\n      key={id}\n      className={highlight.includes(id) ? 'bg-gray-3' : undefined}\n      icon={isRelationship ? <ModelIcon /> : getColumnTypeIcon({ type })}\n      extra={\n        <>\n          {isPrimaryKey && <PrimaryKeyIcon />}{' '}\n          {isMoreButtonShow && (\n            <ColumnDropdown\n              data={props}\n              onMoreClick={onMoreClick}\n              onMenuEnter={onMenuEnter}\n            >\n              <MoreButton\n                className=\"gray-8\"\n                marginRight={-4}\n                onMouseEnter={onMoreMouseEnter}\n                onMouseLeave={onMoreMouseLeave}\n              />\n            </ColumnDropdown>\n          )}\n        </>\n      }\n      onMouseLeave={onMouseLeave}\n      onMouseEnter={onMouseEnter}\n    />\n  );\n};\n\nconst ColumnIterator = makeIterable(ColumnTemplate);\n\nconst getColumns = (\n  columns: ComposeDiagramField[],\n  data: CustomNodeProps<ComposeDiagram>['data'],\n  pagination?: { limit: number },\n) => {\n  const moreCount = pagination ? columns.length - pagination.limit : 0;\n  const slicedColumns = pagination\n    ? columns.slice(0, pagination.limit)\n    : columns;\n  return (\n    <>\n      <ColumnIterator\n        data={slicedColumns}\n        highlight={data.highlight}\n        modelId={data.originalData.modelId}\n      />\n      {moreCount > 0 && <Column.MoreTip count={moreCount} />}\n    </>\n  );\n};\n"
  },
  {
    "path": "wren-ui/src/components/diagram/customNode/ViewNode.tsx",
    "content": "import { memo, useCallback, useContext } from 'react';\nimport { Button, Typography } from 'antd';\nimport { MoreIcon, ViewIcon } from '@/utils/icons';\nimport { MORE_ACTION } from '@/utils/enum';\nimport { ComposeDiagram, ComposeDiagramField, DiagramView } from '@/utils/data';\nimport { getColumnTypeIcon } from '@/utils/columnType';\nimport { Config } from '@/utils/diagram';\nimport { makeIterable } from '@/utils/iteration';\nimport { DiagramContext } from '@/components/diagram/Context';\nimport {\n  CustomNodeProps,\n  NodeBody,\n  NodeHeader,\n  StyledNode,\n} from '@/components/diagram/customNode/utils';\nimport MarkerHandle from '@/components/diagram/customNode/MarkerHandle';\nimport Column from '@/components/diagram/customNode/Column';\nimport { ViewDropdown } from '@/components/diagram/CustomDropdown';\n\nconst { Text } = Typography;\n\nexport const ViewNode = ({ data }: CustomNodeProps<DiagramView>) => {\n  const context = useContext(DiagramContext);\n  const onMoreClick = (type: MORE_ACTION) => {\n    context?.onMoreClick({\n      type,\n      data: data.originalData,\n    });\n  };\n  const onNodeClick = () => {\n    context?.onNodeClick({\n      data: data.originalData,\n    });\n  };\n\n  const renderColumns = useCallback(\n    (columns: ComposeDiagramField[]) =>\n      getColumns(columns, data, { limit: Config.columnsLimit }),\n    [data.highlight],\n  );\n\n  return (\n    <StyledNode\n      onClick={onNodeClick}\n      data-testid={`diagram__view-node__${data.originalData.displayName}`}\n    >\n      <NodeHeader className=\"dragHandle\" color=\"var(--green-6)\">\n        <span className=\"adm-model-header\">\n          <ViewIcon />\n          <Text ellipsis title={data.originalData.displayName}>\n            {data.originalData.displayName}\n          </Text>\n        </span>\n        <span>\n          <ViewDropdown onMoreClick={onMoreClick}>\n            <Button\n              className=\"gray-1\"\n              icon={<MoreIcon />}\n              onClick={(event) => event.stopPropagation()}\n              type=\"text\"\n              size=\"small\"\n            />\n          </ViewDropdown>\n        </span>\n\n        <MarkerHandle id={data.originalData.id} />\n      </NodeHeader>\n      <NodeBody draggable={false}>\n        {renderColumns(data.originalData.fields)}\n      </NodeBody>\n    </StyledNode>\n  );\n};\n\nexport default memo(ViewNode);\n\nconst ColumnTemplate = (props) => {\n  const { id, type } = props;\n  return <Column {...props} key={id} icon={getColumnTypeIcon({ type })} />;\n};\n\nconst ColumnIterator = makeIterable(ColumnTemplate);\n\nfunction getColumns(\n  columns: ComposeDiagramField[],\n  data: CustomNodeProps<ComposeDiagram>['data'],\n  pagination?: { limit: number },\n) {\n  const moreCount = pagination ? columns.length - pagination.limit : 0;\n  const slicedColumns = pagination\n    ? columns.slice(0, pagination.limit)\n    : columns;\n  return (\n    <>\n      <ColumnIterator data={slicedColumns} highlight={data.highlight} />\n      {moreCount > 0 && <Column.MoreTip count={moreCount} />}\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/diagram/customNode/index.ts",
    "content": "export { default as ModelNode } from './ModelNode';\nexport { default as ViewNode } from './ViewNode';\n"
  },
  {
    "path": "wren-ui/src/components/diagram/customNode/utils.tsx",
    "content": "import { CachedProps } from '@/utils/data';\nimport { LightningIcon } from '@/utils/icons';\nimport { Tooltip } from 'antd';\nimport { NodeProps } from 'reactflow';\nimport styled from 'styled-components';\n\nexport type CustomNodeProps<T> = NodeProps<{\n  originalData: T;\n  index: number;\n  highlight: string[];\n}>;\n\nexport const StyledNode = styled.div`\n  position: relative;\n  width: 200px;\n  border-radius: 4px;\n  overflow: hidden;\n  box-shadow:\n    0px 3px 6px -4px rgba(0, 0, 0, 0.12),\n    0px 6px 16px rgba(0, 0, 0, 0.08),\n    0px 9px 28px 8px rgba(0, 0, 0, 0.05);\n  cursor: pointer;\n\n  &:before {\n    content: '';\n    pointer-events: none;\n    position: absolute;\n    top: 0;\n    left: 0;\n    right: 0;\n    bottom: 0;\n    z-index: 1;\n    border: 2px solid transparent;\n    transition: border-color 0.15s ease-in-out;\n  }\n\n  &:hover,\n  &:focus {\n    &:before {\n      border-color: var(--geekblue-6);\n    }\n  }\n\n  .react-flow__handle {\n    border: none;\n    opacity: 0;\n\n    &-left {\n      left: 0;\n    }\n\n    &-right {\n      right: 0;\n    }\n  }\n`;\n\nexport const NodeHeader = styled.div`\n  position: relative;\n  background-color: ${(props) => props.color || 'var(--geekblue-6)'};\n  font-size: 14px;\n  color: white;\n  padding: 6px 8px;\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  height: 36px;\n\n  &.dragHandle {\n    cursor: move;\n  }\n\n  .adm-model-header {\n    display: flex;\n    align-items: center;\n\n    svg {\n      margin-right: 6px;\n    }\n    + svg {\n      cursor: pointer;\n    }\n\n    .ant-typography {\n      width: 140px;\n      color: white;\n    }\n  }\n`;\n\nexport const NodeBody = styled.div`\n  background-color: white;\n  padding-bottom: 4px;\n`;\n\nexport const CachedIcon = ({ originalData }: { originalData: CachedProps }) => {\n  return originalData.cached ? (\n    <Tooltip\n      title={\n        <>\n          Cached\n          {originalData.refreshTime\n            ? `: refresh every ${originalData.refreshTime}`\n            : null}\n        </>\n      }\n      placement=\"top\"\n    >\n      <LightningIcon className=\"cursor-pointer\" />\n    </Tooltip>\n  ) : null;\n};\n"
  },
  {
    "path": "wren-ui/src/components/diagram/index.tsx",
    "content": "import {\n  ForwardedRef,\n  forwardRef,\n  useCallback,\n  useEffect,\n  useImperativeHandle,\n  useMemo,\n  useState,\n} from 'react';\nimport ReactFlow, {\n  MiniMap,\n  Background,\n  Controls,\n  ControlButton,\n  useNodesState,\n  useEdgesState,\n  Edge,\n  useReactFlow,\n  ReactFlowProvider,\n} from 'reactflow';\nimport { ModelNode, ViewNode } from './customNode';\nimport { ModelEdge } from './customEdge';\nimport Marker from './Marker';\nimport { DiagramContext, ClickPayload } from './Context';\nimport { trimId, highlightNodes, highlightEdges } from './utils';\nimport { Diagram as DiagramData } from '@/utils/data';\nimport { RefreshIcon } from '@/utils/icons';\nimport { EDGE_TYPE, NODE_TYPE } from '@/utils/enum';\nimport { DiagramCreator } from '@/utils/diagram';\nimport { nextTick } from '@/utils/time';\n\nimport 'reactflow/dist/style.css';\n\nconst nodeTypes = {\n  [NODE_TYPE.MODEL]: ModelNode,\n  [NODE_TYPE.VIEW]: ViewNode,\n};\nconst edgeTypes = {\n  [EDGE_TYPE.MODEL]: ModelEdge,\n};\nconst minimapStyle = {\n  height: 120,\n};\n\ninterface Props {\n  forwardRef?: ForwardedRef<unknown>;\n  data: DiagramData;\n  onMoreClick: (data: ClickPayload) => void;\n  onNodeClick: (data: ClickPayload) => void;\n  onAddClick: (data: ClickPayload) => void;\n}\n\nconst ReactFlowDiagram = forwardRef(function ReactFlowDiagram(\n  props: Props,\n  ref,\n) {\n  const { data, onMoreClick, onNodeClick, onAddClick } = props;\n  const [forceRender, setForceRender] = useState(false);\n  const reactFlowInstance = useReactFlow();\n  useImperativeHandle(ref, () => reactFlowInstance, [reactFlowInstance]);\n\n  const diagram = useMemo(() => {\n    return new DiagramCreator(data).toJsonObject();\n  }, [data]);\n\n  useEffect(() => {\n    setNodes(diagram.nodes);\n    setEdges(diagram.edges);\n\n    nextTick(50).then(() => reactFlowInstance.fitView());\n  }, [diagram]);\n\n  const [nodes, setNodes, onNodesChange] = useNodesState(diagram.nodes);\n  const [edges, setEdges, onEdgesChange] = useEdgesState(diagram.edges);\n\n  const onEdgeMouseEnter = useCallback(\n    (_event: React.MouseEvent, edge: Edge) => {\n      setEdges(highlightEdges([edge.id], true));\n      setNodes(\n        highlightNodes(\n          [edge.source, edge.target],\n          [\n            trimId(edge.sourceHandle as string),\n            trimId(edge.targetHandle as string),\n          ],\n        ),\n      );\n    },\n    [],\n  );\n\n  const onEdgeMouseLeave = useCallback(\n    (_event: React.MouseEvent, _edge: Edge) => {\n      setEdges(highlightEdges([], false));\n      setNodes(highlightNodes([], []));\n    },\n    [],\n  );\n\n  const onRestore = async () => {\n    setNodes(diagram.nodes);\n    setEdges(diagram.edges);\n  };\n\n  const onInit = async () => {\n    await nextTick();\n    reactFlowInstance.fitView();\n    await nextTick(100);\n    setForceRender(!forceRender);\n  };\n\n  const triggerMouseDown = (event: React.MouseEvent | MouseEvent) => {\n    const mouseDownEvent = new MouseEvent('mousedown', {\n      bubbles: true,\n      cancelable: true,\n      clientX: event.clientX,\n      clientY: event.clientY,\n      button: 0,\n    });\n    document.dispatchEvent(mouseDownEvent);\n  };\n\n  const isTargetInDropdown = (target: EventTarget | null) => {\n    const dropdowns = document.querySelectorAll('.ant-dropdown');\n    return Array.from(dropdowns).some((dropdown) =>\n      dropdown.contains(target as Node),\n    );\n  };\n\n  const dispatchMouseEvent = (event: React.MouseEvent | MouseEvent) => {\n    if (!event.isTrusted || isTargetInDropdown(event.target)) return;\n    triggerMouseDown(event);\n  };\n\n  return (\n    <>\n      <DiagramContext.Provider value={{ onMoreClick, onNodeClick, onAddClick }}>\n        <ReactFlow\n          nodes={nodes}\n          edges={edges}\n          onNodesChange={onNodesChange}\n          onEdgesChange={onEdgesChange}\n          onEdgeMouseEnter={onEdgeMouseEnter}\n          onEdgeMouseLeave={onEdgeMouseLeave}\n          onInit={onInit}\n          nodeTypes={nodeTypes}\n          edgeTypes={edgeTypes}\n          maxZoom={1}\n          onPointerDown={(event) => dispatchMouseEvent(event)}\n          proOptions={{ hideAttribution: true }}\n        >\n          <MiniMap style={minimapStyle} zoomable pannable />\n          <Controls showInteractive={false}>\n            <ControlButton onClick={onRestore}>\n              <RefreshIcon style={{ maxWidth: 24, maxHeight: 24 }} />\n            </ControlButton>\n          </Controls>\n          <Background gap={16} />\n        </ReactFlow>\n      </DiagramContext.Provider>\n\n      <Marker />\n    </>\n  );\n});\n\nconst Diagram = (props: Props) => {\n  return (\n    <ReactFlowProvider>\n      <ReactFlowDiagram ref={props.forwardRef} {...props} />\n    </ReactFlowProvider>\n  );\n};\n\nexport default Diagram;\n"
  },
  {
    "path": "wren-ui/src/components/diagram/utils.ts",
    "content": "export const trimId = (id: string) => id.split('_')[0];\n\nexport const highlightEdges = (edgeIds: string[], highlight: boolean) => {\n  return (edges: any) =>\n    edges.map((edge: any) => {\n      const selected = '_selected';\n      const markerStart = edge.markerStart.replace(selected, '');\n      const markerEnd = edge.markerEnd.replace(selected, '');\n      return edgeIds.includes(edge.id)\n        ? {\n            ...edge,\n            data: { ...edge.data, highlight },\n            markerStart: markerStart + selected,\n            markerEnd: markerEnd + selected,\n          }\n        : {\n            ...edge,\n            data: { ...edge.data, highlight: false },\n            markerStart,\n            markerEnd,\n          };\n    });\n};\n\nexport const highlightNodes = (nodeIds: string[], highlight: string[]) => {\n  return (nodes: any) =>\n    nodes.map((node: any) =>\n      nodeIds.includes(node.id)\n        ? { ...node, data: { ...node.data, highlight } }\n        : { ...node, data: { ...node.data, highlight: [] } },\n    );\n};\n"
  },
  {
    "path": "wren-ui/src/components/editor/AceEditor.tsx",
    "content": "import AceEditor from 'react-ace';\n\nimport 'ace-builds/src-noconflict/mode-sql';\nimport 'ace-builds/src-noconflict/mode-json';\nimport 'ace-builds/src-noconflict/theme-tomorrow';\nimport 'ace-builds/src-noconflict/ext-language_tools';\n\nexport default AceEditor;\n"
  },
  {
    "path": "wren-ui/src/components/editor/MarkdownBlock.tsx",
    "content": "import styled from 'styled-components';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\n\nconst ReactMarkdownBlock = styled(ReactMarkdown)`\n  h1,\n  h2,\n  h3,\n  h4,\n  h5,\n  h6 {\n    color: var(--gray-10);\n    margin-bottom: 8px;\n  }\n  h1 {\n    font-size: 20px;\n  }\n  h2 {\n    font-size: 18px;\n  }\n  h3 {\n    font-size: 16px;\n  }\n  h4 {\n    font-size: 14px;\n  }\n  hr {\n    border-top: 1px solid var(--gray-5);\n    border-bottom: none;\n    border-left: none;\n    border-right: none;\n    margin: 18px 0;\n  }\n  pre {\n    background-color: var(--gray-2);\n    border: 1px var(--gray-4) solid;\n    padding: 16px;\n    border-radius: 4px;\n  }\n  table td,\n  table th {\n    border: 1px solid var(--gray-4);\n    padding: 4px 8px;\n  }\n  table th {\n    background-color: var(--gray-2);\n    font-weight: 600;\n  }\n  table {\n    border: 1px solid var(--gray-4);\n    border-collapse: collapse;\n    margin-bottom: 16px;\n  }\n  ol,\n  ul,\n  dl {\n    padding-inline-start: 20px;\n  }\n  h1 code,\n  h2 code,\n  h3 code,\n  h4 code,\n  li code,\n  p code {\n    font-size: 12px;\n    background: var(--gray-4);\n    color: var(--gray-8);\n    padding: 2px 4px;\n    border-radius: 4px;\n  }\n`;\n\nexport default function MarkdownBlock(props: { content: string }) {\n  return (\n    <ReactMarkdownBlock remarkPlugins={[remarkGfm]}>\n      {props.content}\n    </ReactMarkdownBlock>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/editor/MarkdownEditor.tsx",
    "content": "import clsx from 'clsx';\nimport { Button, Mentions, Typography } from 'antd';\nimport styled from 'styled-components';\nimport { useState, useContext, useRef } from 'react';\nimport ReadOutlined from '@ant-design/icons/ReadOutlined';\nimport EditOutlined from '@ant-design/icons/EditOutlined';\nimport { nextTick } from '@/utils/time';\nimport { Mention } from '@/hooks/useAutoComplete';\nimport { FormItemInputContext } from 'antd/lib/form/context';\nimport MarkdownBlock from './MarkdownBlock';\n\nconst Wrapper = styled.div`\n  transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);\n\n  &:hover {\n    border-color: var(--geekblue-5) !important;\n  }\n\n  &.adm-markdown-editor-error {\n    border-color: var(--red-5) !important;\n\n    .adm-markdown-editor-length {\n      color: var(--red-5) !important;\n    }\n  }\n  &:not(.adm-markdown-editor-error).adm-markdown-editor-focused {\n    border-color: var(--geekblue-5) !important;\n    box-shadow: 0 0 0 2px rgba(47, 84, 235, 0.2);\n  }\n\n  &.adm-markdown-editor-focused.adm-markdown-editor-error {\n    borer-color: var(--red-4) !important;\n    box-shadow: 0 0 0 2px rgba(255, 77, 79, 0.2);\n  }\n`;\n\nconst OverflowContainer = styled.div`\n  overflow-y: auto;\n  max-height: 318px;\n`;\n\nconst LinkButton = styled(Button)`\n  color: var(--gray-7);\n`;\n\nconst StyledTextArea = styled(Mentions)`\n  border: none;\n  border-radius: 0;\n\n  textarea {\n    padding: 16px 16px 16px 20px;\n  }\n`;\n\ninterface Props {\n  value?: string;\n  onChange?: (value: string) => void;\n  maxLength?: number;\n  autoFocus?: boolean;\n  mentions?: Mention[];\n}\n\nconst MENTION_PREFIX = '@';\n\nconst MentionOption = (props: Mention) => {\n  return (\n    <Mentions.Option key={props.id} value={props.value}>\n      <div className=\"d-flex align-center justify-space-between\">\n        <div className=\"d-flex align-center gray-8\">\n          {props.icon}\n          <Typography.Text\n            className=\"gray-8 mr-2\"\n            style={{ maxWidth: 240 }}\n            ellipsis\n          >\n            {props.label}\n          </Typography.Text>\n        </div>\n        {props.meta && (\n          <div className=\"gray-6\">\n            <Typography.Text\n              className=\"gray-6 text-sm mr-1\"\n              style={{ maxWidth: 240 }}\n              ellipsis\n            >\n              ({props.meta})\n            </Typography.Text>\n            {props.nodeType}\n          </div>\n        )}\n      </div>\n    </Mentions.Option>\n  );\n};\n\nexport default function MarkdownEditor(props: Props) {\n  const { value, onChange, maxLength, autoFocus, mentions } = props;\n  const $wrapper = useRef<HTMLDivElement>(null);\n  const $textarea = useRef<HTMLElement & { textarea: HTMLTextAreaElement }>(\n    null,\n  );\n  const [focused, setFocused] = useState<boolean>(false);\n  const [isPreviewMode, setIsPreviewMode] = useState<boolean>(false);\n\n  const formItemContext = useContext(FormItemInputContext);\n  const { status } = formItemContext;\n\n  const change = (targetValue: string) => {\n    onChange?.(targetValue);\n  };\n\n  const select = (option: Mention) => {\n    const textarea = $textarea.current?.textarea;\n    if (!textarea) return;\n\n    // go to the start of the mention\n    const mentionStart = (\n      value?.slice(0, textarea.selectionStart) || ''\n    ).lastIndexOf(MENTION_PREFIX);\n    const start = mentionStart >= 0 ? mentionStart : textarea.selectionStart;\n    const end = textarea.selectionEnd;\n    const newValue = value?.slice(0, start) + option.value + value?.slice(end);\n    // update the value and move the cursor\n    onChange?.(newValue || '');\n    nextTick().then(() => {\n      textarea.selectionStart = textarea.selectionEnd =\n        start + option.value.length;\n    });\n  };\n\n  const keydown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n    if (e.key === 'Tab') {\n      e.preventDefault();\n      const textarea = e.currentTarget;\n      const start = textarea.selectionStart;\n      const end = textarea.selectionEnd;\n      // Set the value with a tab character or spaces\n      const tabCharacter = '  '; // Use '\\t' for a tab character or spaces for spaces\n      const newValue =\n        value?.slice(0, start) + tabCharacter + value?.slice(end);\n      // update the value and move the cursor\n      onChange?.(newValue || '');\n      nextTick().then(() => {\n        textarea.selectionStart = textarea.selectionEnd =\n          start + tabCharacter.length;\n      });\n    }\n    if (e.key === '`') {\n      const textarea = e.currentTarget;\n      const start = textarea.selectionStart;\n      const end = textarea.selectionEnd;\n\n      if (start !== end) {\n        e.preventDefault();\n        const selection = `\\`${value?.slice(start, end)}\\``;\n        const newValue = value?.slice(0, start) + selection + value?.slice(end);\n        // update the value and move the cursor\n        onChange?.(newValue || '');\n        nextTick().then(() => {\n          textarea.selectionStart = textarea.selectionEnd =\n            start + selection.length;\n        });\n      }\n    }\n    if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n      // check if the mention dropdown menu exist\n      const dropdownMenu = $wrapper.current?.querySelector(\n        '.ant-mentions-dropdown-menu',\n      );\n      if (dropdownMenu) {\n        // delay to make sure the menu active item is rendered\n        nextTick().then(() => {\n          const activeItem = dropdownMenu.querySelector(\n            '.ant-mentions-dropdown-menu-item-active',\n          ) as HTMLLIElement;\n          if (activeItem) {\n            const menuRect = dropdownMenu.getBoundingClientRect();\n            const activeRect = activeItem.getBoundingClientRect();\n            // check if active item is outside viewport\n            if (activeRect.bottom > menuRect.bottom) {\n              // scroll down\n              dropdownMenu.scrollTo({\n                top:\n                  dropdownMenu.scrollTop +\n                  (activeRect.bottom - menuRect.bottom),\n                behavior: 'smooth',\n              });\n            } else if (activeRect.top < menuRect.top) {\n              // scroll up\n              dropdownMenu.scrollTo({\n                top: dropdownMenu.scrollTop - (menuRect.top - activeRect.top),\n                behavior: 'smooth',\n              });\n            }\n          }\n        });\n      }\n    }\n  };\n\n  return (\n    <Wrapper\n      ref={$wrapper}\n      className={clsx(\n        'border border-gray-5 rounded overflow-hidden',\n        status ? `adm-markdown-editor-${status}` : '',\n        focused ? 'adm-markdown-editor-focused' : '',\n      )}\n      tabIndex={-1}\n    >\n      <div className=\"bg-gray-3 px-2 py-1 d-flex align-center justify-space-between\">\n        <div className=\"adm-markdown-editor-length gray-6 text-sm mr-2\">\n          {maxLength ? (\n            <>\n              {value?.length} / {maxLength} characters\n            </>\n          ) : (\n            <>{value?.length} characters</>\n          )}\n        </div>\n        <LinkButton\n          icon={isPreviewMode ? <EditOutlined /> : <ReadOutlined />}\n          type=\"link\"\n          size=\"small\"\n          onClick={() => setIsPreviewMode(!isPreviewMode)}\n        >\n          {isPreviewMode ? 'Edit mode' : 'Read mode'}\n        </LinkButton>\n      </div>\n      <OverflowContainer className={clsx({ 'p-4': isPreviewMode })}>\n        {isPreviewMode ? (\n          <MarkdownBlock content={value} />\n        ) : (\n          <StyledTextArea\n            ref={$textarea}\n            rows={13}\n            autoFocus={autoFocus}\n            getPopupContainer={() => $wrapper?.current}\n            onChange={change}\n            onSelect={select}\n            onKeyDown={keydown}\n            onFocus={() => setFocused(true)}\n            onBlur={() => setFocused(false)}\n            value={value}\n            prefix={MENTION_PREFIX}\n            maxLength={maxLength}\n          >\n            {(mentions || []).map(MentionOption)}\n          </StyledTextArea>\n        )}\n      </OverflowContainer>\n    </Wrapper>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/editor/SQLEditor.tsx",
    "content": "import clsx from 'clsx';\nimport { useState, useContext, useRef, useEffect } from 'react';\nimport styled from 'styled-components';\nimport AceEditor from '@/components/editor/AceEditor';\nimport { FormItemInputContext } from 'antd/lib/form/context';\nimport useAutoComplete from '@/hooks/useAutoComplete';\n\nconst Wrapper = styled.div`\n  transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);\n\n  &:hover {\n    border-color: var(--geekblue-5) !important;\n  }\n\n  &.adm-markdown-editor-error {\n    border-color: var(--red-5) !important;\n\n    .adm-markdown-editor-length {\n      color: var(--red-5) !important;\n    }\n  }\n  &:not(.adm-markdown-editor-error).adm-markdown-editor-focused {\n    border-color: var(--geekblue-5) !important;\n    box-shadow: 0 0 0 2px rgba(47, 84, 235, 0.2);\n  }\n\n  &.adm-markdown-editor-focused.adm-markdown-editor-error {\n    borer-color: var(--red-4) !important;\n    box-shadow: 0 0 0 2px rgba(255, 77, 79, 0.2);\n  }\n`;\n\nconst Toolbar = styled.div`\n  color: var(--gray-8);\n  background-color: var(--gray-3);\n  border-bottom: 1px solid var(--gray-5);\n  height: 32px;\n  padding: 4px 8px;\n  border-radius: 4px 4px 0px 0px;\n`;\n\ninterface Props {\n  value?: string;\n  onChange?: (value: string) => void;\n  autoFocus?: boolean;\n  autoComplete?: boolean;\n  toolbar?: React.ReactNode;\n}\n\nconst getLangTools = () => {\n  const { ace } = window as any;\n  return ace ? ace.require('ace/ext/language_tools') : null;\n};\n\nexport default function SQLEditor(props: Props) {\n  const { value, onChange, autoFocus, autoComplete, toolbar } = props;\n  const $wrapper = useRef<HTMLDivElement>(null);\n  const [focused, setFocused] = useState<boolean>(false);\n\n  const formItemContext = useContext(FormItemInputContext);\n  const { status } = formItemContext;\n\n  const completers = useAutoComplete({\n    includeColumns: true,\n    skip: !autoComplete,\n  });\n\n  const resetCompleters = () => {\n    // clear custom completer\n    const langTools = getLangTools();\n    langTools?.setCompleters([\n      langTools.keyWordCompleter,\n      langTools.snippetCompleter,\n      langTools.textCompleter,\n    ]);\n  };\n\n  useEffect(() => {\n    resetCompleters();\n    if (!autoComplete || completers.length === 0) return;\n\n    const langTools = getLangTools();\n    const customCompleter = {\n      getCompletions: (_editor, _session, _pos, _prefix, callback) => {\n        callback(null, completers);\n      },\n    };\n    langTools?.addCompleter(customCompleter);\n\n    return () => resetCompleters();\n  }, [focused, autoComplete, completers]);\n\n  const [sql, setSql] = useState(value || '');\n\n  const change = (sql) => {\n    setSql(sql);\n    onChange?.(sql);\n  };\n\n  return (\n    <Wrapper\n      ref={$wrapper}\n      className={clsx(\n        'border border-gray-5 rounded overflow-hidden',\n        status ? `adm-markdown-editor-${status}` : '',\n        focused ? 'adm-markdown-editor-focused' : '',\n      )}\n      tabIndex={-1}\n    >\n      {!!toolbar && <Toolbar>{toolbar}</Toolbar>}\n      <AceEditor\n        mode=\"sql\"\n        width=\"100%\"\n        height=\"300px\"\n        fontSize={14}\n        theme=\"tomorrow\"\n        value={value || sql}\n        onChange={change}\n        onFocus={() => setFocused(true)}\n        onBlur={() => setFocused(false)}\n        name=\"sql_editor\"\n        editorProps={{ $blockScrolling: true }}\n        enableLiveAutocompletion\n        enableBasicAutocompletion\n        showPrintMargin={false}\n        focus={autoFocus}\n      />\n    </Wrapper>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/layouts/PageLayout.tsx",
    "content": "import { Typography } from 'antd';\n\ninterface PageLayoutProps {\n  title: string | React.ReactNode;\n  description?: string | React.ReactNode;\n  children: React.ReactNode;\n  titleExtra?: string | React.ReactNode;\n}\n\nexport default function PageLayout(props: PageLayoutProps) {\n  const { title, titleExtra, description, children } = props;\n  return (\n    <div className=\"px-6 py-4\">\n      <div className=\"d-flex align-center justify-space-between mb-3\">\n        <Typography.Title level={4} className=\"text-medium gray-8 mb-0\">\n          {title}\n        </Typography.Title>\n        {titleExtra}\n      </div>\n      {description && (\n        <Typography.Text className=\"gray-7\">{description}</Typography.Text>\n      )}\n      <div className=\"mt-3\">{children}</div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/layouts/SiderLayout.tsx",
    "content": "import { Layout } from 'antd';\nimport styled, { css } from 'styled-components';\nimport SimpleLayout from '@/components/layouts/SimpleLayout';\nimport Sidebar from '@/components/sidebar';\nimport Settings from '@/components/settings';\nimport useModalAction from '@/hooks/useModalAction';\n\nconst { Sider } = Layout;\n\nconst basicStyle = css`\n  height: calc(100vh - 48px);\n  overflow: auto;\n`;\n\nconst StyledContentLayout = styled(Layout)<{ color?: string }>`\n  position: relative;\n  ${basicStyle}\n  ${(props) => props.color && `background-color: var(--${props.color});`}\n`;\n\nconst StyledSider = styled(Sider)`\n  ${basicStyle}\n`;\n\ntype Props = React.ComponentProps<typeof SimpleLayout> & {\n  sidebar?: React.ComponentProps<typeof Sidebar>;\n  color?: string;\n};\n\nexport default function SiderLayout(props: Props) {\n  const { sidebar, loading, color } = props;\n  const settings = useModalAction();\n\n  return (\n    <SimpleLayout loading={loading}>\n      <Layout className=\"adm-layout\">\n        <StyledSider width={280}>\n          <Sidebar {...sidebar} onOpenSettings={settings.openModal} />\n        </StyledSider>\n        <StyledContentLayout color={color}>\n          {props.children}\n        </StyledContentLayout>\n      </Layout>\n      <Settings {...settings.state} onClose={settings.closeModal} />\n    </SimpleLayout>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/layouts/SimpleLayout.tsx",
    "content": "import { Layout } from 'antd';\nimport HeaderBar from '@/components/HeaderBar';\nimport PageLoading from '@/components/PageLoading';\nimport { useWithOnboarding } from '@/hooks/useCheckOnboarding';\nimport clsx from 'clsx';\n\nconst { Content } = Layout;\n\ninterface Props {\n  children: React.ReactNode;\n  loading?: boolean;\n}\n\nexport default function SimpleLayout(props: Props) {\n  const { loading: fetching } = useWithOnboarding();\n  const { children, loading } = props;\n  const pageLoading = fetching || loading;\n  return (\n    <Layout\n      className={clsx('adm-main bg-gray-3', {\n        'overflow-hidden': pageLoading,\n      })}\n    >\n      <HeaderBar />\n      <Content className=\"adm-content\">{children}</Content>\n      <PageLoading visible={pageLoading} />\n    </Layout>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/learning/guide/index.tsx",
    "content": "import { driver } from 'driver.js';\nimport { useRouter } from 'next/router';\nimport {\n  forwardRef,\n  useEffect,\n  useImperativeHandle,\n  useMemo,\n  useRef,\n} from 'react';\nimport { Dispatcher, DriverObj } from './utils';\nimport { makeStoriesPlayer } from './stories';\nimport { useGetSettingsQuery } from '@/apollo/client/graphql/settings.generated';\n\nimport 'driver.js/dist/driver.css';\n\ninterface Props {}\n\ninterface Attributes {\n  play: (id: string, dispatcher: Dispatcher) => void;\n}\n\nexport default forwardRef<Attributes, Props>(function Guide(_props, ref) {\n  const router = useRouter();\n  const $driver = useRef<DriverObj>(null);\n\n  const { data: settingsResult } = useGetSettingsQuery();\n  const storyPayload = useMemo(() => {\n    return {\n      sampleDataset: settingsResult?.settings?.dataSource.sampleDataset,\n      language: settingsResult?.settings?.language,\n    };\n  }, [settingsResult?.settings]);\n\n  useEffect(() => {\n    if ($driver.current !== null) return;\n    $driver.current = driver();\n    return () => {\n      $driver.current.destroy();\n      $driver.current = null;\n    };\n  }, []);\n\n  const play = (id: string, dispatcher: Dispatcher) => {\n    const playStoryWithId = makeStoriesPlayer(\n      $driver.current,\n      router,\n      storyPayload,\n    );\n    playStoryWithId(id, dispatcher);\n  };\n\n  useImperativeHandle(ref, () => ({ play }), [\n    $driver.current,\n    storyPayload,\n    router,\n  ]);\n\n  return null;\n});\n"
  },
  {
    "path": "wren-ui/src/components/learning/guide/stories.tsx",
    "content": "import { useState } from 'react';\nimport { createRoot } from 'react-dom/client';\nimport { NextRouter } from 'next/router';\nimport { Select } from 'antd';\nimport styled from 'styled-components';\nimport { ModelIcon, TranslateIcon } from '@/utils/icons';\nimport { RobotSVG } from '@/utils/svgs';\nimport { renderToString } from 'react-dom/server';\nimport {\n  Dispatcher,\n  DriverConfig,\n  DriverObj,\n  DriverPopoverDOM,\n  LEARNING,\n} from './utils';\nimport { Path } from '@/utils/enum';\nimport {\n  ProjectLanguage,\n  SampleDatasetName,\n} from '@/apollo/client/graphql/__types__';\nimport { TEMPLATE_OPTIONS as SAMPLE_DATASET_INFO } from '@/components/pages/setup/utils';\nimport { getLanguageText } from '@/utils/language';\nimport * as events from '@/utils/events';\nimport { nextTick } from '@/utils/time';\n\nconst RobotIcon = styled(RobotSVG)`\n  width: 24px;\n  height: 24px;\n`;\n\nconst defaultConfigs: DriverConfig = {\n  progressText: '{{current}} / {{total}}',\n  nextBtnText: 'Next',\n  prevBtnText: 'Previous',\n  showButtons: ['next'],\n  allowClose: false,\n};\n\ntype StoryPayload = {\n  sampleDataset: SampleDatasetName;\n  language: ProjectLanguage;\n};\n\nexport const makeStoriesPlayer =\n  (...args: [DriverObj, NextRouter, StoryPayload]) =>\n  (id: string, dispatcher: Dispatcher) => {\n    const action =\n      {\n        [LEARNING.DATA_MODELING_GUIDE]: () =>\n          playDataModelingGuide(...args, dispatcher),\n        [LEARNING.SWITCH_PROJECT_LANGUAGE]: () =>\n          playSwitchProjectLanguageGuide(...args, dispatcher),\n        [LEARNING.KNOWLEDGE_GUIDE]: () =>\n          playKnowledgeGuide(...args, dispatcher),\n        [LEARNING.SAVE_TO_KNOWLEDGE]: () =>\n          playSaveToKnowledgeGuide(...args, dispatcher),\n      }[id] || null;\n    return action && action();\n  };\n\nconst resetPopoverStyle = (popoverDom: DriverPopoverDOM, width: number) => {\n  const wrapper = popoverDom.wrapper;\n  wrapper.style.maxWidth = 'none';\n  wrapper.style.width = `${width}px`;\n};\n\nconst playDataModelingGuide = (\n  $driver: DriverObj,\n  router: NextRouter,\n  payload: StoryPayload,\n  dispatcher: Dispatcher,\n) => {\n  if ($driver === null) {\n    console.error('Driver object is not initialized.');\n    return;\n  }\n  if ($driver.isActive()) $driver.destroy();\n\n  const isSampleDataset = !!payload.sampleDataset;\n  const sampleDatasetInfo = SAMPLE_DATASET_INFO[payload.sampleDataset];\n\n  $driver.setConfig({ ...defaultConfigs, showProgress: true });\n  $driver.setSteps([\n    {\n      popover: {\n        title: renderToString(\n          <div className=\"pt-4\">\n            <div className=\"-mx-4\" style={{ minHeight: 331 }}>\n              <img\n                className=\"mb-4\"\n                src=\"/images/learning/data-modeling.jpg\"\n                alt=\"data-modeling-guide\"\n              />\n            </div>\n            Data modeling guide\n          </div>,\n        ),\n        description: renderToString(\n          <>\n            Data modeling adds a logical layer over your original data schema,\n            organizing relationships, semantics, and calculations. This helps AI\n            align with business logic, retrieve precise data, and generate\n            meaningful insights.{' '}\n            <a\n              href=\"https://docs.getwren.ai/oss/guide/modeling/overview\"\n              target=\"_blank\"\n              rel=\"noopener noreferrer\"\n            >\n              More details\n            </a>\n            <br />\n            <br />\n            {isSampleDataset ? (\n              <>\n                We use {sampleDatasetInfo.label} Dataset to present the guide.\n                To know more, please visit{' '}\n                <a\n                  href={sampleDatasetInfo.guide}\n                  target=\"_blank\"\n                  rel=\"noopener noreferrer\"\n                >\n                  about the {sampleDatasetInfo.label} Dataset.\n                </a>\n              </>\n            ) : null}\n          </>,\n        ),\n        showButtons: ['next', 'close'],\n        onPopoverRender: (popoverDom: DriverPopoverDOM) => {\n          resetPopoverStyle(popoverDom, 720);\n        },\n        onCloseClick: () => {\n          $driver.destroy();\n          window.sessionStorage.setItem('skipDataModelingGuide', '1');\n        },\n      },\n    },\n    {\n      element: '[data-guideid=\"add-model\"]',\n      popover: {\n        title: renderToString(\n          <>\n            <div className=\"mb-1\">\n              <ModelIcon style={{ fontSize: 24 }} />\n            </div>\n            Create a model\n          </>,\n        ),\n        description: renderToString(\n          <>Click the add icon to start create your first model.</>,\n        ),\n      },\n    },\n    {\n      element: '[data-guideid=\"edit-model-0\"]',\n      popover: {\n        title: renderToString(\n          <>\n            <div className=\"-mx-4\" style={{ minHeight: 175 }}>\n              <img\n                className=\"mb-2\"\n                src=\"/images/learning/edit-model.gif\"\n                alt=\"edit-model\"\n              />\n            </div>\n            Edit a model\n          </>,\n        ),\n        description: renderToString(\n          <>Click the more icon to update the columns of model or delete it.</>,\n        ),\n      },\n    },\n    {\n      element: '[data-guideid=\"model-0\"]',\n      popover: {\n        title: renderToString(\n          <>\n            <div className=\"-mx-4\" style={{ minHeight: 214 }}>\n              <img\n                className=\"mb-2\"\n                src=\"/images/learning/edit-metadata.gif\"\n                alt=\"edit-metadata\"\n              />\n            </div>\n            Edit metadata\n          </>,\n        ),\n        description: renderToString(\n          <>\n            You could edit alias (alternative name) and descriptions of models\n            and columns.\n          </>,\n        ),\n        onPopoverRender: (popoverDom: DriverPopoverDOM) => {\n          resetPopoverStyle(popoverDom, 360);\n        },\n      },\n    },\n    {\n      element: '[data-guideid=\"deploy-model\"]',\n      popover: {\n        title: renderToString(\n          <>\n            <div className=\"-mx-4\" style={{ minHeight: 102 }}>\n              <img\n                className=\"mb-2\"\n                src=\"/images/learning/deploy-modeling.jpg\"\n                alt=\"deploy-modeling\"\n              />\n            </div>\n            Deploy modeling\n          </>,\n        ),\n        description: renderToString(\n          <>After editing the models, remember to deploy the changes.</>,\n        ),\n      },\n    },\n    {\n      popover: {\n        title: renderToString(\n          <>\n            <div className=\"-mx-4\" style={{ minHeight: 331 }}>\n              <img\n                className=\"mb-2\"\n                src=\"/images/learning/ask-question.jpg\"\n                alt=\"ask-question\"\n              />\n            </div>\n            Ask questions\n          </>,\n        ),\n        description: renderToString(\n          <>\n            When you finish editing your models, you can visit “Home” and start\n            asking questions.\n          </>,\n        ),\n        onPopoverRender: (popoverDom: DriverPopoverDOM) => {\n          resetPopoverStyle(popoverDom, 720);\n        },\n        doneBtnText: 'Go to Home',\n        onNextClick: () => {\n          router.push(Path.Home);\n          $driver.destroy();\n          dispatcher?.onDone && dispatcher.onDone();\n        },\n      },\n    },\n  ]);\n  events.dispatch(events.EVENT_NAME.GO_TO_FIRST_MODEL);\n  $driver.drive();\n};\n\n// React component for home guide\nconst LanguageSwitcher = (props: { defaultValue: ProjectLanguage }) => {\n  const [value, setValue] = useState(props.defaultValue);\n  const languageOptions = Object.keys(ProjectLanguage).map((key) => {\n    return { label: getLanguageText(key as ProjectLanguage), value: key };\n  });\n  const onChange = (value: string) => {\n    setValue(value as ProjectLanguage);\n  };\n\n  return (\n    <>\n      <label className=\"d-block mb-2\">Project language</label>\n      <Select\n        showSearch\n        style={{ width: '100%' }}\n        options={languageOptions}\n        getPopupContainer={(trigger) => trigger.parentElement}\n        onChange={onChange}\n        value={value}\n      />\n      <input name=\"language\" type=\"hidden\" value={value} />\n    </>\n  );\n};\n\nconst playSwitchProjectLanguageGuide = (\n  $driver: DriverObj,\n  _router: NextRouter,\n  payload: StoryPayload,\n  dispatcher: Dispatcher,\n) => {\n  if ($driver === null) {\n    console.error('Driver object is not initialized.');\n    return;\n  }\n  if ($driver.isActive()) $driver.destroy();\n\n  $driver.setConfig({ ...defaultConfigs, showProgress: false });\n  $driver.setSteps([\n    {\n      popover: {\n        title: renderToString(\n          <>\n            <div className=\"mb-1\">\n              <TranslateIcon style={{ fontSize: 24 }} />\n            </div>\n            Switch the language\n          </>,\n        ),\n        description: renderToString(\n          <>\n            Choose your preferred language. Once set up, AI will respond in your\n            chosen language.\n            <div className=\"my-3\">\n              <div id=\"projectLanguageContainer\" />\n            </div>\n            You can go to project settings to change it if you change your mind.\n          </>,\n        ),\n        onPopoverRender: (popoverDom: DriverPopoverDOM) => {\n          resetPopoverStyle(popoverDom, 400);\n          // Render react component to #projectLanguageContainer\n          const selectDom = document.getElementById('projectLanguageContainer');\n          if (selectDom) {\n            createRoot(selectDom).render(\n              <LanguageSwitcher defaultValue={payload.language} />,\n            );\n          }\n        },\n        showButtons: ['next', 'close'],\n        nextBtnText: 'Submit',\n        onCloseClick: () => {\n          $driver.destroy();\n          window.sessionStorage.setItem('skipSwitchProjectLanguageGuide', '1');\n        },\n        onNextClick: async () => {\n          const selectDom = document.getElementById('projectLanguageContainer');\n          if (selectDom) {\n            const input = selectDom.querySelector(\n              'input[name=\"language\"]',\n            ) as HTMLInputElement;\n            const nextButton = document.querySelectorAll(\n              '.driver-popover-next-btn',\n            )[0];\n\n            const loadingSvg = document.createElement('span');\n            loadingSvg.setAttribute('aria-hidden', 'loading');\n            loadingSvg.setAttribute('role', 'img');\n            loadingSvg.className =\n              'anticon anticon-loading anticon-spin text-sm gray-6 ml-2';\n            loadingSvg.innerHTML = `<svg viewBox=\"0 0 1024 1024\" focusable=\"false\" data-icon=\"loading\" width=\"1em\" height=\"1em\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z\"></path></svg>`;\n            nextButton.setAttribute('disabled', 'true');\n            nextButton.appendChild(loadingSvg);\n            await dispatcher\n              ?.onSaveLanguage(input.value as ProjectLanguage)\n              .catch((err) => console.error(err))\n              .finally(() => {\n                nextButton.removeAttribute('disabled');\n                nextButton.removeChild(loadingSvg);\n              });\n          }\n          $driver.destroy();\n          dispatcher?.onDone();\n        },\n      },\n    },\n  ]);\n  $driver.drive();\n};\n\nconst playKnowledgeGuide = (\n  $driver: DriverObj,\n  _router: NextRouter,\n  _payload: StoryPayload,\n  dispatcher: Dispatcher,\n) => {\n  if ($driver === null) {\n    console.error('Driver object is not initialized.');\n    return;\n  }\n\n  if ($driver.isActive()) $driver.destroy();\n\n  $driver.setConfig({ ...defaultConfigs, showProgress: true });\n\n  $driver.setSteps([\n    {\n      element: '[data-guideid=\"question-sql-pairs\"]',\n      popover: {\n        title: renderToString(\n          <div className=\"pt-4\">\n            <div className=\"-mx-4\" style={{ minHeight: 317 }}>\n              <img\n                className=\"mb-4\"\n                src=\"/images/learning/save-to-knowledge.gif\"\n                alt=\"question-sql-pairs-guide\"\n              />\n            </div>\n            Build knowledge base: Question-SQL pairs\n          </div>,\n        ),\n        description: renderToString(\n          <>\n            Create and manage <b>Question-SQL pairs</b> to refine Wren AI’s SQL\n            generation. You can manually add pairs here or go to Home, ask a\n            question, and save the correct answer to Knowledge. The more you\n            save, the smarter Wren AI becomes!\n          </>,\n        ),\n        onPopoverRender: (popoverDom: DriverPopoverDOM) => {\n          resetPopoverStyle(popoverDom, 640);\n        },\n      },\n    },\n    {\n      element: '[data-guideid=\"instructions\"]',\n      popover: {\n        title: renderToString(\n          <div className=\"pt-4\">\n            <div className=\"-mx-4\" style={{ minHeight: 260 }}>\n              <img\n                className=\"mb-4\"\n                src=\"/images/learning/instructions.png\"\n                alt=\"instructions-guide\"\n              />\n            </div>\n            Build knowledge base: Instructions\n          </div>,\n        ),\n        description: renderToString(\n          <>\n            In addition to Question-SQL pairs, you can create instructions to\n            define <b>business rules</b> and <b>query logic</b>. These rules\n            guide Wren AI in applying consistent filters, constraints, and best\n            practices to SQL queries.\n          </>,\n        ),\n        onPopoverRender: (popoverDom: DriverPopoverDOM) => {\n          resetPopoverStyle(popoverDom, 520);\n        },\n        doneBtnText: 'Got it',\n        onNextClick: () => {\n          $driver.destroy();\n          dispatcher?.onDone && dispatcher.onDone();\n        },\n      },\n    },\n  ]);\n  $driver.drive();\n};\n\nconst playSaveToKnowledgeGuide = async (\n  $driver: DriverObj,\n  _router: NextRouter,\n  _payload: StoryPayload,\n  dispatcher: Dispatcher,\n) => {\n  if ($driver === null) {\n    console.error('Driver object is not initialized.');\n    return;\n  }\n  if ($driver.isActive()) $driver.destroy();\n\n  $driver.setConfig({ ...defaultConfigs, showProgress: false });\n\n  const selectors = {\n    saveToKnowledge:\n      '[data-guideid=\"last-answer-result\"] [data-guideid=\"save-to-knowledge\"]',\n    previewData:\n      '[data-guideid=\"last-answer-result\"] [data-guideid=\"text-answer-preview-data\"]',\n  };\n\n  $driver.setSteps([\n    {\n      element: selectors.saveToKnowledge,\n      popover: {\n        side: 'top',\n        align: 'start',\n        title: renderToString(\n          <>\n            <div className=\"mb-1\">\n              <RobotIcon />\n            </div>\n            Save to knowledge\n          </>,\n        ),\n        description: renderToString(\n          <>\n            If the AI-generated answer is correct, save it as a{' '}\n            <b>Question-SQL pair</b> to improve AI learning. If it's incorrect,\n            refine it with follow-ups before saving to ensure accuracy.\n          </>,\n        ),\n        onPopoverRender: (popoverDom: DriverPopoverDOM) => {\n          resetPopoverStyle(popoverDom, 360);\n        },\n        doneBtnText: 'Got it',\n        onNextClick: () => {\n          $driver.destroy();\n          dispatcher?.onDone && dispatcher.onDone();\n        },\n      },\n    },\n  ]);\n\n  let mutationObserver: MutationObserver | null = null;\n  let intersectionObserver: IntersectionObserver | null = null;\n\n  const cleanMutationObserverup = () => {\n    // if MutationObserver is listening to the element, disable it\n    if (mutationObserver) {\n      mutationObserver.disconnect();\n      mutationObserver = null;\n    }\n  };\n\n  const cleanIntersectionObserverup = () => {\n    if (intersectionObserver) {\n      intersectionObserver.disconnect();\n      intersectionObserver = null;\n    }\n  };\n\n  const startDriver = () => {\n    const target = document.querySelector(\n      selectors.previewData,\n    ) as HTMLElement | null;\n\n    if (!target) return false;\n\n    cleanMutationObserverup();\n\n    // use IntersectionObserver to ensure the element is in viewport before driving\n    intersectionObserver = new IntersectionObserver(\n      async (entries) => {\n        for (const entry of entries) {\n          if (entry.isIntersecting) {\n            cleanIntersectionObserverup();\n\n            await nextTick(700);\n            $driver.drive();\n            return;\n          }\n        }\n      },\n      { threshold: 0.5 }, // 50% of the element is visible\n    );\n\n    intersectionObserver.observe(target);\n    return true;\n  };\n\n  // try to start Driver.js\n  if (startDriver()) return;\n\n  // if the target element not appear, use MutationObserver to listen DOM changes\n  mutationObserver = new MutationObserver(() => {\n    if (startDriver()) {\n      cleanMutationObserverup();\n    }\n  });\n\n  mutationObserver.observe(document.body, { childList: true, subtree: true });\n\n  // 60 seconds after, observer will be cleared\n  await nextTick(60000);\n  cleanMutationObserverup();\n  cleanIntersectionObserverup();\n};\n"
  },
  {
    "path": "wren-ui/src/components/learning/guide/utils.ts",
    "content": "import { Driver, Config, Popover, PopoverDOM } from 'driver.js';\n\nexport type DriverPopover = Popover;\nexport type DriverObj = Driver;\nexport type DriverPopoverDOM = PopoverDOM;\nexport type DriverConfig = Config;\nexport type Dispatcher = {\n  onDone?: () => Promise<void>;\n  onSaveLanguage?: (value: string) => Promise<void>;\n};\n\n// NOTE: Don't change the enum values, it's used in save to db\nexport enum LEARNING {\n  // modeling\n  DATA_MODELING_GUIDE = 'DATA_MODELING_GUIDE',\n  CREATING_MODEL = 'CREATING_MODEL',\n  CREATING_VIEW = 'CREATING_VIEW',\n  WORKING_RELATIONSHIP = 'WORKING_RELATIONSHIP',\n  CONNECT_OTHER_DATA_SOURCES = 'CONNECT_OTHER_DATA_SOURCES',\n\n  // home\n  SWITCH_PROJECT_LANGUAGE = 'SWITCH_PROJECT_LANGUAGE',\n  VIEW_FULL_SQL = 'VIEW_FULL_SQL',\n\n  // knowledge\n  KNOWLEDGE_GUIDE = 'KNOWLEDGE_GUIDE',\n  SAVE_TO_KNOWLEDGE = 'SAVE_TO_KNOWLEDGE',\n}\n"
  },
  {
    "path": "wren-ui/src/components/learning/index.tsx",
    "content": "import {\n  ComponentRef,\n  MutableRefObject,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from 'react';\nimport { sortBy } from 'lodash';\nimport styled from 'styled-components';\nimport ReadOutlined from '@ant-design/icons/ReadOutlined';\nimport RightOutlined from '@ant-design/icons/RightOutlined';\nimport { IterableComponent, makeIterable } from '@/utils/iteration';\nimport LearningGuide from '@/components/learning/guide';\nimport { LEARNING } from './guide/utils';\nimport { useRouter } from 'next/router';\nimport { Path } from '@/utils/enum';\nimport {\n  useLearningRecordQuery,\n  useSaveLearningRecordMutation,\n} from '@/apollo/client/graphql/learning.generated';\nimport { nextTick } from '@/utils/time';\nimport { ProjectLanguage } from '@/apollo/client/graphql/__types__';\nimport { useUpdateCurrentProjectMutation } from '@/apollo/client/graphql/settings.generated';\n\nconst Progress = styled.div<{ total: number; current: number }>`\n  display: block;\n  border-radius: 999px;\n  height: 6px;\n  width: 100%;\n  background-color: var(--gray-4);\n\n  &::before {\n    content: '';\n    display: block;\n    border-radius: 999px;\n    width: ${({ total, current }) => `${(current / total) * 100}%`};\n    height: 100%;\n    background: linear-gradient(to left, #75eaff, #6150e0);\n    transition: width 0.3s;\n  }\n`;\n\nconst CollapseBlock = styled.div`\n  overflow: hidden;\n`;\n\nconst PlayIcon = styled.div`\n  position: relative;\n  width: 16px;\n  height: 16px;\n  border-radius: 50%;\n  background-color: var(--gray-5);\n  &::before {\n    content: '';\n    display: block;\n    position: absolute;\n    top: 50%;\n    left: 50%;\n    margin-top: -4px;\n    margin-left: -2px;\n    border-top: 4px solid transparent;\n    border-left: 6px solid var(--gray-8);\n    border-bottom: 4px solid transparent;\n  }\n`;\n\nconst List = styled.div<{ finished: boolean }>`\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  cursor: pointer;\n  font-size: 12px;\n  color: ${({ finished }) => (finished ? 'var(--gray-6)' : 'var(--gray-8)')};\n  text-decoration: ${({ finished }) => (finished ? 'line-through' : 'none')};\n  padding: 2px 16px;\n\n  &:hover {\n    transition: background-color 0.3s;\n    background-color: var(--gray-4);\n    color: ${({ finished }) => (finished ? 'var(--gray-6)' : 'var(--gray-8)')};\n    text-decoration: ${({ finished }) => (finished ? 'line-through' : 'none')};\n  }\n`;\n\nconst ListTemplate = (props: IterableComponent<LearningConfig>) => {\n  const { title, onClick, href, finished } = props;\n  const as = href ? 'a' : 'div';\n  const hrefAttrs = href\n    ? { href, target: '_blank', rel: 'noopener noreferrer' }\n    : {};\n  return (\n    <List\n      className=\"select-none\"\n      finished={finished}\n      onClick={onClick}\n      as={as}\n      {...hrefAttrs}\n    >\n      {title}\n      <PlayIcon />\n    </List>\n  );\n};\n\nconst ListIterator = makeIterable(ListTemplate);\n\ninterface LearningConfig {\n  id: LEARNING;\n  title: string;\n  onClick?: () => void;\n  href?: string;\n  finished?: boolean;\n}\n\nconst getData = (\n  $guide: MutableRefObject<ComponentRef<typeof LearningGuide>>,\n  pathname: string,\n  saveRecord: (id: LEARNING) => Promise<void>,\n  saveLanguage: (value: ProjectLanguage) => Promise<void>,\n) => {\n  const getDispatcher = (id: LEARNING) => ({\n    onDone: () => saveRecord(id),\n    onSaveLanguage: saveLanguage,\n  });\n\n  const modeling = [\n    {\n      id: LEARNING.DATA_MODELING_GUIDE,\n      title: 'Data modeling guide',\n      onClick: () =>\n        $guide?.current?.play(\n          LEARNING.DATA_MODELING_GUIDE,\n          getDispatcher(LEARNING.DATA_MODELING_GUIDE),\n        ),\n    },\n    {\n      id: LEARNING.CREATING_MODEL,\n      title: 'Creating a model',\n      href: 'https://docs.getwren.ai/oss/guide/modeling/models',\n      onClick: () => saveRecord(LEARNING.CREATING_MODEL),\n    },\n    {\n      id: LEARNING.CREATING_VIEW,\n      title: 'Creating a view',\n      href: 'https://docs.getwren.ai/oss/guide/modeling/views',\n      onClick: () => saveRecord(LEARNING.CREATING_VIEW),\n    },\n    {\n      id: LEARNING.WORKING_RELATIONSHIP,\n      title: 'Working on relationship',\n      href: 'https://docs.getwren.ai/oss/guide/modeling/relationships',\n      onClick: () => saveRecord(LEARNING.WORKING_RELATIONSHIP),\n    },\n    {\n      id: LEARNING.CONNECT_OTHER_DATA_SOURCES,\n      title: 'Connect to other data sources',\n      href: 'https://docs.getwren.ai/oss/guide/connect/overview',\n      onClick: () => saveRecord(LEARNING.CONNECT_OTHER_DATA_SOURCES),\n    },\n  ] as LearningConfig[];\n\n  const home = [\n    {\n      id: LEARNING.SWITCH_PROJECT_LANGUAGE,\n      title: 'Switch the language',\n      onClick: () =>\n        $guide?.current?.play(\n          LEARNING.SWITCH_PROJECT_LANGUAGE,\n          getDispatcher(LEARNING.SWITCH_PROJECT_LANGUAGE),\n        ),\n    },\n    {\n      id: LEARNING.VIEW_FULL_SQL,\n      title: 'View full SQL',\n      href: 'https://docs.getwren.ai/oss/guide/home/answer#view-sqlview-full-sql',\n      onClick: () => saveRecord(LEARNING.VIEW_FULL_SQL),\n    },\n  ];\n\n  if (pathname.startsWith(Path.Modeling)) {\n    return modeling;\n  } else if (pathname.startsWith(Path.Home)) {\n    return home;\n  }\n  return [];\n};\n\nconst isLearningAccessible = (pathname: string) =>\n  pathname.startsWith(Path.Modeling) || pathname.startsWith(Path.Home);\n\ninterface Props {}\n\nexport default function SidebarSection(_props: Props) {\n  const router = useRouter();\n  const [active, setActive] = useState(true);\n  const $guide = useRef<ComponentRef<typeof LearningGuide>>(null);\n  const $collapseBlock = useRef<HTMLDivElement>(null);\n\n  const { data: learningRecordResult } = useLearningRecordQuery();\n\n  const [saveLearningRecord] = useSaveLearningRecordMutation({\n    onError: (error) => console.error(error),\n    refetchQueries: ['LearningRecord'],\n  });\n\n  const [updateCurrentProject] = useUpdateCurrentProjectMutation({\n    onError: (error) => console.error(error),\n    refetchQueries: ['GetSettings'],\n  });\n\n  const saveRecord = async (path: LEARNING) => {\n    await saveLearningRecord({ variables: { data: { path } } });\n  };\n\n  const saveLanguage = async (value: ProjectLanguage) => {\n    await updateCurrentProject({ variables: { data: { language: value } } });\n  };\n\n  const stories = useMemo(() => {\n    const learningData = getData(\n      $guide,\n      router.pathname,\n      saveRecord,\n      saveLanguage,\n    );\n    const record = learningRecordResult?.learningRecord.paths || [];\n    return sortBy(\n      learningData.map((story) => ({\n        ...story,\n        finished: record.includes(story.id),\n      })),\n      'finished',\n    );\n  }, [learningRecordResult?.learningRecord]);\n\n  const total = useMemo(() => stories.length, [stories]);\n  const current = useMemo(\n    () => stories.filter((item) => item?.finished).length,\n    [stories],\n  );\n\n  const collapseBlock = async (isActive: boolean) => {\n    if ($collapseBlock.current) {\n      const blockHeight = $collapseBlock.current.scrollHeight;\n      $collapseBlock.current.style.height = isActive\n        ? `${blockHeight}px`\n        : '0px';\n      await nextTick(300);\n      $collapseBlock.current &&\n        ($collapseBlock.current.style.transition = 'height 0.3s');\n    }\n  };\n\n  useEffect(() => {\n    const learningRecord = learningRecordResult?.learningRecord;\n    if (learningRecord) {\n      setActive(\n        stories.some((item) => !learningRecord.paths.includes(item.id)),\n      );\n\n      const routerAction = {\n        [Path.Modeling]: async () => {\n          const isGuideDone = learningRecord.paths.includes(\n            LEARNING.DATA_MODELING_GUIDE,\n          );\n          const isSkipBefore = !!window.sessionStorage.getItem(\n            'skipDataModelingGuide',\n          );\n          if (!(isGuideDone || isSkipBefore)) {\n            await nextTick(1000);\n            $guide.current?.play(LEARNING.DATA_MODELING_GUIDE, {\n              onDone: () => saveRecord(LEARNING.DATA_MODELING_GUIDE),\n            });\n          }\n        },\n        [Path.Home]: async () => {\n          const isGuideDone = learningRecord.paths.includes(\n            LEARNING.SWITCH_PROJECT_LANGUAGE,\n          );\n          const isSkipBefore = !!window.sessionStorage.getItem(\n            'skipSwitchProjectLanguageGuide',\n          );\n          if (!(isGuideDone || isSkipBefore)) {\n            await nextTick(1000);\n            $guide.current?.play(LEARNING.SWITCH_PROJECT_LANGUAGE, {\n              onDone: () => saveRecord(LEARNING.SWITCH_PROJECT_LANGUAGE),\n              onSaveLanguage: saveLanguage,\n            });\n          }\n        },\n        [Path.Thread]: async () => {\n          const isGuideDone = learningRecord.paths.includes(\n            LEARNING.SAVE_TO_KNOWLEDGE,\n          );\n          if (!isGuideDone) {\n            await nextTick(1500);\n            $guide.current?.play(LEARNING.SAVE_TO_KNOWLEDGE, {\n              onDone: () => saveRecord(LEARNING.SAVE_TO_KNOWLEDGE),\n            });\n          }\n        },\n        [Path.KnowledgeQuestionSQLPairs]: async () => {\n          const isGuideDone = learningRecord.paths.includes(\n            LEARNING.KNOWLEDGE_GUIDE,\n          );\n          if (!isGuideDone) {\n            await nextTick(1000);\n            $guide.current?.play(LEARNING.KNOWLEDGE_GUIDE, {\n              onDone: () => saveRecord(LEARNING.KNOWLEDGE_GUIDE),\n            });\n          }\n        },\n      };\n\n      routerAction[router.pathname] && routerAction[router.pathname]();\n    }\n  }, [learningRecordResult?.learningRecord, router.pathname]);\n\n  useEffect(() => {\n    collapseBlock(active);\n  }, [active]);\n\n  const onCollapseBarClick = () => {\n    setActive(!active);\n  };\n\n  // Hide learning section if the page not in whitelist\n  return (\n    <>\n      <LearningGuide ref={$guide} />\n      {isLearningAccessible(router.pathname) && (\n        <div className=\"border-t border-gray-4\">\n          <div\n            className=\"px-4 py-1 d-flex align-center cursor-pointer select-none\"\n            onClick={onCollapseBarClick}\n          >\n            <div className=\"flex-grow-1\">\n              <ReadOutlined className=\"mr-1\" />\n              Learning\n            </div>\n            <RightOutlined\n              className=\"text-sm\"\n              style={{ transform: `rotate(${active ? '90deg' : '0deg'})` }}\n            />\n          </div>\n          <CollapseBlock ref={$collapseBlock}>\n            <ListIterator data={stories} />\n            <div className=\"px-4 py-2 d-flex align-center\">\n              <Progress total={total} current={current} />\n              <span className=\"text-xs gray-6 text-nowrap pl-2\">\n                {current}/{total} Finished\n              </span>\n            </div>\n          </CollapseBlock>\n        </div>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/modals/AdjustReasoningStepsModal.tsx",
    "content": "import { useEffect, useMemo } from 'react';\nimport { keyBy } from 'lodash';\nimport styled from 'styled-components';\nimport { Form, Modal, Select, Tag } from 'antd';\nimport QuestionCircleOutlined from '@ant-design/icons/QuestionCircleOutlined';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport useAutoComplete, { convertMention } from '@/hooks/useAutoComplete';\nimport { ModalAction } from '@/hooks/useModalAction';\nimport MarkdownEditor from '@/components/editor/MarkdownEditor';\nimport { useListModelsQuery } from '@/apollo/client/graphql/model.generated';\n\nconst MultiSelect = styled(Select)`\n  .ant-select-selector {\n    padding-top: 3px;\n  }\n  .ant-tag {\n    padding: 3px 5px;\n    margin-right: 3px;\n    margin-bottom: 3px;\n  }\n`;\n\nconst TagText = styled.div`\n  line-height: 16px;\n`;\n\ntype Props = ModalAction<{\n  responseId: number;\n  retrievedTables: string[];\n  sqlGenerationReasoning: string;\n}> & {\n  loading?: boolean;\n};\n\nexport default function AdjustReasoningStepsModal(props: Props) {\n  const { visible, defaultValue, loading, onSubmit, onClose } = props;\n  const [form] = Form.useForm();\n\n  const mentions = useAutoComplete({\n    convertor: convertMention,\n    includeColumns: true,\n    skip: !visible,\n  });\n  const listModelsResult = useListModelsQuery({ skip: !visible });\n  const modelNameMap = keyBy(\n    listModelsResult.data?.listModels,\n    'referenceName',\n  );\n  const modelOptions = useMemo(() => {\n    return listModelsResult.data?.listModels.map((model) => ({\n      label: model.displayName,\n      value: model.referenceName,\n    }));\n  }, [listModelsResult.data?.listModels]);\n\n  useEffect(() => {\n    if (!visible) return;\n    const listModels = listModelsResult.data?.listModels || [];\n    const retrievedTables = listModels.reduce((result, model) => {\n      if (defaultValue?.retrievedTables.includes(model.referenceName)) {\n        result.push(model.referenceName);\n      }\n      return result;\n    }, []);\n    form.setFieldsValue({\n      tables: retrievedTables,\n      sqlGenerationReasoning: defaultValue?.sqlGenerationReasoning,\n    });\n  }, [form, defaultValue, visible, listModelsResult.data?.listModels]);\n\n  const tagRender = (props) => {\n    const { value, closable, onClose } = props;\n    const model = modelNameMap[value];\n    return (\n      <Tag\n        onMouseDown={(e) => e.stopPropagation()}\n        closable={closable}\n        onClose={onClose}\n        className=\"d-flex align-center bg-gray-3 border-gray-3\"\n        style={{ maxWidth: 140 }}\n      >\n        <div className=\"pr-1\" style={{ minWidth: 0 }}>\n          <TagText className=\"gray-8 text-truncate\" title={model.displayName}>\n            {model.displayName}\n          </TagText>\n          <TagText\n            className=\"gray-7 text-xs text-truncate\"\n            title={model.referenceName}\n          >\n            {model.referenceName}\n          </TagText>\n        </div>\n      </Tag>\n    );\n  };\n\n  const reset = () => {\n    form.resetFields();\n  };\n\n  const submit = async () => {\n    form\n      .validateFields()\n      .then(async (values) => {\n        await onSubmit({\n          responseId: defaultValue.responseId,\n          data: values,\n        });\n        onClose();\n      })\n      .catch(console.error);\n  };\n\n  return (\n    <Modal\n      title=\"Adjust steps\"\n      width={640}\n      visible={visible}\n      okText=\"Regenerate answer\"\n      onOk={submit}\n      onCancel={onClose}\n      confirmLoading={loading}\n      maskClosable={false}\n      destroyOnClose\n      centered\n      afterClose={reset}\n    >\n      <Form form={form} preserve={false} layout=\"vertical\">\n        <Form.Item\n          label=\"Selected models\"\n          name=\"tables\"\n          required={false}\n          rules={[\n            {\n              required: true,\n              message: ERROR_TEXTS.ADJUST_REASONING.SELECTED_MODELS.REQUIRED,\n            },\n          ]}\n          extra={\n            <div className=\"text-sm gray-6 mt-1\">\n              Select the tables needed to answer your question.{' '}\n              <span className=\"gray-7\">\n                Tables not selected won't be used in SQL generation.\n              </span>\n            </div>\n          }\n        >\n          <MultiSelect\n            mode=\"multiple\"\n            placeholder=\"Select models\"\n            options={modelOptions}\n            tagRender={tagRender}\n          />\n        </Form.Item>\n        <Form.Item\n          label=\"Reasoning steps\"\n          className=\"pb-0\"\n          extra={\n            <div className=\"text-sm gray-6 mt-1\">\n              <QuestionCircleOutlined className=\"mr-1\" />\n              Protip: Use @ to choose model in the textarea.\n            </div>\n          }\n        >\n          <div className=\"text-sm gray-6 mb-1\">\n            Edit the reasoning logic below. Each step should build toward\n            answering the question accurately.\n          </div>\n          <Form.Item\n            noStyle\n            name=\"sqlGenerationReasoning\"\n            required={false}\n            rules={[\n              {\n                required: true,\n                message: ERROR_TEXTS.ADJUST_REASONING.STEPS.REQUIRED,\n              },\n              {\n                max: 6000,\n                message: ERROR_TEXTS.ADJUST_REASONING.STEPS.MAX_LENGTH,\n              },\n            ]}\n          >\n            <MarkdownEditor maxLength={6000} mentions={mentions} />\n          </Form.Item>\n        </Form.Item>\n      </Form>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/modals/AdjustSQLModal.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { Alert, Button, Form, Modal, Typography } from 'antd';\nimport InfoCircleOutlined from '@ant-design/icons/InfoCircleOutlined';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { ModalAction } from '@/hooks/useModalAction';\nimport SQLEditor from '@/components/editor/SQLEditor';\nimport { parseGraphQLError } from '@/utils/errorHandler';\nimport ErrorCollapse from '@/components/ErrorCollapse';\nimport PreviewData from '@/components/dataPreview/PreviewData';\nimport { usePreviewSqlMutation } from '@/apollo/client/graphql/sql.generated';\n\ninterface AdjustSQLFormValues {\n  responseId: number;\n  sql: string;\n}\n\ntype Props = ModalAction<AdjustSQLFormValues, AdjustSQLFormValues> & {\n  loading?: boolean;\n};\n\nexport default function AdjustSQLModal(props: Props) {\n  const { defaultValue, loading, onClose, onSubmit, visible } = props;\n\n  const [form] = Form.useForm();\n  const [error, setError] =\n    useState<ReturnType<typeof parseGraphQLError>>(null);\n  const [previewing, setPreviewing] = useState<boolean>(false);\n  const [submitting, setSubmitting] = useState<boolean>(false);\n  const [showPreview, setShowPreview] = useState<boolean>(false);\n\n  // Handle errors via try/catch blocks rather than onError callback\n  const [previewSqlMutation, previewSqlResult] = usePreviewSqlMutation();\n\n  const sqlValue = Form.useWatch('sql', form);\n\n  useEffect(() => {\n    if (visible) {\n      form.setFieldsValue({\n        sql: defaultValue?.sql,\n      });\n    }\n  }, [visible, defaultValue]);\n\n  const handleReset = () => {\n    previewSqlResult.reset();\n    setShowPreview(false);\n    setError(null);\n    form.resetFields();\n  };\n\n  const onValidateSQL = async () => {\n    await previewSqlMutation({\n      variables: {\n        data: {\n          sql: sqlValue,\n          limit: 1,\n          dryRun: true,\n        },\n      },\n    });\n  };\n\n  const handleError = (error) => {\n    const graphQLError = parseGraphQLError(error);\n    setError({ ...graphQLError, shortMessage: 'Invalid SQL syntax' });\n    console.error(graphQLError);\n  };\n\n  const onPreviewData = async () => {\n    setError(null);\n    setPreviewing(true);\n    try {\n      await onValidateSQL();\n      setShowPreview(true);\n      await previewSqlMutation({\n        variables: {\n          data: {\n            sql: sqlValue,\n            limit: 50,\n          },\n        },\n      });\n    } catch (error) {\n      setShowPreview(false);\n      handleError(error);\n    } finally {\n      setPreviewing(false);\n    }\n  };\n\n  const onSubmitButton = () => {\n    setError(null);\n    setSubmitting(true);\n    setShowPreview(false);\n    form\n      .validateFields()\n      .then(async (values) => {\n        try {\n          await onValidateSQL();\n          await onSubmit({\n            responseId: defaultValue?.responseId,\n            sql: values.sql,\n          });\n          onClose();\n        } catch (error) {\n          handleError(error);\n        } finally {\n          setSubmitting(false);\n        }\n      })\n      .catch((err) => {\n        setSubmitting(false);\n        console.error(err);\n      });\n  };\n\n  const confirmLoading = loading || submitting;\n  const disabled = !sqlValue;\n\n  return (\n    <Modal\n      title=\"Adjust SQL\"\n      centered\n      closable\n      confirmLoading={confirmLoading}\n      destroyOnClose\n      maskClosable={false}\n      onCancel={onClose}\n      visible={visible}\n      width={640}\n      cancelButtonProps={{ disabled: confirmLoading }}\n      okButtonProps={{ disabled: previewSqlResult.loading }}\n      afterClose={() => handleReset()}\n      footer={\n        <div className=\"d-flex justify-space-between align-center\">\n          <div\n            className=\"text-sm ml-2 d-flex justify-space-between align-center\"\n            style={{ width: 300 }}\n          >\n            <InfoCircleOutlined className=\"mr-2 text-sm gray-7\" />\n            <Typography.Text\n              type=\"secondary\"\n              className=\"text-sm gray-7 text-left\"\n            >\n              The SQL statement used here follows <b>Wren SQL</b>, which is\n              based on ANSI SQL and optimized for Wren AI.{` `}\n              <Typography.Link\n                type=\"secondary\"\n                href=\"https://docs.getwren.ai/oss/guide/home/wren_sql\"\n                target=\"_blank\"\n                rel=\"noopener noreferrer\"\n              >\n                Learn more about the syntax.\n              </Typography.Link>\n            </Typography.Text>\n          </div>\n          <div>\n            <Button onClick={onClose}>Cancel</Button>\n            <Button\n              type=\"primary\"\n              onClick={onSubmitButton}\n              loading={confirmLoading}\n            >\n              Submit\n            </Button>\n          </div>\n        </div>\n      }\n    >\n      <Form form={form} preserve={false} layout=\"vertical\">\n        <Form.Item\n          label=\"SQL statement\"\n          name=\"sql\"\n          required\n          rules={[\n            {\n              required: true,\n              message: ERROR_TEXTS.SQL_PAIR.SQL.REQUIRED,\n            },\n          ]}\n        >\n          <SQLEditor autoComplete autoFocus />\n        </Form.Item>\n      </Form>\n      <div className=\"my-3\">\n        <Typography.Text className=\"d-block gray-7 mb-2\">\n          Data preview (50 rows)\n        </Typography.Text>\n        <Button\n          onClick={onPreviewData}\n          loading={previewing}\n          disabled={disabled}\n        >\n          Preview data\n        </Button>\n        {showPreview && (\n          <div className=\"my-3\">\n            <PreviewData\n              loading={previewing}\n              previewData={previewSqlResult?.data?.previewSql}\n              copyable={false}\n            />\n          </div>\n        )}\n      </div>\n      {!!error && (\n        <Alert\n          showIcon\n          type=\"error\"\n          message={error.shortMessage}\n          description={<ErrorCollapse message={error.message} />}\n        />\n      )}\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/modals/CalculatedFieldModal.tsx",
    "content": "import { useCallback, useEffect, useMemo, useState } from 'react';\nimport { Modal, Form, Input, Typography, Button, Alert } from 'antd';\nimport LinkOutlined from '@ant-design/icons/LinkOutlined';\nimport { FORM_MODE } from '@/utils/enum';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { DiagramModel } from '@/utils/data/type';\nimport { ModalAction } from '@/hooks/useModalAction';\nimport {\n  createLineageSelectorNameValidator,\n  createLineageSelectorValidator,\n} from '@/utils/validator';\nimport { ERROR_CODES, parseGraphQLError } from '@/utils/errorHandler';\nimport { FieldValue } from '@/components/selectors/lineageSelector/FieldSelect';\nimport useExpressionFieldOptions from '@/hooks/useExpressionFieldOptions';\nimport LineageSelector, {\n  getLineageOptions,\n} from '@/components/selectors/lineageSelector';\nimport DescriptiveSelector from '@/components/selectors/DescriptiveSelector';\nimport ErrorCollapse from '@/components/ErrorCollapse';\nimport { useValidateCalculatedFieldMutation } from '@/apollo/client/graphql/calculatedField.generated';\nimport { CreateCalculatedFieldInput } from '@/apollo/client/graphql/__types__';\n\nexport type CalculatedFieldValue = {\n  name: string;\n  expression: string;\n  lineage: FieldValue[];\n  columnId?: number;\n\n  payload: {\n    models: DiagramModel[];\n    sourceModel: DiagramModel;\n  };\n};\n\ntype Props = ModalAction<\n  CalculatedFieldValue,\n  { id?: number; data: CreateCalculatedFieldInput }\n> & {\n  loading?: boolean;\n};\n\nexport default function AddCalculatedFieldModal(props: Props) {\n  const {\n    visible,\n    loading,\n    onSubmit,\n    onClose,\n    defaultValue,\n    payload,\n    formMode,\n  } = props;\n\n  const isEditMode = formMode === FORM_MODE.EDIT;\n  const [error, setError] =\n    useState<ReturnType<typeof parseGraphQLError>>(null);\n\n  const [form] = Form.useForm();\n  const expression = Form.useWatch('expression', form);\n  const lineage = Form.useWatch('lineage', form);\n\n  const expressionOptions = useExpressionFieldOptions();\n\n  const models = useMemo(() => payload?.models, [payload]);\n  const sourceModel = useMemo(() => payload?.sourceModel, [payload]);\n\n  const [validateCalculatedField] = useValidateCalculatedFieldMutation();\n  const validateCalculatedFieldName = useCallback(\n    async (name: string) =>\n      await validateCalculatedField({\n        variables: {\n          data: {\n            name,\n            modelId: sourceModel.modelId,\n            columnId: defaultValue?.columnId,\n          },\n        },\n      }),\n    [sourceModel, defaultValue],\n  );\n\n  useEffect(() => {\n    if (!visible) return;\n    form.setFieldsValue(defaultValue || {});\n  }, [form, defaultValue, visible]);\n\n  const fetchOptions = useCallback(\n    async (value) => {\n      const selectedModel = models.find(\n        (model) => model.referenceName === value.referenceName,\n      );\n      // use current model options when initial\n      return getLineageOptions({\n        model: selectedModel,\n        sourceModel,\n        expression,\n        values: lineage,\n      });\n    },\n    [models, lineage, expression],\n  );\n\n  const reset = () => {\n    setError(null);\n    form.resetFields();\n  };\n\n  const submit = () => {\n    setError(null);\n    form\n      .validateFields()\n      .then(async (values) => {\n        const id = defaultValue?.columnId;\n        const modelId = !id ? sourceModel.modelId : undefined;\n\n        await onSubmit({\n          id,\n          data: {\n            modelId,\n            expression: values.expression,\n            name: values.name,\n            // lineage output example: [relationId1, relationId2, columnId], the last item is always a columnId\n            lineage: values.lineage.map(\n              (field) => field.relationId || field.columnId,\n            ),\n          },\n        });\n        onClose();\n      })\n      .catch((err) => {\n        const graphQLError = parseGraphQLError(err);\n        if (graphQLError.code === ERROR_CODES.INVALID_CALCULATED_FIELD) {\n          setError(graphQLError);\n        }\n        console.error(err);\n      });\n  };\n\n  return (\n    <Modal\n      title={`${isEditMode ? 'Update' : 'Add'} calculated field`}\n      width={750}\n      visible={visible}\n      onCancel={onClose}\n      confirmLoading={loading}\n      maskClosable={false}\n      destroyOnClose\n      afterClose={() => reset()}\n      footer={\n        <div className=\"d-flex justify-space-between align-center\">\n          <div className=\"text-sm ml-2\">\n            <LinkOutlined className=\"gray-6 mr-2\" />\n            <Typography.Link\n              type=\"secondary\"\n              href=\"https://docs.getwren.ai/oss/guide/modeling/models#update-primary-key\"\n              target=\"_blank\"\n              rel=\"noopener noreferrer\"\n            >\n              How to set primary key in a model.\n            </Typography.Link>\n          </div>\n          <div>\n            <Button onClick={onClose}>Cancel</Button>\n            <Button type=\"primary\" onClick={submit} loading={loading}>\n              Save\n            </Button>\n          </div>\n        </div>\n      }\n    >\n      <Form form={form} preserve={false} layout=\"vertical\">\n        <Form.Item\n          label=\"Name\"\n          name=\"name\"\n          required\n          rules={[\n            {\n              validator: createLineageSelectorNameValidator(\n                validateCalculatedFieldName,\n              ),\n            },\n          ]}\n        >\n          <Input />\n        </Form.Item>\n\n        <Form.Item\n          label=\"Select an expression\"\n          name=\"expression\"\n          required\n          rules={[\n            {\n              required: true,\n              message: ERROR_TEXTS.CALCULATED_FIELD.EXPRESSION.REQUIRED,\n            },\n          ]}\n        >\n          <DescriptiveSelector\n            placeholder=\"Select an expression\"\n            options={expressionOptions}\n            descriptiveContentRender={(content) => {\n              return (\n                <>\n                  <div className=\"mb-1\">{content?.description || '-'}</div>\n                  {content?.expression && (\n                    <Typography.Text className=\"mb-1\" code>\n                      {content.expression}\n                    </Typography.Text>\n                  )}\n                </>\n              );\n            }}\n          />\n        </Form.Item>\n        <div className=\"py-1\" />\n        {!!expression && (\n          <Form.Item\n            name=\"lineage\"\n            rules={[\n              {\n                validator: createLineageSelectorValidator(expression),\n              },\n            ]}\n          >\n            <LineageSelector\n              sourceModel={sourceModel}\n              onFetchOptions={fetchOptions}\n            />\n          </Form.Item>\n        )}\n      </Form>\n\n      {!!error && (\n        <Alert\n          showIcon\n          type=\"error\"\n          message={error.shortMessage}\n          description={<ErrorCollapse message={error.message} />}\n        />\n      )}\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/modals/DeleteModal.tsx",
    "content": "import { ReactNode } from 'react';\nimport { ButtonProps, Modal, ModalProps } from 'antd';\nimport ExclamationCircleOutlined from '@ant-design/icons/ExclamationCircleOutlined';\nimport DeleteOutlined from '@ant-design/icons/DeleteOutlined';\n\ntype DeleteModalProps = {\n  disabled?: boolean;\n  modalProps?: ModalProps;\n  onConfirm: () => void;\n  style?: any;\n} & Partial<ButtonProps>;\n\ntype Config = {\n  icon?: ReactNode;\n  itemName?: string;\n  content?: string;\n};\n\nexport const makeDeleteModal =\n  (Component, config?: Config) => (props: DeleteModalProps) => {\n    const { title, content, modalProps = {}, onConfirm, ...restProps } = props;\n\n    return (\n      <Component\n        icon={config.icon}\n        onClick={() =>\n          Modal.confirm({\n            autoFocusButton: null,\n            cancelText: 'Cancel',\n            content:\n              config?.content ||\n              'This will be permanently deleted, please confirm you want to delete it.',\n            icon: <ExclamationCircleOutlined />,\n            okText: 'Delete',\n            onOk: onConfirm,\n            title: `Are you sure you want to delete this ${config?.itemName}?`,\n            width: 464,\n            ...modalProps,\n            okButtonProps: {\n              ...modalProps.okButtonProps,\n              danger: true,\n            },\n          })\n        }\n        {...restProps}\n      />\n    );\n  };\n\nconst DefaultDeleteButton = (props) => {\n  const { icon = null, disabled, ...restProps } = props;\n  return (\n    <a className={disabled ? '' : 'red-5'} {...restProps}>\n      {icon}Delete\n    </a>\n  );\n};\n\nexport default makeDeleteModal(DefaultDeleteButton);\n\n// Customize delete modal\nexport const DeleteThreadModal = makeDeleteModal(DefaultDeleteButton, {\n  icon: <DeleteOutlined className=\"mr-2\" />,\n  itemName: 'thread',\n  content:\n    'This will permanently delete all results history in this thread, please confirm you want to delete it.',\n});\n\nexport const DeleteViewModal = makeDeleteModal(DefaultDeleteButton, {\n  icon: <DeleteOutlined className=\"mr-2\" />,\n  itemName: 'view',\n  content:\n    'This will be permanently deleted, please confirm you want to delete it.',\n});\n\nexport const DeleteModelModal = makeDeleteModal(DefaultDeleteButton, {\n  icon: <DeleteOutlined className=\"mr-2\" />,\n  itemName: 'model',\n  content:\n    'This will be permanently deleted, please confirm you want to delete it.',\n});\n\nexport const DeleteCalculatedFieldModal = makeDeleteModal(DefaultDeleteButton, {\n  icon: <DeleteOutlined className=\"mr-2\" />,\n  itemName: 'calculated field',\n  content:\n    'This will be permanently deleted, please confirm you want to delete it.',\n});\n\nexport const DeleteRelationshipModal = makeDeleteModal(DefaultDeleteButton, {\n  icon: <DeleteOutlined className=\"mr-2\" />,\n  itemName: 'relationship',\n  content:\n    'This will be permanently deleted, please confirm you want to delete it.',\n});\n\nexport const DeleteDashboardItemModal = makeDeleteModal(DefaultDeleteButton, {\n  icon: <DeleteOutlined className=\"mr-2\" />,\n  itemName: 'dashboard item',\n  content:\n    'This will be permanently deleted, please confirm you want to delete it.',\n});\n\nexport const DeleteQuestionSQLPairModal = makeDeleteModal(DefaultDeleteButton, {\n  icon: <DeleteOutlined className=\"mr-2\" />,\n  itemName: 'question-SQL pair',\n  content:\n    'This action is permanent and cannot be undone. Are you sure you want to proceed?',\n});\n\nexport const DeleteInstructionModal = makeDeleteModal(DefaultDeleteButton, {\n  icon: <DeleteOutlined className=\"mr-2\" />,\n  itemName: 'instruction',\n  content:\n    'This action is permanent and cannot be undone. Are you sure you want to proceed?',\n});\n"
  },
  {
    "path": "wren-ui/src/components/modals/FixSQLModal.tsx",
    "content": "import { useEffect, useMemo, useState } from 'react';\nimport { Button, Form, Modal, Typography, Alert } from 'antd';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { ModalAction } from '@/hooks/useModalAction';\nimport { attachLoading } from '@/utils/helper';\nimport { parseGraphQLError } from '@/utils/errorHandler';\nimport SQLEditor from '@/components/editor/SQLEditor';\nimport ErrorCollapse from '@/components/ErrorCollapse';\nimport PreviewData from '@/components/dataPreview/PreviewData';\nimport { usePreviewSqlMutation } from '@/apollo/client/graphql/sql.generated';\n\ntype Props = ModalAction<{ sql: string; responseId: number }> & {\n  loading?: boolean;\n};\n\nexport function FixSQLModal(props: Props) {\n  const { visible, defaultValue, loading, onSubmit, onClose } = props;\n  const [previewLoading, setPreviewLoading] = useState(false);\n  const [form] = Form.useForm();\n\n  // Handle errors via try/catch blocks rather than onError callback\n  const [previewSqlMutation, previewSqlResult] = usePreviewSqlMutation();\n\n  const error = useMemo(() => {\n    if (!previewSqlResult.error) return null;\n    const graphQLError = parseGraphQLError(previewSqlResult.error);\n    return { ...graphQLError, shortMessage: 'Invalid SQL syntax' };\n  }, [previewSqlResult.error]);\n\n  useEffect(() => {\n    if (!visible) return;\n    form.setFieldsValue(defaultValue || {});\n  }, [form, defaultValue, visible]);\n\n  const validateSql = async () => {\n    const sql = form.getFieldValue('sql');\n    await previewSqlMutation({\n      variables: { data: { sql, limit: 1, dryRun: true } },\n    });\n  };\n\n  const previewData = async () => {\n    form\n      .validateFields()\n      .then(async (values) => {\n        await attachLoading(\n          previewSqlMutation,\n          setPreviewLoading,\n        )({\n          variables: { data: { sql: values.sql, limit: 50 } },\n        });\n      })\n      .catch(console.error);\n  };\n\n  const reset = () => {\n    form.resetFields();\n    previewSqlResult.reset();\n  };\n\n  const submit = async () => {\n    form\n      .validateFields()\n      .then(async (values) => {\n        await validateSql();\n        await onSubmit(values.sql);\n        onClose();\n      })\n      .catch(console.error);\n  };\n\n  const showPreview = previewSqlResult.data || previewSqlResult.loading;\n\n  return (\n    <Modal\n      title=\"Fix SQL\"\n      width={640}\n      visible={visible}\n      okText=\"Submit\"\n      onOk={submit}\n      onCancel={onClose}\n      confirmLoading={loading}\n      maskClosable={false}\n      destroyOnClose\n      centered\n      afterClose={reset}\n    >\n      <Typography.Text className=\"d-block gray-7 mb-3\">\n        The following SQL statement needs to be fixed:\n      </Typography.Text>\n      <Form form={form} preserve={false} layout=\"vertical\">\n        <Form.Item\n          label=\"SQL statement\"\n          name=\"sql\"\n          required\n          rules={[\n            {\n              required: true,\n              message: ERROR_TEXTS.FIX_SQL.SQL.REQUIRED,\n            },\n          ]}\n        >\n          <SQLEditor autoComplete autoFocus />\n        </Form.Item>\n      </Form>\n      <div className=\"my-3\">\n        <Typography.Text className=\"d-block gray-7 mb-2\">\n          Data preview (50 rows)\n        </Typography.Text>\n        <Button\n          onClick={previewData}\n          loading={previewLoading}\n          disabled={previewLoading}\n        >\n          Preview data\n        </Button>\n        {showPreview && (\n          <div className=\"my-3\">\n            <PreviewData\n              loading={previewLoading}\n              previewData={previewSqlResult?.data?.previewSql}\n              copyable={false}\n            />\n          </div>\n        )}\n      </div>\n      {!!error && (\n        <Alert\n          showIcon\n          type=\"error\"\n          message={error.shortMessage}\n          description={<ErrorCollapse message={error.message} />}\n        />\n      )}\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/modals/ImportDataSourceSQLModal.tsx",
    "content": "import { useMemo } from 'react';\nimport { Modal, Form, Alert } from 'antd';\nimport { ModalAction } from '@/hooks/useModalAction';\nimport { getDataSourceImage, getDataSourceName } from '@/utils/dataSourceType';\nimport { DATA_SOURCES } from '@/utils/enum';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { parseGraphQLError } from '@/utils/errorHandler';\nimport SQLEditor from '@/components/editor/SQLEditor';\nimport ErrorCollapse from '@/components/ErrorCollapse';\nimport { useModelSubstituteMutation } from '@/apollo/client/graphql/sql.generated';\nimport { DataSource, DataSourceName } from '@/apollo/client/graphql/__types__';\n\ntype Props = ModalAction<{ dataSource: DATA_SOURCES }>;\n\nconst Toolbar = (props) => {\n  const { dataSource } = props;\n  if (!dataSource) return null;\n  const logo = getDataSourceImage(dataSource);\n  const name = getDataSourceName(dataSource);\n  return (\n    <>\n      <span className=\"d-flex align-center gx-2\">\n        <img src={logo} alt=\"logo\" width=\"20\" height=\"20\" />\n        {name}\n      </span>\n    </>\n  );\n};\n\nexport const isSupportSubstitute = (dataSource: DataSource) => {\n  // DuckDB not supported, sample dataset as well\n  return (\n    !dataSource?.sampleDataset && dataSource?.type !== DataSourceName.DUCKDB\n  );\n};\n\nexport default function ImportDataSourceSQLModal(props: Props) {\n  const { visible, defaultValue, onSubmit, onClose } = props;\n  const name = getDataSourceName(defaultValue?.dataSource) || 'data source';\n\n  // Handle errors via try/catch blocks rather than onError callback\n  const [substituteDialectSQL, modelSubstitudeResult] =\n    useModelSubstituteMutation();\n\n  const error = useMemo(\n    () =>\n      modelSubstitudeResult.error\n        ? {\n            ...parseGraphQLError(modelSubstitudeResult.error),\n            shortMessage: `Invalid ${name} SQL syntax`,\n          }\n        : null,\n    [modelSubstitudeResult.error],\n  );\n\n  const [form] = Form.useForm();\n\n  const reset = () => {\n    form.resetFields();\n    modelSubstitudeResult.reset();\n  };\n\n  const submit = async () => {\n    form\n      .validateFields()\n      .then(async (values) => {\n        const response = await substituteDialectSQL({\n          variables: { data: { sql: values.dialectSql } },\n        });\n        await onSubmit(response.data?.modelSubstitute);\n        onClose();\n      })\n      .catch(console.error);\n  };\n\n  const loading = modelSubstitudeResult.loading;\n\n  return (\n    <Modal\n      title={`Import from ${name} SQL`}\n      centered\n      closable\n      confirmLoading={loading}\n      destroyOnClose\n      maskClosable={false}\n      onCancel={onClose}\n      onOk={submit}\n      okText=\"Convert\"\n      visible={visible}\n      width={600}\n      cancelButtonProps={{ disabled: loading }}\n      afterClose={() => reset()}\n    >\n      <Form form={form} layout=\"vertical\">\n        <Form.Item\n          name=\"dialectSql\"\n          label=\"SQL statement\"\n          rules={[\n            {\n              required: true,\n              message: ERROR_TEXTS.IMPORT_DATA_SOURCE_SQL.SQL.REQUIRED,\n            },\n          ]}\n        >\n          <SQLEditor\n            toolbar={<Toolbar dataSource={defaultValue?.dataSource} />}\n            autoFocus\n          />\n        </Form.Item>\n      </Form>\n      {!!error && (\n        <Alert\n          showIcon\n          type=\"error\"\n          message={error.shortMessage}\n          description={<ErrorCollapse message={error.message} />}\n        />\n      )}\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/modals/InstructionModal.tsx",
    "content": "import { useEffect } from 'react';\nimport { Button, Form, Input, Modal, Row, Col, Radio } from 'antd';\nimport DeleteOutlined from '@ant-design/icons/DeleteOutlined';\nimport PlusOutlined from '@ant-design/icons/PlusOutlined';\nimport { isEmpty } from 'lodash';\nimport { FORM_MODE } from '@/utils/enum';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { ModalAction } from '@/hooks/useModalAction';\nimport { Instruction } from '@/apollo/client/graphql/__types__';\n\nconst MAX_QUESTIONS = 100;\n\ntype Props = ModalAction<Instruction> & {\n  loading?: boolean;\n};\n\nexport default function InstructionModal(props: Props) {\n  const { defaultValue, formMode, loading, onClose, onSubmit, visible } = props;\n\n  const isCreateMode = formMode === FORM_MODE.CREATE;\n\n  const [form] = Form.useForm();\n  const isDefault = Form.useWatch('isDefault', form);\n\n  useEffect(() => {\n    if (visible) {\n      form.setFieldsValue({\n        isDefault: isEmpty(defaultValue) ? true : defaultValue.isDefault,\n        instruction: defaultValue?.instruction,\n        questions: defaultValue?.questions,\n      });\n    }\n  }, [visible, defaultValue]);\n\n  const onSubmitButton = () => {\n    form\n      .validateFields()\n      .then(async (values) => {\n        const data = {\n          isDefault: values.isDefault,\n          instruction: values.instruction,\n          questions: values?.questions || [],\n        };\n        await onSubmit({ data, id: defaultValue?.id });\n        onClose();\n      })\n      .catch(console.error);\n  };\n\n  return (\n    <Modal\n      title={`${isCreateMode ? 'Add' : 'Update'} an instruction`}\n      centered\n      closable\n      confirmLoading={loading}\n      destroyOnClose\n      maskClosable={false}\n      onCancel={onClose}\n      visible={visible}\n      width={720}\n      cancelButtonProps={{ disabled: loading }}\n      okText=\"Submit\"\n      onOk={onSubmitButton}\n      afterClose={() => form.resetFields()}\n    >\n      <Form form={form} preserve={false} layout=\"vertical\">\n        <Form.Item\n          label=\"Instruction details\"\n          name=\"instruction\"\n          rules={[\n            {\n              required: true,\n              message: ERROR_TEXTS.INSTRUCTION.DETAILS.REQUIRED,\n            },\n          ]}\n        >\n          <Input.TextArea\n            autoFocus\n            placeholder=\"Enter a rule that Wren AI should follow when generating SQL queries.\"\n            maxLength={1000}\n            rows={3}\n            showCount\n          />\n        </Form.Item>\n        <Form.Item\n          label=\"Apply instruction to\"\n          name=\"isDefault\"\n          required={false}\n          rules={[\n            {\n              required: true,\n              message: ERROR_TEXTS.INSTRUCTION.IS_DEFAULT_GLOBAL.REQUIRED,\n            },\n          ]}\n          extra={\n            <>\n              Choose whether this instruction applies to{' '}\n              <span className=\"gray-7\">all queries</span> or{' '}\n              <span className=\"gray-7\">\n                only when similar user questions are detected\n              </span>\n              .\n            </>\n          }\n        >\n          <Radio.Group>\n            <Radio.Button value={true}>\n              Global (applies to all questions)\n            </Radio.Button>\n            <Radio.Button value={false}>\n              Matched to specific questions\n            </Radio.Button>\n          </Radio.Group>\n        </Form.Item>\n        {!isDefault && (\n          <Form.Item\n            label=\"Matching questions\"\n            required\n            extra=\"Wren AI will match user queries based on similarity and apply this instruction when relevant.\"\n          >\n            <Form.List name=\"questions\" initialValue={['']}>\n              {(fields, { add, remove }) => (\n                <>\n                  {fields.map(({ key, name, ...restField }) => (\n                    <Row key={key} wrap={false} gutter={8} className=\"my-2\">\n                      <Col flex=\"1 0\">\n                        <Form.Item\n                          {...restField}\n                          name={name}\n                          required\n                          className=\"mb-2\"\n                          style={{ width: '100%' }}\n                          rules={[\n                            {\n                              required: true,\n                              whitespace: true,\n                              message:\n                                ERROR_TEXTS.INSTRUCTION.QUESTIONS.REQUIRED,\n                            },\n                          ]}\n                        >\n                          <Input\n                            placeholder=\"Enter an example question that should trigger this instruction.\"\n                            maxLength={100}\n                            showCount\n                          />\n                        </Form.Item>\n                      </Col>\n                      <Col flex=\"none\" className=\"p-1\">\n                        <Button\n                          onClick={() => remove(name)}\n                          disabled={fields.length <= 1}\n                          icon={<DeleteOutlined />}\n                          size=\"small\"\n                          style={{ border: 'none' }}\n                          className=\"bg-gray-1\"\n                        />\n                      </Col>\n                    </Row>\n                  ))}\n                  <Form.Item noStyle>\n                    <Button\n                      type=\"dashed\"\n                      onClick={() => add()}\n                      block\n                      icon={<PlusOutlined />}\n                      disabled={fields.length >= MAX_QUESTIONS}\n                      className=\"mb-1\"\n                    >\n                      Add a question\n                    </Button>\n                  </Form.Item>\n                </>\n              )}\n            </Form.List>\n          </Form.Item>\n        )}\n      </Form>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/modals/QuestionSQLPairModal.tsx",
    "content": "import { useEffect, useMemo, useState } from 'react';\nimport styled from 'styled-components';\nimport { Alert, Button, Form, Input, Modal, Typography } from 'antd';\nimport { Logo } from '@/components/Logo';\nimport InfoCircleOutlined from '@ant-design/icons/InfoCircleOutlined';\nimport SelectOutlined from '@ant-design/icons/SelectOutlined';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { FORM_MODE } from '@/utils/enum';\nimport { getDataSourceName } from '@/utils/dataSourceType';\nimport useModalAction, { ModalAction } from '@/hooks/useModalAction';\nimport SQLEditor from '@/components/editor/SQLEditor';\nimport { parseGraphQLError } from '@/utils/errorHandler';\nimport { createSQLPairQuestionValidator } from '@/utils/validator';\nimport ErrorCollapse from '@/components/ErrorCollapse';\nimport PreviewData from '@/components/dataPreview/PreviewData';\nimport ImportDataSourceSQLModal, {\n  isSupportSubstitute,\n} from '@/components/modals/ImportDataSourceSQLModal';\nimport { usePreviewSqlMutation } from '@/apollo/client/graphql/sql.generated';\nimport { useGetSettingsQuery } from '@/apollo/client/graphql/settings.generated';\nimport { useGenerateQuestionMutation } from '@/apollo/client/graphql/sql.generated';\nimport { SqlPair } from '@/apollo/client/graphql/__types__';\n\ntype Props = ModalAction<SqlPair> & {\n  loading?: boolean;\n  payload?: {\n    isCreateMode: boolean;\n  };\n};\n\nconst StyledForm = styled(Form)`\n  .adm-question-form-item > div > label {\n    width: 100%;\n  }\n`;\n\nconst Toolbar = (props: { dataSource: string; onClick: () => void }) => {\n  const { dataSource, onClick } = props;\n  const name = getDataSourceName(dataSource);\n  return (\n    <div className=\"d-flex justify-space-between align-center px-1\">\n      <span className=\"d-flex align-center gx-2\">\n        <Logo size={16} />\n        Wren SQL\n      </span>\n      <Button className=\"px-0\" type=\"link\" size=\"small\" onClick={onClick}>\n        <SelectOutlined />\n        Import from {name} SQL\n      </Button>\n    </div>\n  );\n};\n\nexport default function QuestionSQLPairModal(props: Props) {\n  const {\n    defaultValue,\n    formMode,\n    loading,\n    onClose,\n    onSubmit,\n    visible,\n    payload,\n  } = props;\n\n  // pass payload?.isCreateMode to prevent formMode from being set to Update when passing defaultValue, for the 'Add a SQL pair from an existing answer' scenario use.\n  const isCreateMode = formMode === FORM_MODE.CREATE || payload?.isCreateMode;\n  const importDataSourceSQLModal = useModalAction();\n\n  const { data: settingsResult } = useGetSettingsQuery();\n  const settings = settingsResult?.settings;\n  const dataSource = useMemo(\n    () => ({\n      isSupportSubstitute: isSupportSubstitute(settings?.dataSource),\n      type: settings?.dataSource?.type,\n    }),\n    [settings?.dataSource],\n  );\n\n  const [form] = Form.useForm();\n  const [error, setError] =\n    useState<ReturnType<typeof parseGraphQLError>>(null);\n  const [previewing, setPreviewing] = useState<boolean>(false);\n  const [submitting, setSubmitting] = useState<boolean>(false);\n  const [generatingQuestion, setGeneratingQuestion] = useState<boolean>(false);\n  const [showPreview, setShowPreview] = useState<boolean>(false);\n\n  // Handle errors via try/catch blocks rather than onError callback\n  const [previewSqlMutation, previewSqlResult] = usePreviewSqlMutation();\n\n  const [generateQuestionMutation] = useGenerateQuestionMutation({\n    onError: (error) => console.error(error),\n  });\n\n  const sqlValue = Form.useWatch('sql', form);\n\n  useEffect(() => {\n    if (visible) {\n      form.setFieldsValue({\n        question: defaultValue?.question,\n        sql: defaultValue?.sql,\n      });\n    }\n  }, [visible, defaultValue]);\n\n  const handleReset = () => {\n    previewSqlResult.reset();\n    setShowPreview(false);\n    setError(null);\n    form.resetFields();\n  };\n\n  const onValidateSQL = async () => {\n    await previewSqlMutation({\n      variables: {\n        data: {\n          sql: sqlValue,\n          limit: 1,\n          dryRun: true,\n        },\n      },\n    });\n  };\n\n  const handleError = (error) => {\n    const graphQLError = parseGraphQLError(error);\n    setError({ ...graphQLError, shortMessage: 'Invalid SQL syntax' });\n    console.error(graphQLError);\n  };\n\n  const onPreviewData = async () => {\n    setError(null);\n    setPreviewing(true);\n    try {\n      await onValidateSQL();\n      setShowPreview(true);\n      await previewSqlMutation({\n        variables: {\n          data: {\n            sql: sqlValue,\n            limit: 50,\n          },\n        },\n      });\n    } catch (error) {\n      handleError(error);\n    } finally {\n      setPreviewing(false);\n    }\n  };\n\n  const onSubmitButton = () => {\n    setError(null);\n    setSubmitting(true);\n    setShowPreview(false);\n    form\n      .validateFields()\n      .then(async (values) => {\n        try {\n          await onValidateSQL();\n          await onSubmit({ data: values, id: defaultValue?.id });\n          onClose();\n        } catch (error) {\n          handleError(error);\n        } finally {\n          setSubmitting(false);\n        }\n      })\n      .catch((err) => {\n        setSubmitting(false);\n        console.error(err);\n      });\n  };\n\n  const onGenerateQuestion = async () => {\n    setGeneratingQuestion(true);\n    const { data } = await generateQuestionMutation({\n      variables: {\n        data: {\n          sql: sqlValue,\n        },\n      },\n    });\n\n    form.setFieldsValue({ question: data?.generateQuestion || '' });\n    setGeneratingQuestion(false);\n  };\n\n  const confirmLoading = loading || submitting;\n  const disabled = !sqlValue;\n\n  return (\n    <>\n      <Modal\n        title={`${isCreateMode ? 'Add' : 'Update'} question-SQL pair`}\n        centered\n        closable\n        confirmLoading={confirmLoading}\n        destroyOnClose\n        maskClosable={false}\n        onCancel={onClose}\n        visible={visible}\n        width={640}\n        cancelButtonProps={{ disabled: confirmLoading }}\n        okButtonProps={{ disabled: previewSqlResult.loading }}\n        afterClose={() => handleReset()}\n        footer={\n          <div className=\"d-flex justify-space-between align-center\">\n            <div\n              className=\"text-sm ml-2 d-flex justify-space-between align-center\"\n              style={{ width: 300 }}\n            >\n              <InfoCircleOutlined className=\"mr-2 text-sm gray-7\" />\n              <Typography.Text\n                type=\"secondary\"\n                className=\"text-sm gray-7 text-left\"\n              >\n                The SQL statement used here follows <b>Wren SQL</b>, which is\n                based on ANSI SQL and optimized for Wren AI.{` `}\n                <Typography.Link\n                  type=\"secondary\"\n                  href=\"https://docs.getwren.ai/oss/guide/home/wren_sql\"\n                  target=\"_blank\"\n                  rel=\"noopener noreferrer\"\n                >\n                  Learn more about the syntax.\n                </Typography.Link>\n              </Typography.Text>\n            </div>\n            <div>\n              <Button onClick={onClose}>Cancel</Button>\n              <Button\n                type=\"primary\"\n                onClick={onSubmitButton}\n                loading={confirmLoading}\n              >\n                Submit\n              </Button>\n            </div>\n          </div>\n        }\n      >\n        <StyledForm form={form} preserve={false} layout=\"vertical\">\n          <Form.Item\n            className=\"adm-question-form-item\"\n            label={\n              <div\n                className=\"d-flex justify-space-between\"\n                style={{ width: '100%' }}\n              >\n                <span>Question</span>\n                <div className=\"gray-8 text-sm\">\n                  Let AI create a matching question for this SQL statement.\n                  <Button\n                    className=\"ml-2\"\n                    size=\"small\"\n                    loading={generatingQuestion}\n                    onClick={onGenerateQuestion}\n                    disabled={disabled}\n                  >\n                    <span className=\"text-sm\">Generate question</span>\n                  </Button>\n                </div>\n              </div>\n            }\n            name=\"question\"\n            required\n            rules={[\n              {\n                validator: createSQLPairQuestionValidator(\n                  ERROR_TEXTS.SQL_PAIR.QUESTION,\n                ),\n              },\n            ]}\n          >\n            <Input />\n          </Form.Item>\n          <Form.Item\n            label=\"SQL statement\"\n            name=\"sql\"\n            required\n            rules={[\n              {\n                required: true,\n                message: ERROR_TEXTS.SQL_PAIR.SQL.REQUIRED,\n              },\n            ]}\n          >\n            <SQLEditor\n              toolbar={\n                dataSource.isSupportSubstitute && (\n                  <Toolbar\n                    dataSource={dataSource.type}\n                    onClick={() =>\n                      importDataSourceSQLModal.openModal({\n                        dataSource: dataSource.type,\n                      })\n                    }\n                  />\n                )\n              }\n              autoComplete\n              autoFocus\n            />\n          </Form.Item>\n        </StyledForm>\n        <div className=\"my-3\">\n          <Typography.Text className=\"d-block gray-7 mb-2\">\n            Data preview (50 rows)\n          </Typography.Text>\n          <Button\n            onClick={onPreviewData}\n            loading={previewing}\n            disabled={disabled}\n          >\n            Preview data\n          </Button>\n          {showPreview && (\n            <div className=\"my-3\">\n              <PreviewData\n                loading={previewing}\n                previewData={previewSqlResult?.data?.previewSql}\n                copyable={false}\n              />\n            </div>\n          )}\n        </div>\n        {!!error && (\n          <Alert\n            showIcon\n            type=\"error\"\n            message={error.shortMessage}\n            description={<ErrorCollapse message={error.message} />}\n          />\n        )}\n      </Modal>\n      {dataSource.isSupportSubstitute && (\n        <ImportDataSourceSQLModal\n          {...importDataSourceSQLModal.state}\n          onClose={importDataSourceSQLModal.closeModal}\n          onSubmit={async (convertedSql: string) => {\n            form.setFieldsValue({ sql: convertedSql });\n          }}\n        />\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/modals/RelationModal.tsx",
    "content": "import { useEffect } from 'react';\nimport { isEmpty } from 'lodash';\nimport { Modal, Form, Select } from 'antd';\nimport { ModalAction } from '@/hooks/useModalAction';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport CombineFieldSelector from '@/components/selectors/CombineFieldSelector';\nimport { JOIN_TYPE, FORM_MODE, convertIdentifierToObject } from '@/utils/enum';\nimport { getJoinTypeText } from '@/utils/data';\nimport {\n  createRelationshipFromFieldValidator,\n  createRelationshipToFieldValidator,\n} from '@/utils/validator';\nimport useCombineFieldOptions, {\n  convertDefaultValueToIdentifier,\n} from '@/hooks/useCombineFieldOptions';\nimport { RelationsDataType } from '@/components/table/ModelRelationSelectionTable';\nimport { SelectedRecommendRelations } from '@/components/pages/setup/DefineRelations';\n\nexport const FormFieldKey = {\n  FROM_FIELD: 'fromField',\n  TO_FIELD: 'toField',\n  TYPE: 'type',\n};\n\nexport interface RelationFormValues {\n  fromField: { model: string; field: string };\n  toField: { model: string; field: string };\n  type?: string;\n}\n\nexport type RelationFieldValue = Pick<\n  RelationsDataType,\n  'type' | 'fromField' | 'toField'\n>;\n\ntype Props = ModalAction<RelationFieldValue, RelationFormValues> & {\n  model: string;\n  loading?: boolean;\n  relations: SelectedRecommendRelations;\n  isRecommendMode?: boolean;\n};\n\nexport default function RelationModal(props: Props) {\n  const {\n    defaultValue,\n    loading,\n    model,\n    onClose,\n    onSubmit,\n    relations,\n    visible,\n    formMode,\n    isRecommendMode,\n  } = props;\n  const [form] = Form.useForm();\n\n  // only suitable use for modeling page\n  const isUpdateMode = formMode === FORM_MODE.EDIT;\n\n  const fromCombineField = useCombineFieldOptions({ model });\n  const modelValue = fromCombineField.modelOptions.find((option) => {\n    const value: any = convertIdentifierToObject(option.value);\n    return value.referenceName === model;\n  })?.value;\n\n  const toFieldModel = defaultValue?.toField.modelName;\n  const toCombineField = useCombineFieldOptions({\n    model: toFieldModel,\n    excludeModels: [model],\n  });\n\n  useEffect(() => {\n    if (!visible || isEmpty(defaultValue)) return;\n\n    const transformedValue = convertDefaultValueToIdentifier(defaultValue);\n    form.setFieldsValue(transformedValue);\n\n    toCombineField.onModelChange(transformedValue.toField.model);\n  }, [form, defaultValue, visible]);\n\n  const relationTypeOptions = Object.keys(JOIN_TYPE).map((key) => ({\n    label: getJoinTypeText(key),\n    value: JOIN_TYPE[key],\n  }));\n\n  const submit = () => {\n    form\n      .validateFields()\n      .then(async (values) => {\n        await onSubmit({ ...defaultValue, ...values });\n        onClose();\n      })\n      .catch(console.error);\n  };\n\n  return (\n    <Modal\n      title={`${isEmpty(defaultValue) ? 'Add' : 'Update'} relationship`}\n      width={750}\n      visible={visible}\n      okText=\"Submit\"\n      onOk={submit}\n      onCancel={onClose}\n      confirmLoading={loading}\n      maskClosable={false}\n      destroyOnClose\n      afterClose={() => form.resetFields()}\n      centered\n    >\n      <Form form={form} preserve={false} layout=\"vertical\">\n        <Form.Item\n          label=\"From\"\n          name={FormFieldKey.FROM_FIELD}\n          required\n          rules={[\n            ({ getFieldValue }) => ({\n              validator: createRelationshipFromFieldValidator(\n                isUpdateMode || isRecommendMode,\n                relations,\n                getFieldValue,\n              ),\n            }),\n          ]}\n        >\n          <CombineFieldSelector\n            modelValue={modelValue}\n            modelDisabled={true}\n            fieldDisabled={isUpdateMode}\n            onModelChange={fromCombineField.onModelChange}\n            modelOptions={fromCombineField.modelOptions}\n            fieldOptions={fromCombineField.fieldOptions}\n          />\n        </Form.Item>\n        <Form.Item\n          label=\"To\"\n          name={FormFieldKey.TO_FIELD}\n          required\n          rules={[\n            ({ getFieldValue }) => ({\n              validator: createRelationshipToFieldValidator(\n                isUpdateMode || isRecommendMode,\n                relations,\n                getFieldValue,\n              ),\n            }),\n          ]}\n        >\n          <CombineFieldSelector\n            onModelChange={toCombineField.onModelChange}\n            modelOptions={toCombineField.modelOptions}\n            fieldOptions={toCombineField.fieldOptions}\n            modelDisabled={isUpdateMode}\n            fieldDisabled={isUpdateMode}\n          />\n        </Form.Item>\n        <Form.Item\n          label=\"Type\"\n          name={FormFieldKey.TYPE}\n          required\n          rules={[\n            {\n              required: true,\n              message: ERROR_TEXTS.ADD_RELATION.RELATION_TYPE.REQUIRED,\n            },\n          ]}\n        >\n          <Select\n            data-testid=\"relationship-form__type-select\"\n            options={relationTypeOptions}\n            placeholder=\"Select a relationship type\"\n          />\n        </Form.Item>\n      </Form>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/modals/SaveAsViewModal.tsx",
    "content": "import { Button, Form, Input, Modal, Typography } from 'antd';\nimport InfoCircleOutlined from '@ant-design/icons/InfoCircleOutlined';\nimport { ModalAction } from '@/hooks/useModalAction';\nimport { createViewNameValidator } from '@/utils/validator';\nimport SQLCodeBlock from '@/components/code/SQLCodeBlock';\nimport { useValidateViewMutation } from '@/apollo/client/graphql/view.generated';\n\nconst { Text } = Typography;\n\ntype Props = ModalAction<{ sql: string }> & {\n  loading?: boolean;\n  defaultValue: { sql: string; responseId: number };\n  payload: { rephrasedQuestion: string };\n};\n\nexport default function SaveAsViewModal(props: Props) {\n  const { visible, loading, onSubmit, onClose, defaultValue, payload } = props;\n  const [form] = Form.useForm();\n  const [validateViewMutation] = useValidateViewMutation({\n    fetchPolicy: 'no-cache',\n  });\n\n  const submit = () => {\n    form\n      .validateFields()\n      .then(async (values) => {\n        await onSubmit({\n          responseId: defaultValue.responseId,\n          ...payload,\n          ...values,\n        });\n        onClose();\n      })\n      .catch(console.error);\n  };\n\n  const sql = defaultValue ? defaultValue.sql : '';\n\n  return (\n    <Modal\n      title=\"Save as View\"\n      centered\n      closable\n      destroyOnClose\n      onCancel={onClose}\n      maskClosable={false}\n      visible={visible}\n      width={600}\n      afterClose={() => form.resetFields()}\n      footer={\n        <div className=\"d-flex justify-space-between align-center\">\n          <div\n            className=\"d-flex justify-space-between align-center ml-2\"\n            style={{ width: 300 }}\n          >\n            <InfoCircleOutlined className=\"mr-2 text-sm gray-6\" />\n            <Text type=\"secondary\" className=\"text-sm gray-6 text-left\">\n              After saving, make sure you go to \"Modeling Page\" to deploy all\n              saved views.\n            </Text>\n          </div>\n          <div>\n            <Button onClick={onClose}>Cancel</Button>\n            <Button type=\"primary\" onClick={submit} loading={loading}>\n              Save\n            </Button>\n          </div>\n        </div>\n      }\n    >\n      <Form form={form} preserve={false} layout=\"vertical\">\n        <Form.Item\n          label=\"Name\"\n          name=\"name\"\n          required\n          rules={[\n            {\n              required: true,\n              validator: createViewNameValidator(validateViewMutation),\n            },\n          ]}\n        >\n          <Input />\n        </Form.Item>\n        <Form.Item label=\"SQL Statement\">\n          <SQLCodeBlock code={sql} showLineNumbers maxHeight=\"300\" />\n        </Form.Item>\n      </Form>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/modals/SchemaChangeModal.tsx",
    "content": "import { useMemo } from 'react';\nimport {\n  Modal,\n  Button,\n  Table,\n  Typography,\n  Collapse,\n  Alert,\n  Tag,\n  Popconfirm,\n} from 'antd';\nimport styled from 'styled-components';\nimport WarningOutlined from '@ant-design/icons/WarningOutlined';\nimport PlusSquareOutlined from '@ant-design/icons/PlusSquareOutlined';\nimport LineOutlined from '@ant-design/icons/LineOutlined';\nimport FileDoneOutlined from '@ant-design/icons/FileDoneOutlined';\nimport { ModalAction } from '@/hooks/useModalAction';\nimport EllipsisWrapper from '@/components/EllipsisWrapper';\nimport {\n  DetailedChangeTable,\n  DetailedAffectedCalculatedFields,\n  DetailedAffectedRelationships,\n  NodeType,\n  SchemaChange,\n  SchemaChangeType,\n} from '@/apollo/client/graphql/__types__';\n\nconst StyledCollapse = styled(Collapse)`\n  border: none;\n  background-color: white;\n  .ant-collapse-item:last-child,\n  .ant-collapse-item:last-child > .ant-collapse-header {\n    border-radius: 0;\n  }\n  .ant-collapse-item,\n  .ant-collapse-content {\n    border-color: var(--gray-4);\n  }\n  .ant-collapse-content-box {\n    padding: 0;\n  }\n`;\n\nconst StyledTable = styled(Table)`\n  padding-left: 36px;\n  .ant-table {\n    border: none;\n    border-radius: 0;\n\n    .non-expandable {\n      .ant-table-row-expand-icon {\n        display: none;\n      }\n    }\n\n    .ant-table-expanded-row {\n      .ant-table-cell {\n        background-color: white;\n      }\n    }\n  }\n`;\n\ntype Props = ModalAction<SchemaChange> & {\n  loading?: boolean;\n  payload?: {\n    onResolveSchemaChange?: (type: SchemaChangeType) => void;\n    isResolving?: boolean;\n  };\n};\n\nconst nestedColumns = [\n  {\n    title: 'Affected Resource',\n    dataIndex: 'resourceType',\n    width: 200,\n    render: (resourceType: NodeType) => {\n      if (resourceType === NodeType.CALCULATED_FIELD) {\n        return <Tag className=\"ant-tag--geekblue\">Calculated Field</Tag>;\n      }\n\n      if (resourceType === NodeType.RELATION) {\n        return <Tag className=\"ant-tag--citrus\">Relationship</Tag>;\n      }\n\n      return null;\n    },\n  },\n  {\n    title: 'Name',\n    dataIndex: 'displayName',\n  },\n];\n\nconst checkIsExpandable = (record: DetailedChangeTable) =>\n  record.calculatedFields.length + record.relationships.length > 0\n    ? ''\n    : 'non-expandable';\n\nconst PanelHeader = (props) => {\n  const { title, count, onResolve, isResolving } = props;\n  const resolve = (event) => {\n    event.stopPropagation();\n    onResolve();\n  };\n  return (\n    <div\n      className=\"d-flex align-center flex-grow-1\"\n      style={{ userSelect: 'none' }}\n    >\n      <b className=\"text-medium\">{title}</b>\n      <span className=\"flex-grow-1 text-right d-flex justify-end\">\n        <Typography.Text className=\"gray-6\">\n          {count} table(s) affected\n        </Typography.Text>\n        <div style={{ width: 150 }}>\n          {!!onResolve && (\n            <Popconfirm\n              title=\"Are you sure?\"\n              okText=\"Confirm\"\n              okButtonProps={{ danger: true }}\n              onConfirm={resolve}\n              onCancel={(event) => event.stopPropagation()}\n            >\n              <Button\n                type=\"text\"\n                size=\"small\"\n                className=\"red-5\"\n                onClick={(event) => event.stopPropagation()}\n                loading={isResolving}\n                icon={<FileDoneOutlined />}\n              >\n                Resolve\n              </Button>\n            </Popconfirm>\n          )}\n        </div>\n      </span>\n    </div>\n  );\n};\n\ninterface ExpandedRowsProps {\n  record: DetailedChangeTable & {\n    resources: Array<\n      DetailedAffectedCalculatedFields | DetailedAffectedRelationships\n    >;\n  };\n  tipMessage: string;\n}\n\nconst ExpandedRows = ({ record, tipMessage }: ExpandedRowsProps) => {\n  if (record.resources.length === 0) return null;\n\n  return (\n    <div className=\"pl-12\">\n      <Alert\n        showIcon\n        icon={<WarningOutlined className=\"orange-5\" />}\n        className=\"gray-6 ml-2 bg-gray-1 pl-0\"\n        style={{ border: 'none' }}\n        message={tipMessage}\n      />\n      <Table\n        columns={nestedColumns}\n        dataSource={record.resources || []}\n        pagination={{\n          hideOnSinglePage: true,\n          size: 'small',\n          pageSize: 10,\n        }}\n        rowKey=\"rowKey\"\n        size=\"small\"\n        className=\"adm-nested-table\"\n      />\n    </div>\n  );\n};\n\nexport default function SchemaChangeModal(props: Props) {\n  const { visible, onClose, defaultValue: schemaChange, payload } = props;\n  const { onResolveSchemaChange, isResolving } = payload || {};\n\n  const { deletedTables, deletedColumns, modifiedColumns } = useMemo(() => {\n    const { deletedTables, deletedColumns, modifiedColumns } =\n      schemaChange || {};\n\n    if (!schemaChange)\n      return {\n        deletedTables,\n        deletedColumns,\n        modifiedColumns,\n      };\n\n    // transform data to render UI\n    const transformData = (tables: DetailedChangeTable) => ({\n      ...tables,\n      resources: [\n        ...tables.calculatedFields.map(\n          (\n            calculatedField: DetailedAffectedCalculatedFields,\n            index: number,\n          ) => ({\n            ...calculatedField,\n            resourceType: NodeType.CALCULATED_FIELD,\n            rowKey: `${tables.sourceTableName}-${calculatedField.referenceName}-${index}`,\n          }),\n        ),\n        ...tables.relationships.map(\n          (relationship: DetailedAffectedRelationships, index: number) => ({\n            ...relationship,\n            resourceType: NodeType.RELATION,\n            rowKey: `${tables.sourceTableName}-${relationship.referenceName}-${index}`,\n          }),\n        ),\n      ],\n      rowKey: tables.sourceTableName,\n    });\n\n    return {\n      deletedTables: deletedTables?.map(transformData),\n      deletedColumns: deletedColumns?.map(transformData),\n      modifiedColumns: modifiedColumns?.map(transformData),\n    };\n  }, [schemaChange]);\n\n  const columnsOfDeleteTables = [\n    { title: 'Affected model', width: 200, dataIndex: 'displayName' },\n    { title: 'Source table name', dataIndex: 'sourceTableName' },\n  ];\n\n  const columnsOfDeletedColumns = [\n    { title: 'Affected model', width: 200, dataIndex: 'displayName' },\n    {\n      title: 'Deleted columns',\n      dataIndex: 'columns',\n      render: (columns) => {\n        return (\n          <EllipsisWrapper showMoreCount>\n            {columns.map((column) => (\n              <Tag className=\"ant-tag--geekblue\" key={column.sourceColumnName}>\n                {column.displayName}\n              </Tag>\n            ))}\n          </EllipsisWrapper>\n        );\n      },\n    },\n  ];\n\n  const columnsOfModifiedColumns = [\n    { title: 'Affected model', width: 200, dataIndex: 'displayName' },\n    {\n      title: 'Affected columns',\n      dataIndex: 'columns',\n      render: (columns) => {\n        return (\n          <EllipsisWrapper showMoreCount>\n            {columns.map((column) => (\n              <Tag className=\"ant-tag--geekblue\" key={column.sourceColumnName}>\n                {column.displayName}\n              </Tag>\n            ))}\n          </EllipsisWrapper>\n        );\n      },\n    },\n  ];\n\n  return (\n    <Modal\n      title={\n        <>\n          <WarningOutlined className=\"orange-5 mr-2\" />\n          Schema Changes\n        </>\n      }\n      width={750}\n      visible={visible}\n      onCancel={onClose}\n      destroyOnClose\n      footer={null}\n    >\n      <Typography.Paragraph className=\"gray-6 mb-4\">\n        We have detected schema changes from your connected data source. Please\n        review the impacts of these changes.\n      </Typography.Paragraph>\n      <Alert\n        showIcon\n        type=\"warning\"\n        className=\"gray-8 mb-6\"\n        message={`Please note that clicking \\\"Resolve\\\" may automatically delete all affected models, relationships, and calculated fields.`}\n      />\n      <StyledCollapse\n        expandIcon={(panelProps) =>\n          panelProps.isActive ? <LineOutlined /> : <PlusSquareOutlined />\n        }\n      >\n        {deletedTables && (\n          <Collapse.Panel\n            header={\n              <PanelHeader\n                title=\"Source table deleted\"\n                count={deletedTables.length}\n                onResolve={() =>\n                  onResolveSchemaChange(SchemaChangeType.DELETED_TABLES)\n                }\n                isResolving={isResolving}\n              ></PanelHeader>\n            }\n            key=\"deleteTables\"\n          >\n            <StyledTable\n              rowKey=\"rowKey\"\n              columns={columnsOfDeleteTables}\n              dataSource={deletedTables}\n              size=\"small\"\n              pagination={{\n                hideOnSinglePage: true,\n                size: 'small',\n                pageSize: 10,\n              }}\n              rowClassName={checkIsExpandable}\n              expandable={{\n                expandedRowRender: (record: ExpandedRowsProps['record']) => (\n                  <ExpandedRows\n                    record={record}\n                    tipMessage=\"The following table shows resources affected by this model and will be deleted when resolving.\"\n                  />\n                ),\n              }}\n            />\n          </Collapse.Panel>\n        )}\n        {deletedColumns && (\n          <Collapse.Panel\n            header={\n              <PanelHeader\n                title=\"Source column deleted\"\n                count={deletedColumns.length}\n                onResolve={() =>\n                  onResolveSchemaChange(SchemaChangeType.DELETED_COLUMNS)\n                }\n                isResolving={isResolving}\n              ></PanelHeader>\n            }\n            key=\"deleteColumns\"\n          >\n            <StyledTable\n              rowKey=\"rowKey\"\n              columns={columnsOfDeletedColumns}\n              dataSource={deletedColumns}\n              size=\"small\"\n              pagination={{\n                hideOnSinglePage: true,\n                size: 'small',\n                pageSize: 10,\n              }}\n              rowClassName={checkIsExpandable}\n              expandable={{\n                expandedRowRender: (record: ExpandedRowsProps['record']) => (\n                  <ExpandedRows\n                    record={record}\n                    tipMessage=\"The following table shows resources affected by this column of the model and will be deleted when resolving.\"\n                  />\n                ),\n              }}\n            />\n          </Collapse.Panel>\n        )}\n        {modifiedColumns && (\n          <Collapse.Panel\n            header={\n              <PanelHeader\n                title=\"Source column type changed\"\n                count={modifiedColumns.length}\n              ></PanelHeader>\n            }\n            key=\"modifiedColumns\"\n          >\n            <StyledTable\n              rowKey=\"rowKey\"\n              columns={columnsOfModifiedColumns}\n              dataSource={modifiedColumns}\n              size=\"small\"\n              pagination={{\n                hideOnSinglePage: true,\n                size: 'small',\n                pageSize: 10,\n              }}\n              rowClassName={checkIsExpandable}\n              expandable={{\n                expandedRowRender: (record: ExpandedRowsProps['record']) => (\n                  <ExpandedRows\n                    record={record}\n                    tipMessage=\"The following table shows the resources utilized by this column of the model. Please review each resource and manually update the relevant ones if any changes are required.\"\n                  />\n                ),\n              }}\n            />\n          </Collapse.Panel>\n        )}\n      </StyledCollapse>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/apiManagement/DetailsDrawer.tsx",
    "content": "import { Drawer, Typography, Row, Col, Tag } from 'antd';\nimport { getAbsoluteTime } from '@/utils/time';\nimport { DrawerAction } from '@/hooks/useDrawerAction';\nimport CheckCircleOutlined from '@ant-design/icons/CheckCircleOutlined';\nimport CloseCircleOutlined from '@ant-design/icons/CloseCircleOutlined';\nimport JsonCodeBlock from '@/components/code/JsonCodeBlock';\nimport { ApiHistoryResponse } from '@/apollo/client/graphql/__types__';\n\ntype Props = DrawerAction<ApiHistoryResponse> & {\n  loading?: boolean;\n};\n\nexport default function DetailsDrawer(props: Props) {\n  const { visible, onClose, defaultValue } = props;\n\n  const {\n    threadId,\n    apiType,\n    createdAt,\n    durationMs,\n    statusCode,\n    headers,\n    requestPayload,\n    responsePayload,\n  } = defaultValue || {};\n\n  const getStatusTag = (status: number) => {\n    const isSuccess = status >= 200 && status < 300;\n    return (\n      <Tag\n        icon={isSuccess ? <CheckCircleOutlined /> : <CloseCircleOutlined />}\n        color={isSuccess ? 'success' : 'error'}\n      >\n        {status}\n      </Tag>\n    );\n  };\n\n  return (\n    <Drawer\n      visible={visible}\n      className=\"gray-8\"\n      title=\"API details\"\n      width={760}\n      closable\n      destroyOnClose\n      onClose={onClose}\n      footer={null}\n    >\n      <Row className=\"mb-6\">\n        <Col span={12}>\n          <Typography.Text className=\"d-block gray-7 mb-2\">\n            API type\n          </Typography.Text>\n          <div>\n            <Tag className=\"gray-8\">{apiType?.toLowerCase()}</Tag>\n          </div>\n        </Col>\n        <Col span={12}>\n          <Typography.Text className=\"d-block gray-7 mb-2\">\n            Thread ID\n          </Typography.Text>\n          <div>{threadId || '-'}</div>\n        </Col>\n      </Row>\n      <Row className=\"mb-6\">\n        <Col span={12}>\n          <Typography.Text className=\"d-block gray-7 mb-2\">\n            Created at\n          </Typography.Text>\n          <div>{getAbsoluteTime(createdAt)}</div>\n        </Col>\n        <Col span={12}>\n          <Typography.Text className=\"d-block gray-7 mb-2\">\n            Duration\n          </Typography.Text>\n          <div>{durationMs} ms</div>\n        </Col>\n      </Row>\n      <Row className=\"mb-6\">\n        <Col span={12}>\n          <Typography.Text className=\"d-block gray-7 mb-2\">\n            Status code\n          </Typography.Text>\n          <div>{getStatusTag(statusCode)}</div>\n        </Col>\n      </Row>\n\n      <div className=\"mb-6\">\n        <Typography.Text className=\"d-block gray-7 mb-2\">\n          Headers\n        </Typography.Text>\n        <JsonCodeBlock\n          code={headers}\n          backgroundColor=\"var(--gray-2)\"\n          maxHeight=\"400\"\n          copyable\n        />\n      </div>\n\n      <div className=\"mb-6\">\n        <Typography.Text className=\"d-block gray-7 mb-2\">\n          Request payload\n        </Typography.Text>\n        <JsonCodeBlock\n          code={requestPayload}\n          backgroundColor=\"var(--gray-2)\"\n          maxHeight=\"400\"\n          copyable\n        />\n      </div>\n\n      <div className=\"mb-6\">\n        <Typography.Text className=\"d-block gray-7 mb-2\">\n          Response payload\n        </Typography.Text>\n        <JsonCodeBlock\n          code={responsePayload}\n          backgroundColor=\"var(--gray-2)\"\n          maxHeight=\"400\"\n          copyable\n        />\n      </div>\n    </Drawer>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/RecommendedQuestions.tsx",
    "content": "import clsx from 'clsx';\nimport styled from 'styled-components';\nimport { useMemo } from 'react';\nimport { Skeleton } from 'antd';\nimport BulbOutlined from '@ant-design/icons/BulbOutlined';\nimport { makeIterable } from '@/utils/iteration';\nimport {\n  RecommendedQuestionsTask,\n  RecommendedQuestionsTaskStatus,\n} from '@/apollo/client/graphql/__types__';\n\nexport interface SelectQuestionProps {\n  question: string;\n  sql: string;\n}\n\ninterface Props {\n  items: { question: string; sql: string }[];\n  loading?: boolean;\n  error?: {\n    shortMessage?: string;\n    code?: string;\n    message?: string;\n    stacktrace?: string[];\n  };\n  className?: string;\n  onSelect: ({ question, sql }: SelectQuestionProps) => void;\n}\n\nconst StyledSkeleton = styled(Skeleton)`\n  padding: 4px 0;\n  .ant-skeleton-paragraph {\n    margin-bottom: 0;\n    li {\n      height: 14px;\n      + li {\n        margin-top: 12px;\n      }\n    }\n  }\n`;\n\nexport const getRecommendedQuestionProps = (\n  data: RecommendedQuestionsTask,\n  show = true,\n) => {\n  if (!data || !show) return { show: false };\n  const questions = (data?.questions || []).slice(0, 3).map((item) => ({\n    question: item.question,\n    sql: item.sql,\n  }));\n  const loading = data?.status === RecommendedQuestionsTaskStatus.GENERATING;\n  return {\n    show: loading || questions.length > 0,\n    state: {\n      items: questions,\n      loading,\n      error: data?.error,\n    },\n  };\n};\n\nconst QuestionItem = (props: {\n  index: number;\n  question: string;\n  sql: string;\n  onSelect: ({ question, sql }: SelectQuestionProps) => void;\n}) => {\n  const { index, question, sql, onSelect } = props;\n  return (\n    <div className={clsx(index > 0 && 'mt-1')}>\n      <span\n        className=\"cursor-pointer hover:text\"\n        onClick={() => onSelect({ question, sql })}\n      >\n        {question}\n      </span>\n    </div>\n  );\n};\nconst QuestionList = makeIterable(QuestionItem);\n\nexport default function RecommendedQuestions(props: Props) {\n  const { items, loading, className, onSelect } = props;\n\n  const data = useMemo(\n    () => items.map(({ question, sql }) => ({ question, sql })),\n    [items],\n  );\n\n  return (\n    <div className={clsx('bg-gray-2 rounded p-3', className)}>\n      <div className=\"mb-2\">\n        <BulbOutlined className=\"mr-1 gray-6\" />\n        <b className=\"text-semi-bold text-sm gray-7\">Recommended questions</b>\n      </div>\n      <div className=\"pl-1 gray-8\">\n        <StyledSkeleton\n          active\n          loading={loading}\n          paragraph={{ rows: 3 }}\n          title={false}\n        >\n          <QuestionList data={data} onSelect={onSelect} />\n        </StyledSkeleton>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/dashboardGrid/CacheSettingsDrawer.tsx",
    "content": "import { useEffect } from 'react';\nimport { capitalize } from 'lodash';\nimport { CronExpressionParser } from 'cron-parser';\nimport moment from 'moment';\nimport {\n  Button,\n  Drawer,\n  Form,\n  Space,\n  Switch,\n  Select,\n  Input,\n  Row,\n  Col,\n  Divider,\n  TimePicker,\n} from 'antd';\nimport { browserTimeZone } from '@/utils/time';\nimport { DrawerAction } from '@/hooks/useDrawerAction';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { isValidCronLength, cronValidator } from '@/utils/validator';\nimport { CacheScheduleDayEnum } from '@/apollo/client/graphql/__types__';\n\ntype Props = DrawerAction & {\n  loading?: boolean;\n};\n\nexport interface Schedule {\n  frequency: string;\n  day?: string;\n  hour?: number;\n  minute?: number;\n  cron?: string;\n  timezone?: string;\n}\n\nconst timeFormat = 'HH:mm';\n\nconst FREQUENCY = {\n  DAILY: 'DAILY',\n  WEEKLY: 'WEEKLY',\n  CUSTOM: 'CUSTOM',\n  NEVER: 'NEVER',\n};\n\n// This sequence follows the first day of the week\nconst DAY_OF_WEEK = [\n  CacheScheduleDayEnum.SUN,\n  CacheScheduleDayEnum.MON,\n  CacheScheduleDayEnum.TUE,\n  CacheScheduleDayEnum.WED,\n  CacheScheduleDayEnum.THU,\n  CacheScheduleDayEnum.FRI,\n  CacheScheduleDayEnum.SAT,\n];\n\nconst getDayOfWeekText = (day: CacheScheduleDayEnum) => {\n  return (\n    {\n      [CacheScheduleDayEnum.MON]: 'Monday',\n      [CacheScheduleDayEnum.TUE]: 'Tuesday',\n      [CacheScheduleDayEnum.WED]: 'Wednesday',\n      [CacheScheduleDayEnum.THU]: 'Thursday',\n      [CacheScheduleDayEnum.FRI]: 'Friday',\n      [CacheScheduleDayEnum.SAT]: 'Saturday',\n      [CacheScheduleDayEnum.SUN]: 'Sunday',\n    }[day] || ''\n  );\n};\n\nconst getFrequencyText = (frequency: string) => {\n  if (frequency === FREQUENCY.NEVER) return 'Manual refresh only';\n  return capitalize(frequency);\n};\n\nconst getInitialSchedule = (frequency: string) => {\n  let schedule = {};\n  switch (frequency) {\n    case FREQUENCY.DAILY:\n      schedule = {\n        day: null,\n        time: moment('00:00', timeFormat),\n        cron: null,\n      };\n      break;\n    case FREQUENCY.WEEKLY:\n      schedule = {\n        day: DAY_OF_WEEK[0],\n        time: moment('00:00', timeFormat),\n        cron: null,\n      };\n      break;\n    case FREQUENCY.CUSTOM:\n      schedule = {\n        day: null,\n        time: null,\n        cron: '0 0 * * *',\n      };\n      break;\n    case FREQUENCY.NEVER:\n      schedule = {\n        day: null,\n        time: null,\n        cron: null,\n      };\n      break;\n    default:\n      break;\n  }\n  return schedule;\n};\n\nexport const getScheduleText = (schedule: Schedule): string => {\n  if (!schedule) return '';\n  const { frequency } = schedule;\n\n  const convertTime = (schedule: Schedule) => {\n    const time = moment(\n      `${schedule.hour}:${schedule.minute}`,\n      timeFormat,\n    ).format(timeFormat);\n    return time;\n  };\n\n  switch (frequency) {\n    case FREQUENCY.DAILY: {\n      const time = convertTime(schedule);\n      return `Cache refreshes daily at ${time}`;\n    }\n    case FREQUENCY.WEEKLY: {\n      const time = convertTime(schedule);\n      return `Cache refreshes every ${getDayOfWeekText(schedule.day as CacheScheduleDayEnum)} at ${time}`;\n    }\n    case FREQUENCY.CUSTOM: {\n      return `Cache refreshes on custom schedule`;\n    }\n    case FREQUENCY.NEVER: {\n      return 'Cache refresh: manual only';\n    }\n    default: {\n      return '';\n    }\n  }\n};\n\nconst getNextSchedule = (data: {\n  frequency: string;\n  day: string;\n  time: moment.Moment;\n  cron: string;\n}) => {\n  const { frequency, day, time, cron } = data;\n  if (frequency === FREQUENCY.CUSTOM) return getNextScheduleByCron(cron);\n  if (frequency === FREQUENCY.NEVER || !time) return null;\n\n  // frequency daily or weekly calculation\n  const now = moment();\n  const targetTime = moment(\n    `${now.format('YYYY-MM-DD')} ${time.format(timeFormat)}`,\n  );\n\n  // set the day of the week if it's a weekly schedule\n  if (day) {\n    const dayIndex = DAY_OF_WEEK.findIndex((d) => d === day);\n    targetTime.set({ day: dayIndex });\n  }\n\n  // postpond the time if it's already passed\n  if (now.isAfter(targetTime)) {\n    if (frequency === FREQUENCY.DAILY) {\n      targetTime.add(1, 'd');\n    } else if (frequency === FREQUENCY.WEEKLY) {\n      targetTime.add(7, 'd');\n    }\n  }\n\n  return targetTime.isValid() ? targetTime.format('YYYY-MM-DD HH:mm') : null;\n};\n\nconst getNextScheduleByCron = (cron: string) => {\n  if (!cron || !isValidCronLength(cron)) return null;\n  try {\n    const interval = CronExpressionParser.parse(cron, { tz: 'UTC' });\n    const targetTime = moment.utc(interval.next().toDate()).local();\n    return targetTime.isValid() ? targetTime.format('YYYY-MM-DD HH:mm') : null;\n  } catch (error) {\n    console.warn(error);\n    return null;\n  }\n};\n\nexport default function CacheSettingsDrawer(props: Props) {\n  const { visible, defaultValue, loading, onClose, onSubmit } = props;\n  const [form] = Form.useForm();\n\n  const cacheEnabled = Form.useWatch('cacheEnabled', form);\n\n  useEffect(() => {\n    if (visible) {\n      const { schedule, ...restValues } = defaultValue || {};\n      form.setFieldsValue({\n        ...restValues,\n        schedule: {\n          day: schedule?.day,\n          frequency: schedule?.frequency,\n          time:\n            schedule?.hour.toString() && schedule?.minute.toString()\n              ? moment(`${schedule?.hour}:${schedule?.minute}`, timeFormat)\n              : null,\n          cron: schedule?.cron,\n        },\n      });\n    }\n  }, [visible, defaultValue]);\n\n  const afterVisibleChange = (visible: boolean) => {\n    if (!visible) {\n      form.resetFields();\n    }\n  };\n\n  const submit = () => {\n    form\n      .validateFields()\n      .then(async (values) => {\n        const { schedule } = values;\n        await onSubmit({\n          ...values,\n          schedule: values.cacheEnabled\n            ? {\n                frequency: schedule?.frequency,\n                day: schedule?.day,\n                hour: schedule?.time?.hour(),\n                minute: schedule?.time?.minute(),\n                cron: schedule?.cron,\n                timezone: browserTimeZone,\n              }\n            : null,\n        });\n        onClose();\n      })\n      .catch(console.error);\n  };\n\n  return (\n    <Drawer\n      visible={visible}\n      title=\"Cache settings\"\n      width={410}\n      closable\n      destroyOnClose\n      maskClosable={false}\n      afterVisibleChange={afterVisibleChange}\n      onClose={onClose}\n      footer={\n        <Space className=\"d-flex justify-end\">\n          <Button onClick={onClose} disabled={loading}>\n            Cancel\n          </Button>\n          <Button\n            type=\"primary\"\n            onClick={submit}\n            loading={loading}\n            disabled={loading}\n          >\n            Submit\n          </Button>\n        </Space>\n      }\n    >\n      <Form form={form} layout=\"vertical\">\n        <Form.Item\n          label=\"Enable caching\"\n          name=\"cacheEnabled\"\n          valuePropName=\"checked\"\n          extra=\"Enable caching to speed up dashboard loading by reusing recent results. Choose a refresh schedule that fits your needs below.\"\n        >\n          <Switch />\n        </Form.Item>\n        {cacheEnabled && <Schedule />}\n      </Form>\n    </Drawer>\n  );\n}\n\nfunction Schedule() {\n  const form = Form.useFormInstance();\n  const frequency = Form.useWatch(['schedule', 'frequency'], form);\n  const day = Form.useWatch(['schedule', 'day'], form);\n  const time = Form.useWatch(['schedule', 'time'], form);\n  const cron = Form.useWatch(['schedule', 'cron'], form);\n\n  const onFrequencyChange = (value: string) => {\n    form.setFieldsValue({\n      schedule: { frequency: value, ...getInitialSchedule(value) },\n    });\n  };\n\n  const nextSchedule = getNextSchedule({ frequency, day, time, cron });\n\n  return (\n    <>\n      <Divider className=\"gray-6 text-sm\">Refresh settings</Divider>\n      <Form.Item label=\"Frequency\" name={['schedule', 'frequency']}>\n        <Select\n          placeholder=\"Select frequency\"\n          options={Object.keys(FREQUENCY).map((key) => ({\n            label: getFrequencyText(key),\n            value: FREQUENCY[key],\n          }))}\n          onChange={onFrequencyChange}\n        />\n      </Form.Item>\n\n      {frequency === FREQUENCY.DAILY && <DailyTimeSelection />}\n      {frequency === FREQUENCY.WEEKLY && <WeeklyTimeSelection />}\n      {frequency === FREQUENCY.CUSTOM && (\n        <Form.Item\n          label=\"Cron expression\"\n          name={['schedule', 'cron']}\n          required={false}\n          rules={[{ validator: cronValidator }]}\n          extra=\"Cron expression will be executed in UTC timezone (e.g. '0 0 * * *' for daily at midnight UTC)\"\n        >\n          <Input style={{ maxWidth: 200 }} placeholder=\"* * * * *\" />\n        </Form.Item>\n      )}\n\n      {nextSchedule && (\n        <div className=\"gray-7\">\n          Next scheduled refresh:\n          <div className=\"gray-8\">\n            {nextSchedule} {browserTimeZone && <span>({browserTimeZone})</span>}\n          </div>\n        </div>\n      )}\n    </>\n  );\n}\n\nfunction DailyTimeSelection() {\n  return (\n    <>\n      <Form.Item\n        label=\"Time\"\n        name={['schedule', 'time']}\n        required={false}\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CACHE_SETTINGS.TIME.REQUIRED,\n          },\n        ]}\n      >\n        <TimePicker minuteStep={10} format={timeFormat} />\n      </Form.Item>\n    </>\n  );\n}\n\nfunction WeeklyTimeSelection() {\n  return (\n    <>\n      <Row gutter={16}>\n        <Col>\n          <Form.Item\n            label=\"Day\"\n            name={['schedule', 'day']}\n            required={false}\n            rules={[\n              {\n                required: true,\n                message: ERROR_TEXTS.CACHE_SETTINGS.DAY.REQUIRED,\n              },\n            ]}\n          >\n            <Select\n              style={{ minWidth: 123 }}\n              options={DAY_OF_WEEK.map((value) => ({\n                label: getDayOfWeekText(value),\n                value,\n              }))}\n              placeholder=\"Select day\"\n            />\n          </Form.Item>\n        </Col>\n        <Col>\n          <Form.Item\n            label=\"Time\"\n            name={['schedule', 'time']}\n            required={false}\n            rules={[\n              {\n                required: true,\n                message: ERROR_TEXTS.CACHE_SETTINGS.TIME.REQUIRED,\n              },\n            ]}\n          >\n            <TimePicker minuteStep={10} format={timeFormat} />\n          </Form.Item>\n        </Col>\n      </Row>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/dashboardGrid/DashboardHeader.tsx",
    "content": "import { Button, Tooltip } from 'antd';\nimport styled from 'styled-components';\nimport { MoreIcon } from '@/utils/icons';\nimport { MORE_ACTION } from '@/utils/enum';\nimport { getCompactTime } from '@/utils/time';\nimport { DashboardDropdown } from '@/components/diagram/CustomDropdown';\nimport {\n  Schedule,\n  getScheduleText,\n} from '@/components/pages/home/dashboardGrid/CacheSettingsDrawer';\n\ninterface Props {\n  isSupportCached: boolean;\n  nextScheduleTime?: string;\n  schedule?: Schedule;\n  onCacheSettings?: () => void;\n  onRefreshAll?: () => void;\n}\n\nconst StyledHeader = styled.div`\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  min-height: 49px;\n  padding: 8px 16px;\n  background-color: white;\n  border-bottom: 1px solid var(--gray-4);\n`;\n\nexport default function DashboardHeader(props: Props) {\n  const {\n    isSupportCached,\n    nextScheduleTime,\n    schedule,\n    onCacheSettings,\n    onRefreshAll,\n  } = props;\n\n  const scheduleTime = getScheduleText(schedule);\n\n  const onMoreClick = async (action: MORE_ACTION) => {\n    if (action === MORE_ACTION.CACHE_SETTINGS) {\n      onCacheSettings?.();\n    } else if (action === MORE_ACTION.REFRESH) {\n      onRefreshAll?.();\n    }\n  };\n\n  return (\n    <StyledHeader>\n      <div />\n      <div>\n        {schedule && (\n          <div className=\"d-flex align-center gray-6 gx-2\">\n            {isSupportCached && (\n              <>\n                {nextScheduleTime ? (\n                  <Tooltip\n                    placement=\"bottom\"\n                    title={\n                      <>\n                        <div>\n                          <span className=\"gray-6\">Next schedule:</span>{' '}\n                          {getCompactTime(nextScheduleTime)}\n                        </div>\n                        {schedule.cron && (\n                          <div>\n                            <span className=\"gray-6\">Cron expression:</span>{' '}\n                            {schedule.cron}\n                          </div>\n                        )}\n                      </>\n                    }\n                  >\n                    <span className=\"cursor-pointer\">{scheduleTime}</span>\n                  </Tooltip>\n                ) : (\n                  scheduleTime\n                )}\n              </>\n            )}\n            <DashboardDropdown\n              onMoreClick={onMoreClick}\n              isSupportCached={isSupportCached}\n            >\n              <Button type=\"text\" icon={<MoreIcon className=\"gray-8\" />} />\n            </DashboardDropdown>\n          </div>\n        )}\n      </div>\n    </StyledHeader>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/dashboardGrid/EmptyDashboard.tsx",
    "content": "import Link from 'next/link';\nimport Image from 'next/image';\nimport { Row, Col } from 'antd';\nimport { Logo } from '@/components/Logo';\nimport { makeIterable } from '@/utils/iteration';\n\nconst StepTemplate = (props: { title: string; image: string }) => {\n  return (\n    <Col>\n      <div\n        className=\"p-3 rounded bg-gray-1 border border-gray-5\"\n        style={{ boxShadow: '2px 2px 2px 0px #00000006' }}\n      >\n        <div className=\"mb-2\">\n          <span\n            className=\"d-inline-block bg-geekblue-1 geekblue-6 rounded-pill text-sm px-2\"\n            style={{ lineHeight: '22px' }}\n          >\n            {props.title}\n          </span>\n        </div>\n        <Image\n          className=\"rounded border border-gray-4\"\n          src={props.image}\n          width={160}\n          height={80}\n          alt={props.title}\n        />\n      </div>\n    </Col>\n  );\n};\n\nconst StepIterator = makeIterable(StepTemplate);\n\nconst EmptyDashboard = (props: {\n  show: boolean;\n  children: React.ReactNode;\n}) => {\n  const { show, children } = props;\n  if (show) {\n    return (\n      <div\n        className=\"d-flex align-center justify-center flex-column -mt-8\"\n        style={{ height: '100%' }}\n      >\n        <Logo size={48} color=\"var(--gray-8)\" />\n        <div className=\"text-lg text-medium text-center gray-8 mt-3\">\n          No charts have been added yet\n        </div>\n        <div className=\"gray-7\">\n          Follow these steps to pin charts to your dashboard.{' '}\n          <Link\n            className=\"gray-8 underline\"\n            href=\"https://docs.getwren.ai/oss/guide/home/dashboard\"\n            rel=\"noopener noreferrer\"\n            target=\"_blank\"\n          >\n            Learn more\n          </Link>\n        </div>\n        <Row className=\"mt-4\" gutter={[16, 16]}>\n          <StepIterator\n            data={[\n              {\n                title: '1. Create a thread',\n                image: '/images/dashboard/s1.jpg',\n              },\n              {\n                title: '2. Generate a chart',\n                image: '/images/dashboard/s2.jpg',\n              },\n              {\n                title: '3. Pin to dashboard',\n                image: '/images/dashboard/s3.jpg',\n              },\n            ]}\n          />\n        </Row>\n      </div>\n    );\n  }\n  return <>{children}</>;\n};\n\nexport default EmptyDashboard;\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/dashboardGrid/index.tsx",
    "content": "import dynamic from 'next/dynamic';\nimport React, {\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n  createRef,\n  forwardRef,\n  useImperativeHandle,\n} from 'react';\nimport { Button, Form } from 'antd';\nimport styled from 'styled-components';\nimport GridLayout, { Layout } from 'react-grid-layout';\nimport { MoreIcon } from '@/utils/icons';\nimport { MORE_ACTION } from '@/utils/enum';\nimport { getCompactTime, nextTick } from '@/utils/time';\nimport { LoadingWrapper } from '@/components/PageLoading';\nimport { DashboardItemDropdown } from '@/components/diagram/CustomDropdown';\nimport EditableWrapper, { EditableContext } from '@/components/EditableWrapper';\nimport {\n  DashboardItem,\n  ItemLayoutInput,\n} from '@/apollo/client/graphql/__types__';\nimport {\n  usePreviewItemSqlMutation,\n  useUpdateDashboardItemMutation,\n} from '@/apollo/client/graphql/dashboard.generated';\n\nimport 'react-grid-layout/css/styles.css';\nimport 'react-resizable/css/styles.css';\n\nconst Chart = dynamic(() => import('@/components/chart'), {\n  ssr: false,\n});\n\nconst StyledDashboardGrid = styled.div`\n  flex: 1;\n  padding: 16px;\n\n  .react-grid-layout {\n    width: 100%;\n    height: 100%;\n  }\n\n  .adm-pinned-item {\n    cursor: grab;\n    background-color: white;\n    height: 100%;\n    border-radius: 4px;\n    border: 2px solid transparent;\n    box-shadow: rgba(45, 62, 80, 0.12) 0px 1px 5px 0px;\n    transition: border-color 0.2s ease;\n\n    &:hover {\n      border-color: var(--geekblue-6);\n    }\n  }\n\n  .adm-pinned-item-header {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    padding: 16px 8px 0 16px;\n    * {\n      min-width: 0;\n    }\n  }\n\n  .adm-pinned-item-title {\n    font-size: 14px;\n    font-weight: 700;\n    flex-grow: 1;\n  }\n\n  .adm-pinned-actions {\n    display: flex;\n    gap: 4px;\n    align-items: center;\n    flex-shrink: 0;\n  }\n\n  .adm-pinned-content {\n    height: calc(100% - 40px);\n    padding: 16px 12px 16px;\n\n    &-overflow {\n      overflow: auto;\n      height: calc(100% - 18px);\n      padding: 8px 12px;\n    }\n\n    &-info {\n      font-size: 12px;\n      color: var(--gray-6);\n      text-align: right;\n      user-select: none;\n    }\n  }\n\n  .adm-pinned-item-chart {\n    height: 100%;\n  }\n\n  .react-grid-placeholder {\n    background-color: var(--blue-6);\n  }\n`;\n\nconst GUTTER = 8;\nconst COLUMN_COUNT = 6;\n\nconst calculateLayoutWidth = (itemWidth: number) => {\n  return itemWidth * COLUMN_COUNT + GUTTER * COLUMN_COUNT;\n};\n\nconst calculateColumnSize = (containerWidth: number) => {\n  return (containerWidth - GUTTER * COLUMN_COUNT) / COLUMN_COUNT;\n};\n\nconst getLayoutToGrid = (item: DashboardItem) => {\n  return {\n    i: item.id.toString(),\n    x: item.layout.x,\n    y: item.layout.y,\n    w: item.layout.w,\n    h: item.layout.h,\n  };\n};\n\nconst getLayoutToUpdateItem = (layout: Layout) => {\n  return {\n    itemId: Number(layout.i),\n    x: layout.x,\n    y: layout.y,\n    w: layout.w,\n    h: layout.h,\n  };\n};\n\ninterface Props {\n  items: DashboardItem[];\n  isSupportCached: boolean;\n  onUpdateChange: (layouts: ItemLayoutInput[]) => void;\n  onDelete: (id: number) => Promise<void>;\n}\n\nconst DashboardGrid = forwardRef(\n  (props: Props, ref: React.RefObject<{ onRefreshAll: () => void }>) => {\n    const { items, isSupportCached, onUpdateChange, onDelete } = props;\n    const itemRefs = useRef<{\n      [key: string]: React.RefObject<{ onRefresh: () => void }>;\n    }>({});\n    const $container = useRef<HTMLDivElement>(null);\n    const [size, setSize] = useState(250);\n\n    // set up initial item refs\n    useEffect(() => {\n      items.forEach((item) => {\n        itemRefs.current[item.id] = createRef();\n      });\n    }, [items]);\n\n    useImperativeHandle(\n      ref,\n      () => ({\n        onRefreshAll: () => {\n          Object.values(itemRefs.current).forEach((itemRef) => {\n            itemRef.current?.onRefresh();\n          });\n        },\n      }),\n      [items],\n    );\n\n    const layouts = useMemo(() => {\n      return items.map((item) => getLayoutToGrid(item));\n    }, [items]);\n\n    const getGridItemLayouts = () =>\n      items.map((item) => {\n        return (\n          <div key={item.id}>\n            <PinnedItem\n              ref={itemRefs.current[item.id]}\n              isSupportCached={isSupportCached}\n              item={item}\n              onDelete={onDelete}\n            />\n          </div>\n        );\n      });\n\n    useEffect(() => {\n      const renderColumnSize = () => {\n        if (!$container.current) return;\n        const sidebarWidth = 280;\n        const padding = 16 * 2;\n        const containerWidth = window.innerWidth - sidebarWidth - padding;\n\n        const minContainerWidth = 1024;\n        let calculatedWidth = containerWidth;\n        if (containerWidth <= minContainerWidth) {\n          calculatedWidth = minContainerWidth;\n          $container.current.style.minWidth = `${minContainerWidth + padding}px`;\n        } else {\n          $container.current.style.minWidth = '100%';\n        }\n\n        const columnSize = calculateColumnSize(calculatedWidth);\n        setSize(columnSize);\n      };\n      renderColumnSize();\n      window.addEventListener('resize', renderColumnSize);\n      return () => {\n        window.removeEventListener('resize', renderColumnSize);\n      };\n    }, [$container]);\n\n    const onLayoutChange = (layouts: Layout[]) => {\n      onUpdateChange(layouts.map((layout) => getLayoutToUpdateItem(layout)));\n    };\n\n    return (\n      <StyledDashboardGrid ref={$container}>\n        <GridLayout\n          layout={layouts}\n          cols={COLUMN_COUNT}\n          margin={[GUTTER, GUTTER]}\n          containerPadding={[0, 0]}\n          rowHeight={size}\n          width={calculateLayoutWidth(size)}\n          onLayoutChange={onLayoutChange}\n        >\n          {getGridItemLayouts()}\n        </GridLayout>\n      </StyledDashboardGrid>\n    );\n  },\n);\n\nexport default DashboardGrid;\n\nconst PinnedItemTitle = (props: { id: number; title: string }) => {\n  const { title } = props;\n  const [form] = Form.useForm();\n\n  const [updateDashboardItem] = useUpdateDashboardItemMutation({\n    onError: (error) => console.error(error),\n  });\n\n  const handleSave = (dashboardItemId: number, values: { title: string }) => {\n    if (values.title === title) return;\n    updateDashboardItem({\n      variables: {\n        where: { id: dashboardItemId },\n        data: {\n          displayName: values.title.trim(),\n        },\n      },\n    });\n  };\n\n  return (\n    <EditableContext.Provider value={form}>\n      <Form className=\"d-flex\" form={form}>\n        <EditableWrapper\n          record={props}\n          dataIndex=\"title\"\n          handleSave={handleSave}\n        >\n          {title}\n        </EditableWrapper>\n      </Form>\n    </EditableContext.Provider>\n  );\n};\n\nconst PinnedItem = forwardRef(\n  (\n    props: {\n      item: DashboardItem;\n      isSupportCached: boolean;\n      onDelete: (id: number) => Promise<void>;\n    },\n    ref: React.RefObject<{ onRefresh: () => void }>,\n  ) => {\n    const { item, isSupportCached, onDelete } = props;\n    const { detail } = item;\n    const [isHideLegend, setIsHideLegend] = useState(true);\n    const [forceLoading, setForceLoading] = useState(false);\n    const [forceUpdate, setForceUpdate] = useState(0);\n\n    useImperativeHandle(\n      ref,\n      () => ({\n        onRefresh: () => {\n          previewItemSQL({\n            variables: { data: { itemId: item.id, refresh: isSupportCached } },\n          });\n        },\n      }),\n      [item.id],\n    );\n\n    const [previewItemSQL, previewItemSQLResult] = usePreviewItemSqlMutation({\n      onError: (error) => console.error(error),\n    });\n    const previewItem = previewItemSQLResult.data?.previewItemSQL;\n    const lastRefreshTime =\n      previewItem?.cacheOverrodeAt || previewItem?.cacheCreatedAt;\n\n    useEffect(() => {\n      previewItemSQL({ variables: { data: { itemId: item.id } } });\n    }, [item.id]);\n\n    useEffect(() => {\n      setForceLoading(true);\n      nextTick(200).then(() => {\n        setForceUpdate((prev) => prev + 1);\n        setForceLoading(false);\n      });\n    }, [item.layout]);\n\n    const title = useMemo(() => {\n      return item.displayName || item.detail.chartSchema?.title || '';\n    }, [item.displayName, item.detail.chartSchema?.title]);\n\n    const onHideLegend = () => {\n      setIsHideLegend(!isHideLegend);\n      setForceUpdate((prev) => prev + 1);\n    };\n\n    const onMoreClick = async (action: MORE_ACTION) => {\n      if (action === MORE_ACTION.DELETE) {\n        await onDelete(item.id);\n      } else if (action === MORE_ACTION.REFRESH) {\n        previewItemSQL({\n          variables: { data: { itemId: item.id, refresh: isSupportCached } },\n        });\n      } else if (action === MORE_ACTION.HIDE_CATEGORY) {\n        onHideLegend();\n      }\n    };\n\n    const loading = forceLoading || previewItemSQLResult.loading;\n\n    return (\n      <div className=\"adm-pinned-item\">\n        <div className=\"adm-pinned-item-header\">\n          <div\n            className=\"adm-pinned-item-title\"\n            title={title}\n            onMouseDown={(e) => e.stopPropagation()}\n          >\n            <PinnedItemTitle id={item.id} title={title} />\n          </div>\n\n          <div className=\"adm-pinned-actions\">\n            <DashboardItemDropdown\n              onMoreClick={onMoreClick}\n              isHideLegend={isHideLegend}\n              isSupportCached={isSupportCached}\n            >\n              <Button\n                className=\"adm-pinned-more gray-8\"\n                type=\"text\"\n                size=\"small\"\n                icon={<MoreIcon />}\n                onMouseDown={(e) => e.stopPropagation()}\n              />\n            </DashboardItemDropdown>\n          </div>\n        </div>\n        <div className=\"adm-pinned-content\">\n          <div className=\"adm-pinned-content-overflow adm-scrollbar-track\">\n            <LoadingWrapper loading={loading} tip=\"Loading...\">\n              <Chart\n                className=\"adm-pinned-item-chart\"\n                width=\"100%\"\n                height=\"100%\"\n                spec={detail.chartSchema}\n                values={previewItem?.data}\n                forceUpdate={forceUpdate}\n                autoFilter\n                hideActions\n                hideTitle\n                hideLegend={isHideLegend}\n                isPinned\n              />\n            </LoadingWrapper>\n          </div>\n          {lastRefreshTime && (\n            <div className=\"adm-pinned-content-info\">\n              Last refreshed: {getCompactTime(lastRefreshTime)}\n            </div>\n          )}\n        </div>\n      </div>\n    );\n  },\n);\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/preparation/ErrorBoundary.tsx",
    "content": "import { Button, Typography, Timeline } from 'antd';\nimport CloseCircleFilled from '@ant-design/icons/CloseCircleFilled';\nimport ToolOutlined from '@ant-design/icons/ToolOutlined';\nimport useModalAction from '@/hooks/useModalAction';\nimport ErrorCollapse from '@/components/ErrorCollapse';\nimport { FixSQLModal } from '@/components/modals/FixSQLModal';\nimport { Error } from '@/apollo/client/graphql/__types__';\n\nexport interface Props {\n  children: React.ReactNode;\n  error?: Error & {\n    invalidSql?: string;\n    fixStatement?: (sql: string) => Promise<void>;\n    fixStatementLoading?: boolean;\n  };\n}\n\nexport default function ErrorBoundary({ children, error }: Props) {\n  const fixItModal = useModalAction();\n  if (!error) return <>{children}</>;\n  const hasInvalidSql = !!error.invalidSql;\n  return (\n    <Timeline className=\"px-1 -mb-4\">\n      <Timeline.Item dot={<CloseCircleFilled className=\"red-5\" />}>\n        <Typography.Text className=\"gray-8\">\n          {hasInvalidSql\n            ? 'Failed to generate SQL statement'\n            : error.shortMessage}\n        </Typography.Text>\n        <div className=\"gray-7 text-sm mt-1\">\n          <div>\n            {hasInvalidSql\n              ? 'We tried to generate SQL based on your question but encountered a small issue. Help us fix it!'\n              : error.message}\n          </div>\n          {hasInvalidSql && (\n            <>\n              <div className=\"bg-gray-2 p-2 my-4\">\n                <ErrorCollapse message={error.message} defaultActive />\n              </div>\n              <Button\n                className=\"mt-2 adm-fix-it-btn\"\n                icon={<ToolOutlined />}\n                size=\"small\"\n                onClick={() => fixItModal.openModal({ sql: error.invalidSql })}\n              >\n                Fix it\n              </Button>\n              <FixSQLModal\n                {...fixItModal.state}\n                loading={error.fixStatementLoading}\n                onClose={fixItModal.closeModal}\n                onSubmit={async (sql: string) => {\n                  await error.fixStatement(sql);\n                }}\n              />\n            </>\n          )}\n        </div>\n      </Timeline.Item>\n    </Timeline>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/preparation/PreparationStatus.tsx",
    "content": "import { useState } from 'react';\nimport { Button, Tag, Space } from 'antd';\nimport StopOutlined from '@ant-design/icons/StopOutlined';\nimport ReloadOutlined from '@ant-design/icons/ReloadOutlined';\nimport { attachLoading } from '@/utils/helper';\nimport { getIsFinished } from '@/hooks/useAskPrompt';\nimport { AskingTaskStatus } from '@/apollo/client/graphql/__types__';\nimport type { PreparedTask, Props } from './index';\n\nexport default function PreparationStatus(\n  props: Props & { preparedTask: PreparedTask },\n) {\n  const {\n    data,\n    preparedTask,\n    onStopAskingTask,\n    onReRunAskingTask,\n    onStopAdjustTask,\n    onReRunAdjustTask,\n  } = props;\n  const [stopLoading, setStopLoading] = useState(false);\n  const [reRunLoading, setReRunLoading] = useState(false);\n  const isProcessing = !getIsFinished(preparedTask.status);\n\n  const onCancel = (e) => {\n    e.stopPropagation();\n    const stopPreparedTask = preparedTask.isAdjustment\n      ? onStopAdjustTask\n      : onStopAskingTask;\n    const stopAskingTask = attachLoading(stopPreparedTask, setStopLoading);\n    stopAskingTask(preparedTask.queryId);\n  };\n\n  const onReRun = (e) => {\n    e.stopPropagation();\n    const reRunPreparedTask = preparedTask.isAdjustment\n      ? onReRunAdjustTask\n      : onReRunAskingTask;\n    const reRunAskingTask = attachLoading(reRunPreparedTask, setReRunLoading);\n    reRunAskingTask(data);\n  };\n\n  if (isProcessing) {\n    return (\n      <Button\n        icon={<StopOutlined />}\n        danger\n        size=\"small\"\n        onClick={onCancel}\n        loading={stopLoading}\n      >\n        Cancel\n      </Button>\n    );\n  } else if (preparedTask.status === AskingTaskStatus.STOPPED) {\n    return (\n      <Space className=\"-mr-4\">\n        <Tag color=\"red\">Cancelled by user</Tag>\n        <Button\n          icon={<ReloadOutlined />}\n          className=\"gray-7\"\n          size=\"small\"\n          type=\"text\"\n          onClick={onReRun}\n          loading={reRunLoading}\n        >\n          Re-run\n        </Button>\n      </Space>\n    );\n  } else if (preparedTask.status === AskingTaskStatus.FINISHED) {\n    const showView = data.view !== null;\n    const showSqlPair = !!preparedTask?.candidates[0]?.sqlPair;\n    return (\n      <div className=\"gray-6\">\n        {showView || showSqlPair ? '1 step' : '3 steps'}\n      </div>\n    );\n  }\n\n  return null;\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/preparation/PreparationSteps.tsx",
    "content": "import { useMemo } from 'react';\nimport styled from 'styled-components';\nimport { Timeline, Badge } from 'antd';\nimport FileDoneOutlined from '@ant-design/icons/FileDoneOutlined';\nimport Retrieving from './step/Retrieving';\nimport Organizing from './step/Organizing';\nimport Generating from './step/Generating';\nimport FixedSQLFinished from './step/FixedSQLFinished';\nimport ViewFinished from './step/ViewFinished';\nimport SQLPairFinished from './step/SQLPairFinished';\nimport { PROCESS_STATE } from '@/utils/enum';\nimport {\n  ProcessStateMachine,\n  convertAskingTaskToProcessState,\n} from '@/hooks/useAskProcessState';\nimport type { Props, PreparedTask } from './index';\n\nconst StyledBadge = styled(Badge)`\n  position: absolute;\n  top: -5px;\n  left: -3px;\n  .ant-badge-status-dot {\n    width: 7px;\n    height: 7px;\n  }\n  .ant-badge-status-text {\n    display: none;\n  }\n`;\n\nconst retrievingNextStates = ProcessStateMachine.getAllNextStates(\n  PROCESS_STATE.SEARCHING,\n  true,\n);\nconst organizingNextStates = ProcessStateMachine.getAllNextStates(\n  PROCESS_STATE.PLANNING,\n  true,\n);\nconst generatingNextStates = ProcessStateMachine.getAllNextStates(\n  PROCESS_STATE.GENERATING,\n  true,\n);\n\nconst getProcessDot = (processing: boolean) => {\n  return processing ? (\n    <StyledBadge color=\"geekblue\" status=\"processing\" />\n  ) : null;\n};\n\nexport default function PreparationSteps(\n  props: Props & { preparedTask: PreparedTask },\n) {\n  const { className, data, askingStreamTask, minimized, preparedTask } = props;\n  const { view, sql } = data;\n\n  const processState = useMemo(\n    () => convertAskingTaskToProcessState(preparedTask),\n    [preparedTask],\n  );\n  const isFixedSQL = useMemo(() => {\n    return sql && preparedTask?.invalidSql;\n  }, [sql, preparedTask?.invalidSql]);\n\n  // displays\n  const showView = !!view;\n  const showSqlPair = !!preparedTask?.candidates[0]?.sqlPair;\n  const showRetrieving = retrievingNextStates.includes(processState);\n  const showOrganizing = organizingNextStates.includes(processState);\n  const showGenerating = generatingNextStates.includes(processState);\n\n  // data\n  const retrievedTables = preparedTask?.retrievedTables || [];\n  const sqlGenerationReasoning =\n    preparedTask?.sqlGenerationReasoning || askingStreamTask || '';\n\n  // loadings\n  const retrieving = processState === PROCESS_STATE.SEARCHING;\n  const organizing = processState === PROCESS_STATE.PLANNING;\n  const generating = processState === PROCESS_STATE.GENERATING;\n  const correcting = processState === PROCESS_STATE.CORRECTING;\n  const wrapping = !minimized;\n\n  // templates\n  if (showView) return <ViewTimelineSteps {...props} />;\n  if (showSqlPair) return <SQLPairTimelineSteps {...props} />;\n  if (isFixedSQL) return <FixedSQLTimelineSteps {...props} />;\n\n  // default\n  return (\n    <Timeline className={className}>\n      {showRetrieving && (\n        <Timeline.Item dot={getProcessDot(retrieving)}>\n          <Retrieving\n            loading={retrieving}\n            tables={retrievedTables}\n            isAdjustment={preparedTask.isAdjustment}\n          />\n        </Timeline.Item>\n      )}\n      {showOrganizing && (\n        <Timeline.Item dot={getProcessDot(organizing)}>\n          <Organizing\n            loading={organizing}\n            stream={sqlGenerationReasoning}\n            isAdjustment={preparedTask.isAdjustment}\n          />\n        </Timeline.Item>\n      )}\n      {showGenerating && (\n        <Timeline.Item dot={getProcessDot(generating || correcting)}>\n          <Generating\n            generating={generating}\n            correcting={correcting}\n            loading={wrapping}\n          />\n        </Timeline.Item>\n      )}\n    </Timeline>\n  );\n}\n\nconst fileDone = (\n  <FileDoneOutlined\n    className=\"gray-6\"\n    style={{ position: 'relative', top: -2, left: 2 }}\n  />\n);\n\nfunction FixedSQLTimelineSteps(props: Props) {\n  const { className } = props;\n\n  return (\n    <Timeline className={className}>\n      <Timeline.Item dot={fileDone}>\n        <FixedSQLFinished />\n      </Timeline.Item>\n    </Timeline>\n  );\n}\n\nfunction ViewTimelineSteps(props: Props) {\n  const { className } = props;\n\n  return (\n    <Timeline className={className}>\n      <Timeline.Item dot={fileDone}>\n        <ViewFinished />\n      </Timeline.Item>\n    </Timeline>\n  );\n}\n\nfunction SQLPairTimelineSteps(props: Props) {\n  const { className } = props;\n\n  return (\n    <Timeline className={className}>\n      <Timeline.Item dot={fileDone}>\n        <SQLPairFinished />\n      </Timeline.Item>\n    </Timeline>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/preparation/index.tsx",
    "content": "import clsx from 'clsx';\nimport Image from 'next/image';\nimport { useEffect, useMemo, useState } from 'react';\nimport { Typography, Collapse } from 'antd';\nimport DownOutlined from '@ant-design/icons/DownOutlined';\nimport ErrorBoundary from './ErrorBoundary';\nimport PreparationStatus from './PreparationStatus';\nimport PreparationSteps from './PreparationSteps';\nimport { IPromptThreadStore } from '@/components/pages/home/promptThread/store';\nimport {\n  ThreadResponse,\n  AskingTaskStatus,\n  AskingTask,\n  AdjustmentTask,\n} from '@/apollo/client/graphql/__types__';\n\nexport type Props = IPromptThreadStore['preparation'] & {\n  className?: string;\n  data: ThreadResponse;\n  minimized?: boolean;\n};\n\nexport type PreparedTask = AskingTask &\n  AdjustmentTask & { isAdjustment: boolean };\n\nexport default function Preparation(props: Props) {\n  const { className, data, minimized, onFixSQLStatement, fixStatementLoading } =\n    props;\n  const { askingTask, adjustmentTask, adjustment, id: responseId, sql } = data;\n\n  const [isActive, setIsActive] = useState(!sql);\n\n  // Adapt askingTask and adjustmentTask for preparation steps\n  const preparedTask = useMemo(() => {\n    if (askingTask === null && adjustmentTask === null) return null;\n    const { payload } = adjustment || {};\n    return {\n      candidates: [],\n      invalidSql: '',\n      retrievedTables: payload?.retrievedTables || [],\n      sqlGenerationReasoning: payload?.sqlGenerationReasoning || '',\n      isAdjustment: !!adjustmentTask,\n      ...(askingTask || {}),\n      ...(adjustmentTask || {}),\n    } as PreparedTask;\n  }, [askingTask?.status, adjustmentTask?.status, adjustment?.payload]);\n\n  // wrapping up after answer is prepared\n  useEffect(() => {\n    setIsActive(!minimized);\n  }, [minimized]);\n  const error = useMemo(() => {\n    return preparedTask?.error && !sql\n      ? {\n          ...preparedTask.error,\n          invalidSql: preparedTask?.invalidSql,\n          fixStatement: (sql: string) => onFixSQLStatement(responseId, sql),\n          fixStatementLoading,\n        }\n      : null;\n  }, [preparedTask, responseId, sql, fixStatementLoading]);\n\n  if (preparedTask === null) return null;\n\n  const isStopped = preparedTask.status === AskingTaskStatus.STOPPED;\n\n  return (\n    <div className={clsx('border border-gray-4 rounded', className)}>\n      <Collapse\n        className=\"bg-gray-1\"\n        bordered={false}\n        expandIconPosition=\"right\"\n        expandIcon={({ isActive }) =>\n          !isStopped && (\n            <DownOutlined\n              className=\"gray-6 text-sm\"\n              rotate={isActive ? 180 : 0}\n            />\n          )\n        }\n        activeKey={isActive && !isStopped ? 'preparation' : undefined}\n        onChange={([key]) => setIsActive(key === 'preparation')}\n      >\n        <Collapse.Panel\n          key=\"preparation\"\n          header={\n            <div className=\"flex-grow-1 d-flex align-center justify-space-between gx-2 select-none\">\n              <Typography.Title level={5} className=\"gray-8 text-medium mb-0\">\n                <Image\n                  src=\"/images/icon/message-ai.svg\"\n                  alt=\"Answer Preparation Steps\"\n                  width={24}\n                  height={24}\n                  className=\"mr-1\"\n                />\n                Answer preparation steps\n              </Typography.Title>\n              <PreparationStatus {...props} preparedTask={preparedTask} />\n            </div>\n          }\n        >\n          <ErrorBoundary error={error}>\n            <PreparationSteps\n              {...props}\n              preparedTask={preparedTask}\n              className=\"px-1 -mb-4\"\n            />\n          </ErrorBoundary>\n        </Collapse.Panel>\n      </Collapse>\n    </div>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/preparation/step/FixedSQLFinished.tsx",
    "content": "import { Typography } from 'antd';\n\nexport default function FixedSQLFinished() {\n  return (\n    <>\n      <Typography.Text className=\"gray-8\">\n        User-Provided SQL applied\n      </Typography.Text>\n      <div className=\"gray-7 text-sm mt-1\">\n        System encountered an issue generating SQL. The manually submitted query\n        is now being processed.\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/preparation/step/Generating.tsx",
    "content": "import { Typography } from 'antd';\nimport { Spinner } from '@/components/PageLoading';\n\ninterface Props {\n  generating?: boolean;\n  correcting?: boolean;\n  loading?: boolean;\n}\n\nexport default function Generating(props: Props) {\n  const { loading, generating, correcting } = props;\n\n  return (\n    <>\n      <Typography.Text className=\"gray-8\">\n        Generating SQL statement\n      </Typography.Text>\n      <div className=\"gray-7 text-sm mt-1\">\n        {generating || correcting ? (\n          <div className=\"d-flex align-center gx-2\">\n            {correcting ? 'Correcting SQL statement' : 'Generating'}\n            <Spinner className=\"gray-6\" size={12} />\n          </div>\n        ) : (\n          <>\n            <div>Successfully generated SQL statement</div>\n            {loading && (\n              <div className=\"d-flex align-center gx-2 mt-1\">\n                Wrapping up <Spinner className=\"gray-6\" size={16} />\n              </div>\n            )}\n          </>\n        )}\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/preparation/step/Organizing.tsx",
    "content": "import { useEffect, useRef } from 'react';\nimport { Typography } from 'antd';\nimport MarkdownBlock from '@/components/editor/MarkdownBlock';\nimport { Spinner } from '@/components/PageLoading';\n\ninterface Props {\n  stream: string;\n  loading?: boolean;\n  isAdjustment?: boolean;\n}\n\nexport default function Organizing(props: Props) {\n  const $wrapper = useRef<HTMLDivElement>(null);\n  const { stream, loading, isAdjustment } = props;\n\n  const isDone = stream && !loading;\n\n  const scrollBottom = () => {\n    if ($wrapper.current) {\n      $wrapper.current.scrollTo({\n        top: $wrapper.current.scrollHeight,\n      });\n    }\n  };\n\n  useEffect(() => {\n    scrollBottom();\n  }, [stream]);\n\n  useEffect(() => {\n    if (isDone) scrollBottom();\n  }, [isDone]);\n\n  const title = isAdjustment\n    ? 'User-provided reasoning steps applied'\n    : 'Organizing thoughts';\n\n  return (\n    <>\n      <Typography.Text className=\"gray-8\">{title}</Typography.Text>\n      <div\n        ref={$wrapper}\n        className=\"gray-7 text-sm mt-2\"\n        style={{ maxHeight: 'calc(100vh - 550px)', overflowY: 'auto' }}\n      >\n        {loading && !stream ? (\n          <div className=\"d-flex align-center gx-2\">\n            Thinking\n            <Spinner className=\"gray-6\" size={12} />\n          </div>\n        ) : (\n          <MarkdownBlock content={stream} />\n        )}\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/preparation/step/Retrieving.tsx",
    "content": "import { Typography, Tag } from 'antd';\nimport { makeIterable } from '@/utils/iteration';\nimport { Spinner } from '@/components/PageLoading';\n\ninterface Props {\n  tables: string[];\n  loading?: boolean;\n  isAdjustment?: boolean;\n}\n\nconst TagTemplate = ({ name }: { name: string }) => {\n  return <Tag className=\"gray-7 mb-2\">{name}</Tag>;\n};\n\nconst TagIterator = makeIterable(TagTemplate);\n\nexport default function Retrieving(props: Props) {\n  const { tables, loading, isAdjustment } = props;\n\n  const data = tables.map((table) => ({ name: table }));\n\n  const title = isAdjustment\n    ? 'User-selected models applied'\n    : 'Retrieving top 10 model candidates';\n\n  const modelDescription = isAdjustment ? (\n    <>{tables.length} models applied</>\n  ) : (\n    <>Top {tables.length} model candidates identified</>\n  );\n\n  return (\n    <>\n      <Typography.Text className=\"gray-8\">{title}</Typography.Text>\n      <div className=\"gray-7 text-sm mt-1\">\n        {loading ? (\n          <div className=\"d-flex align-center gx-2\">\n            Searching\n            <Spinner className=\"gray-6\" size={12} />\n          </div>\n        ) : (\n          <>\n            <div className=\"mb-1\">{modelDescription}</div>\n            <TagIterator data={data} />\n          </>\n        )}\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/preparation/step/SQLPairFinished.tsx",
    "content": "import { Typography } from 'antd';\n\nexport default function SQLPairFinished() {\n  return (\n    <>\n      <Typography.Text className=\"gray-8\">\n        Using question-SQL pair\n      </Typography.Text>\n      <div className=\"gray-7 text-sm mt-1\">\n        <div>\n          Matching question-SQL pair found. Returning results instantly.\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/preparation/step/ViewFinished.tsx",
    "content": "import { Typography } from 'antd';\n\nexport default function ViewFinished() {\n  return (\n    <>\n      <Typography.Text className=\"gray-8\">Using pre-saved view</Typography.Text>\n      <div className=\"gray-7 text-sm mt-1\">\n        <div>Matching saved view found. Returning results instantly.</div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/prompt/DemoPrompt.tsx",
    "content": "import { Row, Col } from 'antd';\nimport styled from 'styled-components';\nimport { makeIterable } from '@/utils/iteration';\nimport EllipsisWrapper from '@/components/EllipsisWrapper';\n\nconst DemoBlock = styled.div`\n  user-select: none;\n  height: 150px;\n  &:hover {\n    border-color: var(--geekblue-6) !important;\n    transition: border-color ease 0.2s;\n  }\n`;\n\ninterface Props {\n  demo: any[];\n  onSelect: (data: { label: string; question: string }) => void;\n}\n\nconst DemoTemplate = ({ label, question, onSelect }) => {\n  return (\n    <Col span={8}>\n      <DemoBlock\n        className=\"border border-gray-5 rounded px-3 pt-3 pb-4 cursor-pointer\"\n        onClick={() => onSelect({ label, question })}\n      >\n        <div className=\"d-flex justify-space-between align-center text-sm mb-3\">\n          <div className=\"border border-gray-5 px-2 rounded-pill\">{label}</div>\n        </div>\n        <EllipsisWrapper multipleLine={4} text={question} />\n      </DemoBlock>\n    </Col>\n  );\n};\n\nconst DemoColumnIterator = makeIterable(DemoTemplate);\n\nexport default function DemoPrompt(props: Props) {\n  const { demo, onSelect } = props;\n  return (\n    <div className=\"gray-8\" style={{ width: 580 }}>\n      <div className=\"text-center mt-3 mb-2\">Try asking...</div>\n      <Row gutter={16}>\n        <DemoColumnIterator data={demo} onSelect={onSelect} />\n      </Row>\n    </div>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/prompt/Input.tsx",
    "content": "import { useEffect, useRef, useState } from 'react';\nimport { Input, Button } from 'antd';\nimport styled from 'styled-components';\nimport { attachLoading } from '@/utils/helper';\n\nconst PromptButton = styled(Button)`\n  min-width: 72px;\n`;\n\ninterface Props {\n  question: string;\n  isProcessing: boolean;\n  onAsk: (value: string) => Promise<void>;\n  inputProps: {\n    placeholder?: string;\n  };\n}\n\nexport default function PromptInput(props: Props) {\n  const { onAsk, isProcessing, question, inputProps } = props;\n  const $promptInput = useRef<HTMLTextAreaElement>(null);\n  const [inputValue, setInputValue] = useState('');\n  const [innerLoading, setInnerLoading] = useState(false);\n\n  useEffect(() => {\n    if (question) setInputValue(question);\n  }, [question]);\n\n  useEffect(() => {\n    if (!isProcessing) {\n      $promptInput.current?.focus();\n      setInputValue('');\n    }\n  }, [isProcessing]);\n\n  const syncInputValue = (event) => {\n    setInputValue(event.target.value);\n  };\n\n  const handleAsk = () => {\n    const trimmedValue = inputValue.trim();\n    if (!trimmedValue) return;\n    const startAsking = attachLoading(onAsk, setInnerLoading);\n    startAsking(trimmedValue);\n  };\n\n  const inputEnter = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n    if (event.shiftKey) return;\n    event.preventDefault();\n    handleAsk();\n  };\n\n  const isDisabled = innerLoading || isProcessing;\n\n  return (\n    <>\n      <Input.TextArea\n        ref={$promptInput}\n        // disable grammarly\n        data-gramm=\"false\"\n        size=\"large\"\n        autoSize\n        value={inputValue}\n        onInput={syncInputValue}\n        onPressEnter={inputEnter}\n        disabled={isDisabled}\n        {...inputProps}\n      />\n      <PromptButton\n        type=\"primary\"\n        size=\"large\"\n        className=\"ml-3\"\n        onClick={handleAsk}\n        disabled={isDisabled}\n      >\n        Ask\n      </PromptButton>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/prompt/RecommendedQuestionsPrompt.tsx",
    "content": "import { useState, useMemo } from 'react';\nimport clsx from 'clsx';\nimport styled from 'styled-components';\nimport { Space, Button, Row, Col } from 'antd';\nimport ColumnHeightOutlined from '@ant-design/icons/ColumnHeightOutlined';\nimport MinusOutlined from '@ant-design/icons/MinusOutlined';\nimport EllipsisWrapper from '@/components/EllipsisWrapper';\nimport LoadingOutlined from '@ant-design/icons/LoadingOutlined';\nimport { Logo } from '@/components/Logo';\nimport { makeIterable } from '@/utils/iteration';\nimport { GroupedQuestion } from '@/hooks/useRecommendedQuestionsInstruction';\n\nconst CategorySectionBlock = styled.div`\n  background: var(--gray-1);\n  border: 1px solid var(--gray-4);\n  border-radius: 4px;\n  padding: 16px;\n`;\n\nconst QuestionBlock = styled.div`\n  background: var(--gray-1);\n  user-select: none;\n  height: 150px;\n  transition: border-color ease 0.2s;\n\n  &:hover:not(.is-disabled) {\n    border-color: var(--geekblue-6) !important;\n  }\n\n  &.is-active {\n    border-color: var(--geekblue-6) !important;\n  }\n\n  &.is-disabled {\n    opacity: 0.8;\n  }\n`;\n\nconst MAX_EXPANDED_QUESTIONS = 9;\n\ninterface Props {\n  onSelect: (payload: { sql: string; question: string }) => void;\n  recommendedQuestions: GroupedQuestion[];\n  loading: boolean;\n}\n\nconst QuestionTemplate = ({\n  category,\n  sql,\n  question,\n  onSelect,\n  loading,\n  selectedQuestion,\n}) => {\n  const isSelected = selectedQuestion === question;\n  const isDisabled = loading && !isSelected;\n\n  const onClick = () => {\n    if (loading) return;\n    onSelect({ sql, question });\n  };\n\n  return (\n    <Col span={8}>\n      <QuestionBlock\n        className={clsx(\n          'border border-gray-5 rounded px-3 pt-3 pb-4',\n          loading ? 'cursor-wait' : 'cursor-pointer',\n          {\n            'is-active': isSelected,\n            'is-disabled cursor-not-allowed': isDisabled,\n          },\n        )}\n        onClick={onClick}\n      >\n        <div className=\"d-flex justify-space-between align-center text-sm mb-3\">\n          <div\n            className=\"border border-gray-5 px-2 rounded-pill text-truncate\"\n            title={category}\n          >\n            {category}\n          </div>\n          {isSelected && loading && <LoadingOutlined className=\"ml-1 gray-7\" />}\n        </div>\n        <EllipsisWrapper multipleLine={4} text={question} />\n      </QuestionBlock>\n    </Col>\n  );\n};\n\nconst QuestionColumnIterator = makeIterable(QuestionTemplate);\n\nexport default function RecommendedQuestionsPrompt(props: Props) {\n  const { onSelect, recommendedQuestions, loading } = props;\n\n  const [isExpanded, setIsExpanded] = useState<boolean>(false);\n  const [selectedQuestion, setSelectedQuestion] = useState<string>('');\n\n  const questionList = useMemo(() => {\n    return recommendedQuestions.slice(\n      0,\n      isExpanded ? undefined : MAX_EXPANDED_QUESTIONS,\n    );\n  }, [recommendedQuestions, isExpanded]);\n\n  const onHandleToggle = () => setIsExpanded((prev) => !prev);\n\n  const showExpandButton = recommendedQuestions.length > MAX_EXPANDED_QUESTIONS;\n\n  const onSelectQuestion = (payload: { sql: string; question: string }) => {\n    onSelect(payload);\n    setSelectedQuestion(payload.question);\n  };\n\n  return (\n    <div className=\"bg-gray-2 px-10 py-6\">\n      <div className=\"d-flex align-center mb-3\">\n        <Logo size={24} color=\"var(--gray-8)\" />\n        <div className=\"text-md text-medium gray-8 mx-3\">\n          Know more about your data.\n        </div>\n        <div className=\"text-medium gray-7\">\n          Try asking some of the following questions\n        </div>\n      </div>\n      <Space\n        style={{ width: 680 }}\n        className=\"gray-8\"\n        direction=\"vertical\"\n        size={[0, 16]}\n      >\n        <CategorySectionBlock>\n          <Row gutter={[16, 16]} className=\"mt-3\">\n            <QuestionColumnIterator\n              data={questionList}\n              onSelect={onSelectQuestion}\n              loading={loading}\n              selectedQuestion={selectedQuestion}\n            />\n          </Row>\n          {showExpandButton && (\n            <div className=\"text-right\">\n              <Button\n                onClick={() => onHandleToggle()}\n                className=\"gray-6 mt-3\"\n                type=\"text\"\n                size=\"small\"\n                icon={isExpanded ? <MinusOutlined /> : <ColumnHeightOutlined />}\n              >\n                {isExpanded ? 'Collapse' : 'Expand all'}\n              </Button>\n            </div>\n          )}\n        </CategorySectionBlock>\n      </Space>\n    </div>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/prompt/Result.tsx",
    "content": "import clsx from 'clsx';\nimport { ReactNode, useEffect, useRef, memo, useState } from 'react';\nimport { Button } from 'antd';\nimport styled from 'styled-components';\nimport { PROCESS_STATE } from '@/utils/enum';\nimport { attachLoading } from '@/utils/helper';\nimport { BrainSVG } from '@/utils/svgs';\nimport CloseOutlined from '@ant-design/icons/CloseOutlined';\nimport StopOutlined from '@ant-design/icons/StopFilled';\nimport LoadingOutlined from '@ant-design/icons/LoadingOutlined';\nimport CloseCircleFilled from '@ant-design/icons/CloseCircleFilled';\nimport WarningOutlined from '@ant-design/icons/WarningOutlined';\nimport MessageOutlined from '@ant-design/icons/MessageOutlined';\nimport ErrorCollapse from '@/components/ErrorCollapse';\nimport InfoCircleOutlined from '@ant-design/icons/InfoCircleOutlined';\nimport RecommendedQuestions, {\n  getRecommendedQuestionProps,\n} from '@/components/pages/home/RecommendedQuestions';\nimport MarkdownBlock from '@/components/editor/MarkdownBlock';\nimport {\n  AskingTaskType,\n  RecommendedQuestionsTask,\n} from '@/apollo/client/graphql/__types__';\n\nconst StyledResult = styled.div`\n  position: absolute;\n  bottom: calc(100% + 12px);\n  left: 0;\n  width: 100%;\n  background: white;\n  box-shadow:\n    rgba(0, 0, 0, 0.1) 0px 10px 15px -3px,\n    rgba(0, 0, 0, 0.05) 0px 4px 6px -2px;\n\n  .adm-brain-svg {\n    width: 14px;\n    height: 14px;\n  }\n`;\n\ninterface Props {\n  processState: PROCESS_STATE;\n  data: {\n    type: AskingTaskType;\n    originalQuestion: string;\n    askingStreamTask: string;\n    recommendedQuestions: RecommendedQuestionsTask;\n    intentReasoning: string;\n  };\n  error?: any;\n  onIntentSQLAnswer: () => void;\n  onSelectRecommendedQuestion: ({\n    question,\n    sql,\n  }: {\n    question: string;\n    sql: string;\n  }) => void;\n  onClose: () => void;\n  onStop: () => Promise<void>;\n  loading?: boolean;\n}\n\nconst Wrapper = ({ children }) => {\n  return (\n    <StyledResult\n      className=\"border border-gray-3 rounded p-4\"\n      data-testid=\"prompt__result\"\n    >\n      {children}\n    </StyledResult>\n  );\n};\n\nconst makeProcessing = (text: string) => (props: Props) => {\n  const { onStop } = props;\n  const [loading, setLoading] = useState(false);\n  return (\n    <Wrapper>\n      <div className=\"d-flex justify-space-between\">\n        <span>\n          <LoadingOutlined className=\"mr-2 geekblue-6 text-lg\" spin />\n          {text}\n        </span>\n        <Button\n          className={clsx(\n            'adm-btn-no-style bg-gray-3 text-sm px-2',\n            loading ? 'gray-6' : 'gray-7',\n          )}\n          type=\"text\"\n          size=\"small\"\n          onClick={attachLoading(onStop, setLoading)}\n          disabled={loading}\n        >\n          <StopOutlined className=\"-mr-1\" />\n          Stop\n        </Button>\n      </div>\n    </Wrapper>\n  );\n};\n\nconst makeProcessingError =\n  (config: { icon: ReactNode; title?: string; description?: string }) =>\n  (props: Props) => {\n    const { onClose, onSelectRecommendedQuestion, data, error } = props;\n    const { message, shortMessage, stacktrace } = error || {};\n    const hasStacktrace = !!stacktrace;\n\n    const recommendedQuestionProps = getRecommendedQuestionProps(\n      data?.recommendedQuestions,\n    );\n\n    return (\n      <Wrapper>\n        <div className=\"d-flex justify-space-between text-medium mb-2\">\n          <div className=\"d-flex align-center\">\n            {config.icon}\n            {config.title || shortMessage}\n          </div>\n          <Button\n            className=\"adm-btn-no-style gray-7 bg-gray-3 text-sm px-2\"\n            type=\"text\"\n            size=\"small\"\n            onClick={onClose}\n          >\n            <CloseOutlined className=\"-mr-1\" />\n            Close\n          </Button>\n        </div>\n        <div className=\"gray-7\">\n          {config.description || data.intentReasoning || message}\n        </div>\n        {hasStacktrace && (\n          <ErrorCollapse className=\"mt-2\" message={stacktrace.join('\\n')} />\n        )}\n\n        {recommendedQuestionProps.show && (\n          <RecommendedQuestions\n            className=\"mt-2\"\n            {...recommendedQuestionProps.state}\n            onSelect={onSelectRecommendedQuestion}\n          />\n        )}\n      </Wrapper>\n    );\n  };\n\nconst ErrorIcon = () => <CloseCircleFilled className=\"mr-2 red-5 text-lg\" />;\n\nconst Failed = makeProcessingError({\n  icon: <ErrorIcon />,\n});\n\nconst Understanding = makeProcessing('Understanding question');\n\nconst IntentionFinished = (props: Props) => {\n  const { data, onIntentSQLAnswer } = props;\n  const { type } = data;\n\n  useEffect(() => {\n    // create an empty response first if this is a text to sql task\n    if (type === AskingTaskType.TEXT_TO_SQL) {\n      onIntentSQLAnswer && onIntentSQLAnswer();\n    }\n  }, [type]);\n\n  // To keep the UI result keep showing as understanding\n  return <Understanding {...props} />;\n};\n\nconst GeneralAnswer = (props: Props) => {\n  const { onClose, onSelectRecommendedQuestion, data, loading } = props;\n  const $wrapper = useRef<HTMLDivElement>(null);\n\n  const { originalQuestion, askingStreamTask, recommendedQuestions } = data;\n  const isDone = askingStreamTask && !loading;\n\n  const scrollBottom = () => {\n    if ($wrapper.current) {\n      $wrapper.current.scrollTo({\n        top: $wrapper.current.scrollHeight,\n      });\n    }\n  };\n\n  useEffect(() => {\n    scrollBottom();\n  }, [askingStreamTask]);\n\n  useEffect(() => {\n    if (isDone) scrollBottom();\n  }, [isDone]);\n\n  const recommendedQuestionProps =\n    getRecommendedQuestionProps(recommendedQuestions);\n\n  return (\n    <Wrapper>\n      <div className=\"d-flex justify-space-between\">\n        <div className=\"d-flex align-start\">\n          <MessageOutlined className=\"mr-2 mt-1 geekblue-6\" />\n          <b className=\"text-semi-bold\">{originalQuestion}</b>\n        </div>\n        <Button\n          className=\"adm-btn-no-style gray-7 bg-gray-3 text-sm px-2\"\n          type=\"text\"\n          size=\"small\"\n          onClick={onClose}\n        >\n          <CloseOutlined className=\"-mr-1\" />\n          Close\n        </Button>\n      </div>\n      <div className=\"py-3\">\n        <div className=\"bg-gray-2 gray-6 py-2 px-3\">\n          <div className=\"d-flex align-center\">\n            <BrainSVG className=\"mr-2 adm-brain-svg\" />\n            <span className=\"text-medium \">User Intent Recognized</span>\n          </div>\n          <div style={{ paddingLeft: 22 }}>{data.intentReasoning}</div>\n        </div>\n\n        <div\n          ref={$wrapper}\n          className=\"py-2 px-3\"\n          style={{ maxHeight: 'calc(100vh - 480px)', overflowY: 'auto' }}\n        >\n          <MarkdownBlock content={askingStreamTask} />\n          {isDone && (\n            <div className=\"gray-6\">\n              <InfoCircleOutlined className=\"mr-2\" />\n              For the most accurate semantics, please visit the modeling page.\n            </div>\n          )}\n        </div>\n      </div>\n\n      {recommendedQuestionProps.show && (\n        <RecommendedQuestions\n          {...recommendedQuestionProps.state}\n          onSelect={onSelectRecommendedQuestion}\n        />\n      )}\n    </Wrapper>\n  );\n};\n\nconst MisleadingQuery = makeProcessingError({\n  icon: <WarningOutlined className=\"mr-2 text-lg gold-6\" />,\n  title: 'Clarification needed',\n});\n\nconst getGeneralAnswerStateComponent = (state: PROCESS_STATE) => {\n  return (\n    {\n      [PROCESS_STATE.FINISHED]: GeneralAnswer,\n    }[state] || null\n  );\n};\n\nconst getMisleadingQueryStateComponent = (state: PROCESS_STATE) => {\n  return (\n    {\n      [PROCESS_STATE.FINISHED]: MisleadingQuery,\n    }[state] || null\n  );\n};\n\nconst getDefaultStateComponent = (state: PROCESS_STATE) => {\n  return (\n    {\n      [PROCESS_STATE.UNDERSTANDING]: Understanding,\n      // Polling AI status for every 1 second might skip the searching state.\n      [PROCESS_STATE.SEARCHING]: IntentionFinished,\n      [PROCESS_STATE.PLANNING]: IntentionFinished,\n      [PROCESS_STATE.GENERATING]: IntentionFinished,\n      // The finished status will respond by AI directly if viewId found, so we need to handle with intention finished.\n      [PROCESS_STATE.FINISHED]: IntentionFinished,\n      [PROCESS_STATE.FAILED]: Failed,\n    }[state] || null\n  );\n};\n\nconst makeProcessStateStrategy = (type: AskingTaskType) => {\n  // note that the asking task type only has value when the asking status was finished\n  // by default, we use the default state component (also the text to sql state component)\n  if (type === AskingTaskType.GENERAL) return getGeneralAnswerStateComponent;\n  if (type === AskingTaskType.MISLEADING_QUERY)\n    return getMisleadingQueryStateComponent;\n  return getDefaultStateComponent;\n};\n\nexport default memo(function PromptResult(props: Props) {\n  const { processState, data } = props;\n\n  const getProcessStateComponent = makeProcessStateStrategy(data?.type);\n  const StateComponent = getProcessStateComponent(processState);\n\n  if (StateComponent === null) return null;\n\n  return <StateComponent {...props} />;\n});\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/prompt/index.tsx",
    "content": "import {\n  useEffect,\n  useMemo,\n  useState,\n  forwardRef,\n  useImperativeHandle,\n} from 'react';\nimport styled from 'styled-components';\nimport { PROCESS_STATE } from '@/utils/enum';\nimport PromptInput from '@/components/pages/home/prompt/Input';\nimport PromptResult from '@/components/pages/home/prompt/Result';\nimport useAskProcessState, {\n  getIsProcessing,\n} from '@/hooks/useAskProcessState';\nimport { AskPromptData } from '@/hooks/useAskPrompt';\nimport {\n  CreateThreadInput,\n  CreateThreadResponseInput,\n} from '@/apollo/client/graphql/__types__';\n\ninterface Props {\n  onCreateResponse: (\n    payload: CreateThreadInput | CreateThreadResponseInput,\n  ) => Promise<void>;\n  onStop: () => void;\n  onSubmit: (value: string) => Promise<void>;\n  onStopPolling: () => void;\n  onStopStreaming: () => void;\n  onStopRecommend: () => void;\n  data: AskPromptData;\n  loading: boolean;\n  inputProps: {\n    placeholder: string;\n  };\n}\n\ninterface Attributes {\n  submit: (value: string) => void;\n  close: () => void;\n}\n\nconst PromptStyle = styled.div`\n  position: fixed;\n  width: 680px;\n  left: 50%;\n  margin-left: calc(-340px + 133px);\n  bottom: 18px;\n  z-index: 999;\n  box-shadow:\n    rgba(0, 0, 0, 0.1) 0px 10px 15px -3px,\n    rgba(0, 0, 0, 0.05) 0px 4px 6px -2px;\n`;\n\nexport default forwardRef<Attributes, Props>(function Prompt(props, ref) {\n  const {\n    data,\n    loading,\n    onSubmit,\n    onStop,\n    onCreateResponse,\n    onStopStreaming,\n    onStopRecommend,\n    inputProps,\n  } = props;\n  const askProcessState = useAskProcessState();\n\n  const {\n    originalQuestion,\n    askingTask,\n    askingStreamTask,\n    recommendedQuestions,\n  } = data;\n\n  const result = useMemo(\n    () => ({\n      type: askingTask?.type, // question's type\n      originalQuestion, // original question\n      askingStreamTask, // for general answer\n      recommendedQuestions, // guiding user to ask\n      intentReasoning: askingTask?.intentReasoning || '',\n    }),\n    [data],\n  );\n  const error = useMemo(() => askingTask?.error || null, [askingTask?.error]);\n  const [showResult, setShowResult] = useState(false);\n  const [question, setQuestion] = useState('');\n  const currentProcessState = useMemo(\n    () => askProcessState.currentState,\n    [askProcessState.currentState],\n  );\n  const isProcessing = useMemo(\n    () => getIsProcessing(currentProcessState),\n    [currentProcessState],\n  );\n\n  useEffect(() => {\n    if (askingTask) {\n      const processState = askProcessState.matchedState(askingTask);\n      askProcessState.transitionTo(processState);\n    }\n  }, [askingTask]);\n\n  useEffect(() => {\n    if (error) {\n      !askProcessState.isFailed() &&\n        askProcessState.transitionTo(PROCESS_STATE.FAILED);\n    }\n  }, [error]);\n\n  // create thread response for recommended question\n  const selectRecommendedQuestion = async (payload: {\n    question: string;\n    sql: string;\n  }) => {\n    onCreateResponse && (await onCreateResponse(payload));\n    closeResult();\n  };\n\n  // create thread response for text to sql\n  const intentSQLAnswer = async () => {\n    onCreateResponse &&\n      (await onCreateResponse({ question, taskId: askingTask?.queryId }));\n    setShowResult(false);\n  };\n\n  const closeResult = () => {\n    askProcessState.resetState();\n    setQuestion('');\n    onStopStreaming && onStopStreaming();\n    onStopRecommend && onStopRecommend();\n  };\n\n  const stopProcess = async () => {\n    onStop && (await onStop());\n    setShowResult(false);\n    askProcessState.resetState();\n  };\n\n  const submitAsk = async (value: string) => {\n    setQuestion(value);\n    if (isProcessing || !value) return;\n    // start the state as understanding when user submit question\n    askProcessState.transitionTo(PROCESS_STATE.UNDERSTANDING);\n    setShowResult(true);\n    onSubmit && (await onSubmit(value));\n  };\n\n  useImperativeHandle(\n    ref,\n    () => ({\n      submit: submitAsk,\n      close: closeResult,\n    }),\n    [question, isProcessing, setQuestion],\n  );\n\n  return (\n    <PromptStyle className=\"d-flex align-end bg-gray-2 p-3 border border-gray-3 rounded\">\n      <PromptInput\n        question={question}\n        isProcessing={isProcessing}\n        onAsk={submitAsk}\n        inputProps={inputProps}\n      />\n\n      {showResult && (\n        <PromptResult\n          data={result}\n          error={error}\n          loading={loading}\n          processState={currentProcessState}\n          onSelectRecommendedQuestion={selectRecommendedQuestion}\n          onIntentSQLAnswer={intentSQLAnswer}\n          onClose={closeResult}\n          onStop={stopProcess}\n        />\n      )}\n    </PromptStyle>\n  );\n});\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/promptThread/AnswerResult.tsx",
    "content": "import { useEffect, useMemo } from 'react';\nimport { isEmpty, debounce } from 'lodash';\nimport clsx from 'clsx';\nimport { Button, Typography, Tabs, Tag, Tooltip } from 'antd';\nimport styled from 'styled-components';\nimport CheckCircleFilled from '@ant-design/icons/CheckCircleFilled';\nimport CodeFilled from '@ant-design/icons/CodeFilled';\nimport PieChartFilled from '@ant-design/icons/PieChartFilled';\nimport MessageOutlined from '@ant-design/icons/MessageOutlined';\nimport ShareAltOutlined from '@ant-design/icons/ShareAltOutlined';\nimport { RobotSVG } from '@/utils/svgs';\nimport { ANSWER_TAB_KEYS } from '@/utils/enum';\nimport { canGenerateAnswer } from '@/hooks/useAskPrompt';\nimport usePromptThreadStore from './store';\nimport { RecommendedQuestionsProps } from '@/components/pages/home/promptThread';\nimport RecommendedQuestions, {\n  getRecommendedQuestionProps,\n} from '@/components/pages/home/RecommendedQuestions';\nimport ViewBlock from '@/components/pages/home/promptThread/ViewBlock';\nimport ViewSQLTabContent from '@/components/pages/home/promptThread/ViewSQLTabContent';\nimport TextBasedAnswer, {\n  getAnswerIsFinished,\n} from '@/components/pages/home/promptThread/TextBasedAnswer';\nimport ChartAnswer from '@/components/pages/home/promptThread/ChartAnswer';\nimport Preparation from '@/components/pages/home/preparation';\nimport {\n  AskingTaskStatus,\n  ThreadResponse,\n  ThreadResponseAnswerDetail,\n  ThreadResponseAnswerStatus,\n  ThreadResponseAdjustment,\n  ThreadResponseAdjustmentType,\n} from '@/apollo/client/graphql/__types__';\n\nconst { Title, Text } = Typography;\n\nconst adjustmentType = {\n  [ThreadResponseAdjustmentType.APPLY_SQL]: 'User-provided SQL applied',\n  [ThreadResponseAdjustmentType.REASONING]: 'Reasoning steps adjusted',\n};\n\nconst knowledgeTooltip = (\n  <>\n    Store this answer as a Question-SQL pair to help Wren AI improve SQL\n    generation.\n    <br />\n    <Typography.Link\n      className=\"gray-1 underline\"\n      href=\"https://docs.getwren.ai/oss/guide/knowledge/question-sql-pairs#save-to-knowledge\"\n      target=\"_blank\"\n      rel=\"noopener noreferrer\"\n    >\n      Learn more\n    </Typography.Link>\n  </>\n);\n\nconst StyledTabs = styled(Tabs)`\n  .ant-tabs-nav {\n    margin-bottom: 0;\n  }\n\n  .ant-tabs-content-holder {\n    border-left: 1px var(--gray-4) solid;\n    border-right: 1px var(--gray-4) solid;\n    border-bottom: 1px var(--gray-4) solid;\n  }\n\n  .ant-tabs-tab {\n    .ant-typography {\n      color: var(--gray-6);\n    }\n\n    [aria-label='check-circle'] {\n      color: var(--gray-5);\n    }\n\n    [aria-label='code'] {\n      color: var(--gray-5);\n    }\n\n    [aria-label='pie-chart'] {\n      color: var(--gray-5);\n    }\n\n    &.ant-tabs-tab-active {\n      .ant-typography {\n        color: var(--gray-8);\n      }\n\n      [aria-label='check-circle'] {\n        color: var(--green-5);\n      }\n\n      [aria-label='code'] {\n        color: var(--geekblue-5);\n      }\n\n      [aria-label='pie-chart'] {\n        color: var(--gold-6);\n      }\n\n      .adm-beta-tag {\n        background-color: var(--geekblue-2);\n        color: var(--geekblue-5);\n      }\n    }\n\n    .adm-beta-tag {\n      padding: 0 4px;\n      line-height: 18px;\n      margin: 0 0 0 6px;\n      border-radius: 2px;\n      background-color: var(--gray-5);\n      color: white;\n      border: none;\n    }\n  }\n`;\n\nexport interface Props {\n  motion: boolean;\n  threadResponse: ThreadResponse;\n  isLastThreadResponse: boolean;\n  isOpeningQuestion: boolean;\n  onInitPreviewDone: () => void;\n}\n\nconst QuestionTitle = (props) => {\n  const { question, className } = props;\n  return (\n    <Title\n      className={clsx('d-flex bg-gray-1 rounded mt-0', className)}\n      level={4}\n    >\n      <MessageOutlined className=\"geekblue-5 mt-1 mr-3\" />\n      <Text className=\"text-medium gray-8\">{question}</Text>\n    </Title>\n  );\n};\n\nconst renderRecommendedQuestions = (\n  isLastThreadResponse: boolean,\n  recommendedQuestionProps,\n  onSelect: RecommendedQuestionsProps['onSelect'],\n) => {\n  if (!isLastThreadResponse || !recommendedQuestionProps.show) return null;\n\n  return (\n    <RecommendedQuestions\n      className=\"mt-5 mb-4\"\n      {...recommendedQuestionProps.state}\n      onSelect={onSelect}\n    />\n  );\n};\n\nconst AdjustmentInformation = (props: {\n  adjustment: ThreadResponseAdjustment;\n}) => {\n  const { adjustment } = props;\n\n  return (\n    <div className=\"rounded bg-gray-3 gray-6 py-2 px-3 mb-2\">\n      <div className=\"d-flex align-center gx-2\">\n        <ShareAltOutlined className=\"gray-7\" />\n        <div className=\"flex-grow-1 gray-7\">\n          Adjusted answer\n          <Tag className=\"gray-6 border border-gray-5 bg-gray-3 ml-3 text-medium\">\n            {adjustmentType[adjustment.type]}\n          </Tag>\n        </div>\n      </div>\n    </div>\n  );\n};\n\nconst isNeedGenerateAnswer = (answerDetail: ThreadResponseAnswerDetail) => {\n  const isFinished = getAnswerIsFinished(answerDetail?.status);\n  // it means the background task has not started yet, but answer is pending for generating\n  const isProcessing = [\n    ThreadResponseAnswerStatus.NOT_STARTED,\n    ThreadResponseAnswerStatus.PREPROCESSING,\n    ThreadResponseAnswerStatus.FETCHING_DATA,\n  ].includes(answerDetail?.status);\n  return answerDetail?.queryId === null && !isFinished && !isProcessing;\n};\n\nexport default function AnswerResult(props: Props) {\n  const { threadResponse, isLastThreadResponse, isOpeningQuestion } = props;\n\n  const {\n    onOpenSaveAsViewModal,\n    onGenerateThreadRecommendedQuestions,\n    onGenerateTextBasedAnswer,\n    onGenerateChartAnswer,\n    onOpenSaveToKnowledgeModal,\n    // recommend questions\n    recommendedQuestions,\n    showRecommendedQuestions,\n    onSelectRecommendedQuestion,\n    preparation,\n  } = usePromptThreadStore();\n\n  const {\n    askingTask,\n    adjustmentTask,\n    answerDetail,\n    breakdownDetail,\n    id,\n    question,\n    sql,\n    view,\n    adjustment,\n  } = threadResponse;\n\n  const resultStyle = isLastThreadResponse\n    ? { minHeight: 'calc(100vh - (194px))' }\n    : null;\n\n  const isAdjustment = !!adjustment;\n\n  const recommendedQuestionProps = getRecommendedQuestionProps(\n    recommendedQuestions,\n    showRecommendedQuestions,\n  );\n\n  const isAnswerPrepared = !!answerDetail?.queryId || !!answerDetail?.status;\n  const isBreakdownOnly = useMemo(() => {\n    // we support rendering different types of answers now, so we need to check if it's old data.\n    // existing thread response's answerDetail is null.\n    return answerDetail === null && !isEmpty(breakdownDetail);\n  }, [answerDetail, breakdownDetail]);\n\n  // initialize generate answer\n  useEffect(() => {\n    if (isBreakdownOnly) return;\n    if (\n      canGenerateAnswer(askingTask, adjustmentTask) &&\n      isNeedGenerateAnswer(answerDetail)\n    ) {\n      const debouncedGenerateAnswer = debounce(\n        () => {\n          onGenerateTextBasedAnswer(id);\n          onGenerateThreadRecommendedQuestions();\n        },\n        250,\n        { leading: false, trailing: true },\n      );\n      debouncedGenerateAnswer();\n\n      return () => {\n        debouncedGenerateAnswer.cancel();\n      };\n    }\n  }, [\n    isBreakdownOnly,\n    askingTask?.status,\n    adjustmentTask?.status,\n    answerDetail?.status,\n  ]);\n\n  const onTabClick = (activeKey: string) => {\n    if (activeKey === ANSWER_TAB_KEYS.CHART && !threadResponse.chartDetail) {\n      onGenerateChartAnswer(id);\n    }\n  };\n\n  const showAnswerTabs =\n    askingTask?.status === AskingTaskStatus.FINISHED ||\n    isAnswerPrepared ||\n    isBreakdownOnly;\n\n  const rephrasedQuestion =\n    threadResponse?.askingTask?.rephrasedQuestion || question;\n\n  const questionForSaveAsView = useMemo(() => {\n    // use rephrased question for follow-up questions, otherwise use the original question\n\n    if (isOpeningQuestion) return question;\n\n    return rephrasedQuestion;\n  }, [rephrasedQuestion, question, isOpeningQuestion]);\n\n  return (\n    <div style={resultStyle} data-jsid=\"answerResult\">\n      {isAdjustment && <AdjustmentInformation adjustment={adjustment} />}\n      <QuestionTitle className=\"mb-4\" question={question} />\n      <Preparation\n        className=\"mb-3\"\n        {...preparation}\n        data={threadResponse}\n        minimized={isAnswerPrepared}\n      />\n      {showAnswerTabs && (\n        <>\n          <StyledTabs type=\"card\" size=\"small\" onTabClick={onTabClick}>\n            {!isBreakdownOnly && (\n              <Tabs.TabPane\n                key={ANSWER_TAB_KEYS.ANSWER}\n                tab={\n                  <div className=\"select-none\">\n                    <CheckCircleFilled className=\"mr-2\" />\n                    <Text>Answer</Text>\n                  </div>\n                }\n              >\n                <TextBasedAnswer {...props} />\n              </Tabs.TabPane>\n            )}\n            <Tabs.TabPane\n              key={ANSWER_TAB_KEYS.VIEW_SQL}\n              tab={\n                <div className=\"select-none\">\n                  <CodeFilled className=\"mr-2\" />\n                  <Text>View SQL</Text>\n                </div>\n              }\n            >\n              <ViewSQLTabContent {...props} />\n            </Tabs.TabPane>\n            <Tabs.TabPane\n              key=\"chart\"\n              tab={\n                <div className=\"select-none\">\n                  <PieChartFilled className=\"mr-2\" />\n                  <Text>\n                    Chart<Tag className=\"adm-beta-tag\">Beta</Tag>\n                  </Text>\n                </div>\n              }\n            >\n              <ChartAnswer {...props} />\n            </Tabs.TabPane>\n          </StyledTabs>\n          <div className=\"mt-2 d-flex align-center\">\n            <Tooltip\n              overlayInnerStyle={{ width: 'max-content' }}\n              placement=\"topLeft\"\n              title={knowledgeTooltip}\n            >\n              <Button\n                type=\"link\"\n                size=\"small\"\n                className=\"mr-2\"\n                onClick={() =>\n                  onOpenSaveToKnowledgeModal(\n                    {\n                      question: rephrasedQuestion,\n                      sql,\n                    },\n                    { isCreateMode: true },\n                  )\n                }\n                data-guideid=\"save-to-knowledge\"\n              >\n                <div className=\"d-flex align-center\">\n                  <RobotSVG className=\"mr-2\" />\n                  Save to knowledge\n                </div>\n              </Button>\n            </Tooltip>\n            <ViewBlock\n              view={view}\n              onClick={() =>\n                onOpenSaveAsViewModal(\n                  { sql, responseId: id },\n                  {\n                    rephrasedQuestion: questionForSaveAsView,\n                  },\n                )\n              }\n            />\n          </div>\n          {renderRecommendedQuestions(\n            isLastThreadResponse,\n            recommendedQuestionProps,\n            onSelectRecommendedQuestion,\n          )}\n        </>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/promptThread/ChartAnswer.tsx",
    "content": "import clsx from 'clsx';\nimport dynamic from 'next/dynamic';\nimport styled from 'styled-components';\nimport { useEffect, useMemo, useState } from 'react';\nimport { Alert, Form, Button, Skeleton, Modal, message } from 'antd';\nimport { attachLoading } from '@/utils/helper';\nimport ReloadOutlined from '@ant-design/icons/ReloadOutlined';\nimport BasicProperties from '@/components/chart/properties/BasicProperties';\nimport DonutProperties from '@/components/chart/properties/DonutProperties';\nimport LineProperties from '@/components/chart/properties/LineProperties';\nimport StackedBarProperties from '@/components/chart/properties/StackedBarProperties';\nimport GroupedBarProperties from '@/components/chart/properties/GroupedBarProperties';\nimport { Props as AnswerResultProps } from '@/components/pages/home/promptThread/AnswerResult';\nimport { ChartTaskStatus, ChartType } from '@/apollo/client/graphql/__types__';\nimport { usePreviewDataMutation } from '@/apollo/client/graphql/home.generated';\nimport { isEmpty, isEqual } from 'lodash';\nimport {\n  getChartSpecFieldTitleMap,\n  getChartSpecOptionValues,\n} from '@/components/chart/handler';\nimport { useCreateDashboardItemMutation } from '@/apollo/client/graphql/dashboard.generated';\nimport { DashboardItemType } from '@/apollo/server/repositories';\nimport usePromptThreadStore from './store';\n\nconst Chart = dynamic(() => import('@/components/chart'), {\n  ssr: false,\n});\n\nconst StyledSkeleton = styled(Skeleton)`\n  padding: 16px;\n  .ant-skeleton-paragraph {\n    margin-bottom: 0;\n  }\n`;\n\nconst ChartWrapper = styled.div`\n  position: relative;\n  padding-top: 0;\n  transition: padding-top 0.2s ease-out;\n  &.isEditMode {\n    padding-top: 72px;\n  }\n`;\n\nconst Toolbar = styled.div`\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  background-color: var(--gray-3);\n  padding: 8px 16px;\n  position: absolute;\n  top: -72px;\n  left: 0;\n  right: 0;\n  transition: top 0.2s ease-out;\n  &.isEditMode {\n    top: 0;\n  }\n`;\n\nexport const getIsChartFinished = (status: ChartTaskStatus) => {\n  return [\n    ChartTaskStatus.FINISHED,\n    ChartTaskStatus.FAILED,\n    ChartTaskStatus.STOPPED,\n  ].includes(status);\n};\n\nconst getDynamicProperties = (chartType: ChartType) => {\n  const propertiesMap = {\n    [ChartType.GROUPED_BAR]: GroupedBarProperties,\n    [ChartType.STACKED_BAR]: StackedBarProperties,\n    [ChartType.LINE]: LineProperties,\n    [ChartType.MULTI_LINE]: LineProperties,\n    [ChartType.PIE]: DonutProperties,\n  };\n  return propertiesMap[chartType] || BasicProperties;\n};\n\nexport default function ChartAnswer(props: AnswerResultProps) {\n  const { onGenerateChartAnswer, onAdjustChartAnswer } = usePromptThreadStore();\n  const { threadResponse } = props;\n  const [regenerating, setRegenerating] = useState(false);\n  const [isEditMode, setIsEditMode] = useState(false);\n  const [newValues, setNewValues] = useState(null);\n\n  const [form] = Form.useForm();\n  const chartType = Form.useWatch('chartType', form);\n  const { chartDetail } = threadResponse;\n  const { error, status, adjustment } = chartDetail || {};\n\n  const [previewData, previewDataResult] = usePreviewDataMutation({\n    onError: (error) => console.error(error),\n  });\n\n  const [createDashboardItem] = useCreateDashboardItemMutation({\n    onError: (error) => console.error(error),\n    onCompleted: () => {\n      message.success('Successfully pinned chart to dashboard.');\n    },\n  });\n\n  // initial trigger when render\n  useEffect(() => {\n    previewData({\n      variables: { where: { responseId: threadResponse.id } },\n    });\n  }, []);\n\n  const chartSpec = useMemo(() => {\n    if (\n      !chartDetail?.chartSchema ||\n      (getIsChartFinished(status) && isEmpty(chartDetail?.chartSchema))\n    )\n      return null;\n    return chartDetail.chartSchema;\n  }, [chartDetail]);\n\n  const chartOptionValues = useMemo(() => {\n    return getChartSpecOptionValues(chartDetail);\n  }, [chartDetail]);\n\n  const chartSpecFieldTitleMap = useMemo(() => {\n    return getChartSpecFieldTitleMap(chartSpec?.encoding);\n  }, [chartSpec]);\n\n  useEffect(() => {\n    form.setFieldsValue(chartOptionValues);\n  }, [chartOptionValues]);\n\n  const isAdjusted = useMemo(() => {\n    return newValues !== null && !isEqual(chartOptionValues, newValues);\n  }, [chartOptionValues, newValues]);\n\n  const dataValues = useMemo(() => {\n    const { data, columns } = previewDataResult.data?.previewData || {};\n    return (data || []).map((val) => {\n      return (columns || []).reduce((acc, col, index) => {\n        acc[col.name] = val[index];\n        return acc;\n      }, {});\n    });\n  }, [previewDataResult.data]);\n\n  const dataColumns = useMemo(() => {\n    const { columns } = previewDataResult.data?.previewData || {};\n    return columns || [];\n  }, [previewDataResult.data]);\n\n  const loading =\n    previewDataResult.loading || !getIsChartFinished(status) || regenerating;\n\n  const DynamicProperties = getDynamicProperties(chartType as ChartType);\n\n  const onFormChange = () => {\n    setNewValues(form.getFieldsValue());\n  };\n\n  const onRegenerate = () => {\n    attachLoading(onGenerateChartAnswer, setRegenerating)(threadResponse.id);\n    onResetState();\n  };\n\n  const onResetState = () => {\n    setIsEditMode(false);\n    setNewValues(null);\n    form.resetFields();\n  };\n\n  const onReload = () => {\n    Modal.confirm({\n      title: 'Are you sure you want to regenerate the chart?',\n      onOk: onRegenerate,\n    });\n  };\n\n  const onEdit = () => {\n    setIsEditMode(!isEditMode);\n  };\n\n  const onPin = () => {\n    Modal.confirm({\n      title: 'Are you sure you want to pin this chart to the dashboard?',\n      okText: 'Save',\n      onOk: async () =>\n        await createDashboardItem({\n          variables: {\n            data: {\n              // DashboardItemType is compatible with ChartType\n              itemType: chartType as unknown as DashboardItemType,\n              responseId: threadResponse.id,\n            },\n          },\n        }),\n    });\n  };\n\n  const onResetAdjustment = () => {\n    setNewValues(null);\n    form.resetFields();\n  };\n\n  const onAdjustChart = async () => {\n    attachLoading(onAdjustChartAnswer, setRegenerating)(\n      threadResponse.id,\n      form.getFieldsValue(),\n    );\n    onResetState();\n  };\n\n  const regenerateBtn = (\n    <div className=\"text-center mt-4\">\n      <Button icon={<ReloadOutlined />} onClick={onReload}>\n        Regenerate\n      </Button>\n    </div>\n  );\n\n  if (error) {\n    return (\n      <div className=\"p-6\">\n        <Alert\n          message={error.shortMessage}\n          description={error.message}\n          type=\"error\"\n          showIcon\n        />\n        {regenerateBtn}\n      </div>\n    );\n  }\n\n  const chartRegenerateBtn = adjustment ? regenerateBtn : null;\n\n  return (\n    <StyledSkeleton\n      active\n      loading={loading}\n      paragraph={{ rows: 4 }}\n      title={false}\n    >\n      <div className=\"text-md gray-10 p-6\">\n        {chartDetail?.description}\n        {chartSpec ? (\n          <ChartWrapper\n            className={clsx(\n              'border border-gray-4 rounded mt-4 pb-3 overflow-hidden',\n              { isEditMode: isEditMode },\n            )}\n          >\n            <Toolbar className={clsx({ isEditMode: isEditMode })}>\n              <Form\n                size=\"small\"\n                style={{ width: '100%' }}\n                form={form}\n                initialValues={chartOptionValues}\n                onFieldsChange={onFormChange}\n              >\n                <div className=\"d-flex justify-content-between align-center\">\n                  <div className=\"flex-grow-1\">\n                    <DynamicProperties\n                      columns={dataColumns}\n                      titleMap={chartSpecFieldTitleMap}\n                    />\n                  </div>\n                  {isAdjusted && (\n                    <div className=\"d-flex flex-column\">\n                      <Button className=\"ml-4 mb-2\" onClick={onResetAdjustment}>\n                        Reset\n                      </Button>\n                      <Button\n                        className=\"ml-4\"\n                        type=\"primary\"\n                        onClick={onAdjustChart}\n                      >\n                        Adjust\n                      </Button>\n                    </div>\n                  )}\n                </div>\n              </Form>\n            </Toolbar>\n            <Chart\n              width={700}\n              spec={chartSpec}\n              values={dataValues}\n              onEdit={onEdit}\n              onReload={onReload}\n              onPin={onPin}\n            />\n          </ChartWrapper>\n        ) : (\n          chartRegenerateBtn\n        )}\n      </div>\n    </StyledSkeleton>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/promptThread/TextBasedAnswer.tsx",
    "content": "import { useEffect, useMemo, useState } from 'react';\nimport { Alert, Button, Skeleton, Typography } from 'antd';\nimport ReloadOutlined from '@ant-design/icons/ReloadOutlined';\nimport LoadingOutlined from '@ant-design/icons/LoadingOutlined';\nimport CaretDownOutlined from '@ant-design/icons/CaretDownOutlined';\nimport EditOutlined from '@ant-design/icons/EditOutlined';\nimport styled from 'styled-components';\nimport { BinocularsIcon } from '@/utils/icons';\nimport { nextTick } from '@/utils/time';\nimport { MORE_ACTION } from '@/utils/enum';\nimport usePromptThreadStore from './store';\nimport useDropdown from '@/hooks/useDropdown';\nimport useTextBasedAnswerStreamTask from '@/hooks/useTextBasedAnswerStreamTask';\nimport { Props as AnswerResultProps } from '@/components/pages/home/promptThread/AnswerResult';\nimport MarkdownBlock from '@/components/editor/MarkdownBlock';\nimport PreviewData from '@/components/dataPreview/PreviewData';\nimport { AdjustAnswerDropdown } from '@/components/diagram/CustomDropdown';\nimport { usePreviewDataMutation } from '@/apollo/client/graphql/home.generated';\nimport { ThreadResponseAnswerStatus } from '@/apollo/client/graphql/__types__';\n\nconst { Text } = Typography;\n\nconst StyledSkeleton = styled(Skeleton)`\n  padding: 16px;\n  .ant-skeleton-paragraph {\n    margin-bottom: 0;\n  }\n`;\n\nexport const getAnswerIsFinished = (status: ThreadResponseAnswerStatus) =>\n  [\n    ThreadResponseAnswerStatus.FINISHED,\n    ThreadResponseAnswerStatus.FAILED,\n    ThreadResponseAnswerStatus.INTERRUPTED,\n  ].includes(status);\n\nconst getIsLoadingFinished = (status: ThreadResponseAnswerStatus) =>\n  getAnswerIsFinished(status) ||\n  status === ThreadResponseAnswerStatus.STREAMING;\n\nexport default function TextBasedAnswer(props: AnswerResultProps) {\n  const {\n    onGenerateTextBasedAnswer,\n    onOpenAdjustReasoningStepsModal,\n    onOpenAdjustSQLModal,\n  } = usePromptThreadStore();\n  const { isLastThreadResponse, onInitPreviewDone, threadResponse } = props;\n  const { id } = threadResponse;\n  const { content, error, numRowsUsedInLLM, status } =\n    threadResponse?.answerDetail || {};\n\n  const [textAnswer, setTextAnswer] = useState<string>('');\n  const adjustResultsDropdown = useDropdown();\n\n  const [fetchAnswerStreamingTask, answerStreamTaskResult] =\n    useTextBasedAnswerStreamTask();\n\n  const answerStreamTask = answerStreamTaskResult.data;\n\n  const isStreaming = useMemo(\n    () => status === ThreadResponseAnswerStatus.STREAMING,\n    [status],\n  );\n\n  // Adapt askingTask and adjustment reasoning data to dropdown\n  const adjustAnswerDropdownData = useMemo(() => {\n    const { payload } = threadResponse.adjustment || {};\n    return {\n      responseId: threadResponse.id,\n      sql: threadResponse.sql,\n      retrievedTables:\n        threadResponse.askingTask?.retrievedTables ||\n        payload?.retrievedTables ||\n        [],\n      sqlGenerationReasoning:\n        threadResponse.askingTask?.sqlGenerationReasoning ||\n        payload?.sqlGenerationReasoning ||\n        '',\n    };\n  }, [\n    threadResponse.id,\n    threadResponse.sql,\n    threadResponse.adjustment?.payload,\n    threadResponse.askingTask?.retrievedTables,\n    threadResponse.askingTask?.sqlGenerationReasoning,\n  ]);\n\n  useEffect(() => {\n    if (isStreaming) {\n      setTextAnswer(answerStreamTask);\n    } else {\n      setTextAnswer(content);\n    }\n  }, [answerStreamTask, isStreaming, content]);\n\n  useEffect(() => {\n    if (isStreaming) {\n      fetchAnswerStreamingTask(id);\n    }\n  }, [isStreaming, id]);\n\n  useEffect(() => {\n    return () => {\n      answerStreamTaskResult.onReset();\n    };\n  }, []);\n\n  const rowsUsed = useMemo(\n    () =>\n      status === ThreadResponseAnswerStatus.FINISHED ? numRowsUsedInLLM : 0,\n    [numRowsUsedInLLM, status],\n  );\n\n  const allowPreviewData = useMemo(() => Boolean(rowsUsed > 0), [rowsUsed]);\n\n  const [previewData, previewDataResult] = usePreviewDataMutation({\n    onError: (error) => console.error(error),\n  });\n  const hasPreviewData = !!previewDataResult.data?.previewData;\n\n  const onPreviewData = async () => {\n    await previewData({ variables: { where: { responseId: id } } });\n  };\n\n  const autoTriggerPreviewDataButton = async () => {\n    await nextTick();\n    await onPreviewData();\n  };\n\n  useEffect(() => {\n    if (isLastThreadResponse) {\n      if (allowPreviewData) {\n        autoTriggerPreviewDataButton();\n      }\n\n      onInitPreviewDone();\n    }\n  }, [isLastThreadResponse, allowPreviewData]);\n\n  const loading = !getIsLoadingFinished(status);\n\n  const onRegenerateAnswer = () => {\n    setTextAnswer('');\n    onGenerateTextBasedAnswer(id);\n  };\n\n  const onMoreClick = async (payload: {\n    type: MORE_ACTION;\n    data: typeof adjustAnswerDropdownData;\n  }) => {\n    const { type, data } = payload;\n    if (type === MORE_ACTION.ADJUST_STEPS) {\n      onOpenAdjustReasoningStepsModal({\n        responseId: data.responseId,\n        retrievedTables: data.retrievedTables,\n        sqlGenerationReasoning: data.sqlGenerationReasoning,\n      });\n    } else if (type === MORE_ACTION.ADJUST_SQL) {\n      onOpenAdjustSQLModal({ responseId: id, sql: data.sql });\n    }\n  };\n\n  const adjustAnswerDropdown = (\n    <AdjustAnswerDropdown\n      onMoreClick={onMoreClick}\n      data={adjustAnswerDropdownData}\n      onDropdownVisibleChange={adjustResultsDropdown.onVisibleChange}\n    >\n      <Button\n        className=\"px-0\"\n        type=\"link\"\n        size=\"small\"\n        icon={<EditOutlined />}\n        onClick={(event) => event.stopPropagation()}\n      >\n        Adjust the answer\n        <CaretDownOutlined\n          className=\"ml-1\"\n          rotate={adjustResultsDropdown.visible ? 180 : 0}\n        />\n      </Button>\n    </AdjustAnswerDropdown>\n  );\n\n  if (error) {\n    return (\n      <>\n        <div className=\"py-4 px-6\">\n          <div className=\"text-right\">{adjustAnswerDropdown}</div>\n          <Alert\n            className=\"mt-4 mb-2\"\n            message={error.shortMessage}\n            description={error.message}\n            type=\"error\"\n            showIcon\n          />\n        </div>\n      </>\n    );\n  }\n\n  return (\n    <StyledSkeleton\n      active\n      loading={loading}\n      paragraph={{ rows: 4 }}\n      title={false}\n    >\n      <div className=\"text-md gray-10 py-4 px-6\">\n        <div className=\"text-right mb-4\">{adjustAnswerDropdown}</div>\n        <MarkdownBlock content={textAnswer} />\n        {isStreaming && <LoadingOutlined className=\"geekblue-6\" spin />}\n        {status === ThreadResponseAnswerStatus.INTERRUPTED && (\n          <div className=\"mt-2 text-right\">\n            <Button\n              icon={<ReloadOutlined />}\n              size=\"small\"\n              type=\"link\"\n              title=\"Regenerate answer\"\n              onClick={onRegenerateAnswer}\n            >\n              Regenerate\n            </Button>\n          </div>\n        )}\n        {allowPreviewData ? (\n          <div className=\"mt-6\">\n            <Button\n              size=\"small\"\n              icon={\n                <BinocularsIcon\n                  style={{\n                    paddingBottom: 2,\n                    marginRight: 8,\n                  }}\n                />\n              }\n              loading={previewDataResult.loading}\n              onClick={onPreviewData}\n              data-ph-capture=\"true\"\n              data-ph-capture-attribute-name=\"cta_text-answer_preview_data\"\n            >\n              View results\n            </Button>\n\n            <div className=\"mt-2 mb-3\" data-guideid=\"text-answer-preview-data\">\n              {hasPreviewData && (\n                <Text type=\"secondary\" className=\"text-sm\">\n                  Considering the limit of the context window, we retrieve up to\n                  500 rows of results to generate the answer.\n                </Text>\n              )}\n              <PreviewData\n                error={previewDataResult.error}\n                loading={previewDataResult.loading}\n                previewData={previewDataResult?.data?.previewData}\n              />\n            </div>\n          </div>\n        ) : (\n          <>\n            {!isStreaming && (\n              <Alert\n                message={\n                  <>\n                    Click <b>View SQL</b> to review the step-by-step query logic\n                    and verify why the data is unavailable.\n                  </>\n                }\n                type=\"info\"\n              />\n            )}\n          </>\n        )}\n      </div>\n    </StyledSkeleton>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/promptThread/ViewBlock.tsx",
    "content": "import Link from 'next/link';\nimport { Button } from 'antd';\nimport FileDoneOutlined from '@ant-design/icons/FileDoneOutlined';\nimport SaveOutlined from '@ant-design/icons/SaveOutlined';\nimport { Path } from '@/utils/enum';\nimport { ViewInfo } from '@/apollo/client/graphql/__types__';\n\ninterface Props {\n  view?: ViewInfo;\n  onClick: () => void;\n}\n\nexport default function ViewBlock({ view, onClick }: Props) {\n  const isViewSaved = !!view;\n\n  if (isViewSaved) {\n    return (\n      <div className=\"gray-6 text-medium\">\n        <FileDoneOutlined className=\"mr-2\" />\n        Generated from saved view{' '}\n        <Link\n          className=\"gray-7\"\n          href={`${Path.Modeling}?viewId=${view.id}&openMetadata=true`}\n          target=\"_blank\"\n          rel=\"noreferrer noopener\"\n        >\n          {view.displayName}\n        </Link>\n      </div>\n    );\n  }\n\n  return (\n    <Button\n      className=\"gray-6\"\n      type=\"text\"\n      size=\"small\"\n      icon={<SaveOutlined />}\n      onClick={onClick}\n    >\n      Save as View\n    </Button>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/promptThread/ViewSQLTabContent.tsx",
    "content": "import dynamic from 'next/dynamic';\nimport Image from 'next/image';\nimport { useEffect } from 'react';\nimport styled from 'styled-components';\nimport {\n  Alert,\n  Button,\n  Divider,\n  Empty,\n  message,\n  Space,\n  Switch,\n  Typography,\n} from 'antd';\nimport CheckOutlined from '@ant-design/icons/CheckOutlined';\nimport CloseOutlined from '@ant-design/icons/CloseOutlined';\nimport CodeFilled from '@ant-design/icons/CodeFilled';\nimport { BinocularsIcon } from '@/utils/icons';\nimport { nextTick } from '@/utils/time';\nimport useNativeSQL from '@/hooks/useNativeSQL';\nimport { DATA_SOURCE_OPTIONS } from '@/components/pages/setup/utils';\nimport { Logo } from '@/components/Logo';\nimport { Props as AnswerResultProps } from '@/components/pages/home/promptThread/AnswerResult';\nimport usePromptThreadStore from '@/components/pages/home/promptThread/store';\nimport PreviewData from '@/components/dataPreview/PreviewData';\nimport { usePreviewDataMutation } from '@/apollo/client/graphql/home.generated';\n\nconst SQLCodeBlock = dynamic(() => import('@/components/code/SQLCodeBlock'), {\n  ssr: false,\n});\n\nconst { Text } = Typography;\n\nconst StyledPre = styled.pre`\n  .adm_code-block {\n    border-top: none;\n    border-radius: 0px 0px 4px 4px;\n  }\n`;\n\nconst StyledToolBar = styled.div`\n  background-color: var(--gray-2);\n  height: 32px;\n  padding: 4px 8px;\n  border: 1px solid var(--gray-3);\n  border-radius: 4px 4px 0px 0px;\n`;\n\nexport default function ViewSQLTabContent(props: AnswerResultProps) {\n  const { isLastThreadResponse, onInitPreviewDone, threadResponse } = props;\n\n  const { onOpenAdjustSQLModal } = usePromptThreadStore();\n  const { fetchNativeSQL, nativeSQLResult } = useNativeSQL();\n  const [previewData, previewDataResult] = usePreviewDataMutation({\n    onError: (error) => console.error(error),\n  });\n\n  const onPreviewData = async () => {\n    await previewData({ variables: { where: { responseId: id } } });\n  };\n\n  const autoTriggerPreviewDataButton = async () => {\n    await nextTick();\n    await onPreviewData();\n    await nextTick();\n    onInitPreviewDone();\n  };\n\n  // when is the last step of the last thread response, auto trigger preview data button\n  useEffect(() => {\n    if (isLastThreadResponse) {\n      autoTriggerPreviewDataButton();\n    }\n  }, [isLastThreadResponse]);\n\n  const { id, sql } = threadResponse;\n\n  const { hasNativeSQL, dataSourceType } = nativeSQLResult;\n  const showNativeSQL = hasNativeSQL;\n\n  const sqls =\n    nativeSQLResult.nativeSQLMode && nativeSQLResult.loading === false\n      ? nativeSQLResult.data\n      : sql;\n\n  const onChangeNativeSQL = async (checked: boolean) => {\n    nativeSQLResult.setNativeSQLMode(checked);\n    checked && fetchNativeSQL({ variables: { responseId: id } });\n  };\n\n  const onCopy = () => {\n    if (!nativeSQLResult.nativeSQLMode) {\n      message.success(\n        <>\n          You copied Wren SQL. This dialect is for the Wren Engine and may not\n          run directly on your database.\n          {hasNativeSQL && (\n            <>\n              {' '}\n              Click “<b>Show original SQL</b>” to get the executable version.\n            </>\n          )}\n        </>,\n      );\n    }\n  };\n\n  return (\n    <div className=\"text-md gray-10 p-6 pb-4\">\n      <Alert\n        banner\n        className=\"mb-3 adm-alert-info\"\n        message={\n          <>\n            You’re viewing Wren SQL by default. If you want to run this query on\n            your own database, click “Show original SQL” to get the exact\n            syntax.\n            <Typography.Link\n              className=\"underline ml-1\"\n              href=\"https://docs.getwren.ai/oss/guide/home/wren_sql\"\n              target=\"_blank\"\n              rel=\"noopener noreferrer\"\n            >\n              Learn more about Wren SQL\n            </Typography.Link>\n          </>\n        }\n        type=\"info\"\n      />\n      <StyledPre className=\"p-0 mb-3\">\n        <StyledToolBar className=\"d-flex align-center justify-space-between text-family-base\">\n          <div>\n            {nativeSQLResult.nativeSQLMode ? (\n              <>\n                <Image\n                  className=\"mr-2\"\n                  src={DATA_SOURCE_OPTIONS[dataSourceType].logo}\n                  alt={DATA_SOURCE_OPTIONS[dataSourceType].label}\n                  width=\"22\"\n                  height=\"22\"\n                />\n                <Text className=\"gray-8 text-medium text-sm\">\n                  {DATA_SOURCE_OPTIONS[dataSourceType].label}\n                </Text>\n              </>\n            ) : (\n              <span className=\"d-flex align-center gx-2\">\n                <Logo size={18} />\n                <Text className=\"gray-8 text-medium text-sm\">Wren SQL</Text>\n              </span>\n            )}\n          </div>\n          <Space split={<Divider type=\"vertical\" className=\"m-0\" />}>\n            {showNativeSQL && (\n              <div\n                className=\"d-flex align-center cursor-pointer\"\n                onClick={() =>\n                  onChangeNativeSQL(!nativeSQLResult.nativeSQLMode)\n                }\n              >\n                <Switch\n                  checkedChildren={<CheckOutlined />}\n                  unCheckedChildren={<CloseOutlined />}\n                  className=\"mr-2\"\n                  size=\"small\"\n                  checked={nativeSQLResult.nativeSQLMode}\n                  loading={nativeSQLResult.loading}\n                />\n                <Text className=\"gray-8 text-medium text-base\">\n                  Show original SQL\n                </Text>\n              </div>\n            )}\n            <Button\n              type=\"link\"\n              data-ph-capture=\"true\"\n              data-ph-capture-attribute-name=\"view_sql_copy_sql\"\n              icon={<CodeFilled />}\n              size=\"small\"\n              onClick={() => onOpenAdjustSQLModal({ sql, responseId: id })}\n            >\n              Adjust SQL\n            </Button>\n          </Space>\n        </StyledToolBar>\n        <SQLCodeBlock\n          code={sqls}\n          showLineNumbers\n          maxHeight=\"300\"\n          loading={nativeSQLResult.loading}\n          copyable\n          onCopy={onCopy}\n        />\n      </StyledPre>\n      <div className=\"mt-6\">\n        <Button\n          size=\"small\"\n          icon={\n            <BinocularsIcon\n              style={{\n                paddingBottom: 2,\n                marginRight: 8,\n              }}\n            />\n          }\n          loading={previewDataResult.loading}\n          onClick={onPreviewData}\n          data-ph-capture=\"true\"\n          data-ph-capture-attribute-name=\"view_sql_preview_data\"\n        >\n          View results\n        </Button>\n        {previewDataResult?.data?.previewData && (\n          <div className=\"mt-2 mb-3\">\n            <PreviewData\n              error={previewDataResult.error}\n              loading={previewDataResult.loading}\n              previewData={previewDataResult?.data?.previewData}\n              locale={{\n                emptyText: (\n                  <Empty\n                    image={Empty.PRESENTED_IMAGE_SIMPLE}\n                    description=\"Sorry, we couldn't find any records that match your search criteria.\"\n                  />\n                ),\n              }}\n            />\n            <div className=\"text-right\">\n              <Text className=\"text-base gray-6\">Showing up to 500 rows</Text>\n            </div>\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/promptThread/index.tsx",
    "content": "import { useRouter } from 'next/router';\nimport { useEffect, useMemo, useRef } from 'react';\nimport { Divider } from 'antd';\nimport styled from 'styled-components';\nimport { nextTick } from '@/utils/time';\nimport usePromptThreadStore from './store';\nimport AnswerResult from './AnswerResult';\nimport { makeIterable, IterableComponent } from '@/utils/iteration';\nimport { getIsFinished } from '@/hooks/useAskPrompt';\nimport { getAnswerIsFinished } from '@/components/pages/home/promptThread/TextBasedAnswer';\nimport {\n  RecommendedQuestionsTask,\n  ThreadResponse,\n} from '@/apollo/client/graphql/__types__';\nimport { SelectQuestionProps } from '@/components/pages/home/RecommendedQuestions';\n\nexport interface RecommendedQuestionsProps {\n  data: RecommendedQuestionsTask;\n  show: boolean;\n  onSelect: ({ question, sql }: SelectQuestionProps) => void;\n}\n\nconst StyledPromptThread = styled.div`\n  width: 768px;\n  margin-left: auto;\n  margin-right: auto;\n\n  h4.ant-typography {\n    margin-top: 10px;\n  }\n\n  .ant-typography pre {\n    border: none;\n    border-radius: 4px;\n  }\n\n  button {\n    vertical-align: middle;\n  }\n`;\n\nconst AnswerResultTemplate: React.FC<\n  IterableComponent<ThreadResponse> & {\n    motion: boolean;\n    onInitPreviewDone: () => void;\n  }\n> = ({ data, index, motion, onInitPreviewDone, ...threadResponse }) => {\n  const { id } = threadResponse;\n  const lastResponseId = data[data.length - 1].id;\n  const isLastThreadResponse = id === lastResponseId;\n\n  return (\n    <div\n      key={`${id}-${index}`}\n      data-guideid={isLastThreadResponse ? `last-answer-result` : undefined}\n    >\n      {index > 0 && <Divider />}\n      <AnswerResult\n        motion={motion}\n        isOpeningQuestion={index === 0}\n        isLastThreadResponse={isLastThreadResponse}\n        onInitPreviewDone={onInitPreviewDone}\n        threadResponse={threadResponse}\n      />\n    </div>\n  );\n};\n\nconst AnswerResultIterator = makeIterable(AnswerResultTemplate);\n\nexport default function PromptThread() {\n  const router = useRouter();\n  const divRef = useRef<HTMLDivElement>(null);\n  const store = usePromptThreadStore();\n  const { data } = store;\n\n  const responses = useMemo(() => data?.responses || [], [data?.responses]);\n\n  const triggerScrollToBottom = (behavior?: ScrollBehavior) => {\n    if (responses.length <= 1) return;\n    const contentLayout = divRef.current?.parentElement;\n    const allElements = (divRef.current?.querySelectorAll(\n      '[data-jsid=\"answerResult\"]',\n    ) || []) as HTMLElement[];\n    const lastAnswerResult = allElements[allElements.length - 1];\n\n    const dividerSpace = 48;\n    if (contentLayout && lastAnswerResult) {\n      contentLayout.scrollTo({\n        top: lastAnswerResult.offsetTop - dividerSpace,\n        behavior,\n      });\n    }\n  };\n\n  useEffect(() => {\n    // reset to top when thread page changes\n    const contentLayout = divRef.current?.parentElement;\n    if (contentLayout) contentLayout.scrollTo({ top: 0 });\n  }, [router.query]);\n\n  useEffect(() => {\n    const lastResponse = responses[responses.length - 1];\n    const isLastResponseFinished =\n      getIsFinished(lastResponse?.askingTask?.status) ||\n      getAnswerIsFinished(lastResponse?.answerDetail?.status);\n    nextTick().then(() => {\n      triggerScrollToBottom(isLastResponseFinished ? 'auto' : 'smooth');\n    });\n  }, [responses.length]);\n\n  const onInitPreviewDone = () => {\n    triggerScrollToBottom();\n  };\n\n  return (\n    <StyledPromptThread className=\"mt-12\" ref={divRef}>\n      <AnswerResultIterator\n        data={responses}\n        onInitPreviewDone={onInitPreviewDone}\n      />\n    </StyledPromptThread>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/home/promptThread/store.tsx",
    "content": "import { useEffect } from 'react';\nimport useStoreContext, { STORE } from '@/hooks/useStoreContext';\nimport {\n  AdjustThreadResponseChartInput,\n  DetailedThread,\n  RecommendedQuestionsTask,\n  ThreadResponse,\n} from '@/apollo/client/graphql/__types__';\nimport { SelectQuestionProps } from '@/components/pages/home/RecommendedQuestions';\n\nexport type IPromptThreadStore = {\n  data: DetailedThread;\n  recommendedQuestions: RecommendedQuestionsTask;\n  showRecommendedQuestions: boolean;\n  preparation: {\n    askingStreamTask?: string;\n    onStopAskingTask?: (queryId?: string) => Promise<void>;\n    onStopAdjustTask?: (queryId?: string) => Promise<void>;\n    onReRunAskingTask?: (threadResponse: ThreadResponse) => Promise<void>;\n    onReRunAdjustTask?: (threadResponse: ThreadResponse) => Promise<void>;\n    onFixSQLStatement?: (responseId: number, sql: string) => Promise<void>;\n    fixStatementLoading?: boolean;\n  };\n  onOpenSaveAsViewModal: (\n    data: { sql: string; responseId: number },\n    payload: { rephrasedQuestion: string },\n  ) => void;\n  onSelectRecommendedQuestion: ({\n    question,\n    sql,\n  }: SelectQuestionProps) => Promise<void>;\n  onGenerateThreadRecommendedQuestions: () => Promise<void>;\n  onGenerateTextBasedAnswer: (responseId: number) => Promise<void>;\n  onGenerateChartAnswer: (responseId: number) => Promise<void>;\n  onAdjustChartAnswer: (\n    responseId: number,\n    data: AdjustThreadResponseChartInput,\n  ) => Promise<void>;\n  onOpenSaveToKnowledgeModal: (\n    data: { sql: string; question: string },\n    payload: { isCreateMode: boolean },\n  ) => void;\n  onOpenAdjustReasoningStepsModal: (data: {\n    responseId: number;\n    retrievedTables: string[];\n    sqlGenerationReasoning: string;\n  }) => void;\n  onOpenAdjustSQLModal: (data: { responseId: number; sql: string }) => void;\n};\n\n// Register store provider\nexport const PromptThreadProvider = (props: {\n  children: React.ReactNode;\n  value: IPromptThreadStore;\n}) => {\n  const storeContext = useStoreContext();\n  const PromptThreadContext = storeContext.createStore(STORE.PROMPT_THREAD);\n  // clear store when unmount\n  useEffect(() => {\n    return () => storeContext.clearStore(STORE.PROMPT_THREAD);\n  }, []);\n  return (\n    <PromptThreadContext.Provider value={props.value}>\n      {props.children}\n    </PromptThreadContext.Provider>\n  );\n};\n\n// Use store\nexport default function usePromptThreadStore() {\n  const storeContext = useStoreContext();\n  return storeContext.useStore(STORE.PROMPT_THREAD) as IPromptThreadStore;\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/knowledge/GlobalLabel.tsx",
    "content": "import { Typography } from 'antd';\nimport GlobalOutlined from '@ant-design/icons/GlobalOutlined';\n\nconst { Text } = Typography;\n\nexport default function GlobalLabel() {\n  return (\n    <>\n      <GlobalOutlined className=\"mr-2\" />\n      <Text className=\"gray-9\">Global</Text>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/knowledge/InstructionDrawer.tsx",
    "content": "import { Drawer, Tag, Typography } from 'antd';\nimport { getCompactTime } from '@/utils/time';\nimport QuestionOutlined from '@ant-design/icons/QuestionOutlined';\nimport { DrawerAction } from '@/hooks/useDrawerAction';\nimport GlobalLabel from '@/components/pages/knowledge/GlobalLabel';\nimport { Instruction } from '@/apollo/client/graphql/__types__';\n\nconst { Text } = Typography;\n\ntype Props = DrawerAction<Instruction>;\n\nexport default function InstructionDrawer(props: Props) {\n  const { visible, defaultValue, onClose } = props;\n\n  return (\n    <Drawer\n      closable\n      destroyOnClose\n      onClose={onClose}\n      title=\"View instruction\"\n      visible={visible}\n      width={760}\n    >\n      <div className=\"mb-6\">\n        <Typography.Text className=\"gray-7 mb-2\">\n          Instruction details\n        </Typography.Text>\n        <div>{defaultValue?.instruction || '-'}</div>\n      </div>\n      <div className=\"mb-6\">\n        <Typography.Text className=\"gray-7 mb-2\">\n          Matching questions\n        </Typography.Text>\n        <div>\n          {defaultValue?.isDefault ? (\n            <>\n              <GlobalLabel />\n              <Text className=\"gray-7 ml-2\" type=\"secondary\">\n                (applies to all questions)\n              </Text>\n            </>\n          ) : (\n            defaultValue?.questions.map((question, index) => (\n              <div key={`${question}-${index}`} className=\"my-2\">\n                <Tag className=\"bg-gray-1 border-gray-5\">\n                  <QuestionOutlined className=\"geekblue-6\" />\n                  <Text className=\"gray-9\">{question}</Text>\n                </Tag>\n              </div>\n            ))\n          )}\n        </div>\n      </div>\n      <div className=\"mb-6\">\n        <Typography.Text className=\"gray-7 mb-2\">Created time</Typography.Text>\n        <div>\n          {defaultValue?.createdAt\n            ? getCompactTime(defaultValue.createdAt)\n            : '-'}\n        </div>\n      </div>\n    </Drawer>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/knowledge/SQLPairDrawer.tsx",
    "content": "import { Drawer, Typography } from 'antd';\nimport { getCompactTime } from '@/utils/time';\nimport { DrawerAction } from '@/hooks/useDrawerAction';\nimport SQLCodeBlock from '@/components/code/SQLCodeBlock';\nimport { SqlPair } from '@/apollo/client/graphql/__types__';\n\ntype Props = DrawerAction<SqlPair>;\n\nexport default function SQLPairDrawer(props: Props) {\n  const { visible, defaultValue, onClose } = props;\n\n  return (\n    <Drawer\n      closable\n      destroyOnClose\n      onClose={onClose}\n      title=\"View question-SQL pair\"\n      visible={visible}\n      width={760}\n    >\n      <div className=\"mb-6\">\n        <Typography.Text className=\"gray-7 mb-2\">Question</Typography.Text>\n        <div>{defaultValue?.question || '-'}</div>\n      </div>\n      <div className=\"mb-6\">\n        <Typography.Text className=\"gray-7 mb-2\">SQL statement</Typography.Text>\n        <SQLCodeBlock\n          code={defaultValue?.sql || ''}\n          showLineNumbers\n          maxHeight=\"500\"\n        />\n      </div>\n      <div className=\"mb-6\">\n        <Typography.Text className=\"gray-7 mb-2\">Created time</Typography.Text>\n        <div>\n          {defaultValue?.createdAt\n            ? getCompactTime(defaultValue.createdAt)\n            : '-'}\n        </div>\n      </div>\n    </Drawer>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/modeling/EditMetadataModal.tsx",
    "content": "import { Modal, Form } from 'antd';\nimport { ModalAction } from '@/hooks/useModalAction';\nimport { NODE_TYPE } from '@/utils/enum';\nimport { EditableContext } from '@/components/EditableWrapper';\nimport EditModelMetadata, {\n  Props as EditModelProps,\n} from '@/components/pages/modeling/metadata/EditModelMetadata';\nimport EditViewMetadata, {\n  Props as EditViewProps,\n} from '@/components/pages/modeling/metadata/EditViewMetadata';\n\ntype DefaultValue = (EditModelProps | EditViewProps) & {\n  nodeType: NODE_TYPE;\n};\n\ntype Props = ModalAction<DefaultValue> & {\n  loading?: boolean;\n};\n\nconst formNamespace = 'metadata';\n\nexport default function EditMetadataModal(props: Props) {\n  const { visible, defaultValue, loading, onSubmit, onClose } = props;\n  const { nodeType } = defaultValue || {};\n\n  const [form] = Form.useForm();\n\n  const submit = async () => {\n    form\n      .validateFields()\n      .then(async () => {\n        // Get the saved metadata values to submit if there is no editing failed\n        const values = form.getFieldValue(formNamespace);\n        await onSubmit({ data: values, nodeType });\n        onClose();\n      })\n      .catch(console.error);\n  };\n\n  return (\n    <Modal\n      title=\"Edit metadata\"\n      width={800}\n      visible={visible}\n      okText=\"Submit\"\n      onOk={submit}\n      onCancel={onClose}\n      confirmLoading={loading}\n      maskClosable={false}\n      destroyOnClose\n      centered\n      afterClose={() => form.resetFields()}\n    >\n      <EditableContext.Provider value={form}>\n        <Form form={form} component={false}>\n          {nodeType === NODE_TYPE.MODEL && (\n            <EditModelMetadata\n              formNamespace={formNamespace}\n              {...(defaultValue as EditModelProps)}\n            />\n          )}\n\n          {nodeType === NODE_TYPE.VIEW && (\n            <EditViewMetadata\n              formNamespace={formNamespace}\n              {...(defaultValue as EditViewProps)}\n            />\n          )}\n        </Form>\n      </EditableContext.Provider>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/modeling/MetadataDrawer.tsx",
    "content": "import { Button, Drawer } from 'antd';\nimport { NODE_TYPE } from '@/utils/enum';\nimport EditOutlined from '@ant-design/icons/EditOutlined';\nimport { DrawerAction } from '@/hooks/useDrawerAction';\nimport ModelMetadata, {\n  Props as ModelMetadataProps,\n} from './metadata/ModelMetadata';\nimport ViewMetadata, {\n  Props as ViewMetadataProps,\n} from './metadata/ViewMetadata';\n\ntype Metadata = {\n  nodeType: NODE_TYPE;\n} & ModelMetadataProps &\n  ViewMetadataProps;\n\ntype Props = DrawerAction<Metadata> & { onEditClick: (value?: any) => void };\n\nexport default function MetadataDrawer(props: Props) {\n  const { visible, defaultValue, onClose, onEditClick } = props;\n  const { displayName, nodeType = NODE_TYPE.MODEL } = defaultValue || {};\n  const isModel = nodeType === NODE_TYPE.MODEL;\n  const isView = nodeType === NODE_TYPE.VIEW;\n\n  return (\n    <Drawer\n      visible={visible}\n      title={displayName}\n      width={760}\n      closable\n      destroyOnClose\n      onClose={onClose}\n      extra={\n        <Button\n          icon={<EditOutlined />}\n          onClick={() => onEditClick(defaultValue)}\n        >\n          Edit\n        </Button>\n      }\n    >\n      {isModel && <ModelMetadata {...defaultValue} />}\n      {isView && <ViewMetadata {...defaultValue} />}\n    </Drawer>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/modeling/ModelDrawer.tsx",
    "content": "import { Button, Drawer, Form, Space } from 'antd';\nimport { FORM_MODE } from '@/utils/enum';\nimport { DrawerAction } from '@/hooks/useDrawerAction';\nimport ModelForm from './form/ModelForm';\n\ntype Props = DrawerAction & {\n  submitting: boolean;\n};\n\nconst getDrawerTitle = (formMode: FORM_MODE, name?: string) =>\n  ({\n    [FORM_MODE.CREATE]: 'Create a data model',\n    [FORM_MODE.EDIT]: name,\n  })[formMode];\n\nexport default function ModelDrawer(props: Props) {\n  const { visible, formMode, defaultValue, submitting, onClose, onSubmit } =\n    props;\n  const [form] = Form.useForm();\n\n  const afterVisibleChange = (visible: boolean) => {\n    if (!visible) {\n      form.resetFields();\n    }\n  };\n\n  const submit = () => {\n    form\n      .validateFields()\n      .then(async (values) => {\n        await onSubmit({ data: values, id: defaultValue?.modelId });\n        onClose();\n      })\n      .catch(console.error);\n  };\n\n  return (\n    <Drawer\n      visible={visible}\n      title={getDrawerTitle(formMode, defaultValue?.displayName)}\n      width={750}\n      closable\n      destroyOnClose\n      afterVisibleChange={afterVisibleChange}\n      onClose={onClose}\n      footer={\n        <Space className=\"d-flex justify-end\">\n          <Button onClick={onClose} disabled={submitting}>\n            Cancel\n          </Button>\n          <Button\n            type=\"primary\"\n            onClick={submit}\n            loading={submitting}\n            disabled={submitting}\n          >\n            Submit\n          </Button>\n        </Space>\n      }\n    >\n      <ModelForm formMode={formMode} form={form} defaultValue={defaultValue} />\n    </Drawer>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/modeling/form/ModelForm.tsx",
    "content": "import { useEffect, useMemo, useState } from 'react';\nimport { Form, FormInstance, Select } from 'antd';\nimport { TransferItem } from 'antd/es/transfer';\nimport { isEmpty } from 'lodash';\nimport { FORM_MODE } from '@/utils/enum';\nimport { DiagramModelField } from '@/utils/data';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { DrawerAction } from '@/hooks/useDrawerAction';\nimport { Loading } from '@/components/PageLoading';\nimport TableTransfer, {\n  defaultColumns,\n} from '@/components/table/TableTransfer';\nimport { useListDataSourceTablesQuery } from '@/apollo/client/graphql/dataSource.generated';\nimport { useListModelsQuery } from '@/apollo/client/graphql/model.generated';\nimport { CompactTable, CompactColumn } from '@/apollo/client/graphql/__types__';\n\nconst { Option } = Select;\n\nconst FormFieldKey = {\n  SOURCE_TABLE: 'sourceTableName',\n  COLUMNS: 'fields',\n  PRIMARY_KEY: 'primaryKey',\n};\n\ntype Props = Pick<DrawerAction, 'defaultValue' | 'formMode'> & {\n  form: FormInstance;\n};\n\nconst primaryKeyValidator =\n  (selectedColumns: string[]) => async (_rule: any, value: string) => {\n    if (value && !selectedColumns.includes(value)) {\n      return Promise.reject(\n        ERROR_TEXTS.MODELING_CREATE_MODEL.PRIMARY_KEY.INVALID,\n      );\n    }\n\n    return Promise.resolve();\n  };\n\nexport default function ModelForm(props: Props) {\n  const { defaultValue, form, formMode } = props;\n\n  const [selectedColumns, setSelectedColumns] = useState<string[]>([]);\n  const [sourceTableName, setSourceTableName] = useState<string>(undefined);\n  const sourceTableFieldValue = Form.useWatch(FormFieldKey.SOURCE_TABLE, form);\n\n  const isUpdateMode = formMode === FORM_MODE.EDIT;\n\n  const { data: listModelsQueryResult, loading: listModelsQueryLoading } =\n    useListModelsQuery({\n      fetchPolicy: 'cache-and-network',\n      skip: isUpdateMode,\n    });\n\n  const { data, loading: fetching } = useListDataSourceTablesQuery({\n    fetchPolicy: 'cache-and-network',\n    onError: (error) => console.error(error),\n  });\n\n  const dataSourceTables = data?.listDataSourceTables || [];\n  const existingModels = listModelsQueryResult?.listModels;\n  const inUsedModelList = useMemo(\n    () => (existingModels || []).map((model) => model.sourceTableName),\n    [existingModels],\n  );\n\n  useEffect(() => {\n    if (isUpdateMode) return;\n\n    // for create mode, reset selected columns when source table changes\n    setSelectedColumns([]);\n    form.resetFields([FormFieldKey.PRIMARY_KEY]);\n  }, [formMode, sourceTableName]);\n\n  // for create mode\n  useEffect(() => {\n    if (sourceTableFieldValue) {\n      setSourceTableName(sourceTableFieldValue);\n    }\n  }, [sourceTableFieldValue]);\n\n  const columns: Array<{\n    key: string;\n    name: string;\n    type: string;\n  }> = useMemo(() => {\n    if (isEmpty(sourceTableName)) return [];\n\n    const table = dataSourceTables.find(\n      (table) => table.name === sourceTableName,\n    )!;\n    if (!table) return [];\n\n    return table.columns.map((column: CompactColumn) => ({\n      ...column,\n      key: column.name,\n    }));\n  }, [dataSourceTables, sourceTableName]);\n\n  useEffect(() => {\n    if (defaultValue) {\n      const fields: string[] = defaultValue.fields\n        .map((field: DiagramModelField) => field.referenceName)\n        .filter((col) => columns.find((c) => c.name === col));\n\n      const primaryKeyField = defaultValue.fields.find(\n        (field: DiagramModelField) => field.isPrimaryKey,\n      );\n\n      form.setFieldsValue({\n        [FormFieldKey.COLUMNS]: fields,\n        [FormFieldKey.PRIMARY_KEY]: primaryKeyField?.referenceName,\n      });\n\n      setSourceTableName(defaultValue.sourceTableName);\n      setSelectedColumns(fields);\n    }\n  }, [defaultValue, form, columns]);\n\n  const tableOptions: JSX.Element[] = dataSourceTables.map(\n    (table: CompactTable) => {\n      const disabled = inUsedModelList.includes(table.name);\n      const option = {\n        disabled,\n        children: table.name,\n        value: table.name,\n      };\n\n      return <Option {...option} key={option.value} />;\n    },\n  );\n\n  const onChangeColumns = (newKeys: string[]) => setSelectedColumns(newKeys);\n\n  const dataSourceTablesLoading = fetching || listModelsQueryLoading;\n\n  return (\n    <>\n      <Form form={form} layout=\"vertical\">\n        {!isUpdateMode && (\n          <div>\n            <Form.Item\n              label=\"Select a table\"\n              name={FormFieldKey.SOURCE_TABLE}\n              required\n              rules={[\n                {\n                  required: true,\n                  message: ERROR_TEXTS.MODELING_CREATE_MODEL.TABLE.REQUIRED,\n                },\n              ]}\n            >\n              <Select\n                getPopupContainer={(trigger) => trigger.parentElement!}\n                placeholder=\"Select a table\"\n                showSearch\n                loading={dataSourceTablesLoading}\n                disabled={isUpdateMode}\n              >\n                {tableOptions}\n              </Select>\n            </Form.Item>\n          </div>\n        )}\n        <Loading spinning={isUpdateMode ? dataSourceTablesLoading : false}>\n          <Form.Item\n            label=\"Select columns\"\n            name={FormFieldKey.COLUMNS}\n            rules={[\n              {\n                required: true,\n                message: ERROR_TEXTS.MODELING_CREATE_MODEL.COLUMNS.REQUIRED,\n              },\n            ]}\n          >\n            <TableTransfer\n              dataSource={columns}\n              targetKeys={selectedColumns}\n              onChange={onChangeColumns}\n              filterOption={(inputValue: string, item: TransferItem) =>\n                item.name.toLowerCase().indexOf(inputValue.toLowerCase()) !==\n                  -1 ||\n                item.type.toLowerCase().indexOf(inputValue.toLowerCase()) !== -1\n              }\n              leftColumns={defaultColumns}\n              rightColumns={defaultColumns}\n              titles={['Available Columns', 'Target Columns']}\n              showSearch\n            />\n          </Form.Item>\n        </Loading>\n        <Form.Item\n          label=\"Select primary key\"\n          name={FormFieldKey.PRIMARY_KEY}\n          rules={[\n            {\n              validator: primaryKeyValidator(selectedColumns),\n            },\n          ]}\n        >\n          <Select\n            getPopupContainer={(trigger) => trigger.parentElement!}\n            placeholder=\"Select a column\"\n            showSearch\n            allowClear\n          >\n            {selectedColumns.map((column) => (\n              <Option key={column} value={column}>\n                {column}\n              </Option>\n            ))}\n          </Select>\n        </Form.Item>\n      </Form>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/modeling/metadata/EditBasicMetadata.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { Typography, Row, Col } from 'antd';\nimport { cloneDeep, set } from 'lodash';\nimport { NODE_TYPE } from '@/utils/enum';\nimport EditableWrapper from '@/components/EditableWrapper';\n\ninterface Props {\n  dataSource: any;\n  onChange?: (value: any) => void;\n  nodeType: NODE_TYPE;\n  rules?: Record<string, any[]>;\n}\n\nexport default function EditBasicMetadata(props: Props) {\n  const { dataSource, onChange, nodeType, rules } = props;\n  const [data, setData] = useState(dataSource);\n\n  const isModel = nodeType === NODE_TYPE.MODEL;\n  const isView = nodeType === NODE_TYPE.VIEW;\n\n  useEffect(() => {\n    // bind changeable metadata values\n    onChange &&\n      onChange({\n        displayName: data.displayName,\n        description: data.description,\n      });\n  }, [data]);\n\n  const handleSave = (_, value) => {\n    const [dataIndexKey] = Object.keys(value);\n\n    const newData = cloneDeep(data);\n    set(newData, dataIndexKey, value[dataIndexKey]);\n    setData(newData);\n  };\n\n  return (\n    <>\n      {isModel && (\n        <Row>\n          <Col span={12}>\n            <div className=\"mb-6\" data-testid=\"edit-metadata__name\">\n              <Typography.Text className=\"d-block gray-7 mb-2\">\n                Name\n              </Typography.Text>\n              <div>{data.referenceName}</div>\n            </div>\n          </Col>\n          <Col span={12} data-testid=\"edit-metadata__alias\">\n            <div className=\"mb-6\" data-testid=\"metadata__name\">\n              <Typography.Text className=\"d-block gray-7 mb-2\">\n                Alias\n              </Typography.Text>\n              <EditableWrapper\n                record={data}\n                dataIndex=\"displayName\"\n                handleSave={handleSave}\n              >\n                {data.displayName || '-'}\n              </EditableWrapper>\n            </div>\n          </Col>\n        </Row>\n      )}\n\n      {isView && (\n        <div className=\"mb-6\" data-testid=\"edit-metadata__name\">\n          <Typography.Text className=\"d-block gray-7 mb-2\">\n            Name\n          </Typography.Text>\n          <EditableWrapper\n            record={data}\n            dataIndex=\"displayName\"\n            handleSave={handleSave}\n            rules={rules?.displayName}\n          >\n            {data.displayName || '-'}\n          </EditableWrapper>\n        </div>\n      )}\n\n      <div className=\"mb-6\" data-testid=\"edit-metadata__description\">\n        <Typography.Text className=\"d-block gray-7 mb-2\">\n          Description\n        </Typography.Text>\n        <EditableWrapper\n          record={data}\n          dataIndex=\"description\"\n          handleSave={handleSave}\n        >\n          {data.description || '-'}\n        </EditableWrapper>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/modeling/metadata/EditModelMetadata.tsx",
    "content": "import { useContext } from 'react';\nimport { Typography } from 'antd';\nimport { NODE_TYPE } from '@/utils/enum';\nimport FieldTable from '@/components/table/FieldTable';\nimport CalculatedFieldTable from '@/components/table/CalculatedFieldTable';\nimport RelationTable from '@/components/table/RelationTable';\nimport { makeEditableBaseTable } from '@/components/table/EditableBaseTable';\nimport { COLUMN } from '@/components/table/BaseTable';\nimport { EditableContext } from '@/components/EditableWrapper';\nimport EditBasicMetadata from './EditBasicMetadata';\nimport NestedFieldTable from '@/components/table/NestedFieldTable';\n\nexport interface Props {\n  formNamespace: string;\n  displayName: string;\n  referenceName: string;\n  fields: any[];\n  calculatedFields?: any[];\n  relationFields: any[];\n  description: string;\n  properties: Record<string, any>;\n  nodeType: NODE_TYPE;\n  modelId: number;\n}\n\nconst FIELDS_NAME = {\n  FIELDS: 'columns',\n  NESTED_FIELDS: 'nestedColumns',\n  CALCULATED_FIELDS: 'calculatedFields',\n  RELATIONSHIPS: 'relationships',\n};\n\nconst FieldEditableTable = makeEditableBaseTable(FieldTable);\nconst NestedFieldEditableTable = makeEditableBaseTable(NestedFieldTable as any);\nconst CalculatedFieldEditableTable =\n  makeEditableBaseTable(CalculatedFieldTable);\nconst RelationshipEditableTable = makeEditableBaseTable(RelationTable);\n\nexport default function EditModelMetadata(props: Props) {\n  const {\n    formNamespace,\n    displayName,\n    referenceName,\n    fields = [],\n    calculatedFields = [],\n    relationFields = [],\n    description,\n    nodeType,\n    modelId,\n  } = props || {};\n\n  const form = useContext(EditableContext);\n\n  const onChange = (value) => {\n    form.setFieldsValue({\n      [formNamespace]: {\n        ...(form.getFieldValue(formNamespace) || {}),\n        ...value,\n        modelId,\n      },\n    });\n  };\n\n  const handleMetadataChange = (fieldsName: string) => (value: any[]) => {\n    // bind changeable metadata values\n    onChange({\n      [fieldsName]: value.map((item) => ({\n        id: item.relationId || item.columnId || item.nestedColumnId,\n        description: item.description,\n        // Only models & fields, nested fields have alias\n        ...([FIELDS_NAME.FIELDS, FIELDS_NAME.NESTED_FIELDS].includes(fieldsName)\n          ? { displayName: item.displayName }\n          : {}),\n      })),\n    });\n  };\n\n  return (\n    <>\n      <EditBasicMetadata\n        dataSource={{ displayName, referenceName, description }}\n        onChange={onChange}\n        nodeType={nodeType}\n      />\n\n      <div className=\"mb-6\">\n        <Typography.Text className=\"d-block gray-7 mb-2\">\n          Columns ({fields.length})\n        </Typography.Text>\n        <FieldEditableTable\n          dataSource={fields}\n          columns={[\n            COLUMN.NAME,\n            COLUMN.ALIAS,\n            { ...COLUMN.TYPE, width: 150 },\n            { ...COLUMN.DESCRIPTION, width: 280 },\n          ]}\n          onChange={handleMetadataChange(FIELDS_NAME.FIELDS)}\n          showExpandable\n          expandable={{\n            expandedRowRender: (record) => (\n              <div className=\"px-3 py-2\">\n                <NestedFieldEditableTable\n                  dataSource={record.nestedFields as any}\n                  columns={[\n                    COLUMN.NAME,\n                    COLUMN.ALIAS,\n                    COLUMN.TYPE,\n                    COLUMN.DESCRIPTION,\n                  ]}\n                  onChange={handleMetadataChange(FIELDS_NAME.NESTED_FIELDS)}\n                />\n              </div>\n            ),\n            rowExpandable: (record) => !!record.nestedFields,\n          }}\n        />\n      </div>\n\n      {!!calculatedFields.length && (\n        <div className=\"mb-6\">\n          <Typography.Text className=\"d-block gray-7 mb-2\">\n            Calculated fields ({calculatedFields.length})\n          </Typography.Text>\n          <CalculatedFieldEditableTable\n            dataSource={calculatedFields}\n            columns={[\n              { ...COLUMN.NAME, dataIndex: 'displayName', width: 160 },\n              COLUMN.EXPRESSION,\n              { ...COLUMN.DESCRIPTION, width: 280 },\n            ]}\n            onChange={handleMetadataChange(FIELDS_NAME.CALCULATED_FIELDS)}\n          />\n        </div>\n      )}\n\n      {!!relationFields.length && (\n        <div className=\"mb-6\">\n          <Typography.Text className=\"d-block gray-7 mb-2\">\n            Relationships ({relationFields.length})\n          </Typography.Text>\n          <RelationshipEditableTable\n            dataSource={relationFields}\n            columns={[\n              { ...COLUMN.NAME, dataIndex: 'displayName' },\n              COLUMN.RELATION_FROM,\n              COLUMN.RELATION_TO,\n              { ...COLUMN.RELATION, width: 130 },\n              { ...COLUMN.DESCRIPTION, width: 200 },\n            ]}\n            onChange={handleMetadataChange(FIELDS_NAME.RELATIONSHIPS)}\n          />\n        </div>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/modeling/metadata/EditViewMetadata.tsx",
    "content": "import { useContext } from 'react';\nimport { Typography } from 'antd';\nimport { NODE_TYPE } from '@/utils/enum';\nimport FieldTable from '@/components/table/FieldTable';\nimport { makeEditableBaseTable } from '@/components/table/EditableBaseTable';\nimport { createViewNameValidator } from '@/utils/validator';\nimport { COLUMN } from '@/components/table/BaseTable';\nimport { EditableContext } from '@/components/EditableWrapper';\nimport EditBasicMetadata from './EditBasicMetadata';\nimport { useValidateViewMutation } from '@/apollo/client/graphql/view.generated';\n\nexport interface Props {\n  formNamespace: string;\n  displayName: string;\n  fields: any[];\n  description: string;\n  properties: Record<string, any>;\n  nodeType: NODE_TYPE;\n  viewId: number;\n}\n\nconst FIELDS_NAME = {\n  FIELDS: 'columns',\n};\n\nconst FieldEditableTable = makeEditableBaseTable(FieldTable);\n\nexport default function EditViewMetadata(props: Props) {\n  const {\n    formNamespace,\n    displayName,\n    fields = [],\n    description,\n    nodeType,\n    viewId,\n  } = props || {};\n\n  const form = useContext(EditableContext);\n\n  const [validateViewMutation] = useValidateViewMutation({\n    fetchPolicy: 'no-cache',\n  });\n\n  const onChange = (value) => {\n    form.setFieldsValue({\n      [formNamespace]: {\n        ...(form.getFieldValue(formNamespace) || {}),\n        ...value,\n        viewId,\n      },\n    });\n  };\n\n  const handleMetadataChange = (fieldsName: string) => (value: any[]) => {\n    // bind changeable metadata values\n    // The view's columns don't have their own column IDs, so we use the referenceName\n    onChange({\n      [fieldsName]: value.map((item) => ({\n        referenceName: item.referenceName,\n        description: item.description,\n      })),\n    });\n  };\n\n  return (\n    <>\n      <EditBasicMetadata\n        dataSource={{ displayName, description }}\n        onChange={onChange}\n        nodeType={nodeType}\n        rules={{\n          // View display name changing will trigger re-generate reference name\n          // So we need to validate the display name\n          displayName: [\n            {\n              required: true,\n              validator: createViewNameValidator(validateViewMutation),\n            },\n          ],\n        }}\n      />\n\n      <div className=\"mb-6\">\n        <Typography.Text className=\"d-block gray-7 mb-2\">\n          Columns ({fields.length})\n        </Typography.Text>\n        <FieldEditableTable\n          dataSource={fields}\n          columns={[\n            COLUMN.NAME,\n            { ...COLUMN.TYPE },\n            { ...COLUMN.DESCRIPTION, width: 280 },\n          ]}\n          onChange={handleMetadataChange(FIELDS_NAME.FIELDS)}\n        />\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/modeling/metadata/ModelMetadata.tsx",
    "content": "import { useMemo } from 'react';\nimport { keyBy } from 'lodash';\nimport { Col, Row, Typography, Button } from 'antd';\nimport FieldTable from '@/components/table/FieldTable';\nimport CalculatedFieldTable from '@/components/table/CalculatedFieldTable';\nimport RelationTable from '@/components/table/RelationTable';\nimport PreviewData from '@/components/dataPreview/PreviewData';\nimport { DiagramModel } from '@/utils/data';\nimport { usePreviewModelDataMutation } from '@/apollo/client/graphql/model.generated';\n\nexport type Props = DiagramModel;\n\nexport default function ModelMetadata(props: Props) {\n  const {\n    modelId,\n    displayName,\n    referenceName,\n    fields = [],\n    calculatedFields = [],\n    relationFields = [],\n    description,\n  } = props || {};\n\n  const [previewModelData, previewModelDataResult] =\n    usePreviewModelDataMutation({\n      onError: (error) => console.error(error),\n    });\n\n  // Model preview data should show alias as column name.\n  const fieldsMap = useMemo(() => keyBy(fields, 'referenceName'), [fields]);\n  const previewData = useMemo(() => {\n    const previewModelData = previewModelDataResult.data?.previewModelData;\n    const columns = (previewModelData?.columns || []).map((column) => {\n      const alias = fieldsMap[column.name]?.displayName;\n      return { ...column, name: alias || column.name };\n    });\n    return { ...previewModelData, columns };\n  }, [fieldsMap, previewModelDataResult.data]);\n\n  const onPreviewData = () => {\n    previewModelData({ variables: { where: { id: modelId } } });\n  };\n\n  return (\n    <>\n      <Row className=\"mb-6\">\n        <Col span={12} data-testid=\"metadata__name\">\n          <Typography.Text className=\"d-block gray-7 mb-2\">\n            Name\n          </Typography.Text>\n          <div>{referenceName || '-'}</div>\n        </Col>\n        <Col span={12} data-testid=\"metadata__alias\">\n          <Typography.Text className=\"d-block gray-7 mb-2\">\n            Alias\n          </Typography.Text>\n          <div>{displayName || '-'}</div>\n        </Col>\n      </Row>\n      <div className=\"mb-6\" data-testid=\"metadata__description\">\n        <Typography.Text className=\"d-block gray-7 mb-2\">\n          Description\n        </Typography.Text>\n        <div>{description || '-'}</div>\n      </div>\n\n      <div className=\"mb-6\" data-testid=\"metadata__columns\">\n        <Typography.Text className=\"d-block gray-7 mb-2\">\n          Columns ({fields.length})\n        </Typography.Text>\n        <FieldTable dataSource={fields} showExpandable />\n      </div>\n\n      {!!calculatedFields.length && (\n        <div className=\"mb-6\" data-testid=\"metadata__calculated-fields\">\n          <Typography.Text className=\"d-block gray-7 mb-2\">\n            Calculated fields ({calculatedFields.length})\n          </Typography.Text>\n          <CalculatedFieldTable dataSource={calculatedFields} showExpandable />\n        </div>\n      )}\n\n      {!!relationFields.length && (\n        <div className=\"mb-6\" data-testid=\"metadata__relationships\">\n          <Typography.Text className=\"d-block gray-7 mb-2\">\n            Relationships ({relationFields.length})\n          </Typography.Text>\n          <RelationTable dataSource={relationFields} showExpandable />\n        </div>\n      )}\n\n      <div className=\"mb-6\" data-testid=\"metadata__preview-data\">\n        <Typography.Text className=\"d-block gray-7 mb-2\">\n          Data preview (100 rows)\n        </Typography.Text>\n        <Button\n          onClick={onPreviewData}\n          loading={previewModelDataResult.loading}\n        >\n          Preview data\n        </Button>\n        <div className=\"my-3\">\n          <PreviewData\n            error={previewModelDataResult.error}\n            loading={previewModelDataResult.loading}\n            previewData={previewData}\n          />\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/modeling/metadata/ViewMetadata.tsx",
    "content": "import { Button, Typography } from 'antd';\nimport SQLCodeBlock from '@/components/code/SQLCodeBlock';\nimport PreviewData from '@/components/dataPreview/PreviewData';\nimport { COLUMN } from '@/components/table/BaseTable';\nimport FieldTable from '@/components/table/FieldTable';\nimport { DiagramView } from '@/utils/data';\nimport { usePreviewViewDataMutation } from '@/apollo/client/graphql/view.generated';\n\nexport type Props = DiagramView;\n\nexport default function ViewMetadata(props: Props) {\n  const {\n    displayName,\n    description,\n    fields = [],\n    statement,\n    viewId,\n  } = props || {};\n\n  const [previewViewData, previewViewDataResult] = usePreviewViewDataMutation({\n    onError: (error) => console.error(error),\n  });\n\n  const onPreviewData = () => {\n    previewViewData({ variables: { where: { id: viewId } } });\n  };\n\n  // View only can input Name (alias), so it should show alias as Name in metadata.\n  return (\n    <>\n      <div className=\"mb-6\" data-testid=\"metadata__name\">\n        <Typography.Text className=\"d-block gray-7 mb-2\">Name</Typography.Text>\n        <div>{displayName || '-'}</div>\n      </div>\n\n      <div className=\"mb-6\" data-testid=\"metadata__description\">\n        <Typography.Text className=\"d-block gray-7 mb-2\">\n          Description\n        </Typography.Text>\n        <div>{description || '-'}</div>\n      </div>\n\n      <div className=\"mb-6\" data-testid=\"metadata__columns\">\n        <Typography.Text className=\"d-block gray-7 mb-2\">\n          Columns ({fields.length})\n        </Typography.Text>\n        <FieldTable\n          columns={[COLUMN.NAME, COLUMN.TYPE, COLUMN.DESCRIPTION]}\n          dataSource={fields}\n          showExpandable\n        />\n      </div>\n\n      <div className=\"mb-6\" data-testid=\"metadata__sql-statement\">\n        <Typography.Text className=\"d-block gray-7 mb-2\">\n          SQL statement\n        </Typography.Text>\n        <SQLCodeBlock code={statement} showLineNumbers maxHeight=\"300\" />\n      </div>\n\n      <div className=\"mb-6\" data-testid=\"metadata__preview-data\">\n        <Typography.Text className=\"d-block gray-7 mb-2\">\n          Data preview (100 rows)\n        </Typography.Text>\n        <Button onClick={onPreviewData} loading={previewViewDataResult.loading}>\n          Preview data\n        </Button>\n        <div className=\"my-3\">\n          <PreviewData\n            error={previewViewDataResult.error}\n            loading={previewViewDataResult.loading}\n            previewData={previewViewDataResult?.data?.previewViewData}\n          />\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/ButtonItem.tsx",
    "content": "import Image from 'next/image';\nimport { Button } from 'antd';\nimport styled from 'styled-components';\nimport Icon from '@/import/icon';\nimport { IterableComponent } from '@/utils/iteration';\nimport { ButtonOption } from './utils';\nimport { SampleDatasetName } from '@/apollo/client/graphql/__types__';\n\nconst StyledButton = styled(Button)`\n  border: 2px var(--gray-4) solid;\n  background-color: var(--gray-2);\n  border-radius: 4px;\n  width: 100%;\n  height: auto;\n\n  &:focus {\n    border: 2px var(--gray-4) solid;\n    background-color: var(--gray-2);\n  }\n\n  &:hover {\n    border-color: var(--geekblue-6);\n    background-color: var(--gray-2);\n  }\n\n  &.is-active {\n    border-color: var(--geekblue-6) !important;\n    background-color: var(--gray-2) !important;\n  }\n\n  &:disabled {\n    opacity: 0.5;\n  }\n\n  // loading of button\n  .ant-btn-loading-icon .anticon {\n    font-size: 24px;\n  }\n`;\n\nconst StyledIcon = styled(Icon)`\n  width: 40px;\n  height: 40px;\n  font-size: 32px;\n  display: inline-flex;\n  justify-content: center;\n  align-items: center;\n`;\n\nconst PlainImage = styled.div`\n  border: 1px var(--gray-4) solid;\n  background-color: white;\n  width: 40px;\n  height: 40px;\n`;\n\nconst ComingSoon = styled.div`\n  border: 1px var(--gray-7) solid;\n  color: var(--gray-7);\n  font-size: 8px;\n  padding: 2px 6px;\n  border-radius: 999px;\n  &:before {\n    content: 'COMING SOON';\n  }\n`;\n\ntype Props = ButtonOption & {\n  selectedTemplate: SampleDatasetName;\n  onSelect: (value: string) => void;\n};\n\nexport default function ButtonItem(props: IterableComponent<Props>) {\n  const {\n    value,\n    disabled,\n    submitting,\n    logo,\n    IconComponent,\n    label,\n    onSelect,\n    selectedTemplate,\n  } = props;\n\n  const isSelected = selectedTemplate === value;\n  const loading = isSelected && submitting;\n\n  return (\n    <StyledButton\n      className={[\n        'px-4 py-2 gray-8 d-flex align-center',\n        loading ? 'flex-start' : 'justify-space-between',\n        isSelected ? 'is-active' : '',\n      ].join(' ')}\n      disabled={disabled || submitting}\n      loading={loading}\n      onClick={() => onSelect(value)}\n    >\n      <div className=\"d-flex align-center\" style={{ width: '100%' }}>\n        {logo ? (\n          <Image\n            className=\"mr-2\"\n            src={logo}\n            alt={label}\n            width=\"40\"\n            height=\"40\"\n          />\n        ) : IconComponent ? (\n          <StyledIcon component={IconComponent} className=\"mr-2\" />\n        ) : (\n          <PlainImage className=\"mr-2\" />\n        )}\n        {label}\n      </div>\n      {disabled && <ComingSoon />}\n    </StyledButton>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/ConnectDataSource.tsx",
    "content": "import Image from 'next/image';\nimport Link from 'next/link';\nimport { Alert, Typography, Form, Row, Col, Button } from 'antd';\nimport styled from 'styled-components';\nimport { DATA_SOURCES } from '@/utils/enum/dataSources';\nimport { getDataSource, getPostgresErrorMessage } from './utils';\n\nconst StyledForm = styled(Form)`\n  border: 1px var(--gray-4) solid;\n  border-radius: 4px;\n`;\n\nconst DataSource = styled.div`\n  border: 1px var(--gray-4) solid;\n  border-radius: 4px;\n`;\n\ninterface Props {\n  dataSource: DATA_SOURCES;\n  onNext: (data: any) => void;\n  onBack: () => void;\n  submitting: boolean;\n  connectError?: Record<string, any>;\n}\n\nexport default function ConnectDataSource(props: Props) {\n  const { connectError, dataSource, submitting, onNext, onBack } = props;\n  const [form] = Form.useForm();\n  const current = getDataSource(dataSource);\n\n  const submit = () => {\n    form\n      .validateFields()\n      .then((values) => {\n        onNext && onNext({ properties: values });\n      })\n      .catch((error) => {\n        console.error(error);\n      });\n  };\n\n  return (\n    <>\n      <Typography.Title level={1} className=\"mb-3\">\n        Connect the data source\n      </Typography.Title>\n      <Typography.Text>\n        Vote for your favorite data sources on{' '}\n        <Link\n          href=\"https://github.com/Canner/WrenAI/discussions/327\"\n          target=\"_blank\"\n          rel=\"noopener noreferrer\"\n        >\n          GitHub\n        </Link>\n        .\n      </Typography.Text>\n\n      <StyledForm form={form} layout=\"vertical\" className=\"p-6 my-6\">\n        <Row align=\"middle\" className=\"mb-6\">\n          <Col span={12}>\n            <DataSource className=\"d-inline-block px-4 py-2 bg-gray-2 gray-8\">\n              <Image\n                className=\"mr-2\"\n                src={current.logo}\n                alt={dataSource}\n                width=\"40\"\n                height=\"40\"\n              />\n              {current.label}\n            </DataSource>\n          </Col>\n          <Col className=\"text-right\" span={12}>\n            Learn more information in the {current.label}{' '}\n            <Link\n              href={current.guide}\n              target=\"_blank\"\n              rel=\"noopener noreferrer\"\n            >\n              setup guide\n            </Link>\n            .\n          </Col>\n        </Row>\n        <current.component />\n      </StyledForm>\n\n      {connectError && (\n        <Alert\n          message={connectError.shortMessage}\n          description={\n            dataSource === DATA_SOURCES.POSTGRES\n              ? getPostgresErrorMessage(connectError)\n              : connectError.message\n          }\n          type=\"error\"\n          showIcon\n          className=\"my-6\"\n        />\n      )}\n\n      <Row gutter={16} className=\"pt-6\">\n        <Col span={12}>\n          <Button\n            onClick={onBack}\n            size=\"large\"\n            className=\"adm-onboarding-btn\"\n            disabled={submitting}\n          >\n            Back\n          </Button>\n        </Col>\n        <Col className=\"text-right\" span={12}>\n          <Button\n            type=\"primary\"\n            size=\"large\"\n            onClick={submit}\n            loading={submitting}\n            className=\"adm-onboarding-btn\"\n          >\n            Next\n          </Button>\n        </Col>\n      </Row>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/ContainerCard.tsx",
    "content": "import styled from 'styled-components';\nimport { Card, Steps } from 'antd';\n\nconst Container = styled.div<{ maxWidth?: number }>`\n  max-width: ${(props) => props.maxWidth || 1200}px;\n  margin: 68px auto;\n`;\n\ninterface Props {\n  step: number;\n  children: React.ReactNode;\n  maxWidth?: number;\n}\n\nexport default function ContainerCard(props: Props) {\n  const { step, maxWidth } = props;\n\n  return (\n    <Container maxWidth={maxWidth}>\n      <Card>\n        <Steps current={step} className=\"mb-12\">\n          <Steps.Step title=\"Connect\" />\n          <Steps.Step title=\"Select Tables\" />\n          <Steps.Step title=\"Define Relationships\" />\n        </Steps>\n        <div className=\"px-12 pb-6\">{props.children}</div>\n      </Card>\n    </Container>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/DefineRelations.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { omit } from 'lodash';\nimport {\n  Button,\n  Col,\n  Popconfirm,\n  Row,\n  Space,\n  Spin,\n  Typography,\n  Alert,\n} from 'antd';\nimport type { ColumnsType } from 'antd/es/table';\nimport DeleteOutlined from '@ant-design/icons/DeleteOutlined';\nimport EditOutlined from '@ant-design/icons/EditOutlined';\nimport PlusOutlined from '@ant-design/icons/PlusOutlined';\nimport ModelRelationSelectionTable, {\n  RelationsDataType,\n} from '@/components/table/ModelRelationSelectionTable';\nimport { getJoinTypeText } from '@/utils/data';\nimport useModalAction from '@/hooks/useModalAction';\nimport RelationModal, {\n  RelationFieldValue,\n  RelationFormValues,\n} from '@/components/modals/RelationModal';\nimport { convertFormValuesToIdentifier } from '@/hooks/useCombineFieldOptions';\n\nconst { Title, Text } = Typography;\n\n// for omit keys\nconst relationKeys = ['name', 'isAutoGenerated'];\n\nexport interface SelectedRecommendRelations {\n  [modelName: string]: RelationsDataType[];\n}\n\ninterface Props {\n  fetching: boolean;\n  recommendRelations: SelectedRecommendRelations;\n  recommendNameMapping: Record<string, string>;\n  onNext: (data: { relations: SelectedRecommendRelations }) => void;\n  onBack: () => void;\n  onSkip: () => void;\n  submitting: boolean;\n}\n\ninterface EditableRelationTableProps {\n  index: number;\n  modelName: string;\n  onSetRelation: (payload: {\n    modelName: string;\n    defaultValue?: RelationsDataType;\n  }) => void;\n  onDeleteRow: (modelName: string, selectedRelation: RelationsDataType) => void;\n  relations: RelationsDataType[];\n  recommendNameMapping: Record<string, string>;\n}\n\nfunction EditableRelationTable(props: EditableRelationTableProps) {\n  const {\n    index,\n    modelName,\n    onSetRelation,\n    onDeleteRow,\n    relations,\n    recommendNameMapping,\n  } = props;\n\n  const columns: ColumnsType<RelationsDataType> = [\n    {\n      title: 'From',\n      dataIndex: 'fromField',\n      key: 'fromField',\n      render: (fromField) => `${fromField.modelName}.${fromField.fieldName}`,\n      width: '35%',\n    },\n    {\n      title: 'To',\n      dataIndex: 'toField',\n      key: 'toField',\n      render: (toField) => `${toField.modelName}.${toField.fieldName}`,\n      width: '35%',\n    },\n    {\n      title: 'Type',\n      dataIndex: 'type',\n      key: 'type',\n      render: (type, relation) => (\n        <>\n          {getJoinTypeText(type)}\n          {relation.isAutoGenerated && (\n            <Text className=\"pl-1\" type=\"secondary\">\n              (auto-generated)\n            </Text>\n          )}\n        </>\n      ),\n      width: '30%',\n    },\n    {\n      title: '',\n      key: 'action',\n      width: 48,\n      align: 'center',\n      render: (_, record) => (\n        <Space size={[16, 0]}>\n          <EditOutlined\n            onClick={() =>\n              onSetRelation({\n                modelName,\n                defaultValue: record,\n              })\n            }\n          />\n          <Popconfirm\n            title=\"Confirm to delete?\"\n            okText=\"Delete\"\n            okButtonProps={{ danger: true }}\n            onConfirm={() => onDeleteRow(modelName, record)}\n          >\n            <DeleteOutlined />\n          </Popconfirm>\n        </Space>\n      ),\n    },\n  ];\n\n  return (\n    <div className=\"mt-6\">\n      <ModelRelationSelectionTable\n        columns={columns}\n        dataSource={relations}\n        tableTitle={recommendNameMapping[modelName]}\n        extra={(onCollapseOpen) => (\n          <Button\n            onClick={(event) => {\n              onSetRelation({ modelName });\n              onCollapseOpen(event, recommendNameMapping[modelName]);\n            }}\n            size=\"small\"\n            title=\"Add relationship\"\n          >\n            <PlusOutlined />\n            Add\n          </Button>\n        )}\n        rowKey={(record: RelationsDataType) =>\n          `${modelName}-${record.fromField.fieldName}-${record.toField.modelName}-${record.toField.fieldName}-${index}`\n        }\n      />\n    </div>\n  );\n}\n\nexport default function DefineRelations(props: Props) {\n  const {\n    fetching,\n    recommendRelations,\n    recommendNameMapping,\n    onBack,\n    onNext,\n    onSkip,\n    submitting,\n  } = props;\n\n  const [relations, setRelations] =\n    useState<SelectedRecommendRelations>(recommendRelations);\n\n  const [selectedRelation, setSelectedRelation] = useState<{\n    modelName: string;\n    defaultValue?: RelationsDataType;\n  }>(null);\n\n  const [showNoRecommendationAlert, setShowNoRecommendationAlert] =\n    useState<boolean>(false);\n\n  useEffect(() => {\n    setRelations(recommendRelations);\n\n    const recommendRelationsValues = Object.values(recommendRelations);\n    if (recommendRelationsValues.length === 0) return;\n\n    const allEmpty = recommendRelationsValues.every(\n      (value) => value.length === 0,\n    );\n    setShowNoRecommendationAlert(allEmpty);\n  }, [recommendRelations]);\n\n  const relationModal = useModalAction();\n\n  // check is the relation is auto-generated or not\n  const isRecommendRelation = (\n    modelName: string,\n    relation: RelationsDataType,\n  ) => {\n    const isOriginalRelation = (recommendRelations[modelName] || []).find(\n      (originalRelation) =>\n        JSON.stringify(omit(originalRelation, relationKeys)) ===\n        JSON.stringify(omit(relation, relationKeys)),\n    );\n\n    return isOriginalRelation?.isAutoGenerated || false;\n  };\n\n  const onAddRelation = (relationFormValues: RelationFormValues) => {\n    const relation = convertFormValuesToIdentifier(relationFormValues);\n    const modelName = relation.fromField.modelName;\n    const isAutoGenerated = isRecommendRelation(modelName, relation);\n    const newRelations = {\n      ...relations,\n      [modelName]: [\n        ...(relations[modelName] || []),\n        { ...relation, isAutoGenerated },\n      ],\n    };\n    setRelations(newRelations);\n  };\n\n  const onCloseModal = () => {\n    setSelectedRelation(null);\n    relationModal.closeModal();\n  };\n\n  const onDeleteRow = (\n    modelName: string,\n    selectedRelation: RelationsDataType,\n  ) => {\n    const newRelations = {\n      ...relations,\n      [modelName]: relations[modelName].filter(\n        (relation) =>\n          JSON.stringify(relation) !== JSON.stringify(selectedRelation),\n      ),\n    };\n    setRelations(newRelations);\n  };\n\n  const onSetRelation = (payload: {\n    modelName: string;\n    defaultValue?: RelationsDataType;\n  }) => {\n    setSelectedRelation(payload);\n    relationModal.openModal();\n  };\n\n  const onUpdateRelation = (\n    modelName: string,\n    originalRelationValue: RelationsDataType,\n    newRelationValue: RelationFormValues,\n  ) => {\n    const newRelation = convertFormValuesToIdentifier(newRelationValue);\n    const isAutoGenerated = isRecommendRelation(modelName, newRelation);\n    const newRelations = {\n      ...relations,\n      [modelName]: relations[modelName].map((relation) => {\n        if (\n          JSON.stringify(relation) === JSON.stringify(originalRelationValue)\n        ) {\n          return { ...newRelation, isAutoGenerated };\n        }\n        return relation;\n      }),\n    };\n\n    setRelations(newRelations);\n  };\n\n  const submit = () => {\n    onNext && onNext({ relations });\n  };\n\n  return (\n    <div>\n      <Title level={1} className=\"mb-3\">\n        Define relationships\n      </Title>\n      <Text>\n        You can create relationships between selected tables. We provide\n        suggested relationships based on primary and foreign keys defined in\n        your data source. The relationships are then added to data models.\n      </Text>\n      {showNoRecommendationAlert && (\n        <Alert\n          message=\"No recommended relationships\"\n          description=\"No relationships are recommended because no primary or foreign keys were detected.\"\n          type=\"info\"\n          showIcon\n          className=\"my-6\"\n        />\n      )}\n      <div className=\"my-6 text-center\">\n        {Object.entries(relations).map(\n          ([modelReferenceName, relations = []], index) => (\n            <EditableRelationTable\n              key={`${modelReferenceName}-${relations.length}`}\n              index={index}\n              modelName={modelReferenceName}\n              relations={relations}\n              onSetRelation={onSetRelation}\n              onDeleteRow={onDeleteRow}\n              recommendNameMapping={recommendNameMapping}\n            />\n          ),\n        )}\n        <Spin spinning={fetching} tip=\"Loading...\" className=\"my-15\" />\n      </div>\n      <Row gutter={16} className=\"pt-6\">\n        <Col span={12}>\n          <Button onClick={onBack} size=\"large\" className=\"adm-onboarding-btn\">\n            Back\n          </Button>\n        </Col>\n        <Col className=\"text-right\" span={12}>\n          <Button\n            className=\"mr-4 gray-7 adm-onboarding-btn\"\n            type=\"text\"\n            size=\"large\"\n            onClick={onSkip}\n            disabled={submitting}\n            data-ph-capture=\"true\"\n            data-ph-capture-attribute-name=\"cta_skip_define_relationship\"\n          >\n            Skip this step\n          </Button>\n          <Button\n            type=\"primary\"\n            size=\"large\"\n            onClick={submit}\n            className=\"adm-onboarding-btn\"\n            loading={submitting}\n            disabled={fetching}\n            data-ph-capture=\"true\"\n            data-ph-capture-attribute-name=\"cta_finish_define_relationship\"\n          >\n            Finish\n          </Button>\n        </Col>\n      </Row>\n      <RelationModal\n        {...relationModal.state}\n        model={selectedRelation?.modelName}\n        onSubmit={async (values) => {\n          if (selectedRelation?.defaultValue) {\n            onUpdateRelation(\n              selectedRelation.modelName,\n              selectedRelation.defaultValue,\n              values,\n            );\n          } else {\n            onAddRelation(values);\n          }\n          setSelectedRelation(null);\n        }}\n        onClose={onCloseModal}\n        defaultValue={\n          selectedRelation?.defaultValue\n            ? (omit(\n                selectedRelation.defaultValue,\n                relationKeys,\n              ) as RelationFieldValue)\n            : undefined\n        }\n        relations={relations}\n        isRecommendMode={Boolean(selectedRelation?.defaultValue)}\n      />\n    </div>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/SelectModels.tsx",
    "content": "import Link from 'next/link';\nimport { Button, Col, Form, Row, Typography } from 'antd';\nimport type { ColumnsType } from 'antd/es/table';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport MultiSelectBox from '@/components/table/MultiSelectBox';\nimport { CompactTable } from '@/apollo/client/graphql/__types__';\n\nconst { Title, Text } = Typography;\n\ninterface Props {\n  fetching: boolean;\n  tables: CompactTable[];\n  onNext: (data: { selectedTables: string[] }) => void;\n  onBack: () => void;\n  submitting: boolean;\n}\n\nconst columns: ColumnsType<CompactTable> = [\n  {\n    title: 'Table name',\n    dataIndex: 'name',\n  },\n];\n\nexport default function SelectModels(props: Props) {\n  const { fetching, tables, onBack, onNext, submitting } = props;\n  const [form] = Form.useForm();\n\n  const items = tables.map((item) => ({\n    ...item,\n    value: item.name,\n  }));\n\n  const submit = () => {\n    form\n      .validateFields()\n      .then((values) => {\n        onNext && onNext({ selectedTables: values.tables });\n      })\n      .catch((error) => {\n        console.error(error);\n      });\n  };\n\n  return (\n    <div>\n      <Title level={1} className=\"mb-3\">\n        Select tables to create data models\n      </Title>\n      <Text>\n        We will create data models based on selected tables to help AI better\n        understand your data.\n        <br />\n        <Link\n          href=\"https://docs.getwren.ai/oss/guide/modeling/overview\"\n          target=\"_blank\"\n          rel=\"noopener noreferrer\"\n        >\n          Learn more\n        </Link>{' '}\n        about data models.\n      </Text>\n      <div className=\"my-6\">\n        <Form form={form} layout=\"vertical\" style={{ marginTop: 8 }}>\n          <Form.Item\n            name=\"tables\"\n            rules={[\n              {\n                required: true,\n                message: ERROR_TEXTS.SETUP_MODEL.TABLE.REQUIRED,\n              },\n            ]}\n          >\n            <MultiSelectBox\n              columns={columns}\n              items={items}\n              loading={fetching}\n            />\n          </Form.Item>\n        </Form>\n      </div>\n      <Row gutter={16} className=\"pt-6\">\n        <Col span={12}>\n          <Button\n            onClick={onBack}\n            size=\"large\"\n            className=\"adm-onboarding-btn\"\n            disabled={submitting}\n          >\n            Back\n          </Button>\n        </Col>\n        <Col className=\"text-right\" span={12}>\n          <Button\n            type=\"primary\"\n            size=\"large\"\n            onClick={submit}\n            className=\"adm-onboarding-btn\"\n            loading={submitting}\n          >\n            Next\n          </Button>\n        </Col>\n      </Row>\n    </div>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/Starter.tsx",
    "content": "import Link from 'next/link';\nimport { ComponentProps, useState } from 'react';\nimport { Typography, Row, Col } from 'antd';\nimport { getDataSources, getTemplates } from './utils';\nimport { makeIterable } from '@/utils/iteration';\nimport ButtonItem from './ButtonItem';\nimport {\n  DataSourceName,\n  SampleDatasetName,\n} from '@/apollo/client/graphql/__types__';\n\nconst ButtonTemplate = (props: ComponentProps<typeof ButtonItem>) => {\n  return (\n    <Col span={6} key={props.label}>\n      <ButtonItem {...props} />\n    </Col>\n  );\n};\n\nconst DataSourceIterator = makeIterable(ButtonTemplate);\nconst TemplatesIterator = makeIterable(ButtonTemplate);\n\nexport default function Starter(props) {\n  const { onNext, submitting } = props;\n\n  const [template, setTemplate] = useState<SampleDatasetName>();\n\n  const dataSources = getDataSources();\n  const templates = getTemplates();\n\n  const onSelectDataSource = (value: DataSourceName) => {\n    onNext && onNext({ dataSource: value });\n  };\n\n  const onSelectTemplate = (value: string) => {\n    setTemplate(value as SampleDatasetName);\n    onNext && onNext({ template: value });\n  };\n\n  return (\n    <>\n      <Typography.Title level={1} className=\"mb-3\">\n        Connect a data source\n      </Typography.Title>\n      <Typography.Text>\n        Vote for your favorite data sources on{' '}\n        <Link\n          href=\"https://github.com/Canner/WrenAI/discussions/327\"\n          target=\"_blank\"\n          rel=\"noopener noreferrer\"\n        >\n          GitHub\n        </Link>\n        .\n      </Typography.Text>\n      <Row className=\"mt-6\" gutter={[16, 16]}>\n        <DataSourceIterator\n          data={dataSources}\n          onSelect={onSelectDataSource}\n          submitting={submitting}\n        />\n      </Row>\n\n      <div className=\"py-8\" />\n\n      <Typography.Title level={1} className=\"mb-3\">\n        Play around with sample data\n      </Typography.Title>\n      <Row className=\"mt-6\" gutter={[16, 16]}>\n        <TemplatesIterator\n          data={templates}\n          onSelect={onSelectTemplate}\n          submitting={submitting}\n          selectedTemplate={template}\n        />\n      </Row>\n\n      <div className=\"py-12\" />\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/dataSources/AthenaProperties.tsx",
    "content": "import { useEffect, useRef } from 'react';\nimport { Form, Input, Radio } from 'antd';\nimport { FORM_MODE, ATHENA_AUTH_METHOD } from '@/utils/enum';\nimport { ERROR_TEXTS } from '@/utils/error';\n\ninterface Props {\n  mode?: FORM_MODE;\n}\n\nfunction AthenaClassicFields() {\n  return (\n    <>\n      <Form.Item\n        label=\"AWS access key ID\"\n        name=\"awsAccessKey\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.AWS_ACCESS_KEY.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n\n      <Form.Item\n        label=\"AWS secret access key\"\n        name=\"awsSecretKey\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.AWS_SECRET_KEY.REQUIRED,\n          },\n        ]}\n      >\n        <Input.Password />\n      </Form.Item>\n    </>\n  );\n}\n\nfunction AthenaOIDCFields(props: { isEditMode: boolean }) {\n  const { isEditMode } = props;\n\n  return (\n    <>\n      <Form.Item\n        label=\"Web identity token\"\n        name=\"webIdentityToken\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.WEB_IDENTITY_TOKEN.REQUIRED,\n          },\n        ]}\n      >\n        <Input.Password\n          placeholder=\"OAuth 2.0 access token or OpenID Connect ID token\"\n          autoComplete=\"off\"\n        />\n      </Form.Item>\n\n      <Form.Item\n        label=\"AWS role ARN\"\n        name=\"roleArn\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.AWS_ROLE_ARN.REQUIRED,\n          },\n        ]}\n      >\n        <Input\n          placeholder=\"arn:aws:iam::<account-id>:role/<role-name>\"\n          disabled={isEditMode}\n        />\n      </Form.Item>\n\n      <Form.Item\n        label=\"Role session name\"\n        name=\"roleSessionName\"\n        extra=\"Optional session name used in AWS STS assume role operation.\"\n      >\n        <Input placeholder=\"session name\" />\n      </Form.Item>\n    </>\n  );\n}\n\nexport default function AthenaProperties(props: Props) {\n  const { mode } = props;\n  const isEditMode = mode === FORM_MODE.EDIT;\n\n  const form = Form.useFormInstance();\n\n  const initialTypeRef = useRef<ATHENA_AUTH_METHOD | null>(null);\n\n  const authType = Form.useWatch('athenaAuthType', form) as ATHENA_AUTH_METHOD;\n\n  // Set default auth type when creating\n  useEffect(() => {\n    if (!isEditMode) {\n      form.setFieldsValue({\n        athenaAuthType: ATHENA_AUTH_METHOD.classic,\n      });\n    }\n  }, [isEditMode, form]);\n\n  // Preserve initial type on edit mode\n  useEffect(() => {\n    if (isEditMode && authType && initialTypeRef.current === null) {\n      initialTypeRef.current = authType;\n    }\n  }, [isEditMode, authType]);\n\n  const getIsEditModeForComponent = (component: ATHENA_AUTH_METHOD) => {\n    if (!isEditMode) return false;\n    const initial = initialTypeRef.current || authType;\n    return initial === component;\n  };\n\n  return (\n    <>\n      <Form.Item\n        label=\"Display name\"\n        name=\"displayName\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DISPLAY_NAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n\n      {/* Common fields */}\n      <Form.Item\n        label=\"Database (schema)\"\n        name=\"schema\"\n        extra=\"The Athena database (schema) that contains your tables.\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DATABASE.REQUIRED,\n          },\n        ]}\n      >\n        <Input disabled={isEditMode} />\n      </Form.Item>\n\n      <Form.Item\n        label=\"S3 staging directory\"\n        name=\"s3StagingDir\"\n        required\n        extra={\n          <>\n            The S3 path where Athena stores query results and metadata.\n            <br />\n            Find this in Athena console under{' '}\n            <b>Settings → Query result location</b>.\n          </>\n        }\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.S3_STAGING_DIR.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"s3://bucket/path\" />\n      </Form.Item>\n\n      <Form.Item\n        label=\"AWS region\"\n        name=\"awsRegion\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.AWS_REGION.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"us-east-1\" disabled={isEditMode} />\n      </Form.Item>\n\n      {/* Authentication method switch */}\n      <Form.Item label=\"Authentication method\" name=\"athenaAuthType\">\n        <Radio.Group buttonStyle=\"solid\">\n          <Radio.Button value={ATHENA_AUTH_METHOD.classic}>\n            AWS credentials\n          </Radio.Button>\n          <Radio.Button value={ATHENA_AUTH_METHOD.oidc}>\n            OIDC (web identity token)\n          </Radio.Button>\n          <Radio.Button value={ATHENA_AUTH_METHOD.instance_profile}>\n            Instance Profile\n          </Radio.Button>\n        </Radio.Group>\n      </Form.Item>\n\n      {/* Conditional auth fields */}\n      {authType === ATHENA_AUTH_METHOD.classic && <AthenaClassicFields />}\n\n      {authType === ATHENA_AUTH_METHOD.oidc && (\n        <AthenaOIDCFields\n          isEditMode={getIsEditModeForComponent(ATHENA_AUTH_METHOD.oidc)}\n        />\n      )}\n\n      {authType === ATHENA_AUTH_METHOD.instance_profile && (\n        <div className=\"gray-8\" style={{ fontStyle: 'italic' }}>\n          We will automatically detect AWS credentials from the Instance Profile\n          role assigned to this compute environment (EC2, ECS, EKS).\n        </div>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/dataSources/BigQueryProperties.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { Form, Input, Button, Upload, UploadProps, message } from 'antd';\nimport UploadOutlined from '@ant-design/icons/UploadOutlined';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { FORM_MODE } from '@/utils/enum';\nimport { readFileContent } from '@/utils/file';\n\ninterface Props {\n  mode?: FORM_MODE;\n}\n\nconst UploadCredentials = (props: {\n  onChange?: (value: string) => void;\n  value?: string;\n}) => {\n  const { onChange, value } = props;\n\n  const [fileList, setFileList] = useState<UploadProps['fileList']>([]);\n\n  useEffect(() => {\n    if (!value) setFileList([]);\n  }, [value]);\n\n  const onUploadChange = async (info) => {\n    const { file, fileList } = info;\n    if (fileList.length) {\n      const uploadFile = fileList[0];\n\n      try {\n        const result = await readFileContent(file.originFileObj);\n        const parsedJson = JSON.parse(result);\n        onChange && onChange(parsedJson);\n        setFileList([uploadFile]);\n      } catch (error) {\n        console.error('Failed to handle file', error);\n        message.error(\n          'Failed to handle file. Please upload a valid credentials file.',\n        );\n      }\n    }\n  };\n\n  const onRemove = () => {\n    setFileList([]);\n    onChange && onChange(undefined);\n  };\n\n  return (\n    <Upload\n      accept=\".json\"\n      fileList={fileList}\n      onChange={onUploadChange}\n      onRemove={onRemove}\n      maxCount={1}\n    >\n      <Button icon={<UploadOutlined />}>Click to upload JSON key file</Button>\n    </Upload>\n  );\n};\n\nexport default function BigQueryProperties(props: Props) {\n  const { mode } = props;\n  const isEditMode = mode === FORM_MODE.EDIT;\n\n  return (\n    <>\n      <Form.Item\n        label=\"Display name\"\n        required\n        name=\"displayName\"\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DISPLAY_NAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"Our BigQuery\" />\n      </Form.Item>\n      <Form.Item\n        label=\"Project ID\"\n        required\n        name=\"projectId\"\n        rules={[\n          {\n            required: !isEditMode,\n            message: ERROR_TEXTS.CONNECTION.PROJECT_ID.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"The GCP project ID\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"Dataset ID\"\n        required\n        name=\"datasetId\"\n        rules={[\n          {\n            required: !isEditMode,\n            message: ERROR_TEXTS.CONNECTION.DATASET_ID.REQUIRED,\n          },\n        ]}\n      >\n        <Input disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"Credentials\"\n        required={!isEditMode}\n        name=\"credentials\"\n        rules={[\n          {\n            required: !isEditMode,\n            message: ERROR_TEXTS.CONNECTION.CREDENTIAL.REQUIRED,\n          },\n        ]}\n      >\n        <UploadCredentials />\n      </Form.Item>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/dataSources/ClickHouseProperties.tsx",
    "content": "import { Form, Input, Switch } from 'antd';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { FORM_MODE } from '@/utils/enum';\nimport { hostValidator } from '@/utils/validator';\n\ninterface Props {\n  mode?: FORM_MODE;\n}\n\nexport default function ClickHouseProperties(props: Props) {\n  const { mode } = props;\n  const isEditMode = mode === FORM_MODE.EDIT;\n  return (\n    <>\n      <Form.Item\n        label=\"Display name\"\n        name=\"displayName\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DISPLAY_NAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label=\"Host\"\n        name=\"host\"\n        required\n        rules={[\n          {\n            required: true,\n            validator: hostValidator,\n          },\n        ]}\n      >\n        <Input\n          placeholder=\"<your_click_house_account>.clickhouse.cloud\"\n          disabled={isEditMode}\n        />\n      </Form.Item>\n      <Form.Item\n        label=\"Port\"\n        name=\"port\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.PORT.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"8443\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"Username\"\n        name=\"user\"\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.USERNAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label=\"Password\"\n        name=\"password\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.PASSWORD.REQUIRED,\n          },\n        ]}\n      >\n        <Input.Password placeholder=\"input password\" />\n      </Form.Item>\n      <Form.Item\n        label=\"Database name\"\n        name=\"database\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DATABASE.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"ClickHouse database name\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item label=\"Use SSL\" name=\"ssl\" valuePropName=\"checked\">\n        <Switch />\n      </Form.Item>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/dataSources/DatabricksProperties.tsx",
    "content": "import { useEffect } from 'react';\nimport { Form, Input, Radio } from 'antd';\nimport { FORM_MODE, DATABRICKS_AUTH_METHOD } from '@/utils/enum';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { hostValidator } from '@/utils/validator';\n\ninterface Props {\n  mode?: FORM_MODE;\n}\n\nexport default function DatabricksProperties(props: Props) {\n  const { mode } = props;\n  const isEditMode = mode === FORM_MODE.EDIT;\n\n  const form = Form.useFormInstance();\n  const databricksType = Form.useWatch(\n    'databricksType',\n    form,\n  ) as DATABRICKS_AUTH_METHOD;\n\n  useEffect(() => {\n    if (!isEditMode) {\n      form.setFieldsValue({\n        databricksType: DATABRICKS_AUTH_METHOD.token,\n      });\n    }\n  }, [isEditMode, form]);\n\n  return (\n    <>\n      <Form.Item\n        label=\"Display name\"\n        name=\"displayName\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DISPLAY_NAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item label=\"Authentication method\" name=\"databricksType\">\n        <Radio.Group buttonStyle=\"solid\">\n          <Radio.Button value={DATABRICKS_AUTH_METHOD.token}>\n            Personal Access Token (PAT)\n          </Radio.Button>\n          <Radio.Button value={DATABRICKS_AUTH_METHOD.service_principal}>\n            Service Principal\n          </Radio.Button>\n        </Radio.Group>\n      </Form.Item>\n      <Form.Item\n        label=\"Server hostname\"\n        name=\"serverHostname\"\n        required\n        rules={[\n          {\n            required: true,\n            validator: hostValidator,\n          },\n        ]}\n      >\n        <Input\n          placeholder=\"e.g. adb-123456789.12.azuredatabricks.net\"\n          disabled={isEditMode}\n        />\n      </Form.Item>\n      <Form.Item\n        label=\"HTTP path\"\n        name=\"httpPath\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.HTTP_PATH.REQUIRED,\n          },\n        ]}\n      >\n        <Input\n          placeholder=\"e.g. /sql/1.0/endpoints/abc123\"\n          disabled={isEditMode}\n        />\n      </Form.Item>\n      {databricksType === DATABRICKS_AUTH_METHOD.token && (\n        <Form.Item\n          label=\"Access token\"\n          name=\"accessToken\"\n          required\n          rules={[\n            {\n              required: true,\n              message: ERROR_TEXTS.CONNECTION.PERSONAL_ACCESS_TOKEN.REQUIRED,\n            },\n          ]}\n        >\n          <Input.Password placeholder=\"Enter your Databricks personal access token\" />\n        </Form.Item>\n      )}\n      {databricksType === DATABRICKS_AUTH_METHOD.service_principal && (\n        <>\n          <Form.Item\n            label=\"Client ID\"\n            name=\"clientId\"\n            required\n            rules={[\n              {\n                required: true,\n                message: ERROR_TEXTS.CONNECTION.CLIENT_ID.REQUIRED,\n              },\n            ]}\n          >\n            <Input placeholder=\"Enter your service principal’s Client ID\" />\n          </Form.Item>\n          <Form.Item\n            label=\"Client secret\"\n            name=\"clientSecret\"\n            required\n            rules={[\n              {\n                required: true,\n                message: ERROR_TEXTS.CONNECTION.CLIENT_SECRET.REQUIRED,\n              },\n            ]}\n          >\n            <Input.Password placeholder=\"Enter your service principal’s Client Secret\" />\n          </Form.Item>\n          <Form.Item label=\"Azure tenant ID\" name=\"azureTenantId\">\n            <Input placeholder=\"e.g. 72f988bf-86f1-41af-91ab-2d7cd011db47\" />\n          </Form.Item>\n        </>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/dataSources/DuckDBProperties.tsx",
    "content": "import Link from 'next/link';\nimport { Col, Form, Input, Button, Row } from 'antd';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport DeleteOutlined from '@ant-design/icons/DeleteOutlined';\nimport PlusOutlined from '@ant-design/icons/PlusOutlined';\n\nconst { TextArea } = Input;\n\nexport default function DuckDBProperties() {\n  return (\n    <>\n      <Form.Item\n        label=\"Display name\"\n        name=\"displayName\"\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DISPLAY_NAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"DuckDB\" />\n      </Form.Item>\n      <Form.Item\n        label=\"Initial SQL statements\"\n        name=\"initSql\"\n        extra=\"These statements are meant to be executed only once during initialization.\"\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.INIT_SQL.REQUIRED,\n          },\n        ]}\n      >\n        <TextArea\n          placeholder=\"CREATE TABLE new_tbl AS SELECT * FROM read_csv('input.csv');\"\n          rows={4}\n        />\n      </Form.Item>\n\n      <Form.Item\n        label=\"Configuration options\"\n        extra={\n          <>\n            DuckDB offers various configuration options that can modify the\n            system's behavior.{' '}\n            <Link\n              href=\"https://duckdb.org/docs/configuration/overview.html\"\n              target=\"_blank\"\n              rel=\"noopener noreferrer\"\n            >\n              Learn more\n            </Link>\n          </>\n        }\n      >\n        <Form.List name=\"configurations\" initialValue={[{}]}>\n          {(fields, { add, remove }) => (\n            <>\n              {fields.map(({ key, name, ...restField }) => (\n                <Row key={key} wrap={false} gutter={8}>\n                  <Col flex=\"1 0\">\n                    <Form.Item\n                      {...restField}\n                      name={[name, 'key']}\n                      style={{ width: '100%' }}\n                      rules={[\n                        ({ getFieldValue }) => ({\n                          validator(_, value) {\n                            if (\n                              getFieldValue(['configurations', name, 'value'])\n                            ) {\n                              if (!value) {\n                                return Promise.reject(\n                                  ERROR_TEXTS.CONNECTION.CONFIGURATION.KEY\n                                    .REQUIRED,\n                                );\n                              }\n                            }\n\n                            return Promise.resolve();\n                          },\n                        }),\n                      ]}\n                    >\n                      <Input placeholder=\"Key\" />\n                    </Form.Item>\n                  </Col>\n                  <Col flex=\"1 0\">\n                    <Form.Item\n                      {...restField}\n                      name={[name, 'value']}\n                      style={{ width: '100%' }}\n                      rules={[\n                        ({ getFieldValue }) => ({\n                          validator(_, value) {\n                            if (\n                              getFieldValue(['configurations', name, 'key'])\n                            ) {\n                              if (!value) {\n                                return Promise.reject(\n                                  ERROR_TEXTS.CONNECTION.CONFIGURATION.VALUE\n                                    .REQUIRED,\n                                );\n                              }\n                            }\n\n                            return Promise.resolve();\n                          },\n                        }),\n                      ]}\n                    >\n                      <Input placeholder=\"Value\" />\n                    </Form.Item>\n                  </Col>\n                  <Col flex=\"none\" className=\"p-1\">\n                    <DeleteOutlined onClick={() => remove(name)} />\n                  </Col>\n                </Row>\n              ))}\n              <Form.Item noStyle>\n                <Button\n                  type=\"dashed\"\n                  onClick={() => add()}\n                  block\n                  icon={<PlusOutlined />}\n                >\n                  Add an option\n                </Button>\n              </Form.Item>\n            </>\n          )}\n        </Form.List>\n      </Form.Item>\n      <Form.Item\n        label=\"Extensions\"\n        extra={\n          <>\n            DuckDB has an extension mechanism that enables the dynamic loading\n            of extensions.{' '}\n            <Link\n              href=\"https://duckdb.org/docs/extensions/overview.html\"\n              target=\"_blank\"\n              rel=\"noopener noreferrer\"\n            >\n              Learn more\n            </Link>\n          </>\n        }\n      >\n        <Form.List name=\"extensions\" initialValue={['']}>\n          {(fields, { add, remove }) => (\n            <>\n              {fields.map(({ key, name, ...restField }) => (\n                <Row key={key} wrap={false} gutter={8} className=\"my-2\">\n                  <Col flex=\"1 0\">\n                    <Form.Item\n                      {...restField}\n                      name={name}\n                      noStyle\n                      style={{ width: '100%' }}\n                    >\n                      <Input placeholder=\"Extension name\" />\n                    </Form.Item>\n                  </Col>\n                  <Col flex=\"none\" className=\"p-1\">\n                    <DeleteOutlined onClick={() => remove(name)} />\n                  </Col>\n                </Row>\n              ))}\n              <Form.Item noStyle>\n                <Button\n                  type=\"dashed\"\n                  onClick={() => add()}\n                  block\n                  icon={<PlusOutlined />}\n                >\n                  Add an extension\n                </Button>\n              </Form.Item>\n            </>\n          )}\n        </Form.List>\n      </Form.Item>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/dataSources/MySQLProperties.tsx",
    "content": "import { Form, Input, Switch } from 'antd';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { FORM_MODE } from '@/utils/enum';\nimport { hostValidator } from '@/utils/validator';\n\ninterface Props {\n  mode?: FORM_MODE;\n}\n\nexport default function MySQLProperties(props: Props) {\n  const { mode } = props;\n  const isEditMode = mode === FORM_MODE.EDIT;\n  return (\n    <>\n      <Form.Item\n        label=\"Display name\"\n        name=\"displayName\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DISPLAY_NAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label=\"Host\"\n        name=\"host\"\n        required\n        rules={[\n          {\n            required: true,\n            validator: hostValidator,\n          },\n        ]}\n      >\n        <Input placeholder=\"10.1.1.1\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"Port\"\n        name=\"port\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.PORT.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"3306\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"Username\"\n        name=\"user\"\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.USERNAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item label=\"Password\" name=\"password\">\n        <Input.Password placeholder=\"input password\" />\n      </Form.Item>\n      <Form.Item\n        label=\"Database name\"\n        name=\"database\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DATABASE.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"MySQL database name\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item label=\"Use SSL\" name=\"ssl\" valuePropName=\"checked\">\n        <Switch />\n      </Form.Item>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/dataSources/OracleProperties.tsx",
    "content": "import { Form, Input } from 'antd';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { FORM_MODE } from '@/utils/enum';\nimport { hostValidator } from '@/utils/validator';\n\ninterface Props {\n  mode?: FORM_MODE;\n}\n\nexport default function OracleProperties(props: Props) {\n  const { mode } = props;\n  const isEditMode = mode === FORM_MODE.EDIT;\n  return (\n    <>\n      <Form.Item\n        label=\"Display name\"\n        name=\"displayName\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DISPLAY_NAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label=\"Host\"\n        name=\"host\"\n        rules={[\n          {\n            required: false,\n            validator: (_, value) => {\n              if (value) {\n                return hostValidator(_, value);\n              }\n              return Promise.resolve();\n            },\n          },\n        ]}\n      >\n        <Input placeholder=\"10.1.1.1\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"Port\"\n        name=\"port\"\n        rules={[\n          {\n            message: ERROR_TEXTS.CONNECTION.PORT.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"1521\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"Username\"\n        name=\"user\"\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.USERNAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label=\"Password\"\n        name=\"password\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.PASSWORD.REQUIRED,\n          },\n        ]}\n      >\n        <Input.Password placeholder=\"input password\" />\n      </Form.Item>\n      <Form.Item\n        label=\"Database name\"\n        name=\"database\"\n        rules={[\n          {\n            message: ERROR_TEXTS.CONNECTION.DATABASE.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"Oracle database name\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"DSN\"\n        name=\"dsn\"\n        tooltip=\"Oracle Data Source Name (DSN) - Alternative to host/port/database configuration\"\n      >\n        <Input placeholder=\"(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=host)(PORT=port))(CONNECT_DATA=(SERVICE_NAME=service)))\" />\n      </Form.Item>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/dataSources/PostgreSQLProperties.tsx",
    "content": "import { Form, Input, Switch } from 'antd';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { FORM_MODE } from '@/utils/enum';\nimport { hostValidator } from '@/utils/validator';\n\ninterface Props {\n  mode?: FORM_MODE;\n}\n\nexport default function PostgreSQLProperties(props: Props) {\n  const { mode } = props;\n  const isEditMode = mode === FORM_MODE.EDIT;\n  return (\n    <>\n      <Form.Item\n        label=\"Display name\"\n        name=\"displayName\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DISPLAY_NAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label=\"Host\"\n        name=\"host\"\n        required\n        rules={[\n          {\n            required: true,\n            validator: hostValidator,\n          },\n        ]}\n      >\n        <Input placeholder=\"10.1.1.1\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"Port\"\n        name=\"port\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.PORT.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"5432\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"Username\"\n        name=\"user\"\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.USERNAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label=\"Password\"\n        name=\"password\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.PASSWORD.REQUIRED,\n          },\n        ]}\n      >\n        <Input.Password placeholder=\"input password\" />\n      </Form.Item>\n      <Form.Item\n        label=\"Database name\"\n        name=\"database\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DATABASE.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"PostgreSQL database name\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item label=\"Use SSL\" name=\"ssl\" valuePropName=\"checked\">\n        <Switch />\n      </Form.Item>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/dataSources/RedshiftProperties.tsx",
    "content": "import { useEffect, useRef } from 'react';\nimport { Form, Input, Radio } from 'antd';\nimport { FORM_MODE, REDSHIFT_AUTH_METHOD } from '@/utils/enum';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { hostValidator } from '@/utils/validator';\n\ninterface Props {\n  mode?: FORM_MODE;\n}\n\nfunction RedshiftPasswordFields(props: { isEditMode: boolean }) {\n  const { isEditMode } = props;\n  return (\n    <>\n      <Form.Item\n        label=\"Host\"\n        name=\"host\"\n        required\n        rules={[\n          {\n            required: true,\n            validator: hostValidator,\n          },\n        ]}\n      >\n        <Input\n          placeholder=\"mycluster.cmeaswqeuae.us-east-2.redshift.amazonaws.com\"\n          disabled={isEditMode}\n        />\n      </Form.Item>\n      <Form.Item\n        label=\"Port\"\n        name=\"port\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.PORT.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"5439\" />\n      </Form.Item>\n      <Form.Item\n        label=\"Username\"\n        name=\"user\"\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.USERNAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label=\"Password\"\n        name=\"password\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.PASSWORD.REQUIRED,\n          },\n        ]}\n      >\n        <Input.Password placeholder=\"input password\" />\n      </Form.Item>\n      <Form.Item\n        label=\"Database\"\n        name=\"database\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DATABASE.REQUIRED,\n          },\n        ]}\n      >\n        <Input disabled={isEditMode} />\n      </Form.Item>\n    </>\n  );\n}\n\nfunction RedshiftIAMFields(props: { isEditMode: boolean }) {\n  const { isEditMode } = props;\n  return (\n    <>\n      <Form.Item\n        label=\"Cluster identifier\"\n        name=\"clusterIdentifier\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.CLUSTER_IDENTIFIER.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"redshift-cluster-1\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"Username\"\n        name=\"user\"\n        extra=\"The Redshift database username specified in DB user permissions.\"\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.USERNAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label=\"Database\"\n        name=\"database\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DATABASE.REQUIRED,\n          },\n        ]}\n      >\n        <Input disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"AWS region\"\n        name=\"awsRegion\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.AWS_REGION.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"us-east-1\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"AWS access key ID\"\n        name=\"awsAccessKey\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.AWS_ACCESS_KEY.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label=\"AWS secret access key\"\n        name=\"awsSecretKey\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.AWS_SECRET_KEY.REQUIRED,\n          },\n        ]}\n      >\n        <Input.Password />\n      </Form.Item>\n    </>\n  );\n}\n\nexport default function RedshiftProperties(props: Props) {\n  const { mode } = props;\n  const isEditMode = mode === FORM_MODE.EDIT;\n\n  const initialRedshiftTypeRef = useRef<REDSHIFT_AUTH_METHOD | null>(null);\n\n  const form = Form.useFormInstance();\n  const redshiftType = Form.useWatch(\n    'redshiftType',\n    form,\n  ) as REDSHIFT_AUTH_METHOD;\n\n  useEffect(() => {\n    if (!isEditMode) {\n      form.setFieldsValue({\n        redshiftType: REDSHIFT_AUTH_METHOD.redshift,\n      });\n    }\n  }, [isEditMode, form]);\n\n  useEffect(() => {\n    if (isEditMode && redshiftType && initialRedshiftTypeRef.current === null) {\n      initialRedshiftTypeRef.current = redshiftType;\n    }\n  }, [isEditMode, redshiftType]);\n\n  const getIsEditModeForComponent = (componentType: REDSHIFT_AUTH_METHOD) => {\n    if (!isEditMode) return false;\n\n    const initialType = initialRedshiftTypeRef.current || redshiftType;\n    return initialType === componentType;\n  };\n\n  return (\n    <>\n      <Form.Item\n        label=\"Display name\"\n        name=\"displayName\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DISPLAY_NAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item label=\"Authentication method\" name=\"redshiftType\">\n        <Radio.Group buttonStyle=\"solid\">\n          <Radio.Button value={REDSHIFT_AUTH_METHOD.redshift}>\n            Username and password\n          </Radio.Button>\n          <Radio.Button value={REDSHIFT_AUTH_METHOD.redshift_iam}>\n            AWS credentials\n          </Radio.Button>\n        </Radio.Group>\n      </Form.Item>\n      {redshiftType === REDSHIFT_AUTH_METHOD.redshift && (\n        <RedshiftPasswordFields\n          isEditMode={getIsEditModeForComponent(REDSHIFT_AUTH_METHOD.redshift)}\n        />\n      )}\n      {redshiftType === REDSHIFT_AUTH_METHOD.redshift_iam && (\n        <RedshiftIAMFields\n          isEditMode={getIsEditModeForComponent(\n            REDSHIFT_AUTH_METHOD.redshift_iam,\n          )}\n        />\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/dataSources/SQLServerProperties.tsx",
    "content": "import { Form, Input, Switch } from 'antd';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { FORM_MODE } from '@/utils/enum';\nimport { hostValidator } from '@/utils/validator';\n\ninterface Props {\n  mode?: FORM_MODE;\n}\n\nexport default function SQLServerProperties(props: Props) {\n  const { mode } = props;\n  const isEditMode = mode === FORM_MODE.EDIT;\n  return (\n    <>\n      <Form.Item\n        label=\"Display name\"\n        name=\"displayName\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DISPLAY_NAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label=\"Host\"\n        name=\"host\"\n        required\n        rules={[\n          {\n            required: true,\n            validator: hostValidator,\n          },\n        ]}\n      >\n        <Input placeholder=\"10.1.1.1\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"Port\"\n        name=\"port\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.PORT.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"1433\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"Username\"\n        name=\"user\"\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.USERNAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label=\"Password\"\n        name=\"password\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.PASSWORD.REQUIRED,\n          },\n        ]}\n      >\n        <Input.Password placeholder=\"input password\" />\n      </Form.Item>\n      <Form.Item\n        label=\"Database name\"\n        name=\"database\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DATABASE.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"SQL Server database name\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        extra=\"This parameter is used to skip server certificate validation. If you are using a trusted certificate, you can disable it.\"\n        label=\"Enable Trust Server Certificate\"\n        name=\"trustServerCertificate\"\n        valuePropName=\"checked\"\n        initialValue={true}\n      >\n        <Switch />\n      </Form.Item>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/dataSources/SnowflakeProperties.tsx",
    "content": "import Link from 'next/link';\nimport { useEffect, useState } from 'react';\nimport { Button, Form, Input, Radio, Upload, UploadProps, message } from 'antd';\nimport UploadOutlined from '@ant-design/icons/UploadOutlined';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { FORM_MODE } from '@/utils/enum';\nimport { readFileContent, extractPrivateKeyString } from '@/utils/file';\n\nconst TAB_KEY = {\n  PASSWORD_AUTHENTICATION: 'password_authentication',\n  KEY_PAIR_AUTHENTICATION: 'key_pair_authentication',\n};\n\ninterface Props {\n  mode?: FORM_MODE;\n}\n\nconst UploadPrivateKey = (props: {\n  onChange?: (value: string) => void;\n  value?: string;\n}) => {\n  const { onChange, value } = props;\n  const [fileList, setFileList] = useState<UploadProps['fileList']>([]);\n\n  useEffect(() => {\n    if (!value) setFileList([]);\n  }, [value]);\n\n  const onUploadChange = async (info) => {\n    const { file, fileList } = info;\n    if (fileList.length) {\n      const uploadFile = fileList[0];\n\n      try {\n        const result = await readFileContent(file.originFileObj);\n        const extractedPrivateKey = extractPrivateKeyString(result);\n        onChange && onChange(extractedPrivateKey);\n        setFileList([uploadFile]);\n      } catch (error) {\n        console.error('Failed to handle file', error);\n        message.error(\n          'Failed to handle file. Please upload a valid private key file.',\n        );\n      }\n    }\n  };\n\n  const onRemove = () => {\n    setFileList([]);\n    onChange && onChange(undefined);\n  };\n\n  return (\n    <Upload\n      accept=\".pem,.key,.p8\"\n      fileList={fileList}\n      onChange={onUploadChange}\n      onRemove={onRemove}\n      maxCount={1}\n    >\n      <Button icon={<UploadOutlined />}>Upload private key</Button>\n    </Upload>\n  );\n};\n\nexport default function SnowflakeProperties(props: Props) {\n  const { mode } = props;\n  const isEditMode = mode === FORM_MODE.EDIT;\n  const [tabKey, setTabKey] = useState(TAB_KEY.PASSWORD_AUTHENTICATION);\n\n  const changeTabKey = (e) => {\n    setTabKey(e.target.value);\n  };\n\n  return (\n    <>\n      <Form.Item\n        label=\"Display name\"\n        name=\"displayName\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DISPLAY_NAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label=\"Account\"\n        name=\"account\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.ACCOUNT.REQUIRED,\n          },\n        ]}\n      >\n        <Input\n          placeholder=\"<snowflake_org_id>-<snowflake_user_id>\"\n          disabled={isEditMode}\n        />\n      </Form.Item>\n      <Form.Item\n        label=\"Database name\"\n        name=\"database\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DATABASE.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"Snowflake database name\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"Schema\"\n        name=\"schema\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.SCHEMA.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label=\"Warehouse\"\n        name=\"warehouse\"\n        extra={\n          <span className=\"gray-6\">\n            Specifies the virtual warehouse for query execution. If blank, the\n            account's default warehouse is used (if configured).\n          </span>\n        }\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label=\"User\"\n        name=\"user\"\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.USER.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label={\n          <div>\n            Authentication method\n            <div className=\"gray-6\">\n              Username and password authentication will be{' '}\n              <span className=\"gray-7\">deprecated by November 2025</span>. We\n              recommend switching to key pair authentication.{' '}\n              <Link\n                className=\"gray-7 underline\"\n                href=\"https://www.snowflake.com/en/blog/blocking-single-factor-password-authentification\"\n                target=\"_blank\"\n                rel=\"noreferrer noopener\"\n              >\n                Learn more\n              </Link>\n            </div>\n          </div>\n        }\n      >\n        <Radio.Group value={tabKey} onChange={changeTabKey} buttonStyle=\"solid\">\n          <Radio.Button value={TAB_KEY.PASSWORD_AUTHENTICATION}>\n            Password authentication\n          </Radio.Button>\n          <Radio.Button value={TAB_KEY.KEY_PAIR_AUTHENTICATION}>\n            Key pair authentication\n          </Radio.Button>\n        </Radio.Group>\n      </Form.Item>\n\n      <div>\n        {tabKey === TAB_KEY.PASSWORD_AUTHENTICATION && (\n          <Form.Item\n            label=\"Password\"\n            name=\"password\"\n            required\n            rules={[\n              {\n                required: true,\n                message: ERROR_TEXTS.CONNECTION.PASSWORD.REQUIRED,\n              },\n            ]}\n          >\n            <Input.Password placeholder=\"input password\" />\n          </Form.Item>\n        )}\n        {tabKey === TAB_KEY.KEY_PAIR_AUTHENTICATION && (\n          <Form.Item\n            label=\"Private key file\"\n            name=\"privateKey\"\n            required\n            rules={[\n              {\n                required: !isEditMode,\n                message: ERROR_TEXTS.CONNECTION.PRIVATE_KEY_FILE.REQUIRED,\n              },\n            ]}\n            extra={\n              <div className=\"gray-6\">\n                Upload your private key file for key pair authentication.\n              </div>\n            }\n          >\n            <UploadPrivateKey />\n          </Form.Item>\n        )}\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/dataSources/TrinoProperties.tsx",
    "content": "import { Form, Input, Switch } from 'antd';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { FORM_MODE } from '@/utils/enum';\nimport { hostValidator } from '@/utils/validator';\n\ninterface Props {\n  mode?: FORM_MODE;\n}\n\nexport default function TrinoProperties({ mode }: Props) {\n  const isEditMode = mode === FORM_MODE.EDIT;\n  return (\n    <>\n      <Form.Item\n        label=\"Display name\"\n        name=\"displayName\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.DISPLAY_NAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label=\"Host\"\n        name=\"host\"\n        required\n        rules={[\n          {\n            required: true,\n            validator: hostValidator,\n          },\n        ]}\n      >\n        <Input placeholder=\"10.1.1.1\" disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"Port\"\n        name=\"port\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.PORT.REQUIRED,\n          },\n        ]}\n      >\n        <Input disabled={isEditMode} />\n      </Form.Item>\n      <Form.Item\n        label=\"Schemas\"\n        name=\"schemas\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.SCHEMAS.REQUIRED,\n          },\n        ]}\n      >\n        <Input placeholder=\"catalog.schema1, catalog.schema2\" />\n      </Form.Item>\n      <Form.Item\n        label=\"Username\"\n        name=\"username\"\n        required\n        rules={[\n          {\n            required: true,\n            message: ERROR_TEXTS.CONNECTION.USERNAME.REQUIRED,\n          },\n        ]}\n      >\n        <Input />\n      </Form.Item>\n      <Form.Item\n        label=\"Password\"\n        name=\"password\"\n        required\n        rules={[\n          {\n            required: false,\n            message: ERROR_TEXTS.CONNECTION.PASSWORD.REQUIRED,\n          },\n        ]}\n      >\n        <Input.Password placeholder=\"Input password\" />\n      </Form.Item>\n      <Form.Item label=\"Use SSL\" name=\"ssl\" valuePropName=\"checked\">\n        <Switch />\n      </Form.Item>\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/pages/setup/utils.tsx",
    "content": "import { merge } from 'lodash';\nimport { IconComponentProps } from '@/import/icon';\nimport ShoppingCartOutlined from '@ant-design/icons/ShoppingCartOutlined';\nimport IdCardOutlined from '@ant-design/icons/IdcardOutlined';\nimport { SETUP, DATA_SOURCES } from '@/utils/enum';\nimport Starter from './Starter';\nimport ConnectDataSource from './ConnectDataSource';\nimport SelectModels from './SelectModels';\nimport DefineRelations from './DefineRelations';\nimport { SampleDatasetName } from '@/apollo/client/graphql/__types__';\nimport { ERROR_CODES } from '@/utils/errorHandler';\nimport {\n  getDataSourceConfig,\n  getDataSourceFormComponent,\n} from '@/utils/dataSourceType';\n\ntype SetupStep = {\n  step: number;\n  component: (\n    props?: React.ComponentProps<typeof Starter> &\n      React.ComponentProps<typeof ConnectDataSource> &\n      React.ComponentProps<typeof SelectModels> &\n      React.ComponentProps<typeof DefineRelations>,\n  ) => JSX.Element;\n  maxWidth?: number;\n};\n\nexport type ButtonOption = {\n  label: string;\n  logo?: string;\n  IconComponent?: IconComponentProps['component'];\n  guide?: string;\n  disabled?: boolean;\n  submitting?: boolean;\n  value?: string;\n};\n\nexport const SETUP_STEPS = {\n  [SETUP.STARTER]: {\n    step: 0,\n    component: Starter,\n  },\n  [SETUP.CREATE_DATA_SOURCE]: {\n    step: 0,\n    component: ConnectDataSource,\n    maxWidth: 960,\n  },\n  [SETUP.SELECT_MODELS]: {\n    step: 1,\n    component: SelectModels,\n    maxWidth: 960,\n  },\n  [SETUP.DEFINE_RELATIONS]: {\n    step: 2,\n    component: DefineRelations,\n  },\n} as { [key: string]: SetupStep };\n\nexport const DATA_SOURCE_OPTIONS = {\n  [DATA_SOURCES.BIG_QUERY]: {\n    ...getDataSourceConfig(DATA_SOURCES.BIG_QUERY),\n    guide: 'https://docs.getwren.ai/oss/guide/connect/bigquery',\n    disabled: false,\n  },\n  [DATA_SOURCES.DUCKDB]: {\n    ...getDataSourceConfig(DATA_SOURCES.DUCKDB),\n    guide: 'https://docs.getwren.ai/oss/guide/connect/duckdb',\n    disabled: false,\n  },\n  [DATA_SOURCES.POSTGRES]: {\n    ...getDataSourceConfig(DATA_SOURCES.POSTGRES),\n    guide: 'https://docs.getwren.ai/oss/guide/connect/postgresql',\n    disabled: false,\n  },\n  [DATA_SOURCES.MYSQL]: {\n    ...getDataSourceConfig(DATA_SOURCES.MYSQL),\n    guide: 'https://docs.getwren.ai/oss/guide/connect/mysql',\n    disabled: false,\n  },\n  [DATA_SOURCES.ORACLE]: {\n    ...getDataSourceConfig(DATA_SOURCES.ORACLE),\n    guide: 'https://docs.getwren.ai/oss/guide/connect/oracle',\n    disabled: false,\n  },\n  [DATA_SOURCES.MSSQL]: {\n    ...getDataSourceConfig(DATA_SOURCES.MSSQL),\n    guide: 'https://docs.getwren.ai/oss/guide/connect/sqlserver',\n    disabled: false,\n  },\n  [DATA_SOURCES.CLICK_HOUSE]: {\n    ...getDataSourceConfig(DATA_SOURCES.CLICK_HOUSE),\n    guide: 'https://docs.getwren.ai/oss/guide/connect/clickhouse',\n    disabled: false,\n  },\n  [DATA_SOURCES.TRINO]: {\n    ...getDataSourceConfig(DATA_SOURCES.TRINO),\n    guide: 'https://docs.getwren.ai/oss/guide/connect/trino',\n    disabled: false,\n  },\n  [DATA_SOURCES.SNOWFLAKE]: {\n    ...getDataSourceConfig(DATA_SOURCES.SNOWFLAKE),\n    guide: 'https://docs.getwren.ai/oss/guide/connect/snowflake',\n    disabled: false,\n  },\n  [DATA_SOURCES.ATHENA]: {\n    ...getDataSourceConfig(DATA_SOURCES.ATHENA),\n    guide: 'https://docs.getwren.ai/oss/guide/connect/athena',\n    disabled: false,\n  },\n  [DATA_SOURCES.REDSHIFT]: {\n    ...getDataSourceConfig(DATA_SOURCES.REDSHIFT),\n    guide: 'https://docs.getwren.ai/oss/guide/connect/redshift',\n    disabled: false,\n  },\n  [DATA_SOURCES.DATABRICKS]: {\n    ...getDataSourceConfig(DATA_SOURCES.DATABRICKS),\n    guide: 'https://docs.getwren.ai/oss/guide/connect/databricks',\n    disabled: false,\n  },\n} as { [key: string]: ButtonOption };\n\nexport const TEMPLATE_OPTIONS = {\n  [SampleDatasetName.ECOMMERCE]: {\n    label: 'E-commerce',\n    IconComponent: ShoppingCartOutlined,\n    guide: 'https://docs.getwren.ai/oss/getting_started/sample_data/ecommerce',\n  },\n  [SampleDatasetName.HR]: {\n    label: 'Human Resource',\n    IconComponent: IdCardOutlined,\n    guide: 'https://docs.getwren.ai/oss/getting_started/sample_data/hr',\n  },\n};\n\nexport const getDataSources = () => {\n  return Object.values(DATA_SOURCE_OPTIONS) as ButtonOption[];\n};\n\nexport const getDataSource = (dataSource: DATA_SOURCES) => {\n  return merge(\n    DATA_SOURCE_OPTIONS[dataSource],\n    getDataSourceFormComponent(dataSource),\n  );\n};\n\nexport const getTemplates = () => {\n  return Object.keys(TEMPLATE_OPTIONS).map((key) => ({\n    ...TEMPLATE_OPTIONS[key],\n    value: key,\n  })) as ButtonOption[];\n};\n\nexport const getPostgresErrorMessage = (error: Record<string, any>) => {\n  if (error.code === ERROR_CODES.CONNECTION_REFUSED) {\n    return (\n      <div>\n        {error.message}. <br />\n        If you are having trouble connecting to your PostgreSQL database, please\n        refer to our{' '}\n        <a\n          href=\"https://docs.getwren.ai/oss/guide/connect/postgresql#connect\"\n          target=\"_blank\"\n          rel=\"noopener noreferrer\"\n        >\n          documentation\n        </a>{' '}\n        for detailed instructions.\n      </div>\n    );\n  }\n  return error.message;\n};\n"
  },
  {
    "path": "wren-ui/src/components/selectors/CombineFieldSelector.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { Select, Input } from 'antd';\n\ninterface Value {\n  model?: string;\n  field?: string;\n}\n\ninterface Props {\n  modelOptions: { label: string; value: string }[];\n  fieldOptions: { label: string; value: string }[];\n  modelDisabled?: boolean;\n  fieldDisabled?: boolean;\n  modelValue?: string;\n  fieldValue?: string;\n  value?: Value;\n  onModelChange?: (modelLabel: string) => void;\n  onFieldChange?: (fieldLabel: string) => void;\n  onChange?: (value: Value) => void;\n}\n\nexport default function CombineFieldSelector(props: Props) {\n  const {\n    modelValue,\n    fieldValue,\n    value = {},\n    onModelChange,\n    onFieldChange,\n    onChange,\n    modelOptions,\n    fieldOptions,\n    modelDisabled,\n    fieldDisabled,\n  } = props;\n\n  const [internalValue, setInternalValue] = useState<Value>({\n    model: modelValue,\n    field: fieldValue,\n    ...value,\n  });\n\n  const syncOnChange = () => {\n    if (internalValue?.model && internalValue?.field) {\n      onChange && onChange(internalValue);\n    }\n  };\n\n  useEffect(syncOnChange, [internalValue]);\n\n  const changeModel = (model: string) => {\n    onModelChange && onModelChange(model);\n    const newInternalValue = { model, field: undefined };\n    setInternalValue(newInternalValue);\n    onChange && onChange(newInternalValue);\n  };\n\n  const changeField = (field: string) => {\n    onFieldChange && onFieldChange(field);\n    setInternalValue({ ...internalValue, field });\n  };\n\n  return (\n    <Input.Group className=\"d-flex\" compact>\n      <Select\n        style={{ width: '35%' }}\n        options={modelOptions}\n        onChange={changeModel}\n        placeholder=\"Model\"\n        value={value?.model || modelValue}\n        disabled={modelDisabled}\n        showSearch\n        optionFilterProp=\"label\"\n        data-testid=\"common__models-select\"\n      />\n      <Select\n        className=\"flex-grow-1\"\n        options={fieldOptions}\n        onChange={changeField}\n        placeholder=\"Field\"\n        value={value?.field || fieldValue}\n        disabled={fieldDisabled}\n        showSearch\n        optionFilterProp=\"label\"\n        data-testid=\"common__fields-select\"\n      />\n    </Input.Group>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/selectors/DescriptiveSelector.tsx",
    "content": "import React, { useState } from 'react';\nimport { Select, SelectProps, Space, Typography } from 'antd';\nimport styled from 'styled-components';\nimport { omit } from 'lodash';\n\ninterface Props extends SelectProps {\n  listHeight?: number;\n  descriptiveContentRender?: (option: any) => React.ReactNode;\n  dropdownMatchSelectWidth?: number | boolean;\n}\n\nconst { Title } = Typography;\n\nconst DescribeBox = styled.div`\n  display: flex;\n  .rc-virtual-list {\n    min-width: 230px;\n  }\n\n  .describeBox {\n    &-codeBlock {\n      background: var(--gray-3);\n      border-radius: 4px;\n      padding: 6px 8px;\n    }\n  }\n`;\n\nconst defaultDescriptiveContentRender = (content: Record<string, any>) => {\n  return (\n    <Space style={{ width: '100%' }} size={[0, 16]} direction=\"vertical\">\n      <div>\n        <div style={{ marginBottom: 4 }}>\n          <b>Description</b>\n        </div>\n        {content?.description || '-'}\n      </div>\n      <div>\n        <div style={{ marginBottom: 4 }}>\n          <b>Example</b>\n        </div>\n        {content?.example ? (\n          <div className=\"describeBox-codeBlock\">{content?.example}</div>\n        ) : (\n          '-'\n        )}\n      </div>\n    </Space>\n  );\n};\n\nexport default function DescriptiveSelector(props: Props) {\n  const {\n    mode,\n    value,\n    options,\n    onChange,\n    descriptiveContentRender,\n    listHeight,\n    placeholder,\n    dropdownMatchSelectWidth,\n  } = props;\n  // Condition when met group option\n  const [firstOption] = options;\n  const [currentOption, setCurrentOption] = useState<any>(\n    firstOption.options ? firstOption.options[0] : firstOption,\n  );\n  // if descriptiveContentRender is not provided, the maxHeight will auto set for defaultDescriptiveContentRender\n  const maxHeight = descriptiveContentRender ? listHeight : 193;\n\n  const renderDescriptiveMenu = (menu: React.ReactNode) => {\n    return (\n      <DescribeBox>\n        {menu}\n        <div\n          style={{\n            width: '100%',\n            borderLeft: '1px solid var(--gray-3)',\n            margin: '-4px 0',\n            minWidth: 0,\n          }}\n        >\n          <Title\n            level={5}\n            ellipsis\n            style={{\n              padding: '8px 16px',\n              borderBottom: '1px solid var(--gray-3)',\n            }}\n          >\n            {currentOption?.label || currentOption?.value}\n          </Title>\n          <div style={{ padding: '4px 16px 12px' }}>\n            {(descriptiveContentRender\n              ? descriptiveContentRender\n              : defaultDescriptiveContentRender)(currentOption?.content)}\n          </div>\n        </div>\n      </DescribeBox>\n    );\n  };\n\n  const extendOptionMouseEnter = (option) => {\n    setCurrentOption(option);\n  };\n\n  const getOptionStructure = (option) => ({\n    ...omit(option, ['content']),\n    'data-value': option.value,\n    onMouseEnter: (event) => {\n      extendOptionMouseEnter(option);\n      option.onMouseEnter && option.onMouseEnter(event);\n    },\n  });\n\n  const mainOptions = options.map((option) => {\n    const isOptionGroup = Boolean(option.options);\n    return isOptionGroup\n      ? { ...option, options: option.options!.map(getOptionStructure) }\n      : getOptionStructure(option);\n  }) as SelectProps['options'];\n\n  return (\n    <Select\n      style={{ width: '100%' }}\n      mode={mode}\n      options={mainOptions}\n      value={value}\n      onChange={onChange}\n      dropdownRender={renderDescriptiveMenu}\n      listHeight={maxHeight}\n      placeholder={placeholder}\n      dropdownMatchSelectWidth={dropdownMatchSelectWidth}\n      data-testid=\"common__descriptive-select\"\n    />\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/selectors/Selector.tsx",
    "content": "import React, { useCallback, useMemo } from 'react';\nimport { Select } from 'antd';\nimport { compactObject, parseJson } from '@/utils/helper';\n\nexport interface Option {\n  label: string | JSX.Element;\n  value?: any;\n  options?: Option[];\n}\n\ninterface Props extends React.ComponentProps<typeof Select> {\n  options: Option[];\n}\n\nconst getOption = (item) => {\n  const value =\n    typeof item.value === 'object' ? JSON.stringify(item.value) : item.value;\n  return {\n    ...item,\n    value,\n    'data-testid': 'common__fields__select-option',\n  };\n};\n\nexport default function Selector(props: Props) {\n  const { value, onChange, options, ...restProps } = props;\n\n  const handleChange = useCallback((optionValue, option) => {\n    const parsedValue = Array.isArray(optionValue)\n      ? optionValue.map((value) => parseJson(value))\n      : parseJson(optionValue);\n\n    onChange && onChange(parsedValue, option);\n  }, []);\n\n  const antdSelectOptions = useMemo(() => {\n    return options.map((item) =>\n      compactObject({\n        ...getOption(item),\n        options: item.options?.map(getOption),\n      }),\n    );\n  }, [options]);\n\n  const antdValue = useMemo(() => {\n    return Array.isArray(value)\n      ? value.map((item) => JSON.stringify(item))\n      : JSON.stringify(value);\n  }, [value]);\n\n  return (\n    <Select\n      value={antdValue}\n      options={antdSelectOptions}\n      onChange={handleChange}\n      {...restProps}\n    />\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/selectors/lineageSelector/FieldSelect.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport styled from 'styled-components';\nimport { NODE_TYPE } from '@/utils/enum';\nimport { ModelIcon } from '@/utils/icons';\nimport { IterableComponent } from '@/utils/iteration';\nimport Selector, { Option } from '@/components/selectors/Selector';\n\nconst FieldBox = styled.div`\n  user-select: none;\n  border-radius: 4px;\n  background-color: white;\n  width: 170px;\n  box-shadow:\n    0px 9px 28px 8px rgba(0, 0, 0, 0.05),\n    0px 6px 16px 0px rgba(0, 0, 0, 0.08),\n    0px 3px 6px -4px rgba(0, 0, 0, 0.12);\n\n  + .adm-fieldBox {\n    position: relative;\n    margin-left: 40px;\n    &:before {\n      content: '';\n      position: absolute;\n      top: 50%;\n      left: -40px;\n      width: 40px;\n      height: 1px;\n      background-color: var(--gray-8);\n    }\n  }\n\n  .ant-select-selection-placeholder {\n    color: var(--geekblue-6);\n  }\n\n  &:last-child {\n    border: 1px var(--geekblue-6) solid;\n  }\n`;\n\nconst FieldHeader = styled.div`\n  display: flex;\n  align-items: center;\n  border-bottom: 1px var(--gray-4) solid;\n`;\n\nconst StyledSelector = styled(Selector)`\n  &.ant-select-status-error.ant-select:not(.ant-select-disabled):not(\n      .ant-select-customize-input\n    )\n    .ant-select-selector {\n    border-color: transparent !important;\n  }\n`;\n\nexport type FieldOption = Option;\n\nexport interface FieldValue {\n  nodeType: NODE_TYPE;\n  referenceName: string;\n  displayName: string;\n  type?: string;\n  relationId?: number;\n  columnId?: number;\n}\n\ntype Props = FieldValue & {\n  options: FieldOption[];\n  onChange?: (value: any, index: number) => void;\n  onFetchOptions?: (item: any, index: number) => Promise<FieldOption[]>;\n};\n\nexport const getFieldValue = (field): FieldValue => {\n  return {\n    nodeType: field.nodeType,\n    referenceName: field.referenceName,\n    displayName: field.displayName,\n    type: field.type,\n    relationId: field?.relationId,\n    columnId: field?.columnId,\n  };\n};\n\nexport default function FieldSelect(props: IterableComponent<Props>) {\n  const {\n    nodeType,\n    referenceName,\n    displayName,\n\n    data,\n    onFetchOptions,\n    onChange,\n    index,\n  } = props;\n  const selectedValue = data[index + 1];\n  const isModelOrRelationshipNode = [\n    NODE_TYPE.MODEL,\n    NODE_TYPE.RELATION,\n  ].includes(nodeType);\n  const [options, setOptions] = useState([]);\n\n  const getOptions = async () => {\n    const result = onFetchOptions && (await onFetchOptions(props, index));\n    setOptions(result || []);\n  };\n\n  // Get options when field select has value at the beginning (edit mode)\n  useEffect(() => {\n    if (selectedValue) getOptions();\n  }, []);\n\n  const onDropdownVisibleChange = async (open: boolean) => {\n    if (!open) return;\n    getOptions();\n  };\n\n  return isModelOrRelationshipNode ? (\n    <FieldBox\n      className=\"adm-fieldBox flex-shrink-0\"\n      data-testid=\"common__lineage-field-block\"\n    >\n      <FieldHeader className=\"py-1 px-3\">\n        <ModelIcon className=\"mr-1 flex-shrink-0\" />\n        <div\n          className=\"text-truncate flex-grow-1\"\n          title={displayName || referenceName}\n        >\n          {displayName || referenceName}\n        </div>\n      </FieldHeader>\n\n      {selectedValue?.nodeType === NODE_TYPE.RELATION && (\n        <div className=\"gray-7 text-sm px-3 pt-1\">Relationships</div>\n      )}\n\n      <StyledSelector\n        bordered={false}\n        options={options}\n        optionLabelProp=\"label\"\n        placeholder=\"Select field\"\n        suffixIcon={null}\n        value={selectedValue}\n        dropdownClassName=\"adm-model-field-select-dropdown\"\n        onDropdownVisibleChange={onDropdownVisibleChange}\n        onSelect={(value) => {\n          onChange && onChange(value, index);\n        }}\n        data-testid=\"common__lineage-fields-select\"\n      />\n    </FieldBox>\n  ) : null;\n}\n"
  },
  {
    "path": "wren-ui/src/components/selectors/lineageSelector/index.tsx",
    "content": "import { useRef, useContext, useMemo } from 'react';\nimport styled from 'styled-components';\nimport { compact } from 'lodash';\nimport FieldSelect, {\n  FieldValue,\n  FieldOption,\n  getFieldValue,\n} from './FieldSelect';\nimport { nextTick } from '@/utils/time';\nimport { makeIterable } from '@/utils/iteration';\nimport { NODE_TYPE } from '@/utils/enum';\nimport { compactObject, parseJson } from '@/utils/helper';\nimport {\n  FormItemInputContext,\n  FormItemStatusContextProps,\n} from 'antd/lib/form/context';\nimport { DiagramModel } from '@/utils/data';\nimport { getNodeTypeIcon } from '@/utils/nodeType';\nimport { aggregations } from '@/utils/expressionType';\nimport { ExpressionName } from '@/apollo/client/graphql/__types__';\nimport {\n  checkStringFunctionAllowType,\n  checkNumberFunctionAllowType,\n} from '@/utils/validator';\n\ninterface Props {\n  sourceModel: DiagramModel;\n  onChange?: (value: FieldValue[]) => void;\n  onFetchOptions?: (value: any, index: number) => Promise<FieldOption[]>;\n  value?: FieldValue[];\n}\n\nconst Wrapper = styled.div`\n  border: 1px var(--gray-5) solid;\n  border-radius: 4px;\n  overflow-x: auto;\n\n  &.adm-error {\n    border-color: var(--red-5);\n  }\n`;\n\nconst SelectResult = makeIterable(FieldSelect);\n\nexport default function LineageSelector(props: Props) {\n  const wrapper = useRef<HTMLDivElement | null>(null);\n  const { sourceModel, value = [], onChange, onFetchOptions } = props;\n\n  const formItemContext =\n    useContext<FormItemStatusContextProps>(FormItemInputContext);\n  const { status } = formItemContext;\n\n  // prepare value & options here\n  const data = useMemo(() => {\n    // always add model as the first item\n    const selectedData = [\n      {\n        referenceName: sourceModel.referenceName,\n        displayName: sourceModel.displayName,\n        nodeType: NODE_TYPE.MODEL,\n      },\n      ...value,\n    ];\n\n    return selectedData;\n  }, [sourceModel, value]);\n\n  const change = async (selectValue, index) => {\n    const parsePayload = parseJson(selectValue) as FieldValue;\n\n    const prevValue = value.slice(0, index);\n    const nextValue = [...prevValue, parsePayload];\n    onChange && onChange(nextValue);\n\n    await nextTick();\n    wrapper.current?.scrollTo({ left: wrapper.current?.scrollWidth });\n  };\n\n  return (\n    <Wrapper\n      ref={wrapper}\n      className={`d-flex align-center bg-gray-3 px-8 py-12${\n        status ? ` adm-${status}` : ''\n      }`}\n      data-testid=\"common__lineage\"\n    >\n      <SelectResult\n        data={data}\n        onChange={change}\n        onFetchOptions={onFetchOptions}\n      />\n    </Wrapper>\n  );\n}\n\nexport const getLineageOptions = (data: {\n  model: DiagramModel;\n  sourceModel: DiagramModel;\n  expression: ExpressionName;\n  values: FieldValue[];\n}) => {\n  const { model, sourceModel, expression, values = [] } = data;\n  const hasPrimaryKey = model.fields.some((field) => field.isPrimaryKey);\n  const isSourceModel = model.modelId === sourceModel.modelId;\n\n  const convertor = (field) => {\n    const value = compactObject(getFieldValue(field));\n    const isRelationship = field.nodeType === NODE_TYPE.RELATION;\n    // check if source model's calculated field\n    const isSourceModelCalculatedField =\n      isSourceModel && field.nodeType === NODE_TYPE.CALCULATED_FIELD;\n    // check if user select aggregation functions, then the source model fields cannot be selected\n    const isSourceModelFieldsWithAggregation =\n      aggregations.includes(expression) && isSourceModel && !isRelationship;\n    // check if the relationship is in used\n    const isInUsedRelationship =\n      isRelationship &&\n      values.some(\n        (item) => item.relationId && item.relationId === value.relationId,\n      );\n    // The relationship options available only if the model has a primary key\n    const isRelationshipWithoutPrimaryKey = isRelationship && !hasPrimaryKey;\n\n    // check if the field type is valid for the expression\n    let isInvalidType = false;\n    let invalidTypeMessage = '';\n    if (!checkStringFunctionAllowType(expression, value)) {\n      isInvalidType = true;\n      invalidTypeMessage = 'Please select a string type field.';\n    } else if (!checkNumberFunctionAllowType(expression, value)) {\n      isInvalidType = true;\n      invalidTypeMessage = 'Please select a number type field.';\n    }\n\n    const disabled =\n      isSourceModelFieldsWithAggregation ||\n      isRelationshipWithoutPrimaryKey ||\n      isSourceModelCalculatedField ||\n      isInUsedRelationship ||\n      isInvalidType;\n\n    let title = undefined;\n    if (isSourceModelFieldsWithAggregation) {\n      title =\n        \"Aggregation functions don't allow selecting from source model fields to prevent unexpected outcomes.\";\n    } else if (isRelationshipWithoutPrimaryKey) {\n      title =\n        'Please set a primary key within this model to use it in a calculated field.';\n    } else if (isSourceModelCalculatedField) {\n      title = 'Calculated field from the source model is not supported.';\n    } else if (isInUsedRelationship) {\n      title = 'This relationship is in use.';\n    } else if (isInvalidType) {\n      title = invalidTypeMessage;\n    }\n\n    return {\n      label: (\n        <div className=\"d-flex align-center\">\n          {getNodeTypeIcon(\n            { nodeType: field.nodeType, type: field.type },\n            { className: 'mr-1 flex-shrink-0', title: field.type },\n          )}\n          <div\n            // only show column full title when it's not disabled\n            title={!disabled ? field.displayName : null}\n            className=\"text-truncate\"\n          >\n            {field.displayName}\n          </div>\n        </div>\n      ),\n      value,\n      title,\n      disabled,\n    };\n  };\n  const fields = [...(model?.fields || [])].map(convertor);\n  const calculatedFields = (model?.calculatedFields || []).map(convertor);\n  const relationships = (model?.relationFields || []).map(convertor);\n  return compact([\n    ...fields,\n    calculatedFields.length\n      ? { label: 'Calculated fields', options: calculatedFields }\n      : undefined,\n    relationships.length\n      ? { label: 'Relationships', options: relationships }\n      : undefined,\n  ]);\n};\n"
  },
  {
    "path": "wren-ui/src/components/settings/DataSourceSettings.tsx",
    "content": "import { useRouter } from 'next/router';\nimport Image from 'next/image';\nimport { useEffect, useMemo } from 'react';\nimport { Button, Form, Modal, message, Alert } from 'antd';\nimport { makeIterable } from '@/utils/iteration';\nimport { DATA_SOURCES, FORM_MODE, Path } from '@/utils/enum';\nimport { getDataSource, getTemplates } from '@/components/pages/setup/utils';\nimport { FlexLoading } from '@/components/PageLoading';\nimport ButtonItem from '@/components/pages/setup/ButtonItem';\nimport {\n  transformFormToProperties,\n  transformPropertiesToForm,\n} from '@/hooks/useSetupConnectionDataSource';\nimport { parseGraphQLError } from '@/utils/errorHandler';\nimport {\n  useStartSampleDatasetMutation,\n  useUpdateDataSourceMutation,\n} from '@/apollo/client/graphql/dataSource.generated';\nimport {\n  DataSourceName,\n  SampleDatasetName,\n} from '@/apollo/client/graphql/__types__';\n\ninterface Props {\n  type: DataSourceName;\n  properties: Record<string, any>;\n  sampleDataset: SampleDatasetName;\n  refetchSettings: () => void;\n  closeModal: () => void;\n}\n\nconst SampleDatasetIterator = makeIterable(ButtonItem);\n\nconst SampleDatasetPanel = (props: Props) => {\n  const router = useRouter();\n  const { sampleDataset, closeModal } = props;\n  const templates = getTemplates();\n  const [startSampleDataset] = useStartSampleDatasetMutation({\n    onError: (error) => console.error(error),\n    onCompleted: () => {\n      router.push(Path.Home);\n      closeModal();\n    },\n    refetchQueries: 'active',\n  });\n\n  const onSelect = (name: SampleDatasetName) => {\n    const isCurrentTemplate = sampleDataset === name;\n    if (!isCurrentTemplate) {\n      const template = templates.find((item) => item.value === name);\n      Modal.confirm({\n        title: `Are you sure you want to change to \"${template.label}\" dataset?`,\n        okButtonProps: { danger: true },\n        okText: 'Change',\n        onOk: async () => {\n          await startSampleDataset({ variables: { data: { name } } });\n        },\n      });\n    }\n  };\n\n  return (\n    <>\n      <div className=\"mb-2\">Change sample dataset</div>\n      <div className=\"d-grid grid-columns-3 g-4\">\n        <SampleDatasetIterator\n          data={templates}\n          selectedTemplate={sampleDataset}\n          onSelect={onSelect}\n        />\n      </div>\n      <div className=\"gray-6 mt-1\">\n        Please be aware that choosing another sample dataset will delete all\n        thread records in the Home page.\n      </div>\n    </>\n  );\n};\n\nconst DataSourcePanel = (props: Props) => {\n  const { type, properties, refetchSettings } = props;\n\n  const current = getDataSource(type as unknown as DATA_SOURCES);\n  const [form] = Form.useForm();\n\n  const [updateDataSource, { loading, error }] = useUpdateDataSourceMutation({\n    onError: (error) => console.error(error),\n    onCompleted: async () => {\n      refetchSettings();\n      message.success('Successfully update data source.');\n    },\n  });\n\n  const updateError = useMemo(() => parseGraphQLError(error), [error]);\n\n  useEffect(() => properties && reset(), [properties]);\n\n  const reset = () => {\n    form.setFieldsValue(transformPropertiesToForm(properties, type));\n  };\n\n  const submit = () => {\n    form\n      .validateFields()\n      .then((values) => {\n        updateDataSource({\n          variables: {\n            data: { properties: transformFormToProperties(values, type) },\n          },\n        });\n      })\n      .catch((error) => {\n        console.error(error);\n      });\n  };\n\n  if (!type) return <FlexLoading align=\"center\" height={150} />;\n\n  return (\n    <>\n      <div className=\"d-flex align-center\">\n        <Image\n          className=\"mr-2\"\n          src={current.logo}\n          alt={current.label}\n          width=\"24\"\n          height=\"24\"\n        />\n        {current.label}\n      </div>\n      <Form form={form} layout=\"vertical\" className=\"py-3 px-4\">\n        <current.component mode={FORM_MODE.EDIT} />\n\n        {updateError && (\n          <Alert\n            message={updateError.shortMessage}\n            description={updateError.message}\n            type=\"error\"\n            showIcon\n            className=\"my-6\"\n          />\n        )}\n\n        <div className=\"py-2 text-right\">\n          <Button className=\"mr-2\" style={{ width: 80 }} onClick={reset}>\n            Cancel\n          </Button>\n          <Button\n            type=\"primary\"\n            style={{ width: 80 }}\n            onClick={submit}\n            loading={loading}\n          >\n            Save\n          </Button>\n        </div>\n      </Form>\n    </>\n  );\n};\n\nexport default function DataSourceSettings(props: Props) {\n  const { sampleDataset } = props;\n  const Component = sampleDataset ? SampleDatasetPanel : DataSourcePanel;\n  return (\n    <div className=\"py-3 px-4\">\n      <Component {...props} />\n    </div>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/settings/ProjectSettings.tsx",
    "content": "import { Button, Modal, Select, Row, Col, Form, message } from 'antd';\nimport { useRouter } from 'next/router';\nimport { Path } from '@/utils/enum';\nimport {\n  useResetCurrentProjectMutation,\n  useUpdateCurrentProjectMutation,\n} from '@/apollo/client/graphql/settings.generated';\nimport { getLanguageText } from '@/utils/language';\nimport { ProjectLanguage } from '@/apollo/client/graphql/__types__';\n\ninterface Props {\n  data: { language: string };\n}\n\nexport default function ProjectSettings(props: Props) {\n  const { data } = props;\n  const router = useRouter();\n  const [form] = Form.useForm();\n  const [resetCurrentProject, { client }] = useResetCurrentProjectMutation({\n    onError: (error) => console.error(error),\n  });\n  const languageOptions = Object.keys(ProjectLanguage).map((key) => {\n    return { label: getLanguageText(key as ProjectLanguage), value: key };\n  });\n\n  const [updateCurrentProject, { loading }] = useUpdateCurrentProjectMutation({\n    refetchQueries: ['GetSettings'],\n    onError: (error) => console.error(error),\n    onCompleted: () => {\n      message.success('Successfully updated project language.');\n    },\n  });\n\n  const reset = () => {\n    Modal.confirm({\n      title: 'Are you sure you want to reset?',\n      okButtonProps: { danger: true },\n      okText: 'Reset',\n      onOk: async () => {\n        await resetCurrentProject();\n        client.clearStore();\n        router.push(Path.OnboardingConnection);\n      },\n    });\n  };\n\n  const submit = () => {\n    form\n      .validateFields()\n      .then((values) => {\n        updateCurrentProject({ variables: { data: values } });\n      })\n      .catch((error) => console.error(error));\n  };\n\n  return (\n    <div className=\"py-3 px-4\">\n      <Form\n        form={form}\n        layout=\"vertical\"\n        initialValues={{ language: data.language }}\n      >\n        <Form.Item\n          label=\"Project language\"\n          extra=\"This setting will affect the language in which the AI responds to you.\"\n        >\n          <Row gutter={16} wrap={false}>\n            <Col className=\"flex-grow-1\">\n              <Form.Item name=\"language\" noStyle>\n                <Select\n                  placeholder=\"Select a language\"\n                  showSearch\n                  options={languageOptions}\n                />\n              </Form.Item>\n            </Col>\n            <Col>\n              <Button\n                type=\"primary\"\n                style={{ width: 70 }}\n                onClick={submit}\n                loading={loading}\n              >\n                Save\n              </Button>\n            </Col>\n          </Row>\n        </Form.Item>\n      </Form>\n      <div className=\"gray-8 mb-2\">Reset project</div>\n      <Button type=\"primary\" style={{ width: 70 }} danger onClick={reset}>\n        Reset\n      </Button>\n      <div className=\"gray-6 mt-1\">\n        Please be aware that resetting will delete all current settings and\n        records, including those in the Modeling Page and Home Page threads.\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/settings/index.tsx",
    "content": "import { useEffect, useMemo, useState } from 'react';\nimport { Modal, Layout, Button } from 'antd';\nimport styled from 'styled-components';\nimport { SETTINGS } from '@/utils/enum';\nimport { makeIterable } from '@/utils/iteration';\nimport { ModalAction } from '@/hooks/useModalAction';\nimport SettingOutlined from '@ant-design/icons/SettingOutlined';\nimport InfoCircleOutlined from '@ant-design/icons/InfoCircleOutlined';\nimport DataSourceSettings from './DataSourceSettings';\nimport ProjectSettings from './ProjectSettings';\nimport { getSettingMenu } from './utils';\nimport {\n  useGetSettingsLazyQuery,\n  GetSettingsQuery,\n} from '@/apollo/client/graphql/settings.generated';\n\nconst { Sider, Content } = Layout;\n\ntype Props = ModalAction<any, any> & {\n  loading?: boolean;\n};\n\nconst StyledSider = styled(Sider)`\n  .ant-layout-sider-children {\n    display: flex;\n    flex-direction: column;\n    height: 100%;\n  }\n`;\n\nconst StyledModal = styled(Modal)`\n  .ant-modal-content {\n    overflow: hidden;\n  }\n  .ant-modal-close-x {\n    width: 48px;\n    height: 48px;\n    line-height: 48px;\n  }\n`;\n\nconst StyledButton = styled(Button)`\n  display: flex;\n  align-items: center;\n  padding: 12px 8px;\n  margin-bottom: 4px;\n`;\n\nconst DynamicComponent = ({\n  menu,\n  data,\n  refetch,\n  closeModal,\n}: {\n  menu: SETTINGS;\n  data?: GetSettingsQuery['settings'];\n  refetch: () => void;\n  closeModal: () => void;\n}) => {\n  const { dataSource, language } = data || {};\n  return (\n    {\n      [SETTINGS.DATA_SOURCE]: (\n        <DataSourceSettings\n          type={dataSource?.type}\n          sampleDataset={dataSource?.sampleDataset}\n          properties={dataSource?.properties}\n          refetchSettings={refetch}\n          closeModal={closeModal}\n        />\n      ),\n      [SETTINGS.PROJECT]: <ProjectSettings data={{ language }} />,\n    }[menu] || null\n  );\n};\n\nconst MenuTemplate = ({ currentMenu, value, onClick }) => {\n  const current = getSettingMenu(value);\n  return (\n    <StyledButton\n      className={currentMenu === value ? 'geekblue-6 bg-gray-4' : 'gray-8'}\n      type=\"text\"\n      block\n      onClick={() => onClick({ value })}\n      icon={<current.icon />}\n    >\n      {current.label}\n    </StyledButton>\n  );\n};\n\nconst MenuIterator = makeIterable(MenuTemplate);\n\nexport default function Settings(props: Props) {\n  const { onClose, visible } = props;\n  const [menu, setMenu] = useState<SETTINGS>(SETTINGS.DATA_SOURCE);\n  const current = getSettingMenu(menu);\n  const menuList = Object.keys(SETTINGS).map((key) => ({\n    key,\n    value: SETTINGS[key],\n  }));\n  const [fetchSettings, { data, refetch }] = useGetSettingsLazyQuery({\n    fetchPolicy: 'cache-and-network',\n  });\n\n  const productVersion = useMemo(() => {\n    return data?.settings?.productVersion;\n  }, [data?.settings]);\n\n  useEffect(() => {\n    if (visible) fetchSettings();\n  }, [visible]);\n\n  const onMenuClick = ({ value }) => setMenu(value);\n\n  return (\n    <StyledModal\n      width={950}\n      bodyStyle={{ padding: 0, height: 700 }}\n      visible={visible}\n      footer={null}\n      onCancel={onClose}\n      destroyOnClose\n      centered\n    >\n      <Layout style={{ height: '100%' }}>\n        <StyledSider width={310} className=\"border-r border-gray-4\">\n          <div className=\"gray-9 text-bold py-3 px-5\">\n            <SettingOutlined className=\"mr-2\" />\n            Settings\n          </div>\n          <div className=\"p-3 flex-grow-1\">\n            <MenuIterator\n              data={menuList}\n              currentMenu={menu}\n              onClick={onMenuClick}\n            />\n          </div>\n          {!!productVersion && (\n            <div className=\"gray-7 d-flex align-center p-3 px-5\">\n              <InfoCircleOutlined className=\"mr-2 text-sm\" />\n              Wren AI version: {productVersion}\n            </div>\n          )}\n        </StyledSider>\n        <Content className=\"d-flex flex-column\">\n          <div className=\"d-flex align-center gray-9 border-b border-gray-4 text-bold py-3 px-4\">\n            <current.icon className=\"mr-2\" />\n            {current.label}\n          </div>\n          <div className=\"flex-grow-1\" style={{ overflowY: 'auto' }}>\n            <DynamicComponent\n              menu={menu}\n              data={data?.settings}\n              refetch={refetch}\n              closeModal={onClose}\n            />\n          </div>\n        </Content>\n      </Layout>\n    </StyledModal>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/settings/utils.tsx",
    "content": "import { SETTINGS } from '@/utils/enum';\nimport DatabaseOutlined from '@ant-design/icons/DatabaseOutlined';\nimport ProjectOutlined from '@ant-design/icons/ProjectOutlined';\n\nexport const getSettingMenu = (menu: SETTINGS) =>\n  ({\n    [SETTINGS.DATA_SOURCE]: {\n      icon: DatabaseOutlined,\n      label: 'Data source settings',\n    },\n    [SETTINGS.PROJECT]: {\n      icon: ProjectOutlined,\n      label: 'Project settings',\n    },\n  })[menu] || null;\n"
  },
  {
    "path": "wren-ui/src/components/sidebar/APIManagement.tsx",
    "content": "import Link from 'next/link';\nimport { useRouter } from 'next/router';\nimport styled from 'styled-components';\nimport { Path, MENU_KEY } from '@/utils/enum';\nimport { OpenInNewIcon } from '@/utils/icons';\nimport ApiOutlined from '@ant-design/icons/ApiOutlined';\nimport ReadOutlined from '@ant-design/icons/ReadOutlined';\nimport SidebarMenu from '@/components/sidebar/SidebarMenu';\n\nconst Layout = styled.div`\n  padding: 16px 0;\n  position: absolute;\n  z-index: 1;\n  left: 0;\n  top: 0;\n  width: 100%;\n  background-color: var(--gray-2);\n  overflow: hidden;\n`;\n\nconst MENU_KEY_MAP = {\n  [Path.APIManagementHistory]: MENU_KEY.API_HISTORY,\n};\n\nconst linkStyle = { color: 'inherit', transition: 'none' };\n\nexport default function APIManagement() {\n  const router = useRouter();\n\n  const menuItems = [\n    {\n      'data-guideid': 'api-history',\n      label: (\n        <Link style={linkStyle} href={Path.APIManagementHistory}>\n          API history\n        </Link>\n      ),\n      icon: <ApiOutlined />,\n      key: MENU_KEY.API_HISTORY,\n      className: 'pl-4',\n    },\n    {\n      label: (\n        <Link\n          className=\"gray-8 d-inline-flex align-center\"\n          href=\"https://wrenai.readme.io/reference/sql-generation\"\n          target=\"_blank\"\n          rel=\"noopener noreferrer\"\n        >\n          API reference\n          <OpenInNewIcon className=\"ml-1\" />\n        </Link>\n      ),\n      icon: <ReadOutlined />,\n      key: MENU_KEY.API_REFERENCE,\n      className: 'pl-4',\n    },\n  ];\n\n  return (\n    <Layout>\n      <SidebarMenu\n        items={menuItems}\n        selectedKeys={MENU_KEY_MAP[router.pathname]}\n      />\n    </Layout>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/sidebar/Home.tsx",
    "content": "import clsx from 'clsx';\nimport { useEffect } from 'react';\nimport { useRouter } from 'next/router';\nimport { useParams } from 'next/navigation';\nimport styled from 'styled-components';\nimport { Path } from '@/utils/enum';\nimport FundViewOutlined from '@ant-design/icons/FundViewOutlined';\nimport SidebarTree, {\n  StyledTreeNodeLink,\n  useSidebarTreeState,\n} from './SidebarTree';\nimport ThreadTree, { ThreadData } from './home/ThreadTree';\n\nexport interface Props {\n  data: {\n    threads: ThreadData[];\n  };\n  onSelect: (selectKeys) => void;\n  onDelete: (id: string) => Promise<void>;\n  onRename: (id: string, newName: string) => Promise<void>;\n}\n\nexport const StyledSidebarTree = styled(SidebarTree)`\n  .adm-treeNode {\n    &.adm-treeNode__thread {\n      padding: 0px 16px 0px 4px !important;\n\n      .ant-tree-title {\n        flex-grow: 1;\n        display: inline-flex;\n        align-items: center;\n        span:first-child,\n        .adm-treeTitle__title {\n          flex-grow: 1;\n        }\n      }\n    }\n  }\n`;\n\nexport default function Home(props: Props) {\n  const { data, onSelect, onRename, onDelete } = props;\n  const router = useRouter();\n  const params = useParams<{ id: string }>();\n  const { threads } = data;\n\n  const { treeSelectedKeys, setTreeSelectedKeys } = useSidebarTreeState();\n\n  useEffect(() => {\n    params?.id && setTreeSelectedKeys([params.id] as string[]);\n  }, [params?.id]);\n\n  const onDeleteThread = async (threadId: string) => {\n    try {\n      await onDelete(threadId);\n      if (params?.id == threadId) {\n        router.push(Path.Home);\n      }\n    } catch (error) {\n      console.error(error);\n    }\n  };\n\n  const onTreeSelect = (selectedKeys: React.Key[], _info: any) => {\n    // prevent deselected\n    if (selectedKeys.length === 0) return;\n\n    setTreeSelectedKeys(selectedKeys);\n    onSelect(selectedKeys);\n  };\n\n  return (\n    <>\n      <StyledTreeNodeLink\n        className={clsx({\n          'adm-treeNode--selected': router.pathname === Path.HomeDashboard,\n        })}\n        href={Path.HomeDashboard}\n      >\n        <FundViewOutlined className=\"mr-2\" />\n        <span className=\"text-medium\">Dashboard</span>\n      </StyledTreeNodeLink>\n      <ThreadTree\n        threads={threads}\n        selectedKeys={treeSelectedKeys}\n        onSelect={onTreeSelect}\n        onRename={onRename}\n        onDeleteThread={onDeleteThread}\n      />\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/sidebar/Knowledge.tsx",
    "content": "import Link from 'next/link';\nimport { useRouter } from 'next/router';\nimport styled from 'styled-components';\nimport FunctionOutlined from '@ant-design/icons/FunctionOutlined';\nimport { Path, MENU_KEY } from '@/utils/enum';\nimport { InstructionsSVG } from '@/utils/svgs';\nimport SidebarMenu from '@/components/sidebar/SidebarMenu';\n\nconst Layout = styled.div`\n  padding: 16px 0;\n  position: absolute;\n  z-index: 1;\n  left: 0;\n  top: 0;\n  width: 100%;\n  background-color: var(--gray-2);\n  overflow: hidden;\n`;\n\nconst MENU_KEY_MAP = {\n  [Path.KnowledgeQuestionSQLPairs]: MENU_KEY.QUESTION_SQL_PAIRS,\n  [Path.KnowledgeInstructions]: MENU_KEY.INSTRUCTIONS,\n};\n\nconst linkStyle = { color: 'inherit', transition: 'none' };\n\nexport default function Knowledge() {\n  const router = useRouter();\n\n  const menuItems = [\n    {\n      'data-guideid': 'question-sql-pairs',\n      label: (\n        <Link style={linkStyle} href={Path.KnowledgeQuestionSQLPairs}>\n          Question-SQL pairs\n        </Link>\n      ),\n      icon: <FunctionOutlined />,\n      key: MENU_KEY.QUESTION_SQL_PAIRS,\n      className: 'pl-4',\n    },\n    {\n      'data-guideid': 'instructions',\n      label: (\n        <Link style={linkStyle} href={Path.KnowledgeInstructions}>\n          Instructions\n        </Link>\n      ),\n      icon: <InstructionsSVG />,\n      key: MENU_KEY.INSTRUCTIONS,\n      className: 'pl-4',\n    },\n  ];\n\n  return (\n    <Layout>\n      <SidebarMenu\n        items={menuItems}\n        selectedKeys={MENU_KEY_MAP[router.pathname]}\n      />\n    </Layout>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/sidebar/LabelTitle.tsx",
    "content": "interface LabelTitleProps {\n  title: string;\n  appendIcon?: React.ReactNode | null;\n}\n\nexport default function LabelTitle({\n  title,\n  appendIcon = null,\n}: LabelTitleProps) {\n  return (\n    <>\n      <span className=\"adm-treeTitle__title\" title={title}>\n        {title}\n      </span>\n      {appendIcon && <span className=\"adm-actionIcon\">{appendIcon}</span>}\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/sidebar/Modeling.tsx",
    "content": "import styled from 'styled-components';\nimport SidebarTree, { sidebarCommonStyle } from './SidebarTree';\nimport ModelTree from './modeling/ModelTree';\nimport { Diagram } from '@/utils/data';\nimport ViewTree from './modeling/ViewTree';\n\nexport const StyledSidebarTree = styled(SidebarTree)`\n  ${sidebarCommonStyle}\n\n  .adm-treeNode {\n    .ant-tree-title {\n      display: inline-flex;\n      flex-wrap: nowrap;\n      min-width: 1px;\n      flex-grow: 0;\n    }\n  }\n`;\n\nexport interface Props {\n  data: Diagram;\n  onOpenModelDrawer: () => void;\n  onSelect: (selectKeys) => void;\n}\n\nexport default function Modeling(props: Props) {\n  const { data, onSelect, onOpenModelDrawer } = props;\n  const { models = [], views = [] } = data || {};\n\n  return (\n    <>\n      <ModelTree\n        models={models}\n        onSelect={onSelect}\n        selectedKeys={[]}\n        onOpenModelDrawer={onOpenModelDrawer}\n      />\n      <ViewTree views={views} onSelect={onSelect} selectedKeys={[]} />\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/sidebar/SidebarMenu.tsx",
    "content": "import React from 'react';\nimport styled from 'styled-components';\nimport { Menu, MenuProps } from 'antd';\n\nconst StyledMenu = styled(Menu)`\n  &.ant-menu {\n    background-color: transparent;\n    border-right: 0;\n    color: var(--gray-8);\n\n    &:not(.ant-menu-horizontal) {\n      .ant-menu-item-selected {\n        color: var(--gray-8);\n        background-color: var(--gray-5);\n      }\n    }\n\n    .ant-menu-item-group {\n      margin-top: 20px;\n\n      &:first-child {\n        margin-top: 0;\n      }\n    }\n\n    .ant-menu-item-group-title {\n      font-size: 12px;\n      font-weight: 700;\n      padding: 5px 16px;\n    }\n\n    .ant-menu-item {\n      line-height: 28px;\n      height: auto;\n      margin: 0;\n      font-weight: 500;\n\n      &:not(last-child) {\n        margin-bottom: 0;\n      }\n\n      &:not(.ant-menu-item-disabled):hover {\n        color: inherit;\n        background-color: var(--gray-4);\n      }\n\n      &:not(.ant-menu-item-disabled):active {\n        background-color: var(--gray-6);\n      }\n\n      &:active {\n        background-color: transparent;\n      }\n\n      &-selected {\n        color: var(--gray-8);\n\n        &:after {\n          display: none;\n        }\n\n        &:hover {\n          color: var(--gray-8);\n        }\n      }\n    }\n  }\n`;\n\nexport default function SidebarMenu({\n  items,\n  selectedKeys,\n  onSelect,\n}: MenuProps) {\n  return (\n    <StyledMenu\n      mode=\"inline\"\n      items={items}\n      selectedKeys={selectedKeys}\n      onSelect={onSelect}\n    />\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/sidebar/SidebarTree.tsx",
    "content": "import Link from 'next/link';\nimport { useState } from 'react';\nimport styled, { css } from 'styled-components';\nimport { Tree, TreeProps } from 'antd';\n\nconst anticonStyle = css`\n  [class^='anticon anticon-'] {\n    transition: background-color ease-out 0.12s;\n    border-radius: 2px;\n    width: 12px;\n    height: 12px;\n    font-size: 12px;\n    vertical-align: middle;\n\n    &:hover {\n      background-color: var(--gray-5);\n    }\n    &:active {\n      background-color: var(--gray-6);\n    }\n\n    &[disabled] {\n      cursor: not-allowed;\n      color: var(--gray-6);\n      &:hover,\n      &:active {\n        background-color: transparent;\n      }\n    }\n  }\n  .anticon + .anticon {\n    margin-left: 4px;\n  }\n`;\n\nconst StyledTree = styled(Tree)`\n  &.ant-tree {\n    background-color: transparent;\n    color: var(--gray-8);\n\n    .ant-tree-indent-unit {\n      width: 12px;\n    }\n\n    .ant-tree-node-content-wrapper {\n      display: flex;\n      align-items: center;\n      line-height: 18px;\n      min-height: 28px;\n      min-width: 1px;\n      padding: 0;\n    }\n\n    .ant-tree-node-content-wrapper:hover,\n    .ant-tree-node-content-wrapper.ant-tree-node-selected {\n      background-color: transparent;\n    }\n\n    .ant-tree-treenode {\n      padding: 0 16px;\n      background-color: transparent;\n      transition: background-color ease-out 0.12s;\n\n      &-selected {\n        color: var(--geekblue-6);\n        background-color: var(--gray-4);\n      }\n\n      .ant-tree-switcher {\n        width: 12px;\n        align-self: center;\n        .ant-tree-switcher-icon {\n          font-size: 12px;\n          vertical-align: middle;\n        }\n        ${anticonStyle}\n      }\n\n      .ant-tree-iconEle {\n        flex-shrink: 0;\n      }\n    }\n\n    .adm {\n      &-treeTitle__title {\n        overflow: hidden;\n        text-overflow: ellipsis;\n        white-space: nowrap;\n      }\n\n      &-treeNode {\n        &:hover {\n          background-color: var(--gray-4);\n        }\n        &:active {\n          background-color: var(--gray-6);\n        }\n\n        .ant-tree-title {\n          display: inline-flex;\n          flex-wrap: nowrap;\n          min-width: 1px;\n        }\n\n        &--relation,\n        &--primary {\n          margin-left: 4px;\n        }\n\n        &--group {\n          color: var(--gray-8);\n          margin-top: 16px;\n\n          font-size: 14px;\n          font-weight: 500;\n\n          .ant-tree-switcher-noop {\n            display: none;\n          }\n\n          > * {\n            cursor: inherit;\n          }\n        }\n\n        &--empty {\n          color: var(--gray-7);\n          font-size: 12px;\n          .ant-tree-switcher {\n            display: none;\n          }\n          .ant-tree-node-content-wrapper {\n            min-height: auto;\n          }\n        }\n\n        &--selectNode {\n          * {\n            cursor: auto;\n          }\n          &:hover,\n          &:active {\n            background-color: transparent;\n          }\n        }\n\n        &--subtitle {\n          color: var(--gray-7);\n          font-size: 12px;\n          font-weight: 500;\n          .ant-tree-switcher {\n            display: none;\n          }\n          .ant-tree-node-content-wrapper {\n            min-height: auto;\n          }\n        }\n\n        &--selectNone {\n          * {\n            cursor: auto;\n          }\n          &:hover,\n          &:active {\n            background-color: transparent;\n          }\n        }\n      }\n\n      &-actionIcon {\n        font-size: 14px;\n        border-radius: 2px;\n        margin-right: -3px;\n        &:not(.adm-actionIcon--disabled) {\n          cursor: pointer;\n          &:hover {\n            background-color: var(--gray-5);\n          }\n        }\n        .anticon {\n          padding: 2px;\n          cursor: inherit;\n        }\n        &--disabled {\n          color: var(--gray-6);\n          cursor: not-allowed;\n        }\n      }\n    }\n  }\n`;\n\nexport const sidebarCommonStyle = css`\n  .ant-tree-title {\n    flex-grow: 1;\n    display: inline-flex;\n    align-items: center;\n    span:first-child,\n    .adm-treeTitle__title {\n      flex-grow: 1;\n    }\n  }\n`;\n\nexport const StyledTreeNodeLink = styled(Link)`\n  display: block;\n  cursor: pointer;\n  user-select: none;\n  margin-top: 16px;\n  padding: 0 16px;\n  line-height: 28px;\n  color: var(--gray-8);\n  &:hover {\n    background-color: var(--gray-4);\n  }\n  &:active {\n    background-color: var(--gray-6);\n  }\n  &.adm-treeNode--selected {\n    background-color: var(--gray-4);\n    color: var(--geekblue-6);\n  }\n`;\n\nexport const useSidebarTreeState = () => {\n  const [treeSelectedKeys, setTreeSelectedKeys] = useState<React.Key[]>([]);\n  const [treeExpandKeys, setTreeExpandKeys] = useState<React.Key[]>([]);\n  const [treeLoadedKeys, setTreeLoadedKeys] = useState<React.Key[]>([]);\n  const [autoExpandParent, setAutoExpandParent] = useState(true);\n\n  return {\n    treeSelectedKeys,\n    treeExpandKeys,\n    treeLoadedKeys,\n    autoExpandParent,\n    setTreeSelectedKeys,\n    setTreeExpandKeys,\n    setTreeLoadedKeys,\n    setAutoExpandParent,\n  };\n};\n\nexport default function SidebarTree(props: TreeProps) {\n  return (\n    <StyledTree\n      blockNode\n      showIcon\n      motion={null} // https://github.com/ant-design/ant-design/issues/16943#issuecomment-859966751\n      {...props}\n    />\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/sidebar/home/ThreadTree.tsx",
    "content": "import { useState, useEffect } from 'react';\nimport styled from 'styled-components';\nimport { DataNode } from 'antd/lib/tree';\nimport { Path } from '@/utils/enum';\nimport { useParams, useRouter } from 'next/navigation';\nimport PlusOutlined from '@ant-design/icons/PlusOutlined';\nimport SidebarTree, {\n  sidebarCommonStyle,\n} from '@/components/sidebar/SidebarTree';\nimport {\n  createTreeGroupNode,\n  GroupActionButton,\n} from '@/components/sidebar/utils';\nimport TreeTitle from './TreeTitle';\n\nconst StyledSidebarTree = styled(SidebarTree)`\n  ${sidebarCommonStyle}\n\n  .adm-treeNode {\n    &.adm-treeNode__thread {\n      padding: 0px 16px 0px 4px !important;\n\n      .ant-tree-title {\n        flex-grow: 1;\n        display: inline-flex;\n        align-items: center;\n        span:first-child,\n        .adm-treeTitle__title {\n          flex-grow: 1;\n        }\n      }\n    }\n  }\n`;\n\nexport interface ThreadData {\n  id: string;\n  name: string;\n}\n\ninterface Props {\n  threads: ThreadData[];\n  selectedKeys: React.Key[];\n  onSelect: (selectKeys: React.Key[], info: any) => void;\n  onRename: (id: string, newName: string) => Promise<void>;\n  onDeleteThread: (id: string) => Promise<void>;\n}\n\nexport default function ThreadTree(props: Props) {\n  const params = useParams<{ id: string }>();\n  const router = useRouter();\n  const {\n    threads = [],\n    selectedKeys,\n    onSelect,\n    onRename,\n    onDeleteThread,\n  } = props;\n\n  const getThreadGroupNode = createTreeGroupNode({\n    groupName: 'Threads',\n    groupKey: 'threads',\n    actions: [\n      {\n        key: 'new-thread',\n        render: () => (\n          <GroupActionButton\n            size=\"small\"\n            icon={<PlusOutlined />}\n            onClick={() => router.push(Path.Home)}\n          >\n            New\n          </GroupActionButton>\n        ),\n      },\n    ],\n  });\n\n  const [tree, setTree] = useState<DataNode[]>(getThreadGroupNode());\n\n  useEffect(() => {\n    setTree((_tree) =>\n      getThreadGroupNode({\n        quotaUsage: threads.length,\n        children: threads.map((thread) => {\n          const nodeKey = thread.id;\n\n          return {\n            className: 'adm-treeNode adm-treeNode__thread',\n            id: nodeKey,\n            isLeaf: true,\n            key: nodeKey,\n            title: (\n              <TreeTitle\n                id={nodeKey}\n                title={thread.name}\n                onRename={onRename}\n                onDelete={onDeleteThread}\n              />\n            ),\n          };\n        }),\n      }),\n    );\n  }, [params?.id, threads]);\n\n  return (\n    <StyledSidebarTree\n      treeData={tree}\n      selectedKeys={selectedKeys}\n      onSelect={onSelect}\n    />\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/sidebar/home/TreeTitle.tsx",
    "content": "import { useState } from 'react';\nimport styled from 'styled-components';\nimport { Dropdown, Menu } from 'antd';\nimport EditOutlined from '@ant-design/icons/EditOutlined';\nimport MoreOutlined from '@ant-design/icons/MoreOutlined';\nimport LabelTitle from '@/components/sidebar/LabelTitle';\nimport TreeTitleInput from '@/components/sidebar/home/TreeTitleInput';\nimport { DeleteThreadModal } from '@/components/modals/DeleteModal';\n\nconst MENU_ITEM_KEYS = {\n  RENAME: 'rename',\n  DELETE: 'delete',\n};\n\nconst StyledMenu = styled(Menu)`\n  a:hover {\n    color: white;\n  }\n`;\n\ninterface TreeTitleProps {\n  id: string;\n  title: string;\n  onDelete?: (id: string) => void;\n  onRename?: (id: string, newName: string) => void;\n}\n\nexport default function TreeTitle(props: TreeTitleProps) {\n  const { id, onDelete, onRename } = props;\n  const [title, setTitle] = useState(props.title);\n  const [isEditing, setIsEditing] = useState(false);\n\n  const onCancelChange = () => {\n    setIsEditing(false);\n    setTitle(props.title);\n  };\n\n  const onChangeTitle = (newThreadTitle: string) => {\n    setIsEditing(false);\n    setTitle(newThreadTitle);\n    onRename && onRename(id, newThreadTitle);\n  };\n\n  const onDeleteData = (id: string) => {\n    onDelete && onDelete(id);\n  };\n\n  return isEditing ? (\n    <TreeTitleInput\n      title={title}\n      onCancelChange={onCancelChange}\n      onSetTitle={setTitle}\n      onRename={onChangeTitle}\n    />\n  ) : (\n    <LabelTitle\n      title={title}\n      appendIcon={\n        <Dropdown\n          trigger={['click']}\n          overlayStyle={{ userSelect: 'none', minWidth: 150 }}\n          overlay={\n            <StyledMenu\n              items={[\n                {\n                  label: (\n                    <>\n                      <EditOutlined className=\"mr-2\" />\n                      Rename\n                    </>\n                  ),\n                  key: MENU_ITEM_KEYS.RENAME,\n                  onClick: ({ domEvent }) => {\n                    domEvent.stopPropagation();\n                    setIsEditing(true);\n                  },\n                },\n                {\n                  label: (\n                    <DeleteThreadModal onConfirm={() => onDeleteData(id)} />\n                  ),\n                  key: MENU_ITEM_KEYS.DELETE,\n                  onClick: ({ domEvent }) => {\n                    domEvent.stopPropagation();\n                  },\n                },\n              ]}\n            />\n          }\n        >\n          <MoreOutlined onClick={(event) => event.stopPropagation()} />\n        </Dropdown>\n      }\n    />\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/sidebar/home/TreeTitleInput.tsx",
    "content": "import { Input } from 'antd';\n\nconst ESCAPE = 'escape';\n\nexport default function TreeTitleInput(props: {\n  title: string;\n  onCancelChange: () => void;\n  onSetTitle: (newTitle: string) => void;\n  onRename: (newName: string) => void;\n}) {\n  const { title, onCancelChange, onRename, onSetTitle } = props;\n\n  return (\n    <Input\n      autoFocus\n      size=\"small\"\n      value={title}\n      onClick={(e) => e.stopPropagation()}\n      onKeyDown={(e: React.KeyboardEvent) => {\n        // change back to the original title\n        if (e.key.toLowerCase() === ESCAPE) onCancelChange();\n      }}\n      onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n        onSetTitle(e.target.value)\n      }\n      onPressEnter={(_e) => onRename(title)}\n      onBlur={(_e) => onRename(title)}\n    />\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/sidebar/index.tsx",
    "content": "import Link from 'next/link';\nimport { useRouter } from 'next/router';\nimport { Button } from 'antd';\nimport styled from 'styled-components';\nimport { Path } from '@/utils/enum';\nimport { DiscordIcon, GithubIcon } from '@/utils/icons';\nimport SettingOutlined from '@ant-design/icons/SettingOutlined';\nimport Home, { Props as HomeSidebarProps } from './Home';\nimport Modeling, { Props as ModelingSidebarProps } from './Modeling';\nimport Knowledge from './Knowledge';\nimport APIManagement from './APIManagement';\nimport LearningSection from '@/components/learning';\n\nconst Layout = styled.div`\n  position: relative;\n  height: 100%;\n  background-color: var(--gray-2);\n  color: var(--gray-8);\n  padding-bottom: 12px;\n  overflow-x: hidden;\n`;\n\nconst Content = styled.div`\n  flex-grow: 1;\n  overflow-y: auto;\n`;\n\nconst StyledButton = styled(Button)`\n  cursor: pointer;\n  display: flex;\n  align-items: center;\n  padding-left: 16px;\n  padding-right: 16px;\n  color: var(--gray-8) !important;\n  border-radius: 0;\n\n  &:hover,\n  &:focus {\n    background-color: var(--gray-4);\n  }\n`;\n\ntype Props = (ModelingSidebarProps | HomeSidebarProps) & {\n  onOpenSettings?: () => void;\n};\n\nconst DynamicSidebar = (\n  props: Props & {\n    pathname: string;\n  },\n) => {\n  const { pathname, ...restProps } = props;\n\n  const getContent = () => {\n    if (pathname.startsWith(Path.Home)) {\n      return <Home {...(restProps as HomeSidebarProps)} />;\n    }\n\n    if (pathname.startsWith(Path.Modeling)) {\n      return <Modeling {...(restProps as ModelingSidebarProps)} />;\n    }\n\n    if (pathname.startsWith(Path.Knowledge)) {\n      return <Knowledge />;\n    }\n\n    if (pathname.startsWith(Path.APIManagement)) {\n      return <APIManagement />;\n    }\n\n    return null;\n  };\n\n  return <Content>{getContent()}</Content>;\n};\n\nexport default function Sidebar(props: Props) {\n  const { onOpenSettings } = props;\n  const router = useRouter();\n\n  const onSettingsClick = (event) => {\n    onOpenSettings && onOpenSettings();\n    event.target.blur();\n  };\n\n  return (\n    <Layout className=\"d-flex flex-column\">\n      <DynamicSidebar {...props} pathname={router.pathname} />\n      <LearningSection />\n      <div className=\"border-t border-gray-4 pt-2\">\n        <StyledButton type=\"text\" block onClick={onSettingsClick}>\n          <SettingOutlined className=\"text-md\" />\n          Settings\n        </StyledButton>\n        <StyledButton type=\"text\" block>\n          <Link\n            className=\"d-flex align-center\"\n            href=\"https://discord.com/invite/5DvshJqG8Z\"\n            target=\"_blank\"\n            rel=\"noopener noreferrer\"\n            data-ph-capture=\"true\"\n            data-ph-capture-attribute-name=\"cta_go_to_discord\"\n          >\n            <DiscordIcon className=\"mr-2\" style={{ width: 16 }} /> Discord\n          </Link>\n        </StyledButton>\n        <StyledButton type=\"text\" block>\n          <Link\n            className=\"d-flex align-center\"\n            href=\"https://github.com/Canner/WrenAI\"\n            target=\"_blank\"\n            rel=\"noopener noreferrer\"\n            data-ph-capture=\"true\"\n            data-ph-capture-attribute-name=\"cta_go_to_github\"\n          >\n            <GithubIcon className=\"mr-2\" style={{ width: 16 }} /> GitHub\n          </Link>\n        </StyledButton>\n      </div>\n    </Layout>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/sidebar/modeling/GroupTreeTitle.tsx",
    "content": "import { Fragment } from 'react';\nimport Icon from '@/import/icon';\n\nexport type ActionType = {\n  icon?: React.ComponentType<{ className?: string }>;\n  key: React.Key;\n  className?: string;\n  style?: React.CSSProperties;\n  disabled?: boolean;\n  render?: (props: { key: React.Key; disabled: boolean }) => React.ReactNode;\n};\n\ninterface GroupTitleProps {\n  title: string;\n  quotaUsage?: number;\n  appendSlot?: React.ReactNode;\n  actions: ActionType[];\n}\n\nconst Actions = ({ actions }: { actions: ActionType[] }) => {\n  const iconComponents = (actions || []).map(\n    ({ key, icon, render, disabled = false, className = '', ...restProps }) =>\n      icon ? (\n        <Icon\n          key={key}\n          component={icon}\n          className={`adm-actionIcon ${className} ${\n            disabled ? 'adm-actionIcon--disabled' : ''\n          }`}\n          {...restProps}\n        />\n      ) : render ? (\n        <Fragment key={key}>{render({ key, disabled })}</Fragment>\n      ) : null,\n  );\n\n  return (\n    <span className=\"d-inline-flex align-center flex-shrink-0 g-2\">\n      {iconComponents}\n    </span>\n  );\n};\n\nexport default function GroupTreeTitle({\n  title,\n  quotaUsage = 0,\n  appendSlot,\n  ...restProps\n}: GroupTitleProps) {\n  return (\n    <>\n      <span className=\"d-inline-flex align-center\">\n        {title}\n        <span className=\"adm-treeNode-group-count ml-1 text-xs flex-grow-0\">\n          ({quotaUsage})\n        </span>\n        {appendSlot}\n      </span>\n      <Actions {...restProps} />\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/sidebar/modeling/ModelTree.tsx",
    "content": "import { useEffect, useMemo, useState } from 'react';\nimport { message } from 'antd';\nimport { DataNode } from 'antd/es/tree';\nimport { DiagramModel } from '@/utils/data';\nimport { getNodeTypeIcon } from '@/utils/nodeType';\nimport {\n  createTreeGroupNode,\n  getColumnNode,\n  GroupActionButton,\n} from '@/components/sidebar/utils';\nimport useModalAction from '@/hooks/useModalAction';\nimport LabelTitle from '@/components/sidebar/LabelTitle';\nimport PlusOutlined from '@ant-design/icons/PlusOutlined';\nimport WarningOutlined from '@ant-design/icons/WarningOutlined';\nimport ReloadOutlined from '@ant-design/icons/ReloadOutlined';\nimport { StyledSidebarTree } from '@/components/sidebar/Modeling';\nimport SchemaChangeModal from '@/components/modals/SchemaChangeModal';\nimport {\n  SchemaChange,\n  SchemaChangeType,\n} from '@/apollo/client/graphql/__types__';\nimport {\n  useResolveSchemaChangeMutation,\n  useSchemaChangeQuery,\n  useTriggerDataSourceDetectionMutation,\n} from '@/apollo/client/graphql/dataSource.generated';\nimport { DIAGRAM } from '@/apollo/client/graphql/diagram';\nimport { LIST_MODELS } from '@/apollo/client/graphql/model';\nimport { getRelativeTime } from '@/utils/time';\n\ninterface Props {\n  [key: string]: any;\n  models: DiagramModel[];\n  onOpenModelDrawer: () => void;\n}\n\nconst getHasSchemaChange = (schemaChange: SchemaChange) => {\n  return [\n    schemaChange?.deletedTables,\n    schemaChange?.deletedColumns,\n    schemaChange?.modifiedColumns,\n  ].some((changes) => !!changes);\n};\n\nexport default function ModelTree(props: Props) {\n  const { onOpenModelDrawer, models } = props;\n\n  const schemaChangeModal = useModalAction();\n  const [triggerDataSourceDetection, { loading: isDetecting }] =\n    useTriggerDataSourceDetectionMutation({\n      onError: (error) => console.error(error),\n      onCompleted: async (data) => {\n        if (data.triggerDataSourceDetection) {\n          message.warning('Schema change detected.');\n        } else {\n          message.success('There is no schema change.');\n        }\n        await refetchSchemaChange();\n      },\n    });\n  const [resolveSchemaChange, { loading: isResolving }] =\n    useResolveSchemaChangeMutation({\n      onError: (error) => console.error(error),\n      onCompleted: async (_, options) => {\n        const { type } = options.variables?.where;\n        if (type === SchemaChangeType.DELETED_TABLES) {\n          message.success('Source table deleted resolved successfully.');\n        } else if (type === SchemaChangeType.DELETED_COLUMNS) {\n          message.success('Source column deleted resolved successfully.');\n        }\n\n        const { data } = await refetchSchemaChange();\n        // if all schema changes are resolved, close the modal\n        if (!getHasSchemaChange(data.schemaChange)) {\n          schemaChangeModal.closeModal();\n        }\n      },\n      refetchQueries: [{ query: DIAGRAM }, { query: LIST_MODELS }],\n    });\n  const { data: schemaChangeData, refetch: refetchSchemaChange } =\n    useSchemaChangeQuery({\n      fetchPolicy: 'cache-and-network',\n    });\n  const hasSchemaChange = useMemo(\n    () => getHasSchemaChange(schemaChangeData?.schemaChange),\n    [schemaChangeData],\n  );\n  const onOpenSchemaChange = () => {\n    schemaChangeModal.openModal();\n  };\n  const onResolveSchemaChange = (type: SchemaChangeType) => {\n    resolveSchemaChange({ variables: { where: { type } } });\n  };\n\n  const getModelGroupNode = createTreeGroupNode({\n    groupName: 'Models',\n    groupKey: 'models',\n    actions: [\n      {\n        key: 'trigger-schema-detection',\n        disabled: isDetecting,\n        icon: () => (\n          <ReloadOutlined\n            spin={isDetecting}\n            title={\n              schemaChangeData?.schemaChange.lastSchemaChangeTime\n                ? `Last refresh ${getRelativeTime(schemaChangeData?.schemaChange.lastSchemaChangeTime)}`\n                : ''\n            }\n            onClick={() => triggerDataSourceDetection()}\n          />\n        ),\n      },\n      {\n        key: 'add-model',\n        render: () => (\n          <GroupActionButton\n            data-guideid=\"add-model\"\n            data-testid=\"add-model\"\n            icon={<PlusOutlined />}\n            size=\"small\"\n            onClick={() => onOpenModelDrawer()}\n          >\n            New\n          </GroupActionButton>\n        ),\n      },\n    ],\n  });\n\n  const [tree, setTree] = useState<DataNode[]>(getModelGroupNode());\n\n  useEffect(() => {\n    setTree((_tree) =>\n      getModelGroupNode({\n        quotaUsage: models.length,\n        appendSlot: hasSchemaChange && (\n          <span className=\"adm-actionIcon mx-2\" onClick={onOpenSchemaChange}>\n            <WarningOutlined\n              className=\"orange-5\"\n              title=\"Review schema change impacts\"\n            />\n          </span>\n        ),\n        children: models.map((model) => {\n          const nodeKey = model.id;\n\n          const children = [\n            ...getColumnNode(nodeKey, [\n              ...model.fields,\n              ...model.calculatedFields,\n            ]),\n          ];\n\n          return {\n            children,\n            className: 'adm-treeNode',\n            icon: getNodeTypeIcon({ nodeType: model.nodeType }),\n            id: nodeKey,\n            isLeaf: false,\n            key: nodeKey,\n            title: <LabelTitle title={model.displayName} />,\n            type: model.nodeType,\n          };\n        }),\n      }),\n    );\n  }, [models, hasSchemaChange, schemaChangeData, isDetecting]);\n\n  return (\n    <>\n      <StyledSidebarTree {...props} treeData={tree} />\n      <SchemaChangeModal\n        {...schemaChangeModal.state}\n        defaultValue={schemaChangeData?.schemaChange}\n        payload={{ onResolveSchemaChange, isResolving }}\n        onClose={schemaChangeModal.closeModal}\n      />\n    </>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/sidebar/modeling/ViewTree.tsx",
    "content": "import Link from 'next/link';\nimport { useEffect, useState } from 'react';\nimport { Modal } from 'antd';\nimport { DataNode } from 'antd/es/tree';\nimport PlusOutlined from '@ant-design/icons/PlusOutlined';\nimport { Path } from '@/utils/enum';\nimport { DiagramView } from '@/utils/data';\nimport { getNodeTypeIcon } from '@/utils/nodeType';\nimport {\n  createTreeGroupNode,\n  getColumnNode,\n  GroupActionButton,\n} from '@/components/sidebar/utils';\nimport LabelTitle from '@/components/sidebar/LabelTitle';\nimport { StyledSidebarTree } from '@/components/sidebar/Modeling';\n\ninterface Props {\n  [key: string]: any;\n  views: DiagramView[];\n}\n\nexport default function ViewTree(props: Props) {\n  const { views } = props;\n\n  const onAddView = () => {\n    Modal.info({\n      title: 'How to create a View?',\n      content: (\n        <div>\n          Pose your questions at{' '}\n          <Link\n            href={Path.Home}\n            data-ph-capture=\"true\"\n            data-ph-capture-attribute-name=\"cta_add_view_navigate_to_home\"\n          >\n            homepage\n          </Link>\n          , and get some helpful answers to save as views.\n        </div>\n      ),\n      okButtonProps: {\n        ['data-ph-capture']: true,\n        ['data-ph-capture-attribute-name']: 'cta_add_view_ok_btn',\n      } as any,\n    });\n  };\n\n  const getViewGroupNode = createTreeGroupNode({\n    groupName: 'Views',\n    groupKey: 'views',\n    actions: [\n      {\n        key: 'add-view-info',\n        render: () => (\n          <GroupActionButton\n            icon={<PlusOutlined />}\n            size=\"small\"\n            onClick={onAddView}\n            data-ph-capture=\"true\"\n            data-ph-capture-attribute-name=\"cta_add_view\"\n          >\n            New\n          </GroupActionButton>\n        ),\n      },\n    ],\n  });\n\n  const [tree, setTree] = useState<DataNode[]>(getViewGroupNode());\n\n  useEffect(() => {\n    setTree((_tree) =>\n      getViewGroupNode({\n        quotaUsage: views.length,\n        children: views.map((view) => {\n          const nodeKey = view.id;\n          const children = getColumnNode(nodeKey, view.fields || []);\n\n          return {\n            children,\n            className: 'adm-treeNode',\n            icon: getNodeTypeIcon({ nodeType: view.nodeType }),\n            id: nodeKey,\n            isLeaf: false,\n            key: nodeKey,\n            title: <LabelTitle title={view.displayName} />,\n            type: view.nodeType,\n          };\n        }),\n      }),\n    );\n  }, [views]);\n\n  return <StyledSidebarTree {...props} treeData={tree} />;\n}\n"
  },
  {
    "path": "wren-ui/src/components/sidebar/utils.tsx",
    "content": "import styled from 'styled-components';\nimport { Button } from 'antd';\nimport { DataNode } from 'antd/lib/tree';\nimport { getColumnTypeIcon } from '@/utils/columnType';\nimport { PrimaryKeyIcon, RelationshipIcon } from '@/utils/icons';\nimport { ComposeDiagramField } from '@/utils/data';\nimport { assign, isEmpty, snakeCase, lowerCase } from 'lodash';\nimport GroupTreeTitle, { ActionType } from './modeling/GroupTreeTitle';\nimport { getJoinTypeText } from '@/utils/data';\nimport { NODE_TYPE } from '@/utils/enum';\nimport { getNodeTypeIcon } from '@/utils/nodeType';\n\ntype TreeNode = DataNode;\n\nconst ColumnNode = ({ title, relation, primary }) => {\n  const append = (\n    <>\n      {relation && (\n        <span\n          className=\"adm-treeNode--relation\"\n          title={`${relation.name}: ${getJoinTypeText(relation.joinType)}`}\n        >\n          <RelationshipIcon />\n        </span>\n      )}\n      {primary && (\n        <span className=\"adm-treeNode--primary\" title=\"Primary Key\">\n          <PrimaryKeyIcon />\n        </span>\n      )}\n    </>\n  );\n\n  return (\n    <>\n      <span title={title}>{title}</span>\n      {append}\n    </>\n  );\n};\n\nconst getChildrenSubtitle = (nodeKey: string, title: string) => [\n  {\n    title,\n    key: `${nodeKey}_${snakeCase(title)}`,\n    className: 'adm-treeNode--subtitle adm-treeNode--selectNone',\n    selectable: false,\n    isLeaf: true,\n  },\n];\n\nexport const getColumnNode = (\n  nodeKey: string,\n  columns: ComposeDiagramField[],\n  title?: string,\n): TreeNode[] => {\n  if (columns.length === 0) return [];\n\n  return [\n    ...(title ? getChildrenSubtitle(nodeKey, title) : []),\n    ...columns.map((column): TreeNode => {\n      // show the model icon for relation item\n      const isRelation = column.nodeType === NODE_TYPE.RELATION;\n      const icon = isRelation\n        ? getNodeTypeIcon({ nodeType: NODE_TYPE.MODEL })\n        : getColumnTypeIcon(column, { title: column.type });\n\n      return {\n        icon,\n        className: 'adm-treeNode adm-treeNode-column adm-treeNode--selectNode',\n        title: (\n          <ColumnNode\n            title={column.displayName}\n            relation={isRelation ? column : null}\n            primary={column?.isPrimaryKey}\n          />\n        ),\n        key: column.id,\n        selectable: false,\n        isLeaf: true,\n      };\n    }),\n  ];\n};\n\ninterface GroupSet {\n  groupName: string;\n  groupKey: string;\n  quotaUsage?: number;\n  appendSlot?: React.ReactNode;\n  children?: DataNode[];\n  actions: ActionType[];\n}\n\nexport const createTreeGroupNode =\n  (sourceData: GroupSet) => (updatedData?: Partial<GroupSet>) => {\n    const {\n      groupName = '',\n      groupKey = '',\n      quotaUsage,\n      actions,\n      children = [],\n      appendSlot,\n    } = assign(sourceData, updatedData);\n\n    const emptyChildren = [\n      {\n        title: `No ${lowerCase(groupName)}`,\n        key: `${groupKey}-empty`,\n        selectable: false,\n        className: 'adm-treeNode adm-treeNode--empty adm-treeNode--selectNode',\n      },\n    ];\n    const childrenData = isEmpty(children) ? emptyChildren : children;\n\n    return [\n      {\n        className: 'adm-treeNode--group',\n        title: (\n          <GroupTreeTitle\n            title={groupName}\n            quotaUsage={quotaUsage}\n            appendSlot={appendSlot}\n            actions={actions}\n          />\n        ),\n        key: groupKey,\n        selectable: false,\n        isLeaf: true,\n      },\n      ...childrenData,\n    ];\n  };\n\nexport const GroupActionButton = styled(Button)`\n  font-size: 12px;\n  height: auto;\n  background: transparent;\n  color: var(--gray-8);\n  &:hover {\n    background-color: transparent;\n  }\n  &:focus {\n    border-color: var(--gray-5);\n    background: transparent;\n    color: var(--gray-8);\n  }\n`;\n"
  },
  {
    "path": "wren-ui/src/components/table/BaseTable.tsx",
    "content": "import { useMemo } from 'react';\nimport { Table, TableProps, Row, Col } from 'antd';\nimport EllipsisWrapper from '@/components/EllipsisWrapper';\nimport SQLCodeBlock from '@/components/code/SQLCodeBlock';\nimport { getColumnTypeIcon } from '@/utils/columnType';\nimport { ComposeDiagramField, getJoinTypeText } from '@/utils/data';\nimport { makeIterable } from '@/utils/iteration';\n\nexport const COLUMN = {\n  ALIAS: {\n    title: 'Alias',\n    dataIndex: 'displayName',\n    key: 'alias',\n    ellipsis: true,\n    render: (name) => name || '-',\n  },\n  NAME: {\n    title: 'Name',\n    dataIndex: 'referenceName',\n    key: 'referenceName',\n    ellipsis: true,\n    render: (name) => name || '-',\n  },\n  TYPE: {\n    title: 'Type',\n    dataIndex: 'type',\n    render: (type) => {\n      return (\n        <div className=\"d-flex align-center\">\n          {getColumnTypeIcon({ type }, { className: 'mr-2' })}\n          {type}\n        </div>\n      );\n    },\n  },\n  EXPRESSION: {\n    title: 'Expression',\n    dataIndex: 'expression',\n    key: 'expression',\n    render: (expression) => {\n      return (\n        <EllipsisWrapper text={expression}>\n          <SQLCodeBlock code={expression} inline />\n        </EllipsisWrapper>\n      );\n    },\n  },\n  RELATION_FROM: {\n    title: 'From',\n    key: 'fromField',\n    ellipsis: true,\n    render: (relation) =>\n      `${relation.fromModelDisplayName}.${relation.fromColumnDisplayName}`,\n  },\n  RELATION_TO: {\n    title: 'To',\n    key: 'toField',\n    ellipsis: true,\n    render: (relation) =>\n      `${relation.toModelDisplayName}.${relation.toColumnDisplayName}`,\n  },\n  RELATION: {\n    title: 'Type',\n    dataIndex: 'type',\n    key: 'joinType',\n    render: (joinType) => getJoinTypeText(joinType),\n  },\n  DESCRIPTION: {\n    title: 'Description',\n    dataIndex: 'description',\n    key: 'description',\n    ellipsis: true,\n    render: (text) => text || '-',\n  },\n};\n\ntype BaseTableProps = TableProps<ComposeDiagramField>;\n\nexport type Props = BaseTableProps & {\n  showExpandable?: boolean;\n  actionColumns?: BaseTableProps['columns'];\n};\n\nexport default function BaseTable(props: Props) {\n  const { dataSource = [], columns = [], actionColumns, ...restProps } = props;\n\n  const tableColumns = useMemo(\n    () => columns.concat(actionColumns || []),\n    [dataSource],\n  );\n\n  const tableData = useMemo(\n    () =>\n      (dataSource || []).map((record, index) => ({\n        ...record,\n        key: `${record.id}-${index}`,\n      })),\n    [dataSource],\n  );\n\n  return (\n    <Table\n      {...restProps}\n      dataSource={tableData}\n      showHeader={tableData.length > 0}\n      columns={tableColumns}\n      pagination={{\n        hideOnSinglePage: true,\n        pageSize: 10,\n        size: 'small',\n      }}\n    />\n  );\n}\n\nconst ExpandableRowIterator = makeIterable((props) => {\n  const { title, value, index } = props;\n  return (\n    <>\n      {index > 0 && <div className=\"border-b border-gray-5\" />}\n      <Row wrap={false} className=\"py-1 px-2\">\n        <Col span={6} className=\"gray-6\">\n          {title}\n        </Col>\n        <Col style={{ wordBreak: 'break-word' }}>{value}</Col>\n      </Row>\n    </>\n  );\n});\n\nexport function ExpandableRows(props) {\n  const { data, extra } = props;\n  return (\n    <div className=\"pl-12 text-sm gray-8 -my-1\">\n      <ExpandableRowIterator data={data} />\n      {extra}\n    </div>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/table/CalculatedFieldTable.tsx",
    "content": "import BaseTable, {\n  Props,\n  COLUMN,\n  ExpandableRows,\n} from '@/components/table/BaseTable';\n\nexport default function CalculatedFieldTable(props: Props) {\n  const { columns, showExpandable } = props;\n  return (\n    <BaseTable\n      {...props}\n      columns={\n        columns || [\n          { ...COLUMN.NAME, dataIndex: 'displayName', width: 160 },\n          COLUMN.EXPRESSION,\n          { ...COLUMN.DESCRIPTION, width: 160 },\n        ]\n      }\n      expandable={\n        showExpandable\n          ? {\n              expandedRowRender: (record) => (\n                <ExpandableRows\n                  data={[\n                    { title: 'Description', value: record.description || '-' },\n                  ]}\n                />\n              ),\n            }\n          : null\n      }\n    />\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/table/EditableBaseTable.tsx",
    "content": "import React, { useEffect, useState } from 'react';\nimport { set, cloneDeep, isEmpty } from 'lodash';\nimport { COLUMN, Props as BaseTableProps } from '@/components/table/BaseTable';\nimport EditableWrapper from '@/components/EditableWrapper';\n\ntype Props = Omit<BaseTableProps, 'onChange'> & {\n  onChange?: (value: any) => void;\n};\n\nconst EditableCell = (props) => {\n  const {\n    className,\n    colSpan,\n    title,\n    editable,\n    record,\n    handleSave,\n    dataIndex,\n    children,\n  } = props;\n  const childNode = editable ? (\n    <EditableWrapper\n      record={record}\n      dataIndex={dataIndex}\n      handleSave={handleSave}\n    >\n      {children}\n    </EditableWrapper>\n  ) : (\n    children\n  );\n  return (\n    <td className={className} title={title} colSpan={colSpan}>\n      {childNode}\n    </td>\n  );\n};\n\nexport const makeEditableBaseTable = (BaseTable: React.FC<BaseTableProps>) => {\n  const EditableBaseTable = (props: Props) => {\n    const { columns, dataSource, onChange, ...restProps } = props;\n    const [data, setData] = useState(dataSource);\n    const components = {\n      body: { cell: !isEmpty(dataSource) ? EditableCell : undefined },\n    };\n\n    useEffect(() => {\n      onChange && onChange(data);\n    }, [data]);\n\n    const handleSave = (id: string, value: { [key: string]: string }) => {\n      const [dataIndexKey] = Object.keys(value);\n\n      // sync value back to data state\n      const newData = cloneDeep(data);\n      newData.forEach((item) => {\n        if (id === item.id) set(item, dataIndexKey, value[dataIndexKey]);\n      });\n\n      setData(newData);\n    };\n\n    const tableColumns = columns.map((column) => ({\n      ...column,\n      onCell: (record) => ({\n        editable: [COLUMN.ALIAS.title, COLUMN.DESCRIPTION.title].includes(\n          column.title as string,\n        ),\n        dataIndex: (column as any).dataIndex,\n        record,\n        handleSave,\n      }),\n    })) as Props['columns'];\n\n    return (\n      <BaseTable\n        {...restProps}\n        size=\"small\"\n        dataSource={data}\n        columns={tableColumns}\n        components={components}\n      />\n    );\n  };\n\n  return EditableBaseTable;\n};\n"
  },
  {
    "path": "wren-ui/src/components/table/FieldTable.tsx",
    "content": "import { Row, Col } from 'antd';\nimport BaseTable, {\n  Props,\n  COLUMN,\n  ExpandableRows,\n} from '@/components/table/BaseTable';\nimport NestedFieldTable from '@/components/table/NestedFieldTable';\n\nexport default function FieldTable(props: Props) {\n  const { columns, showExpandable, expandable } = props;\n  return (\n    <BaseTable\n      {...props}\n      columns={\n        columns || [COLUMN.NAME, COLUMN.ALIAS, COLUMN.TYPE, COLUMN.DESCRIPTION]\n      }\n      expandable={\n        showExpandable\n          ? expandable || {\n              expandedRowRender: (record) => {\n                return (\n                  <>\n                    <ExpandableRows\n                      data={[\n                        {\n                          title: 'Description',\n                          value: record.description || '-',\n                        },\n                      ]}\n                      extra={\n                        record.nestedFields && (\n                          <div>\n                            <Row wrap={false} className=\"py-1 px-2\">\n                              <Col span={6} className=\"gray-6\">\n                                Nested columns\n                              </Col>\n                              <Col style={{ wordBreak: 'break-word' }}>\n                                {record.nestedFields.length} column(s)\n                              </Col>\n                            </Row>\n                            <NestedFieldTable\n                              dataSource={record.nestedFields as any}\n                            />\n                          </div>\n                        )\n                      }\n                    />\n                  </>\n                );\n              },\n            }\n          : null\n      }\n    />\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/table/ModelRelationSelectionTable.tsx",
    "content": "import type { ColumnsType } from 'antd/es/table';\nimport { JOIN_TYPE } from '@/utils/enum';\nimport { ModelIcon } from '@/utils/icons';\nimport SelectionTable from '@/components/table/SelectionTable';\n\ninterface ModelField {\n  modelId: string;\n  modelName: string;\n  fieldId: string;\n  fieldName: string;\n}\n\nexport interface RelationsDataType {\n  name: string;\n  fromField: ModelField;\n  isAutoGenerated: boolean;\n  type: JOIN_TYPE;\n  toField: ModelField;\n  properties: Record<string, any>;\n}\n\ninterface Props {\n  columns: ColumnsType<RelationsDataType>;\n  dataSource: RelationsDataType[];\n  enableRowSelection?: boolean;\n  extra?: (\n    onCollapseOpen: (\n      event: React.MouseEvent<HTMLElement, MouseEvent>,\n      key: string,\n    ) => void,\n  ) => React.ReactNode;\n  onChange?: (value: any | null) => void;\n  tableTitle: string;\n  rowKey: (record: RelationsDataType) => string;\n}\n\nexport default function ModelRelationSelectionTable(props: Props) {\n  return (\n    <SelectionTable\n      {...props}\n      tableHeader={\n        <>\n          <ModelIcon className=\"pr-2 text-md\" />\n          {props.tableTitle}\n        </>\n      }\n    />\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/table/MultiSelectBox.tsx",
    "content": "import { useState, useMemo, useContext } from 'react';\nimport styled from 'styled-components';\nimport { isString, difference } from 'lodash';\nimport { Input, Table } from 'antd';\nimport { ColumnsType } from 'antd/lib/table';\nimport SearchOutlined from '@ant-design/icons/SearchOutlined';\nimport {\n  FormItemInputContext,\n  FormItemStatusContextProps,\n} from 'antd/lib/form/context';\n\nconst StyledBox = styled.div`\n  border: 1px solid var(--gray-5);\n  border-radius: 4px;\n\n  &.multiSelectBox-input-error {\n    border-color: var(--red-5);\n  }\n\n  .ant-table {\n    border: 0;\n  }\n  .ant-table-body,\n  .ant-table-placeholder {\n    height: 195px;\n  }\n`;\n\nconst StyledTotal = styled.div`\n  padding: 8px 12px;\n  border-bottom: 1px var(--gray-3) solid;\n`;\n\ninterface Props {\n  columns: ColumnsType<any>;\n  loading: boolean;\n  items: { [key: string]: any; value: string }[];\n  value?: string[];\n  onChange?: (value: string[]) => void;\n}\n\nexport default function MultiSelectBox(props: Props) {\n  const { columns, loading, items, onChange, value } = props;\n  const [selectedRowKeys, setSelectedRowKeys] = useState<Set<string>>(\n    new Set(value),\n  );\n  const [searchValue, setSearchValue] = useState<string>('');\n  const formItemContext =\n    useContext<FormItemStatusContextProps>(FormItemInputContext);\n  const { status } = formItemContext;\n\n  const dataSource = useMemo(() => {\n    return searchValue\n      ? items.filter((item) =>\n          columns\n            .map((column) => item[column['dataIndex']])\n            .some((value) => isString(value) && value.includes(searchValue)),\n        )\n      : items;\n  }, [items, searchValue]);\n\n  const onSelect = (rowKey: string) => {\n    const newSelectedRowKey = new Set(selectedRowKeys);\n    if (newSelectedRowKey.has(rowKey)) {\n      newSelectedRowKey.delete(rowKey);\n    } else {\n      newSelectedRowKey.add(rowKey);\n    }\n    setSelectedRowKeys(newSelectedRowKey);\n    onChange && onChange(Array.from(newSelectedRowKey));\n  };\n\n  const onSearchChange = (event) => {\n    event.persist();\n    const { value } = event.target;\n    setSearchValue(value);\n  };\n\n  const total =\n    selectedRowKeys.size === 0\n      ? items.length\n      : `${selectedRowKeys.size}/${items.length}`;\n\n  return (\n    <StyledBox\n      className={status ? `multiSelectBox-input-${status}` : undefined}\n    >\n      <StyledTotal>{total} table(s)</StyledTotal>\n      <div className=\"p-2\">\n        <Input\n          prefix={<SearchOutlined />}\n          onChange={onSearchChange}\n          placeholder=\"Search here\"\n          allowClear\n        />\n      </div>\n      <Table\n        rowSelection={{\n          type: 'checkbox',\n          selectedRowKeys: Array.from(selectedRowKeys),\n          onSelect: (record) => onSelect(record['value']),\n          onChange(keys) {\n            // deselect all\n            if (keys.length === 0) {\n              const tableKeys = dataSource.map((item) => item.value);\n              const newSelectedRowKeys = difference(\n                [...selectedRowKeys.values()],\n                tableKeys,\n              );\n              const newSelectedRowKeySet = new Set(newSelectedRowKeys);\n              setSelectedRowKeys(newSelectedRowKeySet);\n              onChange && onChange(Array.from(newSelectedRowKeySet));\n              return;\n            }\n            // select all\n            if (keys.length === dataSource.length) {\n              const newSelectedRowKeys = [\n                ...selectedRowKeys,\n                ...(keys as string[]),\n              ];\n              const newSelectedRowKeysSet = new Set(newSelectedRowKeys);\n              setSelectedRowKeys(newSelectedRowKeysSet);\n              onChange && onChange(Array.from(newSelectedRowKeysSet));\n            }\n          },\n        }}\n        rowKey={(record) => record.value}\n        columns={columns}\n        dataSource={dataSource}\n        scroll={{ y: 195 }}\n        pagination={false}\n        loading={loading}\n      />\n    </StyledBox>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/table/NestedFieldTable.tsx",
    "content": "import { COLUMN } from '@/components/table/BaseTable';\nimport { Table, TableProps } from 'antd';\nimport { DiagramModelNestedField } from '@/apollo/client/graphql/__types__';\n\ntype Props = TableProps<DiagramModelNestedField>;\n\nexport default function NestedFieldTable(props: Props) {\n  const { columns } = props;\n  return (\n    <Table\n      {...props}\n      columns={\n        columns || [\n          { ...COLUMN.NAME, width: 70 },\n          { ...COLUMN.ALIAS, width: 70 },\n          { ...COLUMN.TYPE, width: 45 },\n          { ...COLUMN.DESCRIPTION, width: 80 },\n        ]\n      }\n      className=\"ant-table--text-sm ml-2\"\n      scroll={{ x: 600 }}\n      size=\"small\"\n      pagination={{\n        hideOnSinglePage: true,\n        size: 'small',\n        pageSize: 10,\n      }}\n    />\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/table/RelationTable.tsx",
    "content": "import BaseTable, {\n  Props,\n  COLUMN,\n  ExpandableRows,\n} from '@/components/table/BaseTable';\n\nexport default function RelationTable(props: Props) {\n  const { columns, showExpandable } = props;\n  return (\n    <BaseTable\n      {...props}\n      columns={\n        columns || [\n          { ...COLUMN.NAME, dataIndex: 'displayName' },\n          COLUMN.RELATION_FROM,\n          COLUMN.RELATION_TO,\n          COLUMN.RELATION,\n          { ...COLUMN.DESCRIPTION, width: 160 },\n        ]\n      }\n      expandable={\n        showExpandable\n          ? {\n              expandedRowRender: (record) => (\n                <ExpandableRows\n                  data={[\n                    {\n                      title: 'From',\n                      value: `${record.fromModelDisplayName}.${record.fromColumnDisplayName}`,\n                    },\n                    {\n                      title: 'To',\n                      value: `${record.toModelDisplayName}.${record.toColumnDisplayName}`,\n                    },\n                    { title: 'Description', value: record.description || '-' },\n                  ]}\n                />\n              ),\n            }\n          : null\n      }\n    />\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/components/table/SelectionTable.tsx",
    "content": "import { forwardRef, useContext, useState } from 'react';\nimport styled from 'styled-components';\nimport { Collapse, Row, RowProps, Table, TableProps } from 'antd';\nimport {\n  FormItemInputContext,\n  FormItemStatusContextProps,\n} from 'antd/lib/form/context';\n\nconst { Panel } = Collapse;\n\nconst StyledCollapse = styled(Collapse)`\n  &.ant-collapse.adm-error {\n    border-color: var(--red-5);\n    border-bottom: 1px solid var(--red-5);\n  }\n\n  &.ant-collapse {\n    background-color: white;\n    border-color: var(--gray-4);\n\n    > .ant-collapse-item > .ant-collapse-header {\n      padding: 16px 12px;\n      align-items: center;\n    }\n\n    > .ant-collapse-item,\n    .ant-collapse-content {\n      border-color: var(--gray-4);\n    }\n\n    .ant-collapse-content-box {\n      padding: 0px;\n    }\n\n    .ant-table {\n      border: none;\n\n      .ant-table-thead > tr > th {\n        color: var(--gray-7);\n        background-color: white;\n      }\n\n      &.ant-table-empty {\n        .ant-empty-normal {\n          margin: 16px 0;\n        }\n      }\n    }\n  }\n`;\n\nconst StyledRow = styled(Row).attrs<{\n  $isRowSelection: boolean;\n}>((props) => ({\n  className: `${props.$isRowSelection ? '' : 'ml-1'}`,\n}))`` as React.ForwardRefExoticComponent<\n  RowProps & React.RefAttributes<HTMLDivElement> & { $isRowSelection: boolean }\n>;\n\ntype Props<T> = TableProps<T> & {\n  enableRowSelection?: boolean;\n  extra?: (\n    onCollapseOpen: (\n      event: React.MouseEvent<HTMLElement, MouseEvent>,\n      collapseKey: string,\n    ) => void,\n  ) => React.ReactNode;\n  onChange?: (value: any | null) => void;\n  rowKey: (record: T) => string;\n  tableTitle: string;\n  tableHeader: React.ReactNode;\n};\n\nfunction SelectionTable<T extends Record<string, any>>(\n  props: Props<T>,\n  ref: React.Ref<HTMLDivElement>,\n) {\n  const {\n    columns,\n    dataSource,\n    extra,\n    enableRowSelection,\n    onChange,\n    rowKey,\n    tableHeader,\n    tableTitle,\n  } = props;\n\n  const formItemContext =\n    useContext<FormItemStatusContextProps>(FormItemInputContext);\n  const { status } = formItemContext;\n\n  const collapseState = useCollapseState(tableTitle);\n\n  const isRowSelection = Boolean(enableRowSelection);\n\n  const rowSelection: TableProps<T>['rowSelection'] = isRowSelection\n    ? {\n        type: 'checkbox',\n        onChange: (_selectedRowKeys: React.Key[], selectedRows) => {\n          onChange && onChange(selectedRows);\n        },\n      }\n    : undefined;\n\n  return (\n    <StyledCollapse\n      className={status ? `adm-${status}` : ''}\n      defaultActiveKey={collapseState.collapseDefaultActiveKey}\n      onChange={collapseState.onChangeCollapsePanelState}\n    >\n      <Panel\n        extra={extra && extra(collapseState.onCollapseOpen)}\n        header={\n          <StyledRow\n            wrap={false}\n            gutter={8}\n            align=\"middle\"\n            $isRowSelection={isRowSelection}\n          >\n            {tableHeader}\n          </StyledRow>\n        }\n        key={tableTitle}\n        showArrow={false}\n      >\n        <Table\n          ref={ref}\n          columns={columns}\n          dataSource={dataSource}\n          rowKey={rowKey}\n          rowSelection={rowSelection}\n          pagination={{ hideOnSinglePage: true, pageSize: 50, size: 'small' }}\n        />\n      </Panel>\n    </StyledCollapse>\n  );\n}\n\nexport default forwardRef(SelectionTable);\n\nfunction useCollapseState(tableTitleName: string) {\n  const [collapseDefaultActiveKey, setCollapseDefaultActiveKey] = useState<\n    string[]\n  >([tableTitleName]);\n\n  const onChangeCollapsePanelState = (key: string | string[]) =>\n    setCollapseDefaultActiveKey(key as string[]);\n\n  const onCollapseOpen = (\n    event: React.MouseEvent<HTMLElement, MouseEvent>,\n    collapseKey: string,\n  ) => {\n    // Make sure the panel is open\n    onChangeCollapsePanelState([collapseKey]);\n    if (collapseDefaultActiveKey.includes(collapseKey)) {\n      event.stopPropagation();\n    }\n  };\n\n  return {\n    collapseDefaultActiveKey,\n    onChangeCollapsePanelState,\n    onCollapseOpen,\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/components/table/TableTransfer.tsx",
    "content": "import React from 'react';\nimport styled from 'styled-components';\nimport { Table, Transfer, Tag } from 'antd';\nimport difference from 'lodash/difference';\nimport { TransferItem, TransferProps } from 'antd/es/transfer';\nimport { ColumnsType, TableRowSelection } from 'antd/es/table/interface';\n\nconst StyledTable = styled(Table)`\n  .ant-table-row {\n    cursor: pointer;\n  }\n  .ant-table-row-disabled {\n    cursor: not-allowed;\n    color: var(--gray-5);\n    .ant-tag {\n      color: var(--gray-5);\n    }\n  }\n`;\n\n// default left and right columns\nexport const defaultColumns = [\n  {\n    dataIndex: 'name',\n    title: 'Column Name',\n  },\n  {\n    dataIndex: 'type',\n    title: 'Column Type',\n    render: (type: string) => <Tag>{type.toUpperCase()}</Tag>,\n  },\n];\n\ninterface TableTransferProps extends TransferProps<TransferItem> {\n  dataSource: any[];\n  leftColumns?: ColumnsType<any>;\n  rightColumns?: ColumnsType<any>;\n}\n\nconst TableTransfer = (\n  {\n    leftColumns = defaultColumns,\n    rightColumns = defaultColumns,\n    ...restProps\n  }: TableTransferProps,\n  ref: any,\n) => {\n  return (\n    <Transfer {...restProps} showSelectAll={false} listStyle={{ height: 332 }}>\n      {({\n        direction,\n        filteredItems,\n        onItemSelectAll,\n        onItemSelect,\n        selectedKeys: listSelectedKeys,\n        disabled: listDisabled,\n      }) => {\n        const columns = direction === 'left' ? leftColumns : rightColumns;\n\n        const rowSelection: TableRowSelection<TransferItem> = {\n          getCheckboxProps: (item) => ({\n            disabled: listDisabled || item.disabled,\n          }),\n          onSelectAll(selected, selectedRows) {\n            const treeSelectedKeys = selectedRows\n              .filter((item) => !item.disabled)\n              .map(({ key }) => key);\n            const diffKeys = selected\n              ? difference(treeSelectedKeys, listSelectedKeys)\n              : difference(listSelectedKeys, treeSelectedKeys);\n            onItemSelectAll(diffKeys as string[], selected);\n          },\n          onSelect({ key }, selected) {\n            onItemSelect(key as string, selected);\n          },\n          selectedRowKeys: listSelectedKeys,\n        };\n\n        return (\n          <div ref={ref}>\n            <StyledTable\n              rowSelection={rowSelection}\n              columns={columns}\n              dataSource={filteredItems}\n              size=\"small\"\n              style={\n                {\n                  pointerEvents: listDisabled ? 'none' : null,\n                } as React.CSSProperties\n              }\n              onRow={({ key, disabled: itemDisabled, title }: any) => ({\n                title,\n                onClick: () => {\n                  if (itemDisabled || listDisabled) return;\n                  onItemSelect(\n                    key as string,\n                    !listSelectedKeys.includes(key as string),\n                  );\n                },\n              })}\n              rowClassName={({ disabled: itemDisabled }: any) =>\n                itemDisabled ? 'ant-table-row-disabled' : ''\n              }\n              scroll={{ y: 200 }}\n              pagination={false}\n            />\n          </div>\n        );\n      }}\n    </Transfer>\n  );\n};\n\nexport default React.forwardRef(TableTransfer);\n"
  },
  {
    "path": "wren-ui/src/hooks/.gitkeep",
    "content": ""
  },
  {
    "path": "wren-ui/src/hooks/useAdjustAnswer.tsx",
    "content": "import { useEffect, useMemo } from 'react';\nimport { cloneDeep } from 'lodash';\nimport { ApolloClient, NormalizedCacheObject } from '@apollo/client';\nimport { THREAD } from '@/apollo/client/graphql/home';\nimport { nextTick } from '@/utils/time';\nimport {\n  useAdjustThreadResponseMutation,\n  useCancelAdjustmentTaskMutation,\n  useRerunAdjustmentTaskMutation,\n  useThreadResponseLazyQuery,\n} from '@/apollo/client/graphql/home.generated';\nimport {\n  AskingTaskStatus,\n  DetailedThread,\n  ThreadResponse,\n} from '@/apollo/client/graphql/__types__';\n\nexport const getIsFinished = (status: AskingTaskStatus) =>\n  [\n    AskingTaskStatus.FINISHED,\n    AskingTaskStatus.FAILED,\n    AskingTaskStatus.STOPPED,\n  ].includes(status);\n\nconst handleUpdateThreadCache = (\n  threadId: number,\n  threadResponse: ThreadResponse,\n  client: ApolloClient<NormalizedCacheObject>,\n) => {\n  const result = client.cache.readQuery<{ thread: DetailedThread }>({\n    query: THREAD,\n    variables: { threadId },\n  });\n\n  if (result?.thread) {\n    client.cache.updateQuery(\n      {\n        query: THREAD,\n        variables: { threadId },\n      },\n      (existingData) => {\n        const isNewResponse = !existingData.thread.responses\n          .map((r) => r.id)\n          .includes(threadResponse.id);\n        return {\n          thread: {\n            ...existingData.thread,\n            responses: isNewResponse\n              ? [...existingData.thread.responses, threadResponse]\n              : existingData.thread.responses.map((response) => {\n                  return response.id === threadResponse.id\n                    ? cloneDeep(threadResponse)\n                    : response;\n                }),\n          },\n        };\n      },\n    );\n  }\n};\n\nexport default function useAdjustAnswer(threadId?: number) {\n  const [cancelAdjustmentTask] = useCancelAdjustmentTaskMutation({\n    onError: (error) => console.error(error),\n  });\n  const [rerunAdjustmentTask] = useRerunAdjustmentTaskMutation({\n    onError: (error) => console.error(error),\n  });\n  const [adjustThreadResponse, adjustThreadResponseResult] =\n    useAdjustThreadResponseMutation({\n      onError: (error) => console.error(error),\n    });\n  const [fetchThreadResponse, threadResponseResult] =\n    useThreadResponseLazyQuery({\n      pollInterval: 1000,\n    });\n\n  const loading = adjustThreadResponseResult.loading;\n\n  const adjustmentTask = useMemo(() => {\n    return threadResponseResult.data?.threadResponse.adjustmentTask || null;\n  }, [threadResponseResult.data]);\n\n  const data = useMemo(() => {\n    return {\n      adjustmentTask,\n    };\n  }, [adjustmentTask]);\n\n  useEffect(() => {\n    const isFinished = getIsFinished(adjustmentTask?.status);\n    if (isFinished) threadResponseResult.stopPolling();\n  }, [adjustmentTask?.status]);\n\n  const onAdjustReasoningSteps = async (\n    responseId: number,\n    input: { tables: string[]; sqlGenerationReasoning: string },\n  ) => {\n    const response = await adjustThreadResponse({\n      variables: {\n        responseId,\n        data: {\n          tables: input.tables,\n          sqlGenerationReasoning: input.sqlGenerationReasoning,\n        },\n      },\n    });\n\n    // start polling new thread response\n    const nextThreadResponse = response.data?.adjustThreadResponse;\n    await fetchThreadResponse({\n      variables: { responseId: nextThreadResponse.id },\n    });\n\n    // update new thread response to cache\n    handleUpdateThreadCache(\n      threadId,\n      nextThreadResponse,\n      threadResponseResult.client,\n    );\n  };\n\n  const onAdjustSQL = async (responseId: number, sql: string) => {\n    const response = await adjustThreadResponse({\n      variables: { responseId, data: { sql } },\n    });\n\n    // update thread cache\n    const nextThreadResponse = response.data?.adjustThreadResponse;\n    handleUpdateThreadCache(\n      threadId,\n      nextThreadResponse,\n      threadResponseResult.client,\n    );\n\n    // It won't have adjusmentTask, no need to fetch\n  };\n\n  const onStop = async (queryId?: string) => {\n    const taskId =\n      queryId ||\n      adjustThreadResponseResult.data?.adjustThreadResponse?.adjustmentTask\n        ?.queryId;\n    if (taskId) {\n      await cancelAdjustmentTask({ variables: { taskId } });\n      // waiting for polling fetching stop\n      await nextTick(1000);\n    }\n  };\n\n  const onReRun = async (threadResponse: ThreadResponse) => {\n    const responseId = threadResponse.id;\n    await rerunAdjustmentTask({ variables: { responseId } });\n    await fetchThreadResponse({ variables: { responseId } });\n  };\n\n  return {\n    data,\n    loading,\n    onAdjustReasoningSteps,\n    onAdjustSQL,\n    onStop,\n    onReRun,\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useAskProcessState.tsx",
    "content": "import { useState } from 'react';\nimport { PROCESS_STATE } from '@/utils/enum';\nimport {\n  AskingTask,\n  AskingTaskStatus,\n  AskingTaskType,\n} from '@/apollo/client/graphql/__types__';\n\nexport const getIsProcessing = (status: PROCESS_STATE) =>\n  [\n    PROCESS_STATE.UNDERSTANDING,\n    PROCESS_STATE.SEARCHING,\n    PROCESS_STATE.PLANNING,\n    PROCESS_STATE.GENERATING,\n    PROCESS_STATE.CORRECTING,\n  ].includes(status);\n\nexport const convertAskingTaskToProcessState = (data: AskingTask) => {\n  if (!data) return null;\n\n  const processState = {\n    [AskingTaskStatus.UNDERSTANDING]: PROCESS_STATE.UNDERSTANDING,\n    [AskingTaskStatus.SEARCHING]: PROCESS_STATE.SEARCHING,\n    [AskingTaskStatus.PLANNING]: PROCESS_STATE.PLANNING,\n    [AskingTaskStatus.GENERATING]: PROCESS_STATE.GENERATING,\n    [AskingTaskStatus.CORRECTING]: PROCESS_STATE.CORRECTING,\n    [AskingTaskStatus.FINISHED]: PROCESS_STATE.FINISHED,\n    [AskingTaskStatus.STOPPED]: PROCESS_STATE.STOPPED,\n    [AskingTaskStatus.FAILED]: PROCESS_STATE.FAILED,\n  }[data.status];\n\n  if (\n    data?.type === AskingTaskType.TEXT_TO_SQL &&\n    processState === PROCESS_STATE.FINISHED &&\n    data.candidates.length === 0\n  ) {\n    return PROCESS_STATE.NO_RESULT;\n  }\n  return processState;\n};\n\nexport default function useAskProcessState() {\n  const [currentState, setCurrentState] = useState<PROCESS_STATE>(\n    PROCESS_STATE.IDLE,\n  );\n\n  const resetState = () => {\n    setCurrentState(PROCESS_STATE.IDLE);\n  };\n\n  const matchedState = (askingTask: AskingTask) => {\n    const targetState = convertAskingTaskToProcessState(askingTask);\n    if (!targetState || targetState === currentState) return currentState;\n    // Prevent unknown status, if not found we keep the current state\n    if (ProcessStateMachine.canTransition(currentState, targetState)) {\n      return targetState;\n    } else {\n      console.warn(\n        `Invalid transition from ${currentState} to ${targetState}.`,\n      );\n      return currentState;\n    }\n  };\n\n  const transitionTo = (targetState: PROCESS_STATE) => {\n    setCurrentState(targetState);\n  };\n\n  const isFinished = () => {\n    return currentState === PROCESS_STATE.FINISHED;\n  };\n\n  const isFailed = () => {\n    return currentState === PROCESS_STATE.FAILED;\n  };\n\n  return {\n    currentState,\n    resetState,\n    matchedState,\n    transitionTo,\n    isFinished,\n    isFailed,\n  };\n}\n\nexport class ProcessStateMachine {\n  private static transitions = {\n    [PROCESS_STATE.IDLE]: {\n      next: [PROCESS_STATE.UNDERSTANDING],\n      prev: [],\n    },\n    [PROCESS_STATE.UNDERSTANDING]: {\n      // probably skipped status if polling delay longer than AI processing time\n      // so need to allow all possible statuses\n      next: [\n        PROCESS_STATE.SEARCHING,\n        PROCESS_STATE.PLANNING,\n        PROCESS_STATE.GENERATING,\n      ],\n      prev: [PROCESS_STATE.IDLE],\n    },\n    [PROCESS_STATE.SEARCHING]: {\n      next: [PROCESS_STATE.PLANNING],\n      prev: [PROCESS_STATE.UNDERSTANDING],\n    },\n    [PROCESS_STATE.PLANNING]: {\n      next: [PROCESS_STATE.GENERATING],\n      prev: [PROCESS_STATE.SEARCHING],\n    },\n    [PROCESS_STATE.GENERATING]: {\n      next: [\n        PROCESS_STATE.CORRECTING,\n        PROCESS_STATE.FINISHED,\n        PROCESS_STATE.FAILED,\n      ],\n      prev: [PROCESS_STATE.PLANNING],\n    },\n    [PROCESS_STATE.CORRECTING]: {\n      next: [PROCESS_STATE.FINISHED, PROCESS_STATE.FAILED],\n      prev: [PROCESS_STATE.GENERATING],\n    },\n    [PROCESS_STATE.FINISHED]: {\n      next: [],\n      prev: [PROCESS_STATE.GENERATING, PROCESS_STATE.CORRECTING],\n    },\n  };\n\n  static canTransition(from: PROCESS_STATE, to: PROCESS_STATE) {\n    // Allow transition to FINISHED & FAILED state from any state\n    return (\n      from === PROCESS_STATE.IDLE ||\n      to === PROCESS_STATE.FINISHED ||\n      to === PROCESS_STATE.FAILED ||\n      to === PROCESS_STATE.STOPPED ||\n      this.transitions[from]?.next.includes(to)\n    );\n  }\n\n  static getAllNextStates(state: PROCESS_STATE, includeSelf = false) {\n    const allNextStates = new Set<PROCESS_STATE>(includeSelf ? [state] : []);\n    const collectNextStates = (currentState: PROCESS_STATE) => {\n      const nextStates = this.transitions[currentState]?.next || [];\n      nextStates.forEach((nextState) => {\n        if (!allNextStates.has(nextState)) {\n          allNextStates.add(nextState);\n          collectNextStates(nextState);\n        }\n      });\n    };\n    collectNextStates(state);\n    return Array.from(allNextStates);\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useAskPrompt.tsx",
    "content": "import { useCallback, useEffect, useMemo, useState } from 'react';\nimport { cloneDeep, uniq } from 'lodash';\nimport {\n  AdjustmentTask,\n  AskingTask,\n  AskingTaskStatus,\n  AskingTaskType,\n  DetailedThread,\n  RecommendedQuestionsTask,\n  RecommendedQuestionsTaskStatus,\n  ThreadResponse,\n} from '@/apollo/client/graphql/__types__';\nimport {\n  useAskingTaskLazyQuery,\n  useCancelAskingTaskMutation,\n  useCreateAskingTaskMutation,\n  useRerunAskingTaskMutation,\n  useCreateInstantRecommendedQuestionsMutation,\n  useInstantRecommendedQuestionsLazyQuery,\n} from '@/apollo/client/graphql/home.generated';\nimport useAskingStreamTask from './useAskingStreamTask';\nimport { THREAD } from '@/apollo/client/graphql/home';\nimport { ApolloClient, NormalizedCacheObject } from '@apollo/client';\nimport { nextTick } from '@/utils/time';\n\nexport interface AskPromptData {\n  originalQuestion: string;\n  askingTask?: AskingTask;\n  askingStreamTask?: string;\n  recommendedQuestions?: RecommendedQuestionsTask;\n}\n\nexport const getIsFinished = (status: AskingTaskStatus) =>\n  [\n    AskingTaskStatus.FINISHED,\n    AskingTaskStatus.FAILED,\n    AskingTaskStatus.STOPPED,\n  ].includes(status);\n\nexport const canGenerateAnswer = (\n  askingTask: AskingTask,\n  adjustmentTask: AdjustmentTask,\n) =>\n  (askingTask === null && adjustmentTask === null) ||\n  askingTask?.status === AskingTaskStatus.FINISHED ||\n  adjustmentTask?.status === AskingTaskStatus.FINISHED;\n\nexport const canFetchThreadResponse = (askingTask: AskingTask) =>\n  askingTask !== null &&\n  askingTask?.status !== AskingTaskStatus.FAILED &&\n  askingTask?.status !== AskingTaskStatus.STOPPED;\n\nexport const isReadyToThreadResponse = (askingTask: AskingTask) =>\n  askingTask?.status === AskingTaskStatus.SEARCHING &&\n  askingTask?.type === AskingTaskType.TEXT_TO_SQL;\n\nexport const isRecommendedFinished = (status: RecommendedQuestionsTaskStatus) =>\n  [\n    RecommendedQuestionsTaskStatus.FINISHED,\n    RecommendedQuestionsTaskStatus.FAILED,\n\n    // for existing thread response & existing projects that are not executed to generate recommendation questions\n    RecommendedQuestionsTaskStatus.NOT_STARTED,\n  ].includes(status);\n\nconst isNeedRecommendedQuestions = (askingTask: AskingTask) => {\n  const isGeneralOrMisleadingQuery = [\n    AskingTaskType.GENERAL,\n    AskingTaskType.MISLEADING_QUERY,\n  ].includes(askingTask?.type);\n  const isFailed =\n    askingTask?.type !== AskingTaskType.TEXT_TO_SQL &&\n    askingTask?.status === AskingTaskStatus.FAILED;\n  return isGeneralOrMisleadingQuery || isFailed;\n};\n\nconst isNeedPreparing = (askingTask: AskingTask) =>\n  askingTask?.type === AskingTaskType.TEXT_TO_SQL;\n\nconst handleUpdateThreadCache = (\n  threadId: number,\n  askingTask: AskingTask,\n  client: ApolloClient<NormalizedCacheObject>,\n) => {\n  if (!askingTask) return;\n\n  const result = client.cache.readQuery<{ thread: DetailedThread }>({\n    query: THREAD,\n    variables: { threadId },\n  });\n\n  if (result?.thread) {\n    client.cache.updateQuery(\n      {\n        query: THREAD,\n        variables: { threadId },\n      },\n      (existingData) => {\n        return {\n          thread: {\n            ...existingData.thread,\n            responses: existingData.thread.responses.map((response) => {\n              if (response.askingTask?.queryId === askingTask?.queryId) {\n                return {\n                  ...response,\n                  askingTask: cloneDeep(askingTask),\n                };\n              }\n              return response;\n            }),\n          },\n        };\n      },\n    );\n  }\n};\n\nconst handleUpdateRerunAskingTaskCache = (\n  threadId: number,\n  threadResponseId: number,\n  askingTask: AskingTask,\n  client: ApolloClient<NormalizedCacheObject>,\n) => {\n  if (!askingTask) return;\n\n  const result = client.cache.readQuery<{ thread: DetailedThread }>({\n    query: THREAD,\n    variables: { threadId },\n  });\n\n  if (result?.thread) {\n    const task = cloneDeep(askingTask);\n    // bypass understanding status to thread response\n    if (task.status === AskingTaskStatus.UNDERSTANDING) {\n      task.status = AskingTaskStatus.SEARCHING;\n      task.type = AskingTaskType.TEXT_TO_SQL;\n    }\n    client.cache.updateQuery(\n      {\n        query: THREAD,\n        variables: { threadId },\n      },\n      (existingData) => {\n        return {\n          thread: {\n            ...existingData.thread,\n            responses: existingData.thread.responses.map((response) => {\n              if (response.id === threadResponseId) {\n                return { ...response, askingTask: task };\n              }\n              return response;\n            }),\n          },\n        };\n      },\n    );\n  }\n};\n\nexport default function useAskPrompt(threadId?: number) {\n  const [originalQuestion, setOriginalQuestion] = useState<string>('');\n  const [threadQuestions, setThreadQuestions] = useState<string[]>([]);\n  // Handle errors via try/catch blocks rather than onError callback\n  const [createAskingTask, createAskingTaskResult] =\n    useCreateAskingTaskMutation();\n  const [cancelAskingTask] = useCancelAskingTaskMutation({\n    onError: (error) => console.error(error),\n  });\n  const [rerunAskingTask] = useRerunAskingTaskMutation({\n    onError: (error) => console.error(error),\n  });\n  const [fetchAskingTask, askingTaskResult] = useAskingTaskLazyQuery({\n    pollInterval: 1000,\n  });\n  const [fetchAskingStreamTask, askingStreamTaskResult] = useAskingStreamTask();\n  const [createInstantRecommendedQuestions] =\n    useCreateInstantRecommendedQuestionsMutation({\n      onError: (error) => console.error(error),\n    });\n  const [fetchInstantRecommendedQuestions, instantRecommendedQuestionsResult] =\n    useInstantRecommendedQuestionsLazyQuery({\n      pollInterval: 1000,\n    });\n\n  const askingTask = useMemo(\n    () => askingTaskResult.data?.askingTask || null,\n    [askingTaskResult.data],\n  );\n  const askingTaskType = useMemo(() => askingTask?.type, [askingTask?.type]);\n  const askingStreamTask = askingStreamTaskResult.data;\n  const recommendedQuestions = useMemo(\n    () =>\n      instantRecommendedQuestionsResult.data?.instantRecommendedQuestions ||\n      null,\n    [instantRecommendedQuestionsResult.data],\n  );\n\n  const loading = askingStreamTaskResult.loading;\n\n  const data = useMemo(\n    () => ({\n      originalQuestion,\n      askingTask,\n      askingStreamTask,\n      recommendedQuestions,\n    }),\n    [originalQuestion, askingTask, askingStreamTask, recommendedQuestions],\n  );\n\n  const startRecommendedQuestions = useCallback(async () => {\n    const previousQuestions = [\n      // slice the last 5 questions in threadQuestions\n      ...uniq(threadQuestions).slice(-5),\n      originalQuestion,\n    ];\n    const response = await createInstantRecommendedQuestions({\n      variables: { data: { previousQuestions } },\n    });\n    fetchInstantRecommendedQuestions({\n      variables: { taskId: response.data.createInstantRecommendedQuestions.id },\n    });\n  }, [originalQuestion]);\n\n  const checkFetchAskingStreamTask = useCallback(\n    (task: AskingTask) => {\n      if (!askingStreamTask && task.status === AskingTaskStatus.PLANNING) {\n        fetchAskingStreamTask(task.queryId);\n      }\n    },\n    [askingStreamTask],\n  );\n\n  useEffect(() => {\n    const isFinished = getIsFinished(askingTask?.status);\n    if (isFinished) askingTaskResult.stopPolling();\n\n    // handle update cache for preparing component\n    if (isNeedPreparing(askingTask)) {\n      if (threadId) {\n        handleUpdateThreadCache(threadId, askingTask, askingTaskResult.client);\n        checkFetchAskingStreamTask(askingTask);\n      }\n    }\n  }, [askingTask?.status, threadId, checkFetchAskingStreamTask]);\n\n  useEffect(() => {\n    // handle instant recommended questions\n    if (isNeedRecommendedQuestions(askingTask)) {\n      startRecommendedQuestions();\n    }\n  }, [askingTask?.type]);\n\n  useEffect(() => {\n    if (isRecommendedFinished(recommendedQuestions?.status))\n      instantRecommendedQuestionsResult.stopPolling();\n  }, [recommendedQuestions]);\n\n  useEffect(() => {\n    const taskId = createAskingTaskResult.data?.createAskingTask.id;\n    if (taskId && askingTaskType === AskingTaskType.GENERAL) {\n      fetchAskingStreamTask(taskId);\n    }\n  }, [askingTaskType, createAskingTaskResult.data]);\n\n  const onStop = async (queryId?: string) => {\n    const taskId = queryId || createAskingTaskResult.data?.createAskingTask.id;\n    if (taskId) {\n      await cancelAskingTask({ variables: { taskId } }).catch((error) =>\n        console.error(error),\n      );\n      // waiting for polling fetching stop\n      await nextTick(1000);\n    }\n  };\n\n  const onReRun = async (threadResponse: ThreadResponse) => {\n    askingStreamTaskResult.reset();\n    setOriginalQuestion(threadResponse.question);\n    try {\n      const response = await rerunAskingTask({\n        variables: { responseId: threadResponse.id },\n      });\n      const { data } = await fetchAskingTask({\n        variables: { taskId: response.data.rerunAskingTask.id },\n      });\n      // update the asking task in cache manually\n      handleUpdateRerunAskingTaskCache(\n        threadId,\n        threadResponse.id,\n        data.askingTask,\n        askingTaskResult.client,\n      );\n    } catch (error) {\n      console.error(error);\n    }\n  };\n\n  const onSubmit = async (value) => {\n    askingStreamTaskResult.reset();\n    setOriginalQuestion(value);\n    try {\n      const response = await createAskingTask({\n        variables: { data: { question: value, threadId } },\n      });\n      await fetchAskingTask({\n        variables: { taskId: response.data.createAskingTask.id },\n      });\n    } catch (error) {\n      console.error(error);\n    }\n  };\n\n  const onFetching = async (queryId: string) => {\n    await fetchAskingTask({\n      variables: { taskId: queryId },\n    });\n  };\n\n  const onStopPolling = () => askingTaskResult.stopPolling();\n\n  const onStopStreaming = () => askingStreamTaskResult.reset();\n\n  const onStopRecommend = () => instantRecommendedQuestionsResult.stopPolling();\n\n  const onStoreThreadQuestions = (questions: string[]) =>\n    setThreadQuestions(questions);\n\n  return {\n    data,\n    loading,\n    onStop,\n    onReRun,\n    onSubmit,\n    onFetching,\n    onStopPolling,\n    onStopStreaming,\n    onStopRecommend,\n    onStoreThreadQuestions,\n    inputProps: {\n      placeholder: threadId\n        ? 'Ask follow-up questions to explore your data'\n        : 'Ask to explore your data',\n    },\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useAskingStreamTask.tsx",
    "content": "import { useRef, useState } from 'react';\n\ntype useAskingStreamTaskReturn = [\n  (queryId: string) => void,\n  { data: string; loading: boolean; reset: () => void },\n];\n\nexport default function useAskingStreamTask() {\n  const eventSourceRef = useRef<EventSource | null>(null);\n  const [loading, setLoading] = useState<boolean>(false);\n  const [data, setData] = useState<string>('');\n\n  const reset = () => {\n    if (eventSourceRef.current) {\n      eventSourceRef.current?.close();\n      eventSourceRef.current = null;\n    }\n    setData('');\n  };\n\n  const fetchAskingStreamingTask = (queryId: string) => {\n    setLoading(true);\n    reset();\n\n    const eventSource = new EventSource(\n      `/api/ask_task/streaming?queryId=${queryId}`,\n    );\n\n    eventSource.onmessage = (event) => {\n      const eventData = JSON.parse(event.data);\n      if (eventData.done) {\n        eventSource.close();\n        setLoading(false);\n      } else {\n        setData((state) => state + (eventData?.message || ''));\n      }\n    };\n\n    eventSource.onerror = (error) => {\n      console.error(error);\n      eventSource.close();\n      setLoading(false);\n    };\n\n    eventSourceRef.current = eventSource;\n  };\n\n  return [\n    fetchAskingStreamingTask,\n    { data, loading, reset },\n  ] as useAskingStreamTaskReturn;\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useAutoComplete.tsx",
    "content": "import { useMemo } from 'react';\nimport { capitalize } from 'lodash';\nimport { useDiagramQuery } from '@/apollo/client/graphql/diagram.generated';\nimport { getNodeTypeIcon } from '@/utils/nodeType';\nimport {\n  DiagramModel,\n  DiagramView,\n  DiagramModelField,\n  DiagramViewField,\n} from '@/apollo/client/graphql/__types__';\n\ntype Model = DiagramModel | DiagramView;\ntype Field = DiagramModelField | DiagramViewField;\ntype Convertor<T> = (item: (Model | Field) & { parent?: Model }) => T;\n\ninterface Props<T> {\n  skip?: boolean;\n  includeColumns?: boolean;\n  convertor?: Convertor<T>;\n}\n\nconst getDocHTML = (item: (Model | Field) & { parent?: Model }) => {\n  return [\n    '<div style=\"max-width: 380px;\">',\n    `<b style=\"display: block;color: var(--gray-8); padding: 0 4px 4px;\">${item.referenceName}</b>`,\n    item.description\n      ? `<div style=\"color: var(--gray-7); padding: 4px 4px 0; border-top: 1px var(--gray-4) solid;\">${item.description}</div>`\n      : null,\n    '</div>',\n  ]\n    .filter(Boolean)\n    .join('');\n};\n\nconst shouldQuoteIdentifier = (word: string) => {\n  return /[^a-z0-9_]/.test(word) || /^\\d/.test(word);\n};\n\n// For mention usage\nexport const convertMention = (item: (Model | Field) & { parent?: Model }) => {\n  return {\n    id: `${item.id}-${item.referenceName}`,\n    label: item.displayName,\n    value: item.referenceName,\n    nodeType: capitalize(item.nodeType),\n    meta: item.parent ? `${item.displayName}.${item.displayName}` : undefined,\n    icon: getNodeTypeIcon(\n      { nodeType: item.nodeType, type: (item as Field).type },\n      { className: 'gray-8 mr-2' },\n    ),\n  };\n};\n\n// For ace completer usage\nexport const convertCompleter = (\n  item: (Model | Field) & { parent?: Model },\n) => {\n  return {\n    caption: item.parent\n      ? `${item.parent.displayName}.${item.displayName}`\n      : item.displayName,\n    value: shouldQuoteIdentifier(item.referenceName)\n      ? `\"${item.referenceName}\"`\n      : item.referenceName,\n    meta: item.nodeType.toLowerCase(),\n    // Higher score for models, views\n    score: item.parent ? 1 : 10,\n    docHTML: getDocHTML(item),\n  };\n};\n\nexport type Mention = ReturnType<typeof convertMention>;\nexport type Completer = ReturnType<typeof convertCompleter>;\n\nexport default function useAutoComplete<T = Completer>(props: Props<T>) {\n  const { includeColumns, skip } = props;\n  const { data } = useDiagramQuery({ skip });\n\n  // Defined convertor\n  const convertor = (props.convertor || convertCompleter) as Convertor<T>;\n\n  return useMemo(() => {\n    const models = data?.diagram.models || [];\n    const views = data?.diagram.views || [];\n\n    return [...models, ...views].reduce((result, item) => {\n      result.push(convertor(item));\n      if (includeColumns) {\n        item.fields.forEach((field) => {\n          result.push(convertor({ ...field, parent: item }));\n        });\n      }\n      return result;\n    }, [] as T[]);\n  }, [data?.diagram, includeColumns]);\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useCheckOnboarding.tsx",
    "content": "import { useEffect } from 'react';\nimport { useRouter } from 'next/router';\nimport { useOnboardingStatusQuery } from '@/apollo/client/graphql/onboarding.generated';\nimport { OnboardingStatus } from '@/apollo/client/graphql/__types__';\nimport { Path } from '@/utils/enum';\n\nconst redirectRoute = {\n  [OnboardingStatus.DATASOURCE_SAVED]: Path.OnboardingModels,\n  [OnboardingStatus.NOT_STARTED]: Path.OnboardingConnection,\n  [OnboardingStatus.ONBOARDING_FINISHED]: Path.Modeling,\n  [OnboardingStatus.WITH_SAMPLE_DATASET]: Path.Modeling,\n};\n\nexport const useWithOnboarding = () => {\n  const router = useRouter();\n  const { data, loading } = useOnboardingStatusQuery();\n\n  const onboardingStatus = data?.onboardingStatus?.status;\n\n  useEffect(() => {\n    if (onboardingStatus) {\n      const newPath = redirectRoute[onboardingStatus];\n      const pathname = router.pathname;\n\n      // redirect to new path if onboarding is not completed\n      if (newPath && newPath !== Path.Modeling) {\n        // do not redirect if the new path and router pathname are the same\n        if (newPath === pathname) {\n          return;\n        }\n\n        // allow return back to previous steps\n        if (\n          router.pathname.startsWith(Path.Onboarding) &&\n          onboardingStatus !== OnboardingStatus.ONBOARDING_FINISHED\n        ) {\n          return;\n        }\n\n        router.push(newPath);\n        return;\n      }\n\n      // redirect to home page if onboarding is completed\n\n      // redirect to the home page when entering the Index page\n      if (pathname === '/') {\n        router.push(newPath);\n        return;\n      }\n\n      // redirect to home page since user using sample dataset\n      if (\n        pathname === Path.OnboardingRelationships &&\n        onboardingStatus === OnboardingStatus.WITH_SAMPLE_DATASET\n      ) {\n        router.push(newPath);\n        return;\n      }\n\n      // redirect to home page when entering the connection page or select models page\n      if (\n        [Path.OnboardingConnection, Path.OnboardingModels].includes(\n          pathname as Path,\n        )\n      ) {\n        router.push(newPath);\n        return;\n      }\n    }\n  }, [onboardingStatus, router.pathname]);\n\n  return {\n    loading,\n    onboardingStatus,\n  };\n};\n\nexport default function useOnboardingStatus() {\n  const { data, loading, error, refetch } = useOnboardingStatusQuery();\n\n  return {\n    loading,\n    error,\n    refetch,\n    onboardingStatus: data?.onboardingStatus?.status,\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useCombineFieldOptions.tsx",
    "content": "import { useEffect, useMemo, useState } from 'react';\nimport { useListModelsQuery } from '@/apollo/client/graphql/model.generated';\nimport {\n  convertObjectToIdentifier,\n  convertIdentifierToObject,\n} from '@/utils/enum';\nimport { RelationsDataType } from '@/components/table/ModelRelationSelectionTable';\nimport { RelationFormValues } from '@/components/modals/RelationModal';\n\ninterface Props {\n  // The initial base model of model select\n  model?: string;\n  // The models to be excluded from model select\n  excludeModels?: string[];\n}\n\n// for identifier keys\nconst modelKeys = ['id', 'referenceName'];\nconst fieldKeys = ['id', 'referenceName'];\n\nexport const convertFormValuesToIdentifier = (\n  relationFormValues: RelationFormValues,\n) => {\n  const fromModel: { id: string; referenceName: string } =\n    convertIdentifierToObject(relationFormValues.fromField.model);\n\n  const fromField: { id: string; referenceName: string } =\n    convertIdentifierToObject(relationFormValues.fromField.field);\n\n  const toModel: { id: string; referenceName: string } =\n    convertIdentifierToObject(relationFormValues.toField.model);\n\n  const toField: { id: string; referenceName: string } =\n    convertIdentifierToObject(relationFormValues.toField.field);\n\n  return {\n    ...relationFormValues,\n    fromField: {\n      modelId: fromModel.id,\n      modelName: fromModel.referenceName,\n      fieldId: fromField.id,\n      fieldName: fromField.referenceName,\n    },\n    toField: {\n      modelId: toModel.id,\n      modelName: toModel.referenceName,\n      fieldId: toField.id,\n      fieldName: toField.referenceName,\n    },\n  } as RelationsDataType;\n};\n\nexport const convertDefaultValueToIdentifier = (defaultValue) => {\n  const fromField = {\n    model: {\n      id: defaultValue.fromField.modelId,\n      referenceName: defaultValue.fromField.modelName,\n    },\n    field: {\n      id: defaultValue.fromField.fieldId,\n      referenceName: defaultValue.fromField.fieldName,\n    },\n  };\n  const toField = {\n    model: {\n      id: defaultValue.toField.modelId,\n      referenceName: defaultValue.toField.modelName,\n    },\n    field: {\n      id: defaultValue.toField.fieldId,\n      referenceName: defaultValue.toField.fieldName,\n    },\n  };\n  return {\n    fromField: {\n      model: convertObjectToIdentifier(fromField.model, modelKeys),\n      field: convertObjectToIdentifier(fromField.field, fieldKeys),\n    },\n    toField: {\n      model: convertObjectToIdentifier(toField.model, modelKeys),\n      field: convertObjectToIdentifier(toField.field, fieldKeys),\n    },\n    type: defaultValue.type,\n  };\n};\n\nexport default function useCombineFieldOptions(props: Props) {\n  const { model, excludeModels } = props;\n\n  const [baseModel, setBaseModel] = useState<string>(model || '');\n\n  // bind model to baseModel\n  useEffect(() => setBaseModel(model), [model]);\n\n  const { data } = useListModelsQuery({\n    fetchPolicy: 'cache-and-network',\n  });\n\n  const allModels = useMemo(() => {\n    if (!data) return [];\n\n    return data.listModels.map((model) => ({\n      id: model.id,\n      referenceName: model.referenceName,\n      displayName: model.displayName,\n      fields: model.fields,\n    }));\n  }, [data]);\n\n  const filteredModels = useMemo(\n    () =>\n      allModels.filter(\n        (item) =>\n          !(excludeModels && excludeModels.includes(item.referenceName)),\n      ),\n    [excludeModels, baseModel, data],\n  );\n\n  const modelOptions = useMemo(\n    () =>\n      filteredModels.map((model) => ({\n        label: model.displayName,\n        value: convertObjectToIdentifier(model, modelKeys),\n        'data-testid': 'common__models__select-option',\n      })),\n    [filteredModels],\n  );\n\n  const selectedModel = useMemo(\n    () => filteredModels.find((item) => item.referenceName === baseModel),\n    [modelOptions, baseModel],\n  );\n\n  const fieldOptions = useMemo(\n    () =>\n      (selectedModel?.fields || []).map((field) => ({\n        label: field.displayName,\n        value: convertObjectToIdentifier(field, fieldKeys),\n        'data-testid': 'common__fields__select-option',\n      })),\n    [selectedModel],\n  );\n\n  const onModelChange = (value: string) => {\n    const model: { id: string; referenceName: string } =\n      convertIdentifierToObject(value);\n    setBaseModel(model.referenceName);\n  };\n\n  return { modelOptions, fieldOptions, onModelChange };\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useDrawerAction.tsx",
    "content": "import { useState } from 'react';\nimport { FORM_MODE } from '@/utils/enum';\n\nexport interface DrawerAction<TData = any> {\n  visible: boolean;\n  onClose: () => void;\n  onSubmit?: (values: any) => Promise<void>;\n  formMode?: FORM_MODE;\n  // use as form default value or view data\n  defaultValue?: TData;\n}\n\nexport default function useDrawerAction() {\n  const [visible, setVisible] = useState(false);\n  const [formMode, setFormMode] = useState(FORM_MODE.CREATE);\n  const [defaultValue, setDefaultValue] = useState(null);\n\n  const openDrawer = (value?: any) => {\n    value && setDefaultValue(value);\n    value && setFormMode(FORM_MODE.EDIT);\n    setVisible(true);\n  };\n\n  const closeDrawer = () => {\n    setVisible(false);\n    setDefaultValue(null);\n    setFormMode(FORM_MODE.CREATE);\n  };\n\n  const updateState = (value?: any) => {\n    setDefaultValue(value);\n  };\n\n  return {\n    state: {\n      visible,\n      formMode,\n      defaultValue,\n    },\n    openDrawer,\n    closeDrawer,\n    updateState,\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useDropdown.tsx",
    "content": "import { useState } from 'react';\n\nexport default function useDropdown() {\n  const [visible, setVisible] = useState<boolean>(false);\n\n  const onVisibleChange = (visible: boolean) => setVisible(visible);\n\n  const onCloseDropdownMenu = () => setVisible(false);\n\n  return {\n    visible,\n    onVisibleChange,\n    onCloseDropdownMenu,\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useExpressionFieldOptions.tsx",
    "content": "import { ExpressionName } from '@/apollo/client/graphql/__types__';\nimport { getExpressionTexts } from '@/utils/data';\nimport {\n  aggregations,\n  mathFunctions,\n  stringFunctions,\n} from '@/utils/expressionType';\nimport { useMemo } from 'react';\n\nexport default function useExpressionFieldOptions() {\n  const expressionOptions = useMemo(() => {\n    const convertor = (name: ExpressionName) => {\n      const texts = getExpressionTexts(name);\n      return {\n        label: texts.name,\n        value: name,\n        content: {\n          title: texts.syntax,\n          description: texts.description,\n          expression: texts.syntax,\n        },\n      };\n    };\n\n    return [\n      {\n        label: 'Aggregation',\n        options: aggregations.map(convertor),\n      },\n      {\n        label: 'Math functions',\n        options: mathFunctions.map(convertor),\n      },\n      {\n        label: 'String functions',\n        options: stringFunctions.map(convertor),\n      },\n    ];\n  }, []);\n\n  return expressionOptions;\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useGlobalConfig.tsx",
    "content": "import { useRouter } from 'next/router';\nimport { createContext, useContext, useEffect, useState } from 'react';\nimport { getUserConfig, UserConfig } from '@/utils/env';\nimport { trackUserTelemetry } from '@/utils/telemetry';\n\ntype ContextProps = {\n  config?: UserConfig | null;\n};\n\nconst GlobalConfigContext = createContext<ContextProps>({});\n\nexport const GlobalConfigProvider = ({ children }) => {\n  const router = useRouter();\n  const [config, setConfig] = useState<UserConfig | null>(null);\n\n  useEffect(() => {\n    getUserConfig()\n      .then((config) => {\n        setConfig(config);\n        // telemetry setup\n        const cleanup = trackUserTelemetry(router, config);\n        return cleanup;\n      })\n      .catch((error) => {\n        console.error('Failed to get user config', error);\n      });\n  }, [router]);\n\n  const value = {\n    config,\n  };\n\n  return (\n    <GlobalConfigContext.Provider value={value}>\n      {children}\n    </GlobalConfigContext.Provider>\n  );\n};\n\nexport default function useGlobalConfig() {\n  return useContext(GlobalConfigContext);\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useHomeSidebar.tsx",
    "content": "import { useMemo } from 'react';\nimport { useRouter } from 'next/router';\nimport { Path } from '@/utils/enum';\nimport {\n  useDeleteThreadMutation,\n  useThreadsQuery,\n  useUpdateThreadMutation,\n} from '@/apollo/client/graphql/home.generated';\n\nexport default function useHomeSidebar() {\n  const router = useRouter();\n  const { data, refetch } = useThreadsQuery({\n    fetchPolicy: 'cache-and-network',\n  });\n  const [updateThread] = useUpdateThreadMutation({\n    onError: (error) => console.error(error),\n  });\n  const [deleteThread] = useDeleteThreadMutation({\n    onError: (error) => console.error(error),\n  });\n\n  const threads = useMemo(\n    () =>\n      (data?.threads || []).map((thread) => ({\n        id: thread.id.toString(),\n        name: thread.summary,\n      })),\n    [data],\n  );\n\n  const onSelect = (selectKeys: string[]) => {\n    router.push(`${Path.Home}/${selectKeys[0]}`);\n  };\n\n  const onRename = async (id: string, newName: string) => {\n    await updateThread({\n      variables: { where: { id: Number(id) }, data: { summary: newName } },\n    });\n    refetch();\n  };\n\n  const onDelete = async (id) => {\n    await deleteThread({ variables: { where: { id: Number(id) } } });\n    refetch();\n  };\n\n  return {\n    data: { threads },\n    onSelect,\n    onRename,\n    onDelete,\n    refetch,\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useModalAction.tsx",
    "content": "import { useState } from 'react';\nimport { FORM_MODE } from '@/utils/enum';\n\nexport interface ModalAction<TData = any, SData = any> {\n  visible: boolean;\n  onClose: () => void;\n  onSubmit?: (values: SData) => Promise<void>;\n  formMode?: FORM_MODE;\n  defaultValue?: TData;\n  payload?: Record<string, any>;\n}\n\nexport default function useModalAction() {\n  const [visible, setVisible] = useState(false);\n  const [formMode, setFormMode] = useState(FORM_MODE.CREATE);\n  const [payload, setPayload] = useState(null);\n  const [defaultValue, setDefaultValue] = useState(null);\n\n  const openModal = (value?: any, payload?: any) => {\n    payload && setPayload(payload);\n    value && setDefaultValue(value);\n    value && setFormMode(FORM_MODE.EDIT);\n    setVisible(true);\n  };\n\n  const closeModal = () => {\n    setVisible(false);\n    setPayload(null);\n    setDefaultValue(null);\n    setFormMode(FORM_MODE.CREATE);\n  };\n\n  return {\n    state: {\n      visible,\n      formMode,\n      defaultValue,\n      payload,\n    },\n    openModal,\n    closeModal,\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useNativeSQL.tsx",
    "content": "import { useState } from 'react';\nimport { useGetSettingsQuery } from '@/apollo/client/graphql/settings.generated';\nimport { useGetNativeSqlLazyQuery } from '@/apollo/client/graphql/home.generated';\nimport { DataSourceName } from '@/apollo/client/graphql/__types__';\n\nexport interface NativeSQLResult {\n  data: string;\n  dataSourceType: DataSourceName;\n  hasNativeSQL: boolean;\n  loading: boolean;\n  nativeSQLMode: boolean;\n  setNativeSQLMode: (value: boolean) => void;\n}\n\n// we assume that not having a sample dataset means supporting native SQL\nfunction useNativeSQLInfo() {\n  const { data: settingsQueryResult } = useGetSettingsQuery();\n  const settings = settingsQueryResult?.settings;\n  const dataSourceType = settings?.dataSource.type;\n  const sampleDataset = settings?.dataSource.sampleDataset;\n\n  return {\n    hasNativeSQL: !Boolean(sampleDataset),\n    dataSourceType,\n  };\n}\n\nexport default function useNativeSQL() {\n  const nativeSQLInfo = useNativeSQLInfo();\n\n  const [nativeSQLMode, setNativeSQLMode] = useState<boolean>(false);\n\n  const [fetchNativeSQL, { data, loading }] = useGetNativeSqlLazyQuery({\n    fetchPolicy: 'cache-and-network',\n  });\n\n  const nativeSQL = data?.nativeSql || '';\n  const nativeSQLResult: NativeSQLResult = {\n    ...nativeSQLInfo,\n    data: nativeSQL,\n    loading,\n    nativeSQLMode,\n    setNativeSQLMode,\n  };\n\n  return {\n    fetchNativeSQL,\n    nativeSQLResult,\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useRecommendedQuestionsInstruction.tsx",
    "content": "import { useMemo, useState, useEffect } from 'react';\nimport { groupBy, orderBy, flatMap } from 'lodash';\nimport { message } from 'antd';\nimport Icon from '@/import/icon';\nimport ReloadOutlined from '@ant-design/icons/ReloadOutlined';\nimport { CopilotSVG } from '@/utils/svgs';\nimport { isRecommendedFinished } from '@/hooks/useAskPrompt';\nimport {\n  ResultQuestion,\n  RecommendedQuestionsTaskStatus,\n} from '@/apollo/client/graphql/__types__';\nimport {\n  useGetProjectRecommendationQuestionsLazyQuery,\n  useGenerateProjectRecommendationQuestionsMutation,\n} from '@/apollo/client/graphql/home.generated';\n\nexport interface GroupedQuestion {\n  category: string;\n  question: string;\n  sql: string;\n}\n\nconst getGroupedQuestions = (\n  questions: ResultQuestion[],\n): GroupedQuestion[] => {\n  const groupedData = groupBy(questions, 'category');\n  return orderBy(\n    flatMap(groupedData),\n    (item) => groupedData[item.category].length, // Sort by number of questions in each category\n    'desc',\n  );\n};\n\nexport default function useRecommendedQuestionsInstruction() {\n  const [showRetry, setShowRetry] = useState<boolean>(false);\n  const [generating, setGenerating] = useState<boolean>(false);\n  const [isRegenerate, setIsRegenerate] = useState<boolean>(false);\n  const [\n    showRecommendedQuestionsPromptMode,\n    setShowRecommendedQuestionsPromptMode,\n  ] = useState<boolean>(false);\n  const [recommendedQuestions, setRecommendedQuestions] = useState<\n    GroupedQuestion[]\n  >([]);\n\n  const [fetchRecommendationQuestions, recommendationQuestionsResult] =\n    useGetProjectRecommendationQuestionsLazyQuery({\n      pollInterval: 2000,\n    });\n\n  // Handle errors via try/catch blocks rather than onError callback\n  const [generateProjectRecommendationQuestions] =\n    useGenerateProjectRecommendationQuestionsMutation();\n\n  const recommendedQuestionsTask = useMemo(\n    () =>\n      recommendationQuestionsResult.data?.getProjectRecommendationQuestions ||\n      null,\n    [recommendationQuestionsResult.data],\n  );\n\n  useEffect(() => {\n    const fetchRecommendationQuestionsData = async () => {\n      const result = await fetchRecommendationQuestions();\n      const data = result.data?.getProjectRecommendationQuestions;\n\n      // for existing projects that do not have to generate recommended questions yet\n      if (isRecommendedFinished(data.status)) {\n        if (data.questions.length > 0) {\n          // for regenerate then leave and go back to the home page\n          setRecommendedQuestions(getGroupedQuestions(data.questions));\n\n          setShowRecommendedQuestionsPromptMode(true);\n        }\n      }\n    };\n\n    fetchRecommendationQuestionsData();\n  }, []);\n\n  useEffect(() => {\n    if (isRecommendedFinished(recommendedQuestionsTask?.status)) {\n      recommendationQuestionsResult.stopPolling();\n\n      if (recommendedQuestionsTask.questions.length === 0) {\n        isRegenerate && setShowRetry(true);\n\n        if (\n          showRecommendedQuestionsPromptMode &&\n          recommendedQuestionsTask.status ===\n            RecommendedQuestionsTaskStatus.FAILED\n        ) {\n          message.error(\n            `We couldn't regenerate questions right now. Let's try again later.`,\n          );\n        }\n      } else {\n        setIsRegenerate(true);\n\n        // update to recommendedQuestions\n        setRecommendedQuestions(\n          getGroupedQuestions(recommendedQuestionsTask.questions),\n        );\n        setShowRecommendedQuestionsPromptMode(true);\n      }\n\n      setGenerating(false);\n    }\n  }, [recommendedQuestionsTask]);\n\n  const onGetRecommendationQuestions = async () => {\n    setGenerating(true);\n    setIsRegenerate(true);\n    try {\n      await generateProjectRecommendationQuestions();\n      fetchRecommendationQuestions();\n    } catch (error) {\n      console.error(error);\n    }\n  };\n\n  const buttonProps = useMemo(() => {\n    const baseProps = {\n      loading: generating,\n      onClick: onGetRecommendationQuestions,\n    };\n\n    if (showRecommendedQuestionsPromptMode && isRegenerate) {\n      return {\n        ...baseProps,\n        icon: <ReloadOutlined />,\n        children: 'Regenerate',\n      };\n    }\n\n    return {\n      ...baseProps,\n      icon: showRetry ? (\n        <ReloadOutlined />\n      ) : (\n        <Icon component={CopilotSVG} className=\"geekblue-6\" />\n      ),\n      children: generating\n        ? 'Generating questions'\n        : showRetry\n          ? 'Retry'\n          : 'What could I ask?',\n    };\n  }, [generating, isRegenerate, showRetry, showRecommendedQuestionsPromptMode]);\n\n  return {\n    recommendedQuestions,\n    generating,\n    showRetry,\n    showRecommendedQuestionsPromptMode,\n    buttonProps,\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useRelationshipModal.tsx",
    "content": "import { useMemo, useState } from 'react';\nimport { NODE_TYPE } from '@/utils/enum';\nimport { Diagram } from '@/utils/data';\nimport useModalAction from '@/hooks/useModalAction';\n\nexport default function useRelationshipModal(diagramData: Diagram | null) {\n  const relationshipModal = useModalAction();\n\n  const [selectedModelReferenceName, setSelectedModelReferenceName] =\n    useState<string>(null);\n\n  // Parse out the relationships data under all models\n  const relationships = useMemo(\n    () =>\n      (diagramData?.models || []).reduce((acc, currentValue) => {\n        const { referenceName, relationFields } = currentValue;\n        const newRelationship = relationFields.map((relationship) => {\n          return {\n            id: relationship.relationId,\n            fromField: {\n              modelId: String(relationship.fromModelId),\n              modelName: relationship.fromModelName,\n              fieldId: String(relationship.fromColumnId),\n              fieldName: relationship.fromColumnName,\n            },\n            toField: {\n              modelId: String(relationship.toModelId),\n              modelName: relationship.toModelName,\n              fieldId: String(relationship.toColumnId),\n              fieldName: relationship.toColumnName,\n            },\n            type: relationship.type,\n          };\n        });\n\n        acc[referenceName] = newRelationship;\n        return acc;\n      }, {}),\n    [diagramData],\n  );\n\n  const onClose = () => {\n    setSelectedModelReferenceName(null);\n    relationshipModal.closeModal();\n  };\n\n  const openModal = (data) => {\n    // update mode\n    if (data.nodeType === NODE_TYPE.RELATION) {\n      setSelectedModelReferenceName(data.fromModelName);\n      relationshipModal.openModal({\n        relationId: data.relationId,\n        fromField: {\n          modelId: String(data.fromModelId),\n          modelName: data.fromModelName,\n          fieldId: String(data.fromColumnId),\n          fieldName: data.fromColumnName,\n        },\n        toField: {\n          modelId: String(data.toModelId),\n          modelName: data.toModelName,\n          fieldId: String(data.toColumnId),\n          fieldName: data.toColumnName,\n        },\n        type: data.type,\n      });\n      return;\n    }\n\n    // create mode\n    setSelectedModelReferenceName(data.referenceName);\n    relationshipModal.openModal();\n  };\n\n  return {\n    onClose,\n    openModal,\n    state: {\n      ...relationshipModal.state,\n      model: selectedModelReferenceName,\n      relations: relationships,\n    },\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useSetupConnection.tsx",
    "content": "import { useState, useEffect } from 'react';\nimport { SETUP } from '@/utils/enum';\nimport { parseGraphQLError } from '@/utils/errorHandler';\nimport useSetupConnectionDataSource from './useSetupConnectionDataSource';\nimport useSetupConnectionSampleDataset from './useSetupConnectionSampleDataset';\nimport {\n  DataSourceName,\n  SampleDatasetName,\n} from '@/apollo/client/graphql/__types__';\n\ntype StepData = {\n  dataSource?: DataSourceName;\n  template?: SampleDatasetName;\n  properties?: JSON;\n};\n\nexport default function useSetupConnection() {\n  const [stepKey, setStepKey] = useState(SETUP.STARTER);\n  const setupConnectionSampleDataset = useSetupConnectionSampleDataset();\n  const setupConnectionDataSource = useSetupConnectionDataSource();\n  const [connectError, setConnectError] = useState(null);\n\n  const dataSource = setupConnectionDataSource.selected;\n  const submitting =\n    setupConnectionDataSource.loading || setupConnectionSampleDataset.loading;\n\n  useEffect(() => {\n    if (stepKey === SETUP.CREATE_DATA_SOURCE) {\n      setConnectError(null);\n    }\n  }, [stepKey]);\n\n  useEffect(() => {\n    setConnectError(parseGraphQLError(setupConnectionDataSource.error));\n  }, [setupConnectionDataSource.error]);\n\n  const onBack = () => {\n    if (stepKey === SETUP.CREATE_DATA_SOURCE) {\n      setStepKey(SETUP.STARTER);\n      setupConnectionDataSource.reset();\n    }\n  };\n\n  const onNext = (data?: StepData) => {\n    const dispatchStarter = (data: StepData) => {\n      if (data.dataSource) {\n        setupConnectionDataSource.selectDataSourceNext({\n          dataSource: data.dataSource,\n          dispatch: () => setStepKey(SETUP.CREATE_DATA_SOURCE),\n        });\n      } else {\n        setupConnectionSampleDataset.saveSampleDataset(data.template);\n      }\n    };\n\n    const dispatchCreateDataSource = (data: StepData) => {\n      setupConnectionDataSource.saveDataSource(data.properties);\n    };\n\n    // Next strategy\n    if (stepKey === SETUP.STARTER) {\n      dispatchStarter(data);\n    } else if (stepKey === SETUP.CREATE_DATA_SOURCE) {\n      dispatchCreateDataSource(data);\n    }\n  };\n\n  return {\n    stepKey,\n    dataSource,\n    onBack,\n    onNext,\n    submitting,\n    connectError,\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useSetupConnectionDataSource.tsx",
    "content": "import { useRouter } from 'next/router';\nimport { useState, useCallback } from 'react';\nimport {\n  Path,\n  REDSHIFT_AUTH_METHOD,\n  DATABRICKS_AUTH_METHOD,\n} from '@/utils/enum';\nimport { useSaveDataSourceMutation } from '@/apollo/client/graphql/dataSource.generated';\nimport { DataSourceName } from '@/apollo/client/graphql/__types__';\n\nconst PASSWORD_PLACEHOLDER = '************';\n\nexport default function useSetupConnectionDataSource() {\n  const router = useRouter();\n  const [selected, setSelected] = useState<DataSourceName>();\n\n  const [saveDataSourceMutation, { loading, error }] =\n    useSaveDataSourceMutation({\n      onError: (error) => console.error(error),\n      onCompleted: () => completedDataSourceSave(),\n    });\n\n  const selectDataSourceNext = useCallback(\n    (payload: { dataSource: DataSourceName; dispatch?: () => void }) => {\n      setSelected(payload.dataSource);\n      payload?.dispatch?.();\n    },\n    [router],\n  );\n\n  const saveDataSource = useCallback(\n    async (properties?: Record<string, any>) => {\n      await saveDataSourceMutation({\n        variables: {\n          data: {\n            type: selected,\n            properties: transformFormToProperties(properties, selected),\n          },\n        },\n      });\n    },\n    [selected, saveDataSourceMutation],\n  );\n\n  const completedDataSourceSave = useCallback(async () => {\n    router.push(Path.OnboardingModels);\n  }, [selected, router]);\n\n  return {\n    loading,\n    error,\n    selected,\n    saveDataSource,\n    selectDataSourceNext,\n    completedDataSourceSave,\n    reset: () => setSelected(undefined),\n  };\n}\n\nexport const transformFormToProperties = (\n  properties: Record<string, any>,\n  dataSourceType: DataSourceName,\n) => {\n  if (dataSourceType === DataSourceName.DUCKDB) {\n    const configurations = properties.configurations.reduce((acc, cur) => {\n      if (cur.key && cur.value) {\n        acc[cur.key] = cur.value;\n      }\n\n      return acc;\n    }, {});\n\n    return {\n      ...properties,\n      configurations,\n      extensions: properties.extensions.filter((i) => i),\n    };\n  } else if (dataSourceType === DataSourceName.SNOWFLAKE) {\n    return {\n      ...properties,\n      ...getSnowflakeAuthentication(properties),\n    };\n  } else if (dataSourceType === DataSourceName.DATABRICKS) {\n    return {\n      ...properties,\n      ...getDatabricksAuthentication(properties),\n    };\n  } else if (dataSourceType === DataSourceName.ATHENA) {\n    return {\n      ...properties,\n      ...getAthenaAuthentication(properties),\n    };\n  }\n\n  return {\n    ...properties,\n    // remove password placeholder if user doesn't change the password\n    password:\n      properties?.password === PASSWORD_PLACEHOLDER\n        ? undefined\n        : properties?.password,\n\n    awsSecretKey:\n      properties?.awsSecretKey === PASSWORD_PLACEHOLDER\n        ? undefined\n        : properties?.awsSecretKey,\n  };\n};\n\nexport const transformPropertiesToForm = (\n  properties: Record<string, any>,\n  dataSourceType: DataSourceName,\n) => {\n  if (dataSourceType === DataSourceName.BIG_QUERY) {\n  } else if (dataSourceType === DataSourceName.DUCKDB) {\n    const configurations = Object.entries(properties?.configurations || {}).map(\n      ([key, value]) => ({ key, value }),\n    );\n    const extensions = properties?.extensions || [];\n    return {\n      ...properties,\n      // If there are no configurations or extensions, add an empty one, or the form properties will break\n      configurations: configurations.length\n        ? configurations\n        : [{ key: '', value: '' }],\n      extensions: extensions.length ? extensions : [''],\n    };\n  } else if (dataSourceType === DataSourceName.REDSHIFT) {\n    return {\n      ...properties,\n      ...(properties?.redshiftType === REDSHIFT_AUTH_METHOD.redshift\n        ? {\n            password: properties?.password || PASSWORD_PLACEHOLDER,\n          }\n        : {\n            awsSecretKey: properties?.awsSecretKey || PASSWORD_PLACEHOLDER,\n          }),\n    };\n  } else if (dataSourceType === DataSourceName.DATABRICKS) {\n    return {\n      ...properties,\n      ...(properties?.databricksType ===\n      DATABRICKS_AUTH_METHOD.service_principal\n        ? {\n            clientSecret: properties?.clientSecret || PASSWORD_PLACEHOLDER,\n          }\n        : {\n            accessToken: properties?.accessToken || PASSWORD_PLACEHOLDER,\n          }),\n    };\n  }\n\n  return {\n    ...properties,\n    // provide a password placeholder to UI\n    password: properties?.password || PASSWORD_PLACEHOLDER,\n    privateKey: properties?.privateKey || undefined,\n  };\n};\n\nfunction getSnowflakeAuthentication(properties: Record<string, any>) {\n  // Set password or private key to null if only one of them is provided\n  if (properties?.privateKey) {\n    return {\n      privateKey: properties?.privateKey,\n      password: null,\n    };\n  }\n  if (properties?.password && properties?.password !== PASSWORD_PLACEHOLDER) {\n    return {\n      password: properties?.password,\n      privateKey: null,\n    };\n  }\n  return {};\n}\n\nfunction getDatabricksAuthentication(properties: Record<string, any>) {\n  if (properties?.databricksType === DATABRICKS_AUTH_METHOD.service_principal) {\n    return {\n      clientSecret:\n        properties?.clientSecret === PASSWORD_PLACEHOLDER\n          ? undefined\n          : properties?.clientSecret,\n    };\n  }\n\n  return {\n    accessToken:\n      properties?.accessToken === PASSWORD_PLACEHOLDER\n        ? undefined\n        : properties?.accessToken,\n  };\n}\n\nfunction getAthenaAuthentication(properties: Record<string, any>) {\n  if (properties?.webIdentityToken) {\n    return {\n      webIdentityToken:\n        properties?.webIdentityToken === PASSWORD_PLACEHOLDER\n          ? undefined\n          : properties?.webIdentityToken,\n    };\n  }\n\n  return {\n    awsSecretKey:\n      properties?.awsSecretKey === PASSWORD_PLACEHOLDER\n        ? undefined\n        : properties?.awsSecretKey,\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useSetupConnectionSampleDataset.tsx",
    "content": "import { useRouter } from 'next/router';\nimport { useCallback } from 'react';\nimport { Path } from '@/utils/enum';\nimport { ONBOARDING_STATUS } from '@/apollo/client/graphql/onboarding';\nimport { useStartSampleDatasetMutation } from '@/apollo/client/graphql/dataSource.generated';\nimport { SampleDatasetName } from '@/apollo/client/graphql/__types__';\n\nexport default function useSetupConnectionSampleDataset() {\n  const router = useRouter();\n\n  const [startSampleDatasetMutation, { loading, error }] =\n    useStartSampleDatasetMutation({\n      onError: (error) => console.error(error),\n      onCompleted: () => router.push(Path.Modeling),\n      refetchQueries: [{ query: ONBOARDING_STATUS }],\n      awaitRefetchQueries: true,\n    });\n\n  const saveSampleDataset = useCallback(\n    async (template: SampleDatasetName) => {\n      await startSampleDatasetMutation({\n        variables: { data: { name: template } },\n      });\n    },\n    [startSampleDatasetMutation],\n  );\n\n  return {\n    loading,\n    error,\n    saveSampleDataset,\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useSetupModels.tsx",
    "content": "import { useState } from 'react';\nimport { Path, SETUP } from '@/utils/enum';\nimport { useRouter } from 'next/router';\nimport {\n  useListDataSourceTablesQuery,\n  useSaveTablesMutation,\n} from '@/apollo/client/graphql/dataSource.generated';\n\nexport default function useSetupModels() {\n  const [stepKey] = useState(SETUP.SELECT_MODELS);\n\n  const router = useRouter();\n\n  const { data, loading: fetching } = useListDataSourceTablesQuery({\n    fetchPolicy: 'no-cache',\n    onError: (error) => console.error(error),\n  });\n\n  // Handle errors via try/catch blocks rather than onError callback\n  const [saveTablesMutation, { loading: submitting }] = useSaveTablesMutation();\n\n  const submitModels = async (tables: string[]) => {\n    try {\n      await saveTablesMutation({\n        variables: {\n          data: { tables },\n        },\n      });\n      router.push(Path.OnboardingRelationships);\n    } catch (error) {\n      console.error(error);\n    }\n  };\n\n  const onBack = () => {\n    router.push(Path.OnboardingConnection);\n  };\n\n  const onNext = (data: { selectedTables: string[] }) => {\n    submitModels(data.selectedTables);\n  };\n\n  return {\n    submitting,\n    fetching,\n    stepKey,\n    onBack,\n    onNext,\n    tables: data?.listDataSourceTables || [],\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useSetupRelations.tsx",
    "content": "import { useMemo, useState } from 'react';\nimport { SETUP } from '@/utils/enum';\nimport { useRouter } from 'next/router';\nimport { SelectedRecommendRelations } from '@/components/pages/setup/DefineRelations';\nimport { Path } from '@/utils/enum';\nimport {\n  useAutoGeneratedRelationsQuery,\n  useSaveRelationsMutation,\n} from '@/apollo/client/graphql/dataSource.generated';\nimport useOnboardingStatus from '@/hooks/useCheckOnboarding';\n\nexport default function useSetupRelations() {\n  const [stepKey] = useState(SETUP.DEFINE_RELATIONS);\n  const router = useRouter();\n  const { refetch: refetchOnboardingStatus } = useOnboardingStatus();\n\n  const { data, loading: fetching } = useAutoGeneratedRelationsQuery({\n    fetchPolicy: 'no-cache',\n  });\n  const autoGenerateRelation = data?.autoGenerateRelation;\n\n  const onFinish = () => {\n    router.push(Path.Modeling);\n    refetchOnboardingStatus();\n  };\n\n  const [saveRelationsMutation, { loading: submitting }] =\n    useSaveRelationsMutation({\n      onError: (error) => console.error(error),\n      onCompleted: onFinish,\n    });\n\n  const submitRelations = async (relationsData: SelectedRecommendRelations) => {\n    const relations = Object.entries(relationsData).reduce(\n      (acc, [_modleName, relations]) => {\n        const newRelations = relations.map((relation) => {\n          return {\n            fromModelId: Number(relation.fromField.modelId),\n            fromColumnId: Number(relation.fromField.fieldId),\n            toModelId: Number(relation.toField.modelId),\n            toColumnId: Number(relation.toField.fieldId),\n            type: relation.type,\n          };\n        });\n\n        acc = [...acc, ...newRelations];\n        return acc;\n      },\n      [],\n    );\n\n    // redirect to the home page if there is no relationship data needs to be saved\n    if (relations.length === 0) {\n      onFinish();\n      return;\n    }\n\n    await saveRelationsMutation({\n      variables: { data: { relations } },\n    });\n  };\n\n  const onBack = () => {\n    router.push('/setup/models');\n  };\n\n  const onNext = (data: { relations: SelectedRecommendRelations }) => {\n    submitRelations(data.relations);\n  };\n\n  const recommendRelationsResult = useMemo(\n    () =>\n      (autoGenerateRelation || []).reduce(\n        (acc, currentValue) => {\n          const { displayName, referenceName, relations } = currentValue;\n          const newRelations = relations.map((relation) => {\n            return {\n              name: relation.name,\n              fromField: {\n                modelId: String(relation.fromModelId),\n                modelName: relation.fromModelReferenceName,\n                fieldId: String(relation.fromColumnId),\n                fieldName: relation.fromColumnReferenceName,\n              },\n              toField: {\n                modelId: String(relation.toModelId),\n                modelName: relation.toModelReferenceName,\n                fieldId: String(relation.toColumnId),\n                fieldName: relation.toColumnReferenceName,\n              },\n              type: relation.type,\n              isAutoGenerated: true,\n            };\n          });\n\n          acc['recommendRelations'][referenceName] = newRelations;\n          acc['recommendNameMapping'][referenceName] = displayName;\n          return acc;\n        },\n        {\n          recommendRelations: {},\n          recommendNameMapping: {},\n        },\n      ),\n    [autoGenerateRelation],\n  );\n\n  return {\n    fetching,\n    submitting,\n    stepKey,\n    recommendRelationsResult,\n    onBack,\n    onNext,\n    onSkip: onFinish,\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useStoreContext.tsx",
    "content": "import { createContext, useContext } from 'react';\n\nconst contextMap = new Map<string, React.Context<any>>();\n\nexport const STORE = {\n  PROMPT_THREAD: 'PromptThread',\n};\n\n// Base store context hook\nexport default function useStoreContext() {\n  const createStore = (id: string) => {\n    if (contextMap.has(id)) return contextMap.get(id);\n    const context = createContext(null);\n    contextMap.set(id, context);\n    return context;\n  };\n\n  const clearStore = (id: string) => {\n    contextMap.delete(id);\n  };\n\n  const useStore = (id: string) => {\n    const context = contextMap.get(id);\n    if (!context) throw new Error(`Context not found for id: ${id}`);\n    return useContext(context);\n  };\n\n  return {\n    createStore,\n    clearStore,\n    useStore,\n  };\n}\n"
  },
  {
    "path": "wren-ui/src/hooks/useTextBasedAnswerStreamTask.tsx",
    "content": "import { useRef, useState } from 'react';\n\ntype TextBasedAnswerStreamTaskReturn = [\n  (responseId: number) => void,\n  {\n    data: string;\n    loading: boolean;\n    onReset: () => void;\n  },\n];\n\nexport default function useTextBasedAnswerStreamTask() {\n  const eventSourceRef = useRef<EventSource | null>(null);\n  const [loading, setLoading] = useState<boolean>(false);\n  const [data, setData] = useState<string>('');\n\n  const onReset = () => {\n    if (eventSourceRef.current) {\n      eventSourceRef.current?.close();\n      eventSourceRef.current = null;\n    }\n    setData('');\n  };\n\n  const fetchAnswerStreamingTask = (responseId: number) => {\n    setLoading(true);\n    onReset();\n\n    const eventSource = new EventSource(\n      `/api/ask_task/streaming_answer?responseId=${responseId}`,\n    );\n\n    eventSource.onmessage = (event) => {\n      const eventData = JSON.parse(event.data);\n      if (eventData.done) {\n        eventSource.close();\n        setLoading(false);\n      } else {\n        setData((state) => state + (eventData?.message || ''));\n      }\n    };\n\n    eventSource.onerror = (error) => {\n      console.error(error);\n      eventSource.close();\n      setLoading(false);\n    };\n\n    eventSourceRef.current = eventSource;\n  };\n\n  return [\n    fetchAnswerStreamingTask,\n    { data, loading, onReset },\n  ] as TextBasedAnswerStreamTaskReturn;\n}\n"
  },
  {
    "path": "wren-ui/src/import/antd.ts",
    "content": "/*\n * On demand import components to avoid bundle size issue\n */\n\n// export { default as Affix } from 'antd/lib/affix';\n// export { default as Anchor } from 'antd/lib/anchor';\n// export { default as AutoComplete } from 'antd/lib/auto-complete';\nexport { default as Alert } from 'antd/lib/alert';\n// export { default as Avatar } from 'antd/lib/avatar';\n// export { default as BackTop } from 'antd/lib/back-top';\nexport { default as Badge } from 'antd/lib/badge';\nexport { default as Breadcrumb } from 'antd/lib/breadcrumb';\nexport { default as Button } from 'antd/lib/button';\n// export { default as Calendar } from 'antd/lib/calendar';\nexport { default as Card } from 'antd/lib/card';\nexport { default as Collapse } from 'antd/lib/collapse';\n// export { default as Carousel } from 'antd/lib/carousel';\n// export { default as Cascader } from 'antd/lib/cascader';\n// export { default as Checkbox } from 'antd/lib/checkbox';\nexport { default as Col } from 'antd/lib/col';\n// export { default as Comment } from 'antd/lib/comment';\n// export { default as ConfigProvider } from 'antd/lib/config-provider';\nexport { default as DatePicker } from 'antd/lib/date-picker';\n// export { default as Descriptions } from 'antd/lib/descriptions';\nexport { default as Divider } from 'antd/lib/divider';\nexport { default as Dropdown } from 'antd/lib/dropdown';\nexport { default as Drawer } from 'antd/lib/drawer';\nexport { default as Empty } from 'antd/lib/empty';\nexport { default as Form } from 'antd/lib/form';\n// export { default as Grid } from 'antd/lib/grid';\nexport { default as Input } from 'antd/lib/input';\n// export { default as Image } from 'antd/lib/image';\n// export { default as InputNumber } from 'antd/lib/input-number';\nexport { default as Layout } from 'antd/lib/layout';\n// export { default as List } from 'antd/lib/list';\nexport { default as message } from 'antd/lib/message';\nexport { default as Menu } from 'antd/lib/menu';\nexport { default as Mentions } from 'antd/lib/mentions';\nexport { default as Modal } from 'antd/lib/modal';\n// export { default as Statistic } from 'antd/lib/statistic';\n// export { default as notification } from 'antd/lib/notification';\n// export { default as PageHeader } from 'antd/lib/page-header';\nexport { default as Pagination } from 'antd/lib/pagination';\nexport { default as Popconfirm } from 'antd/lib/popconfirm';\nexport { default as Popover } from 'antd/lib/popover';\n// export { default as Progress } from 'antd/lib/progress';\nexport { default as Radio } from 'antd/lib/radio';\n// export { default as Rate } from 'antd/lib/rate';\n// export { default as Result } from 'antd/lib/result';\nexport { default as Row } from 'antd/lib/row';\nexport { default as Select } from 'antd/lib/select';\n// export { default as Segmented } from 'antd/lib/segmented';\nexport { default as Skeleton } from 'antd/lib/skeleton';\n// export { default as Slider } from 'antd/lib/slider';\nexport { default as Space } from 'antd/lib/space';\nexport { default as Spin } from 'antd/lib/spin';\nexport { default as Steps } from 'antd/lib/steps';\nexport { default as Switch } from 'antd/lib/switch';\nexport { default as Table } from 'antd/lib/table';\nexport { default as Transfer } from 'antd/lib/transfer';\nexport { default as Tree } from 'antd/lib/tree';\n// export { default as TreeSelect } from 'antd/lib/tree-select';\nexport { default as Tabs } from 'antd/lib/tabs';\nexport { default as Tag } from 'antd/lib/tag';\nexport { default as TimePicker } from 'antd/lib/time-picker';\nexport { default as Timeline } from 'antd/lib/timeline';\nexport { default as Tooltip } from 'antd/lib/tooltip';\nexport { default as Typography } from 'antd/lib/typography';\nexport { default as Upload } from 'antd/lib/upload';\nexport { default as version } from 'antd/lib/version';\n"
  },
  {
    "path": "wren-ui/src/import/icon.ts",
    "content": "/*\n * use client import to avoid bundle size issue\n */\n\nimport dynamic from 'next/dynamic';\nexport type { IconComponentProps } from '@ant-design/icons/lib/components/Icon';\n\nconst Icon = dynamic(() => import('@ant-design/icons/lib/components/Icon'), {\n  ssr: false,\n});\n\nexport default Icon;\n"
  },
  {
    "path": "wren-ui/src/pages/_app.tsx",
    "content": "import { AppProps } from 'next/app';\nimport Head from 'next/head';\nimport { Spin } from 'antd';\nimport posthog from 'posthog-js';\nimport apolloClient from '@/apollo/client';\nimport { GlobalConfigProvider } from '@/hooks/useGlobalConfig';\nimport { PostHogProvider } from 'posthog-js/react';\nimport { ApolloProvider } from '@apollo/client';\nimport { defaultIndicator } from '@/components/PageLoading';\n\nrequire('../styles/index.less');\n\nSpin.setDefaultIndicator(defaultIndicator);\n\nfunction App({ Component, pageProps }: AppProps) {\n  return (\n    <>\n      <Head>\n        <title>Wren AI</title>\n        <link rel=\"icon\" href=\"/favicon.ico\" />\n      </Head>\n      <GlobalConfigProvider>\n        <ApolloProvider client={apolloClient}>\n          <PostHogProvider client={posthog}>\n            <main className=\"app\">\n              <Component {...pageProps} />\n            </main>\n          </PostHogProvider>\n        </ApolloProvider>\n      </GlobalConfigProvider>\n    </>\n  );\n}\n\nexport default App;\n"
  },
  {
    "path": "wren-ui/src/pages/_document.tsx",
    "content": "/* eslint-disable react/display-name */\nimport Document, {\n  Html,\n  Head,\n  Main,\n  NextScript,\n  DocumentContext,\n  DocumentInitialProps,\n} from 'next/document';\nimport { ServerStyleSheet } from 'styled-components';\n\nexport default class AppDocument extends Document {\n  static async getInitialProps(\n    ctx: DocumentContext,\n  ): Promise<DocumentInitialProps> {\n    const originalRenderPage = ctx.renderPage;\n\n    const sheet = new ServerStyleSheet();\n\n    ctx.renderPage = () =>\n      originalRenderPage({\n        enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />),\n        enhanceComponent: (Component) => Component,\n      });\n\n    const intialProps = await Document.getInitialProps(ctx);\n    const styles = sheet.getStyleElement();\n\n    return { ...intialProps, styles };\n  }\n\n  render() {\n    return (\n      <Html>\n        <Head>{this.props.styles}</Head>\n        <body>\n          <Main />\n          <NextScript />\n        </body>\n      </Html>\n    );\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/pages/api/ask_task/streaming.ts",
    "content": "import type { NextApiRequest, NextApiResponse } from 'next';\nimport { components } from '@/common';\n\nconst { wrenAIAdaptor } = components;\n\nexport default async function handler(\n  req: NextApiRequest,\n  res: NextApiResponse,\n) {\n  res.setHeader('Content-Type', 'text/event-stream');\n  res.setHeader('Cache-Control', 'no-cache, no-transform');\n  res.setHeader('Connection', 'keep-alive');\n  res.flushHeaders();\n\n  const { queryId } = req.query;\n  try {\n    const stream = await wrenAIAdaptor.getAskStreamingResult(queryId as string);\n\n    stream.on('data', (chunk) => {\n      // pass the chunk directly to the client\n      res.write(chunk);\n    });\n\n    stream.on('end', () => {\n      res.write(`data: ${JSON.stringify({ done: true })}\\n\\n`);\n      res.end();\n    });\n\n    // destroy the stream if the client closes the connection\n    req.on('close', () => {\n      stream.destroy();\n    });\n  } catch (error) {\n    console.error(error);\n    res.status(500).end();\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/pages/api/ask_task/streaming_answer.ts",
    "content": "import type { NextApiRequest, NextApiResponse } from 'next';\nimport { components } from '@/common';\nimport { ThreadResponseAnswerStatus } from '@/apollo/server/services/askingService';\nimport { TelemetryEvent } from '@/apollo/server/telemetry/telemetry';\n\nconst { wrenAIAdaptor, askingService, telemetry } = components;\n\nclass ContentMap {\n  private contentMap: { [key: string]: string } = {};\n\n  // Method to append (concatenate) content to the map\n  public appendContent(key: string, content: string) {\n    if (!this.contentMap[key]) {\n      this.contentMap[key] = '';\n    }\n    this.contentMap[key] += content;\n  }\n\n  // Method to get content from the map\n  public getContent(key: string): string | undefined {\n    return this.contentMap[key];\n  }\n\n  // Method to remove content from the map\n  public remove(key: string) {\n    delete this.contentMap[key];\n  }\n}\n\nconst contentMap = new ContentMap();\n\nexport default async function handler(\n  req: NextApiRequest,\n  res: NextApiResponse,\n) {\n  if (req.method !== 'GET') {\n    res.status(405).json({ error: 'Method Not Allowed' });\n    return;\n  }\n\n  res.setHeader('Content-Type', 'text/event-stream');\n  res.setHeader('Cache-Control', 'no-cache, no-transform');\n  res.setHeader('Connection', 'keep-alive');\n  res.flushHeaders();\n\n  const { responseId } = req.query;\n  if (!responseId) {\n    res.status(400).json({ error: 'responseId is required' });\n    return;\n  }\n  try {\n    const response = await askingService.getResponse(Number(responseId));\n    if (!response) {\n      throw new Error(`Thread response ${responseId} not found`);\n    }\n\n    // check response status\n    if (\n      response.answerDetail?.status !== ThreadResponseAnswerStatus.STREAMING\n    ) {\n      throw new Error(\n        `Thread response ${responseId} is not in streaming status`,\n      );\n    }\n\n    const queryId = response.answerDetail?.queryId;\n    if (!queryId) {\n      throw new Error(`Thread response ${responseId} does not have queryId`);\n    }\n\n    const stream = await wrenAIAdaptor.streamTextBasedAnswer(queryId);\n\n    stream.on('data', (chunk) => {\n      // pass the chunk directly to the client\n      const chunkString = chunk.toString('utf-8');\n      let message = '';\n      const match = chunkString.match(/data: {\"message\":\"([\\s\\S]*?)\"}/);\n      if (match && match[1]) {\n        message = match[1];\n      } else {\n        console.log(`not able to match: ${chunkString}`);\n      }\n      contentMap.appendContent(queryId, message);\n      res.write(chunk);\n    });\n\n    stream.on('end', () => {\n      res.write(`data: ${JSON.stringify({ done: true })}\\n\\n`);\n      res.end();\n      askingService\n        .changeThreadResponseAnswerDetailStatus(\n          Number(responseId),\n          ThreadResponseAnswerStatus.FINISHED,\n          contentMap.getContent(queryId),\n        )\n        .then(() => {\n          console.log(\n            'Thread response answer detail status updated to FINISHED',\n          );\n          contentMap.remove(queryId);\n          telemetry.sendEvent(TelemetryEvent.HOME_ANSWER_QUESTION, {\n            question: response.question,\n          });\n        })\n        .catch((error) => {\n          console.error(\n            'Failed to update thread response answer detail status',\n            error,\n          );\n          contentMap.remove(queryId);\n          telemetry.sendEvent(\n            TelemetryEvent.HOME_ANSWER_QUESTION,\n            {\n              question: response.question,\n              error: error,\n            },\n            null,\n            false,\n          );\n        });\n    });\n\n    // destroy the stream if the client closes the connection\n    req.on('close', () => {\n      stream.destroy();\n      askingService\n        .changeThreadResponseAnswerDetailStatus(\n          Number(responseId),\n          ThreadResponseAnswerStatus.INTERRUPTED,\n          contentMap.getContent(queryId),\n        )\n        .then(() => {\n          console.log(\n            'Thread response answer detail status updated to INTERRUPTED',\n          );\n          contentMap.remove(queryId);\n          telemetry.sendEvent(TelemetryEvent.HOME_ANSWER_QUESTION_INTERRUPTED, {\n            question: response.question,\n          });\n        })\n        .catch((error) => {\n          console.error(\n            'Failed to update thread response answer detail status',\n            error,\n          );\n          contentMap.remove(queryId);\n          telemetry.sendEvent(\n            TelemetryEvent.HOME_ANSWER_QUESTION_INTERRUPTED,\n            {\n              question: response.question,\n              error: error,\n            },\n            null,\n            false,\n          );\n        });\n    });\n  } catch (error) {\n    console.error(error);\n    res.status(500).end();\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/pages/api/config.ts",
    "content": "import type { NextApiRequest, NextApiResponse } from 'next';\nimport { getConfig } from '@/apollo/server/config';\n\nexport default function handler(_: NextApiRequest, res: NextApiResponse) {\n  const config = getConfig();\n  const encodedTelemetryKey = config.posthogApiKey\n    ? Buffer.from(config.posthogApiKey).toString('base64')\n    : '';\n\n  res.status(200).json({\n    isTelemetryEnabled: config.telemetryEnabled || false,\n    telemetryKey: encodedTelemetryKey,\n    telemetryHost: config.posthogHost || '',\n    userUUID: config.userUUID || '',\n  });\n}\n"
  },
  {
    "path": "wren-ui/src/pages/api/graphql.ts",
    "content": "import microCors from 'micro-cors';\nimport { NextApiRequest, NextApiResponse, PageConfig } from 'next';\nimport { ApolloServer } from 'apollo-server-micro';\nimport { typeDefs } from '@server';\nimport resolvers from '@server/resolvers';\nimport { IContext } from '@server/types';\nimport { GraphQLError } from 'graphql';\nimport { getLogger } from '@server/utils';\nimport { getConfig } from '@server/config';\nimport { ModelService } from '@server/services/modelService';\nimport {\n  defaultApolloErrorHandler,\n  GeneralErrorCodes,\n} from '@/apollo/server/utils/error';\nimport { TelemetryEvent } from '@/apollo/server/telemetry/telemetry';\nimport { components } from '@/common';\n\nconst serverConfig = getConfig();\nconst logger = getLogger('APOLLO');\nlogger.level = 'debug';\n\nconst cors = microCors();\n\nexport const config: PageConfig = {\n  api: {\n    bodyParser: false,\n  },\n};\n\nconst bootstrapServer = async () => {\n  const {\n    telemetry,\n\n    // repositories\n    projectRepository,\n    modelRepository,\n    modelColumnRepository,\n    relationRepository,\n    deployLogRepository,\n    viewRepository,\n    schemaChangeRepository,\n    learningRepository,\n    modelNestedColumnRepository,\n    dashboardRepository,\n    dashboardItemRepository,\n    sqlPairRepository,\n    instructionRepository,\n    apiHistoryRepository,\n    dashboardItemRefreshJobRepository,\n    // adaptors\n    wrenEngineAdaptor,\n    ibisAdaptor,\n    wrenAIAdaptor,\n\n    // services\n    projectService,\n    queryService,\n    askingService,\n    deployService,\n    mdlService,\n    dashboardService,\n    sqlPairService,\n\n    instructionService,\n    // background trackers\n    projectRecommendQuestionBackgroundTracker,\n    threadRecommendQuestionBackgroundTracker,\n    dashboardCacheBackgroundTracker,\n  } = components;\n\n  const modelService = new ModelService({\n    projectService,\n    modelRepository,\n    modelColumnRepository,\n    relationRepository,\n    viewRepository,\n    mdlService,\n    wrenEngineAdaptor,\n    queryService,\n  });\n\n  // initialize services\n  await Promise.all([\n    askingService.initialize(),\n    projectRecommendQuestionBackgroundTracker.initialize(),\n    threadRecommendQuestionBackgroundTracker.initialize(),\n  ]);\n\n  const apolloServer: ApolloServer = new ApolloServer({\n    typeDefs,\n    resolvers,\n    formatError: (error: GraphQLError) => {\n      // stop print error stacktrace of dry run error\n      if (error.extensions?.code === GeneralErrorCodes.DRY_RUN_ERROR) {\n        return defaultApolloErrorHandler(error);\n      }\n\n      // print error stacktrace of graphql error\n      const stacktrace = error.extensions?.exception?.stacktrace;\n      if (stacktrace) {\n        logger.error(stacktrace.join('\\n'));\n      }\n\n      // print original error stacktrace\n      const originalError = error.extensions?.originalError as Error;\n      if (originalError) {\n        logger.error(`== original error ==`);\n        // error may not have stack, so print error message if stack is not available\n        logger.error(originalError.stack || originalError.message);\n      }\n\n      // telemetry: capture internal server error\n      if (error.extensions?.code === GeneralErrorCodes.INTERNAL_SERVER_ERROR) {\n        telemetry.sendEvent(\n          TelemetryEvent.GRAPHQL_ERROR,\n          {\n            originalErrorStack: originalError?.stack,\n            originalErrorMessage: originalError?.message,\n            errorMessage: error.message,\n          },\n          error.extensions?.service,\n          false,\n        );\n      }\n      return defaultApolloErrorHandler(error);\n    },\n    introspection: process.env.NODE_ENV !== 'production',\n    context: (): IContext => ({\n      config: serverConfig,\n      telemetry,\n      // adaptor\n      wrenEngineAdaptor,\n      ibisServerAdaptor: ibisAdaptor,\n      wrenAIAdaptor,\n      // services\n      projectService,\n      modelService,\n      mdlService,\n      deployService,\n      askingService,\n      queryService,\n      dashboardService,\n      sqlPairService,\n      instructionService,\n      // repository\n      projectRepository,\n      modelRepository,\n      modelColumnRepository,\n      modelNestedColumnRepository,\n      relationRepository,\n      viewRepository,\n      deployRepository: deployLogRepository,\n      schemaChangeRepository,\n      learningRepository,\n      dashboardRepository,\n      dashboardItemRepository,\n      sqlPairRepository,\n      instructionRepository,\n      apiHistoryRepository,\n      dashboardItemRefreshJobRepository,\n      // background trackers\n      projectRecommendQuestionBackgroundTracker,\n      threadRecommendQuestionBackgroundTracker,\n      dashboardCacheBackgroundTracker,\n    }),\n  });\n  await apolloServer.start();\n  return apolloServer;\n};\n\nconst startServer = bootstrapServer();\n\nconst handler = async (req: NextApiRequest, res: NextApiResponse) => {\n  const apolloServer = await startServer;\n  await apolloServer.createHandler({\n    path: '/api/graphql',\n  })(req, res);\n};\n\nexport default cors((req: NextApiRequest, res: NextApiResponse) =>\n  req.method === 'OPTIONS' ? res.status(200).end() : handler(req, res),\n);\n"
  },
  {
    "path": "wren-ui/src/pages/api/v1/ask.ts",
    "content": "import { NextApiRequest, NextApiResponse } from 'next';\nimport { components } from '@/common';\nimport { ApiType } from '@server/repositories/apiHistoryRepository';\nimport * as Errors from '@/apollo/server/utils/error';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n  ApiError,\n  respondWith,\n  handleApiError,\n  MAX_WAIT_TIME,\n  isAskResultFinished,\n  validateSummaryResult,\n  transformHistoryInput,\n} from '@/apollo/server/utils/apiUtils';\nimport {\n  AskResult,\n  WrenAILanguage,\n  TextBasedAnswerInput,\n  TextBasedAnswerResult,\n  TextBasedAnswerStatus,\n  AskResultType,\n  WrenAIError,\n} from '@/apollo/server/models/adaptor';\nimport { getLogger } from '@server/utils';\n\nconst logger = getLogger('API_ASK');\nlogger.level = 'debug';\n\nconst {\n  apiHistoryRepository,\n  projectService,\n  deployService,\n  wrenAIAdaptor,\n  queryService,\n} = components;\n\ninterface AskRequest {\n  question: string;\n  sampleSize?: number;\n  language?: string;\n  threadId?: string;\n}\n\nexport default async function handler(\n  req: NextApiRequest,\n  res: NextApiResponse,\n) {\n  const { question, sampleSize, language, threadId } = req.body as AskRequest;\n  const startTime = Date.now();\n  let project;\n\n  try {\n    project = await projectService.getCurrentProject();\n\n    // Only allow POST method\n    if (req.method !== 'POST') {\n      throw new ApiError('Method not allowed', 405);\n    }\n\n    // Input validation\n    if (!question) {\n      throw new ApiError('Question is required', 400);\n    }\n\n    // Get current project's last deployment\n    const lastDeploy = await deployService.getLastDeployment(project.id);\n    if (!lastDeploy) {\n      throw new ApiError(\n        'No deployment found, please deploy your project first',\n        400,\n        Errors.GeneralErrorCodes.NO_DEPLOYMENT_FOUND,\n      );\n    }\n\n    // Create a new thread if it's a new question\n    const newThreadId = threadId || uuidv4();\n\n    // Get conversation history if threadId is provided\n    const histories = threadId\n      ? await apiHistoryRepository.findAllBy({ threadId })\n      : undefined;\n\n    // Step 1: Generate SQL\n    const askTask = await wrenAIAdaptor.ask({\n      query: question,\n      deployId: lastDeploy.hash,\n      histories: transformHistoryInput(histories) as any,\n      configurations: {\n        language:\n          language || WrenAILanguage[project.language] || WrenAILanguage.EN,\n      },\n    });\n\n    // Poll for the SQL generation result\n    const deadline = Date.now() + MAX_WAIT_TIME;\n    let askResult: AskResult;\n    while (true) {\n      askResult = await wrenAIAdaptor.getAskResult(askTask.queryId);\n      if (isAskResultFinished(askResult)) {\n        break;\n      }\n\n      if (Date.now() > deadline) {\n        throw new ApiError(\n          'Timeout waiting for SQL generation',\n          500,\n          Errors.GeneralErrorCodes.POLLING_TIMEOUT,\n        );\n      }\n\n      await new Promise((resolve) => setTimeout(resolve, 1000)); // Poll every second\n    }\n\n    // Validate the AI result\n    // Check for error in result\n    if (askResult.error) {\n      const errorMessage =\n        (askResult.error as WrenAIError).message || 'Unknown error';\n      const additionalData: Record<string, any> = {};\n\n      // Include invalid SQL if available\n      if (askResult.invalidSql) {\n        additionalData.invalidSql = askResult.invalidSql;\n      }\n\n      throw new ApiError(\n        errorMessage,\n        400,\n        askResult.error?.code || Errors.GeneralErrorCodes.INTERNAL_SERVER_ERROR,\n        additionalData,\n      );\n    }\n\n    // Check for general type response (explanation streaming)\n    if (askResult.type === AskResultType.GENERAL) {\n      // Stream the explanation content\n      let explanation = '';\n      const stream = await wrenAIAdaptor.getAskStreamingResult(askTask.queryId);\n\n      // Collect the streamed content\n      const streamPromise = new Promise<void>((resolve, reject) => {\n        stream.on('data', (chunk) => {\n          const chunkString = chunk.toString('utf-8');\n          const match = chunkString.match(/data: {\"message\":\"([\\s\\S]*?)\"}/);\n          if (match && match[1]) {\n            explanation += match[1];\n          }\n        });\n\n        stream.on('end', () => {\n          resolve();\n        });\n\n        stream.on('error', (error) => {\n          reject(error);\n        });\n\n        // Handle client disconnect\n        req.on('close', () => {\n          stream.destroy();\n          reject(new Error('Client disconnected'));\n        });\n      });\n\n      await streamPromise;\n\n      // Return the explanation result\n      await respondWith({\n        res,\n        statusCode: 200,\n        responsePayload: {\n          type: 'NON_SQL_QUERY',\n          explanation,\n          threadId: newThreadId,\n        },\n        projectId: project.id,\n        apiType: ApiType.ASK,\n        startTime,\n        requestPayload: req.body,\n        threadId: newThreadId,\n        headers: req.headers as Record<string, string>,\n      });\n      return;\n    }\n\n    // Get the generated SQL\n    const sql = askResult.response?.[0]?.sql;\n    if (!sql) {\n      throw new ApiError('No SQL generated', 400);\n    }\n\n    // Step 2: Execute SQL to get data\n    let sqlData;\n    try {\n      const queryResult = await queryService.preview(sql, {\n        project,\n        limit: sampleSize || 500,\n        manifest: lastDeploy.manifest,\n        modelingOnly: false,\n      });\n      sqlData = queryResult;\n    } catch (queryError) {\n      throw new ApiError(\n        queryError.message || 'Error executing SQL query',\n        400,\n        Errors.GeneralErrorCodes.INVALID_SQL_ERROR,\n      );\n    }\n\n    // Step 3: Generate summary using text-based answer\n    const textBasedAnswerInput: TextBasedAnswerInput = {\n      query: question,\n      sql,\n      sqlData,\n      threadId: newThreadId,\n      configurations: {\n        language:\n          language || WrenAILanguage[project.language] || WrenAILanguage.EN,\n      },\n    };\n\n    // Start the summary generation task\n    const summaryTask =\n      await wrenAIAdaptor.createTextBasedAnswer(textBasedAnswerInput);\n\n    if (!summaryTask || !summaryTask.queryId) {\n      throw new ApiError('Failed to start summary generation task', 500);\n    }\n\n    // Poll for the summary result\n    let summaryResult: TextBasedAnswerResult;\n    while (true) {\n      summaryResult = await wrenAIAdaptor.getTextBasedAnswerResult(\n        summaryTask.queryId,\n      );\n      if (\n        summaryResult.status === TextBasedAnswerStatus.SUCCEEDED ||\n        summaryResult.status === TextBasedAnswerStatus.FAILED\n      ) {\n        break;\n      }\n\n      if (Date.now() > deadline) {\n        throw new ApiError(\n          'Timeout waiting for summary generation',\n          500,\n          Errors.GeneralErrorCodes.POLLING_TIMEOUT,\n        );\n      }\n\n      await new Promise((resolve) => setTimeout(resolve, 1000)); // Poll every second\n    }\n\n    // Validate the summary result\n    validateSummaryResult(summaryResult);\n\n    // Step 4: Stream the content to get the summary\n    let summary = '';\n    if (summaryResult.status === TextBasedAnswerStatus.SUCCEEDED) {\n      const stream = await wrenAIAdaptor.streamTextBasedAnswer(\n        summaryTask.queryId,\n      );\n\n      // Collect the streamed content\n      const streamPromise = new Promise<void>((resolve, reject) => {\n        stream.on('data', (chunk) => {\n          const chunkString = chunk.toString('utf-8');\n          const match = chunkString.match(/data: {\"message\":\"([\\s\\S]*?)\"}/);\n          if (match && match[1]) {\n            summary += match[1];\n          }\n        });\n\n        stream.on('end', () => {\n          resolve();\n        });\n\n        stream.on('error', (error) => {\n          reject(error);\n        });\n\n        // Handle client disconnect\n        req.on('close', () => {\n          stream.destroy();\n          reject(new Error('Client disconnected'));\n        });\n      });\n\n      await streamPromise;\n    }\n\n    // Return the combined result\n    await respondWith({\n      res,\n      statusCode: 200,\n      responsePayload: {\n        sql,\n        summary,\n        threadId: newThreadId,\n      },\n      projectId: project.id,\n      apiType: ApiType.ASK,\n      startTime,\n      requestPayload: req.body,\n      threadId: newThreadId,\n      headers: req.headers as Record<string, string>,\n    });\n  } catch (error) {\n    await handleApiError({\n      error,\n      res,\n      projectId: project?.id,\n      apiType: ApiType.ASK,\n      requestPayload: req.body,\n      threadId,\n      headers: req.headers as Record<string, string>,\n      startTime,\n      logger,\n    });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/pages/api/v1/generate_sql.ts",
    "content": "import { NextApiRequest, NextApiResponse } from 'next';\nimport { components } from '@/common';\nimport { ApiType } from '@server/repositories/apiHistoryRepository';\nimport { AskResult, WrenAILanguage } from '@/apollo/server/models/adaptor';\nimport * as Errors from '@/apollo/server/utils/error';\nimport { getLogger } from '@server/utils';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n  ApiError,\n  respondWith,\n  handleApiError,\n  MAX_WAIT_TIME,\n  isAskResultFinished,\n  validateAskResult,\n  transformHistoryInput,\n} from '@/apollo/server/utils/apiUtils';\nimport { DataSourceName } from '@server/types';\n\nconst logger = getLogger('API_GENERATE_SQL');\nlogger.level = 'debug';\n\nconst {\n  apiHistoryRepository,\n  projectService,\n  deployService,\n  wrenAIAdaptor,\n  wrenEngineAdaptor,\n  ibisAdaptor,\n} = components;\n\ninterface GenerateSqlRequest {\n  question: string;\n  threadId?: string;\n  language?: string;\n  returnSqlDialect?: boolean;\n}\n\nexport default async function handler(\n  req: NextApiRequest,\n  res: NextApiResponse,\n) {\n  const {\n    question,\n    threadId,\n    language,\n    returnSqlDialect = false,\n  } = req.body as GenerateSqlRequest;\n  const startTime = Date.now();\n  let project;\n\n  try {\n    project = await projectService.getCurrentProject();\n\n    // Only allow POST method\n    if (req.method !== 'POST') {\n      throw new ApiError('Method not allowed', 405);\n    }\n\n    // input validation\n    if (!question) {\n      throw new ApiError('Question is required', 400);\n    }\n\n    // get current project's last deployment\n    const lastDeploy = await deployService.getLastDeployment(project.id);\n\n    if (!lastDeploy) {\n      throw new ApiError(\n        'No deployment found, please deploy a model first',\n        400,\n        Errors.GeneralErrorCodes.NO_DEPLOYMENT_FOUND,\n      );\n    }\n\n    // ask AI service to generate SQL\n    const histories = threadId\n      ? await apiHistoryRepository.findAllBy({ threadId })\n      : undefined;\n    const task = await wrenAIAdaptor.ask({\n      query: question,\n      deployId: lastDeploy.hash,\n      histories: transformHistoryInput(histories) as any,\n      configurations: {\n        language:\n          language || WrenAILanguage[project.language] || WrenAILanguage.EN,\n      },\n    });\n\n    // polling for the result\n    const deadline = Date.now() + MAX_WAIT_TIME;\n    let result: AskResult;\n    while (true) {\n      result = await wrenAIAdaptor.getAskResult(task.queryId);\n      if (isAskResultFinished(result)) {\n        break;\n      }\n\n      if (Date.now() > deadline) {\n        throw new ApiError(\n          'Timeout waiting for SQL generation',\n          500,\n          Errors.GeneralErrorCodes.POLLING_TIMEOUT,\n        );\n      }\n\n      await new Promise((resolve) => setTimeout(resolve, 1000)); // poll every second\n    }\n\n    // Validate the AI result\n    validateAskResult(result, task.queryId);\n\n    // Get the generated SQL\n    let sql = result.response?.[0]?.sql;\n\n    // Create a new thread if it's a new question\n    const newThreadId = threadId || uuidv4();\n\n    // If returnSqlDialect is true, also get and return the native SQL\n    if (returnSqlDialect && sql) {\n      let nativeSql: string;\n      if (project.type === DataSourceName.DUCKDB) {\n        nativeSql = await wrenEngineAdaptor.getNativeSQL(sql, {\n          manifest: lastDeploy.manifest,\n          modelingOnly: false,\n        });\n      } else {\n        nativeSql = await ibisAdaptor.getNativeSql({\n          dataSource: project.type,\n          sql,\n          mdl: lastDeploy.manifest,\n        });\n      }\n\n      // If the native SQL is not empty, use it\n      sql = nativeSql || sql;\n    }\n\n    // Return just the SQL\n    await respondWith({\n      res,\n      statusCode: 200,\n      responsePayload: {\n        sql,\n        threadId: newThreadId,\n      },\n      projectId: project.id,\n      apiType: ApiType.GENERATE_SQL,\n      startTime,\n      requestPayload: req.body,\n      threadId: newThreadId,\n      headers: req.headers as Record<string, string>,\n    });\n  } catch (error) {\n    await handleApiError({\n      error,\n      res,\n      projectId: project?.id,\n      apiType: ApiType.GENERATE_SQL,\n      requestPayload: req.body,\n      threadId,\n      headers: req.headers as Record<string, string>,\n      startTime,\n      logger,\n    });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/pages/api/v1/generate_summary.ts",
    "content": "import { NextApiRequest, NextApiResponse } from 'next';\nimport { components } from '@/common';\nimport { ApiType } from '@server/repositories/apiHistoryRepository';\nimport * as Errors from '@/apollo/server/utils/error';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n  ApiError,\n  respondWith,\n  handleApiError,\n  MAX_WAIT_TIME,\n  validateSummaryResult,\n} from '@/apollo/server/utils/apiUtils';\nimport {\n  TextBasedAnswerInput,\n  TextBasedAnswerResult,\n  TextBasedAnswerStatus,\n  WrenAILanguage,\n} from '@/apollo/server/models/adaptor';\nimport { getLogger } from '@server/utils';\n\nconst logger = getLogger('API_GENERATE_SUMMARY');\nlogger.level = 'debug';\n\nconst { projectService, wrenAIAdaptor, deployService, queryService } =\n  components;\n\ninterface GenerateSummaryRequest {\n  question: string;\n  sql: string;\n  sampleSize?: number;\n  language?: string;\n  threadId?: string;\n}\n\nexport default async function handler(\n  req: NextApiRequest,\n  res: NextApiResponse,\n) {\n  const { question, sql, sampleSize, language, threadId } =\n    req.body as GenerateSummaryRequest;\n  const startTime = Date.now();\n  let project;\n\n  try {\n    project = await projectService.getCurrentProject();\n\n    // Only allow POST method\n    if (req.method !== 'POST') {\n      throw new ApiError('Method not allowed', 405);\n    }\n\n    // Input validation\n    if (!question) {\n      throw new ApiError('Question is required', 400);\n    }\n\n    if (!sql) {\n      throw new ApiError('SQL is required', 400);\n    }\n\n    // Get current project's last deployment\n    const lastDeploy = await deployService.getLastDeployment(project.id);\n    if (!lastDeploy) {\n      throw new ApiError(\n        'No deployment found, please deploy your project first',\n        400,\n        Errors.GeneralErrorCodes.NO_DEPLOYMENT_FOUND,\n      );\n    }\n\n    // Create a new thread if it's a new question\n    const newThreadId = threadId || uuidv4();\n\n    // Get the data from the SQL\n    let sqlData;\n    try {\n      const queryResult = await queryService.preview(sql, {\n        project,\n        limit: sampleSize || 500,\n        manifest: lastDeploy.manifest,\n        modelingOnly: false,\n      });\n      sqlData = queryResult;\n    } catch (queryError) {\n      throw new ApiError(\n        queryError.message || 'Error executing SQL query',\n        400,\n        Errors.GeneralErrorCodes.INVALID_SQL_ERROR,\n      );\n    }\n\n    // Create text-based answer input for summary generation\n    const textBasedAnswerInput: TextBasedAnswerInput = {\n      query: question,\n      sql,\n      sqlData,\n      threadId: newThreadId,\n      configurations: {\n        language:\n          language || WrenAILanguage[project.language] || WrenAILanguage.EN,\n      },\n    };\n\n    // Start the summary generation task\n    const task =\n      await wrenAIAdaptor.createTextBasedAnswer(textBasedAnswerInput);\n\n    if (!task || !task.queryId) {\n      throw new ApiError('Failed to start summary generation task', 500);\n    }\n\n    // Poll for the result\n    const deadline = Date.now() + MAX_WAIT_TIME;\n    let result: TextBasedAnswerResult;\n    while (true) {\n      result = await wrenAIAdaptor.getTextBasedAnswerResult(task.queryId);\n      if (\n        result.status === TextBasedAnswerStatus.SUCCEEDED ||\n        result.status === TextBasedAnswerStatus.FAILED\n      ) {\n        break;\n      }\n\n      if (Date.now() > deadline) {\n        throw new ApiError(\n          'Timeout waiting for summary generation',\n          500,\n          Errors.GeneralErrorCodes.POLLING_TIMEOUT,\n        );\n      }\n\n      await new Promise((resolve) => setTimeout(resolve, 1000)); // Poll every second\n    }\n\n    // Validate the summary result\n    validateSummaryResult(result);\n\n    // Stream the content to get the summary\n    let summary = '';\n    if (result.status === TextBasedAnswerStatus.SUCCEEDED) {\n      const stream = await wrenAIAdaptor.streamTextBasedAnswer(task.queryId);\n\n      // Collect the streamed content\n      const streamPromise = new Promise<void>((resolve, reject) => {\n        stream.on('data', (chunk) => {\n          const chunkString = chunk.toString('utf-8');\n          const match = chunkString.match(/data: {\"message\":\"([\\s\\S]*?)\"}/);\n          if (match && match[1]) {\n            summary += match[1];\n          }\n        });\n\n        stream.on('end', () => {\n          resolve();\n        });\n\n        stream.on('error', (error) => {\n          reject(error);\n        });\n\n        // Handle client disconnect\n        req.on('close', () => {\n          stream.destroy();\n          reject(new Error('Client disconnected'));\n        });\n      });\n\n      await streamPromise;\n    }\n\n    // Return the summary with ID and threadId\n    await respondWith({\n      res,\n      statusCode: 200,\n      responsePayload: {\n        summary,\n        threadId: newThreadId,\n      },\n      projectId: project.id,\n      apiType: ApiType.GENERATE_SUMMARY,\n      startTime,\n      requestPayload: req.body,\n      threadId: newThreadId,\n      headers: req.headers as Record<string, string>,\n    });\n  } catch (error) {\n    await handleApiError({\n      error,\n      res,\n      projectId: project?.id,\n      apiType: ApiType.GENERATE_SUMMARY,\n      requestPayload: req.body,\n      threadId,\n      headers: req.headers as Record<string, string>,\n      startTime,\n      logger,\n    });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/pages/api/v1/generate_vega_chart.ts",
    "content": "import { NextApiRequest, NextApiResponse } from 'next';\nimport { components } from '@/common';\nimport { ApiType } from '@server/repositories/apiHistoryRepository';\nimport * as Errors from '@/apollo/server/utils/error';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n  ApiError,\n  respondWith,\n  handleApiError,\n} from '@/apollo/server/utils/apiUtils';\nimport {\n  ChartResult,\n  ChartStatus,\n  WrenAILanguage,\n} from '@/apollo/server/models/adaptor';\nimport { PreviewDataResponse } from '@server/services/queryService';\nimport { transformToObjects } from '@server/utils/dataUtils';\nimport { enhanceVegaSpec } from '@/utils/vegaSpecUtils';\n\nconst { projectService, wrenAIAdaptor, deployService, queryService } =\n  components;\n\nconst MAX_WAIT_TIME = 1000 * 60 * 3; // 3 minutes\n\n/**\n * Validates the chart generation result and checks for errors\n * @param result The chart result to validate\n * @throws ApiError if the result has errors or is in a failed state\n */\nconst validateChartResult = (result: ChartResult): void => {\n  // Check for errors or failed status\n  if (result.status === ChartStatus.FAILED || result.error) {\n    throw new ApiError(\n      result.error?.message || 'Failed to generate Vega spec',\n      400,\n      Errors.GeneralErrorCodes.FAILED_TO_GENERATE_VEGA_SCHEMA,\n    );\n  }\n\n  // Verify that the chartSchema is present\n  if (!result?.response?.chartSchema) {\n    throw new ApiError('Failed to generate Vega spec', 500);\n  }\n};\n\ninterface GenerateVegaSpecRequest {\n  question: string;\n  sql: string;\n  threadId?: string;\n  sampleSize?: number;\n}\n\nexport default async function handler(\n  req: NextApiRequest,\n  res: NextApiResponse,\n) {\n  const {\n    question,\n    sql,\n    threadId,\n    sampleSize = 10000,\n  } = req.body as GenerateVegaSpecRequest;\n  const startTime = Date.now();\n  let project;\n\n  try {\n    project = await projectService.getCurrentProject();\n\n    // Only allow POST method\n    if (req.method !== 'POST') {\n      throw new ApiError('Method not allowed', 405);\n    }\n\n    // Input validation\n    if (!question) {\n      throw new ApiError('Question is required', 400);\n    }\n\n    if (!sql) {\n      throw new ApiError('SQL is required', 400);\n    }\n\n    if (\n      !Number.isInteger(sampleSize) ||\n      sampleSize <= 0 ||\n      sampleSize > 1000000\n    ) {\n      throw new ApiError('Invalid sampleSize', 400);\n    }\n\n    // Get current project's last deployment\n    const lastDeploy = await deployService.getLastDeployment(project.id);\n    if (!lastDeploy) {\n      throw new ApiError(\n        'No deployment found, please deploy your project first',\n        400,\n        Errors.GeneralErrorCodes.NO_DEPLOYMENT_FOUND,\n      );\n    }\n\n    // Execute the SQL query to get the data\n    let queryResult: PreviewDataResponse;\n    try {\n      queryResult = (await queryService.preview(sql, {\n        project,\n        limit: sampleSize,\n        manifest: lastDeploy.manifest,\n        modelingOnly: false,\n      })) as PreviewDataResponse;\n    } catch (queryError) {\n      throw new ApiError(\n        queryError.message || 'Error executing SQL query',\n        400,\n        Errors.GeneralErrorCodes.INVALID_SQL_ERROR,\n      );\n    }\n\n    // Transform query results to array of objects\n    const dataObjects = transformToObjects(\n      queryResult.columns,\n      queryResult.data,\n    );\n\n    // Ask AI service to generate a Vega spec chart\n    const task = await wrenAIAdaptor.generateChart({\n      query: question,\n      sql,\n      projectId: project.id.toString(),\n      configurations: {\n        language: WrenAILanguage[project.language] || WrenAILanguage.EN,\n      },\n    });\n\n    if (!task || !task.queryId) {\n      throw new ApiError('Failed to start Vega spec generation task', 500);\n    }\n\n    // Poll for the result\n    const deadline = Date.now() + MAX_WAIT_TIME;\n    let result: ChartResult;\n    while (true) {\n      result = await wrenAIAdaptor.getChartResult(task.queryId);\n      if (\n        result.status === ChartStatus.FINISHED ||\n        result.status === ChartStatus.FAILED\n      ) {\n        break;\n      }\n\n      if (Date.now() > deadline) {\n        throw new ApiError(\n          'Timeout waiting for Vega spec generation',\n          500,\n          Errors.GeneralErrorCodes.POLLING_TIMEOUT,\n        );\n      }\n\n      await new Promise((resolve) => setTimeout(resolve, 1000)); // Poll every second\n    }\n\n    // Validate the chart result\n    validateChartResult(result);\n\n    // Create a new thread if it's a new question\n    const newThreadId = threadId || uuidv4();\n\n    // Get the generated Vega spec\n    const vegaSpec = result?.response?.chartSchema;\n\n    // Enhance the Vega spec with styling and configuration\n    const enhancedVegaSpec = enhanceVegaSpec(vegaSpec, dataObjects);\n\n    // Return the Vega spec with data included\n    await respondWith({\n      res,\n      statusCode: 200,\n      responsePayload: {\n        vegaSpec: enhancedVegaSpec,\n        threadId: newThreadId,\n      },\n      projectId: project.id,\n      apiType: ApiType.GENERATE_VEGA_CHART,\n      startTime,\n      requestPayload: req.body,\n      threadId: newThreadId,\n      headers: req.headers as Record<string, string>,\n    });\n  } catch (error) {\n    await handleApiError({\n      error,\n      res,\n      projectId: project?.id,\n      apiType: ApiType.GENERATE_VEGA_CHART,\n      requestPayload: req.body,\n      threadId,\n      headers: req.headers as Record<string, string>,\n      startTime,\n    });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/pages/api/v1/knowledge/instructions/[id].ts",
    "content": "import { NextApiRequest, NextApiResponse } from 'next';\nimport { components } from '@/common';\nimport { ApiType } from '@server/repositories/apiHistoryRepository';\nimport {\n  ApiError,\n  respondWithSimple,\n  handleApiError,\n} from '@/apollo/server/utils/apiUtils';\nimport { getLogger } from '@server/utils';\n\nconst logger = getLogger('API_INSTRUCTION_BY_ID');\nlogger.level = 'debug';\n\nconst { projectService, instructionService } = components;\n\n/**\n * Instructions API - Supports two types of instructions:\n *\n * 1. Global Instructions (isGlobal: true)\n *    - Apply to every query that Wren AI generates\n *    - Ideal for setting consistent standards, enforcing business rules\n *    - Should NOT include questions field\n *\n * 2. Question-Matching Instructions (isGlobal: false or undefined)\n *    - Applied only when user's question matches certain patterns\n *    - Ideal for guiding how Wren AI handles specific business concepts\n *    - MUST include questions array with at least one question\n */\ninterface UpdateInstructionRequest {\n  instruction?: string;\n  questions?: string[];\n  isGlobal?: boolean;\n}\n\n/**\n * Validate instruction ID from request query\n */\nconst validateInstructionId = (id: any): number => {\n  if (!id || typeof id !== 'string') {\n    throw new ApiError('Instruction ID is required', 400);\n  }\n\n  const instructionId = parseInt(id, 10);\n  if (isNaN(instructionId)) {\n    throw new ApiError('Invalid instruction ID', 400);\n  }\n\n  return instructionId;\n};\n\n/**\n * Handle PUT request - update an existing instruction\n */\nconst handleUpdateInstruction = async (\n  req: NextApiRequest,\n  res: NextApiResponse,\n  project: any,\n  startTime: number,\n) => {\n  const { id } = req.query;\n  const instructionId = validateInstructionId(id);\n\n  const { instruction, questions, isGlobal } =\n    req.body as UpdateInstructionRequest;\n\n  // Get the original instruction\n  const existingInstruction =\n    await instructionService.getInstruction(instructionId);\n\n  if (!existingInstruction) {\n    throw new ApiError('Instruction not found', 404);\n  }\n\n  // Merge original with update payload\n  const mergedInstruction = {\n    instruction: instruction ?? existingInstruction.instruction,\n    questions: questions ?? existingInstruction.questions,\n    isGlobal: isGlobal ?? existingInstruction.isDefault,\n  };\n\n  // If isGlobal is true, set questions to empty array\n  if (mergedInstruction.isGlobal === true) {\n    mergedInstruction.questions = [];\n  }\n\n  // Update the instruction\n  const updatedInstruction = await instructionService.updateInstruction({\n    id: instructionId,\n    instruction: mergedInstruction.instruction,\n    questions: mergedInstruction.questions,\n    isDefault: mergedInstruction.isGlobal,\n    projectId: project.id,\n  });\n\n  // Return the updated instruction directly\n  const isGlobalValue =\n    typeof updatedInstruction.isDefault === 'boolean'\n      ? updatedInstruction.isDefault\n      : Boolean(updatedInstruction.isDefault);\n  await respondWithSimple({\n    res,\n    statusCode: 200,\n    responsePayload: {\n      id: updatedInstruction.id,\n      instruction: updatedInstruction.instruction,\n      questions: updatedInstruction.questions,\n      isGlobal: isGlobalValue,\n    },\n    projectId: project.id,\n    apiType: ApiType.UPDATE_INSTRUCTION,\n    startTime,\n    requestPayload: req.body,\n    headers: req.headers as Record<string, string>,\n  });\n};\n\n/**\n * Handle DELETE request - delete an instruction\n */\nconst handleDeleteInstruction = async (\n  req: NextApiRequest,\n  res: NextApiResponse,\n  project: any,\n  startTime: number,\n) => {\n  const { id } = req.query;\n  const instructionId = validateInstructionId(id);\n\n  // Delete the instruction\n  await instructionService.deleteInstruction(instructionId, project.id);\n\n  // Return 204 No Content with no payload\n  await respondWithSimple({\n    res,\n    statusCode: 204,\n    responsePayload: {},\n    projectId: project.id,\n    apiType: ApiType.DELETE_INSTRUCTION,\n    startTime,\n    requestPayload: { id: instructionId },\n    headers: req.headers as Record<string, string>,\n  });\n};\n\nexport default async function handler(\n  req: NextApiRequest,\n  res: NextApiResponse,\n) {\n  const startTime = Date.now();\n  let project;\n\n  try {\n    project = await projectService.getCurrentProject();\n\n    // Handle PUT method - update instruction\n    if (req.method === 'PUT') {\n      await handleUpdateInstruction(req, res, project, startTime);\n      return;\n    }\n\n    // Handle DELETE method - delete instruction\n    if (req.method === 'DELETE') {\n      await handleDeleteInstruction(req, res, project, startTime);\n      return;\n    }\n\n    // Method not allowed\n    throw new ApiError('Method not allowed', 405);\n  } catch (error) {\n    await handleApiError({\n      error,\n      res,\n      projectId: project?.id,\n      apiType:\n        req.method === 'PUT'\n          ? ApiType.UPDATE_INSTRUCTION\n          : ApiType.DELETE_INSTRUCTION,\n      requestPayload: req.method === 'PUT' ? req.body : { id: req.query.id },\n      headers: req.headers as Record<string, string>,\n      startTime,\n      logger,\n    });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/pages/api/v1/knowledge/instructions/index.ts",
    "content": "import { NextApiRequest, NextApiResponse } from 'next';\nimport { components } from '@/common';\nimport { ApiType } from '@server/repositories/apiHistoryRepository';\nimport {\n  ApiError,\n  respondWithSimple,\n  handleApiError,\n} from '@/apollo/server/utils/apiUtils';\nimport { getLogger } from '@server/utils';\nimport { isNil } from 'lodash';\n\nconst logger = getLogger('API_INSTRUCTIONS');\nlogger.level = 'debug';\n\nconst { projectService, instructionService } = components;\n\n/**\n * Instructions API - Supports two types of instructions:\n *\n * 1. Global Instructions (isGlobal: true)\n *    - Apply to every query that Wren AI generates\n *    - Ideal for setting consistent standards, enforcing business rules\n *    - Should NOT include questions field\n *\n * 2. Question-Matching Instructions (isGlobal: false or undefined)\n *    - Applied only when user's question matches certain patterns\n *    - Ideal for guiding how Wren AI handles specific business concepts\n *    - MUST include questions array with at least one question\n */\ninterface CreateInstructionRequest {\n  instruction: string;\n  questions?: string[];\n  isGlobal?: boolean;\n}\n\n/**\n * Handle GET request - list all instructions for the current project\n */\nconst handleGetInstructions = async (\n  req: NextApiRequest,\n  res: NextApiResponse,\n  project: any,\n  startTime: number,\n) => {\n  // Get all instructions for the current project\n  const instructions = (\n    (await instructionService.getInstructions(project.id)) || []\n  ).map((instruction) => {\n    const isGlobalValue =\n      typeof instruction.isDefault === 'boolean'\n        ? instruction.isDefault\n        : Boolean(instruction.isDefault);\n    return {\n      id: instruction.id,\n      instruction: instruction.instruction,\n      questions: instruction.questions,\n      isGlobal: isGlobalValue,\n    };\n  });\n\n  // Return the instructions array directly\n  await respondWithSimple({\n    res,\n    statusCode: 200,\n    responsePayload: instructions,\n    projectId: project.id,\n    apiType: ApiType.GET_INSTRUCTIONS,\n    startTime,\n    requestPayload: {},\n    headers: req.headers as Record<string, string>,\n  });\n};\n\n/**\n * Handle POST request - create a new instruction\n */\nconst handleCreateInstruction = async (\n  req: NextApiRequest,\n  res: NextApiResponse,\n  project: any,\n  startTime: number,\n) => {\n  const { instruction, questions, isGlobal } =\n    req.body as CreateInstructionRequest;\n\n  // Input validation\n  if (!instruction) {\n    throw new ApiError('Instruction is required', 400);\n  }\n\n  if (instruction.length > 1000) {\n    throw new ApiError('Instruction is too long (max 1000 characters)', 400);\n  }\n\n  if (isNil(isGlobal) && isNil(questions)) {\n    throw new ApiError('isGlobal or questions is required', 400);\n  }\n\n  // Validate instruction type and fields\n  if (isGlobal === true) {\n    // Global instruction - questions should not be provided\n    if (questions && questions.length > 0) {\n      throw new ApiError(\n        'Global instructions should not include questions. Questions are only for question-matching instructions.',\n        400,\n      );\n    }\n  } else {\n    // Question-matching instruction - questions are required\n    if (!questions || !Array.isArray(questions) || questions.length === 0) {\n      throw new ApiError(\n        'Question-matching instructions require at least one question',\n        400,\n      );\n    }\n\n    // Validate each question\n    questions.forEach((question, index) => {\n      if (\n        !question ||\n        typeof question !== 'string' ||\n        question.trim().length === 0\n      ) {\n        throw new ApiError(\n          `Question at index ${index} is required and cannot be empty`,\n          400,\n        );\n      }\n      if (question.length > 500) {\n        throw new ApiError(\n          `Question at index ${index} is too long (max 500 characters)`,\n          400,\n        );\n      }\n    });\n  }\n\n  // Create the instruction\n  const newInstruction = await instructionService.createInstruction({\n    instruction,\n    questions: questions || [],\n    isDefault: isGlobal === true,\n    projectId: project.id,\n  });\n\n  // Return the created instruction directly\n  const isGlobalValue =\n    typeof newInstruction.isDefault === 'boolean'\n      ? newInstruction.isDefault\n      : Boolean(newInstruction.isDefault);\n  await respondWithSimple({\n    res,\n    statusCode: 201,\n    responsePayload: {\n      id: newInstruction.id,\n      instruction: newInstruction.instruction,\n      questions: newInstruction.questions,\n      isGlobal: isGlobalValue,\n    },\n    projectId: project.id,\n    apiType: ApiType.CREATE_INSTRUCTION,\n    startTime,\n    requestPayload: req.body,\n    headers: req.headers as Record<string, string>,\n  });\n};\n\nexport default async function handler(\n  req: NextApiRequest,\n  res: NextApiResponse,\n) {\n  const startTime = Date.now();\n  let project;\n\n  try {\n    project = await projectService.getCurrentProject();\n\n    // Handle GET method - list instructions\n    if (req.method === 'GET') {\n      await handleGetInstructions(req, res, project, startTime);\n      return;\n    }\n\n    // Handle POST method - create instruction\n    if (req.method === 'POST') {\n      await handleCreateInstruction(req, res, project, startTime);\n      return;\n    }\n\n    // Method not allowed\n    throw new ApiError('Method not allowed', 405);\n  } catch (error) {\n    await handleApiError({\n      error,\n      res,\n      projectId: project?.id,\n      apiType:\n        req.method === 'GET'\n          ? ApiType.GET_INSTRUCTIONS\n          : ApiType.CREATE_INSTRUCTION,\n      requestPayload: req.method === 'GET' ? {} : req.body,\n      headers: req.headers as Record<string, string>,\n      startTime,\n      logger,\n    });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/pages/api/v1/knowledge/sql_pairs/[id].ts",
    "content": "import { NextApiRequest, NextApiResponse } from 'next';\nimport { components } from '@/common';\nimport { ApiType } from '@server/repositories/apiHistoryRepository';\nimport {\n  ApiError,\n  respondWithSimple,\n  handleApiError,\n  validateSql,\n} from '@/apollo/server/utils/apiUtils';\nimport { getLogger } from '@server/utils';\n\nconst logger = getLogger('API_SQL_PAIR_BY_ID');\nlogger.level = 'debug';\n\nconst { projectService, sqlPairService, deployService, queryService } =\n  components;\n\n/**\n * SQL Pairs API - Manages SQL query and question pairs for knowledge base\n */\ninterface UpdateSqlPairRequest {\n  sql?: string;\n  question?: string;\n}\n\n/**\n * Validate SQL pair ID from request query\n */\nconst validateSqlPairId = (id: any): number => {\n  if (!id || typeof id !== 'string') {\n    throw new ApiError('SQL pair ID is required', 400);\n  }\n\n  const sqlPairId = parseInt(id, 10);\n  if (isNaN(sqlPairId)) {\n    throw new ApiError('Invalid SQL pair ID', 400);\n  }\n\n  return sqlPairId;\n};\n\n/**\n * Handle PUT request - update an existing SQL pair\n */\nconst handleUpdateSqlPair = async (\n  req: NextApiRequest,\n  res: NextApiResponse,\n  project: any,\n  startTime: number,\n) => {\n  const { id } = req.query;\n  const sqlPairId = validateSqlPairId(id);\n\n  const { sql, question } = req.body as UpdateSqlPairRequest;\n\n  // Input validation for provided fields\n  if (sql !== undefined) {\n    if (!sql) {\n      throw new ApiError('SQL cannot be empty', 400);\n    }\n    if (sql.length > 10000) {\n      throw new ApiError('SQL is too long (max 10000 characters)', 400);\n    }\n    // Validate SQL syntax and compatibility\n    await validateSql(sql, project, deployService, queryService);\n  }\n\n  if (question !== undefined) {\n    if (!question) {\n      throw new ApiError('Question cannot be empty', 400);\n    }\n    if (question.length > 1000) {\n      throw new ApiError('Question is too long (max 1000 characters)', 400);\n    }\n  }\n\n  // Update the SQL pair\n  const updatedSqlPair = await sqlPairService.editSqlPair(\n    project.id,\n    sqlPairId,\n    {\n      sql,\n      question,\n    },\n  );\n\n  // Return the updated SQL pair directly\n  await respondWithSimple({\n    res,\n    statusCode: 200,\n    responsePayload: updatedSqlPair,\n    projectId: project.id,\n    apiType: ApiType.UPDATE_SQL_PAIR,\n    startTime,\n    requestPayload: req.body,\n    headers: req.headers as Record<string, string>,\n  });\n};\n\n/**\n * Handle DELETE request - delete a SQL pair\n */\nconst handleDeleteSqlPair = async (\n  req: NextApiRequest,\n  res: NextApiResponse,\n  project: any,\n  startTime: number,\n) => {\n  const { id } = req.query;\n  const sqlPairId = validateSqlPairId(id);\n\n  // Delete the SQL pair\n  await sqlPairService.deleteSqlPair(project.id, sqlPairId);\n\n  // Return 204 No Content with no payload\n  await respondWithSimple({\n    res,\n    statusCode: 204,\n    responsePayload: {},\n    projectId: project.id,\n    apiType: ApiType.DELETE_SQL_PAIR,\n    startTime,\n    requestPayload: { id: sqlPairId },\n    headers: req.headers as Record<string, string>,\n  });\n};\n\nexport default async function handler(\n  req: NextApiRequest,\n  res: NextApiResponse,\n) {\n  const startTime = Date.now();\n  let project;\n\n  try {\n    project = await projectService.getCurrentProject();\n\n    // Handle PUT method - update SQL pair\n    if (req.method === 'PUT') {\n      await handleUpdateSqlPair(req, res, project, startTime);\n      return;\n    }\n\n    // Handle DELETE method - delete SQL pair\n    if (req.method === 'DELETE') {\n      await handleDeleteSqlPair(req, res, project, startTime);\n      return;\n    }\n\n    // Method not allowed\n    throw new ApiError('Method not allowed', 405);\n  } catch (error) {\n    await handleApiError({\n      error,\n      res,\n      projectId: project?.id,\n      apiType:\n        req.method === 'PUT'\n          ? ApiType.UPDATE_SQL_PAIR\n          : ApiType.DELETE_SQL_PAIR,\n      requestPayload: req.method === 'PUT' ? req.body : { id: req.query.id },\n      headers: req.headers as Record<string, string>,\n      startTime,\n      logger,\n    });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/pages/api/v1/knowledge/sql_pairs/index.ts",
    "content": "import { NextApiRequest, NextApiResponse } from 'next';\nimport { components } from '@/common';\nimport { ApiType } from '@server/repositories/apiHistoryRepository';\nimport {\n  ApiError,\n  respondWithSimple,\n  handleApiError,\n  validateSql,\n} from '@/apollo/server/utils/apiUtils';\nimport { getLogger } from '@server/utils';\n\nconst logger = getLogger('API_SQL_PAIRS');\nlogger.level = 'debug';\n\nconst { projectService, sqlPairService, deployService, queryService } =\n  components;\n\n/**\n * SQL Pairs API - Manages SQL query and question pairs for knowledge base\n */\ninterface CreateSqlPairRequest {\n  sql: string;\n  question: string;\n}\n\n/**\n * Handle GET request - list all SQL pairs for the current project\n */\nconst handleGetSqlPairs = async (\n  req: NextApiRequest,\n  res: NextApiResponse,\n  project: any,\n  startTime: number,\n) => {\n  // Get all SQL pairs for the current project\n  const sqlPairs = await sqlPairService.getProjectSqlPairs(project.id);\n\n  // Return the SQL pairs array directly\n  await respondWithSimple({\n    res,\n    statusCode: 200,\n    responsePayload: sqlPairs,\n    projectId: project.id,\n    apiType: ApiType.GET_SQL_PAIRS,\n    startTime,\n    requestPayload: {},\n    headers: req.headers as Record<string, string>,\n  });\n};\n\n/**\n * Handle POST request - create a new SQL pair\n */\nconst handleCreateSqlPair = async (\n  req: NextApiRequest,\n  res: NextApiResponse,\n  project: any,\n  startTime: number,\n) => {\n  const { sql, question } = req.body as CreateSqlPairRequest;\n\n  // Input validation\n  if (!sql) {\n    throw new ApiError('SQL is required', 400);\n  }\n\n  if (!question) {\n    throw new ApiError('Question is required', 400);\n  }\n\n  if (sql.length > 10000) {\n    throw new ApiError('SQL is too long (max 10000 characters)', 400);\n  }\n\n  if (question.length > 1000) {\n    throw new ApiError('Question is too long (max 1000 characters)', 400);\n  }\n\n  // Validate SQL syntax and compatibility\n  await validateSql(sql, project, deployService, queryService);\n\n  // Create the SQL pair\n  const newSqlPair = await sqlPairService.createSqlPair(project.id, {\n    sql,\n    question,\n  });\n\n  // Return the created SQL pair directly\n  await respondWithSimple({\n    res,\n    statusCode: 201,\n    responsePayload: newSqlPair,\n    projectId: project.id,\n    apiType: ApiType.CREATE_SQL_PAIR,\n    startTime,\n    requestPayload: req.body,\n    headers: req.headers as Record<string, string>,\n  });\n};\n\nexport default async function handler(\n  req: NextApiRequest,\n  res: NextApiResponse,\n) {\n  const startTime = Date.now();\n  let project;\n\n  try {\n    project = await projectService.getCurrentProject();\n\n    // Handle GET method - list SQL pairs\n    if (req.method === 'GET') {\n      await handleGetSqlPairs(req, res, project, startTime);\n      return;\n    }\n\n    // Handle POST method - create SQL pair\n    if (req.method === 'POST') {\n      await handleCreateSqlPair(req, res, project, startTime);\n      return;\n    }\n\n    // Method not allowed\n    throw new ApiError('Method not allowed', 405);\n  } catch (error) {\n    await handleApiError({\n      error,\n      res,\n      projectId: project?.id,\n      apiType:\n        req.method === 'GET' ? ApiType.GET_SQL_PAIRS : ApiType.CREATE_SQL_PAIR,\n      requestPayload: req.method === 'GET' ? {} : req.body,\n      headers: req.headers as Record<string, string>,\n      startTime,\n      logger,\n    });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/pages/api/v1/models.ts",
    "content": "import { NextApiRequest, NextApiResponse } from 'next';\nimport { components } from '@/common';\nimport { ApiType } from '@server/repositories/apiHistoryRepository';\nimport * as Errors from '@/apollo/server/utils/error';\nimport {\n  ApiError,\n  respondWithSimple,\n  handleApiError,\n} from '@/apollo/server/utils/apiUtils';\nimport { getLogger } from '@server/utils';\n\nconst logger = getLogger('API_MODELS');\nlogger.level = 'debug';\n\nconst { projectService, deployService } = components;\n\nexport default async function handler(\n  req: NextApiRequest,\n  res: NextApiResponse,\n) {\n  const startTime = Date.now();\n  let project;\n\n  try {\n    project = await projectService.getCurrentProject();\n\n    // Only allow GET method\n    if (req.method !== 'GET') {\n      throw new ApiError('Method not allowed', 405);\n    }\n\n    // Get current project's last deployment\n    const lastDeploy = await deployService.getLastDeployment(project.id);\n    if (!lastDeploy) {\n      throw new ApiError(\n        'No deployment found, please deploy your project first',\n        400,\n        Errors.GeneralErrorCodes.NO_DEPLOYMENT_FOUND,\n      );\n    }\n\n    // Get the MDL from the deployment manifest\n    const mdl = lastDeploy.manifest as any;\n\n    // Extract models, views, and relationships from the MDL with defaults\n    const models = mdl?.models || [];\n    const views = mdl?.views || [];\n    const relationships = mdl?.relationships || [];\n\n    // Return the restructured response\n    await respondWithSimple({\n      res,\n      statusCode: 200,\n      responsePayload: {\n        hash: lastDeploy.hash,\n        models,\n        relationships,\n        views,\n      },\n      projectId: project.id,\n      apiType: ApiType.GET_MODELS,\n      startTime,\n      headers: req.headers as Record<string, string>,\n    });\n  } catch (error) {\n    await handleApiError({\n      error,\n      res,\n      projectId: project?.id,\n      apiType: ApiType.GET_MODELS,\n      headers: req.headers as Record<string, string>,\n      startTime,\n      logger,\n    });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/pages/api/v1/run_sql.ts",
    "content": "import { NextApiRequest, NextApiResponse } from 'next';\nimport { components } from '@/common';\nimport { ApiType } from '@server/repositories/apiHistoryRepository';\nimport * as Errors from '@/apollo/server/utils/error';\nimport { getLogger } from '@server/utils';\nimport { v4 as uuidv4 } from 'uuid';\nimport { PreviewDataResponse } from '@server/services/queryService';\nimport {\n  ApiError,\n  respondWith,\n  handleApiError,\n} from '@/apollo/server/utils/apiUtils';\nimport { transformToObjects } from '@server/utils/dataUtils';\n\nconst logger = getLogger('API_RUN_SQL');\nlogger.level = 'debug';\n\nconst { projectService, queryService, deployService } = components;\n\n/**\n * Validates the SQL result and ensures it has the expected format\n * @param result The result to validate\n * @returns The validated result as PreviewDataResponse\n * @throws ApiError if the result is in an unexpected format\n */\nconst validateSqlResult = (result: any): PreviewDataResponse => {\n  // Ensure we have a valid result with expected properties\n  if (typeof result === 'boolean') {\n    throw new ApiError('Unexpected query result format', 500);\n  }\n\n  return result as PreviewDataResponse;\n};\n\ninterface RunSqlRequest {\n  sql: string;\n  threadId?: string;\n  limit?: number;\n}\n\nexport default async function handler(\n  req: NextApiRequest,\n  res: NextApiResponse,\n) {\n  const { sql, threadId, limit = 1000 } = req.body as RunSqlRequest;\n  const startTime = Date.now();\n  let project;\n\n  try {\n    // Only allow POST method\n    if (req.method !== 'POST') {\n      throw new ApiError('Method not allowed', 405);\n    }\n\n    // input validation\n    if (!sql) {\n      throw new ApiError('SQL is required', 400);\n    }\n\n    project = await projectService.getCurrentProject();\n\n    const deployment = await deployService.getLastDeployment(project.id);\n\n    if (!deployment) {\n      throw new ApiError(\n        'No deployment found, please deploy your project first',\n        400,\n        Errors.GeneralErrorCodes.NO_DEPLOYMENT_FOUND,\n      );\n    }\n\n    const manifest = deployment.manifest;\n\n    // Execute the SQL query\n    try {\n      const result = await queryService.preview(sql, {\n        project,\n        limit,\n        manifest,\n        modelingOnly: false,\n      });\n\n      // Validate the SQL result\n      const queryResult = validateSqlResult(result);\n\n      // Transform data into array of objects\n      const transformedData = transformToObjects(\n        queryResult.columns,\n        queryResult.data,\n      );\n\n      // create a new thread if it's a new query\n      const newThreadId = threadId || uuidv4();\n\n      await respondWith({\n        res,\n        statusCode: 200,\n        responsePayload: {\n          records: transformedData,\n          columns: queryResult.columns,\n          threadId: newThreadId,\n          totalRows: queryResult.data?.length || 0,\n        },\n        projectId: project.id,\n        apiType: ApiType.RUN_SQL,\n        startTime,\n        requestPayload: req.body,\n        threadId: newThreadId,\n        headers: req.headers as Record<string, string>,\n      });\n    } catch (queryError) {\n      logger.error('Error executing SQL:', queryError);\n      throw new ApiError(\n        queryError.message || 'Error executing SQL query',\n        400,\n        Errors.GeneralErrorCodes.INVALID_SQL_ERROR,\n      );\n    }\n  } catch (error) {\n    await handleApiError({\n      error,\n      res,\n      projectId: project?.id,\n      apiType: ApiType.RUN_SQL,\n      requestPayload: req.body,\n      threadId,\n      headers: req.headers as Record<string, string>,\n      startTime,\n      logger,\n    });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/pages/api/v1/stream/ask.ts",
    "content": "import { NextApiRequest, NextApiResponse } from 'next';\nimport { components } from '@/common';\nimport { ApiType } from '@server/repositories/apiHistoryRepository';\nimport * as Errors from '@/apollo/server/utils/error';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n  ApiError,\n  MAX_WAIT_TIME,\n  isAskResultFinished,\n  validateSummaryResult,\n  transformHistoryInput,\n} from '@/apollo/server/utils/apiUtils';\nimport {\n  AskResult,\n  AskResultStatus,\n  WrenAILanguage,\n  TextBasedAnswerInput,\n  TextBasedAnswerResult,\n  TextBasedAnswerStatus,\n  WrenAIError,\n  AskResultType,\n} from '@/apollo/server/models/adaptor';\nimport { getLogger } from '@server/utils';\nimport {\n  EventType,\n  StateType,\n  ContentBlockContentType,\n  AsyncAskRequest,\n  ContentBlockStartEvent,\n  ContentBlockDeltaEvent,\n  ContentBlockStopEvent,\n  sendSSEEvent,\n  sendMessageStart,\n  sendStateUpdate,\n  sendError,\n  getSqlGenerationState,\n  endStream,\n} from '@/apollo/server/utils';\n\nconst logger = getLogger('API_STREAM_ASK');\nlogger.level = 'debug';\n\nconst {\n  apiHistoryRepository,\n  projectService,\n  deployService,\n  wrenAIAdaptor,\n  queryService,\n} = components;\n\n/**\n * Send content block start event to client\n */\nconst sendContentBlockStart = (\n  res: NextApiResponse,\n  name: ContentBlockContentType,\n) => {\n  const contentBlockStartEvent: ContentBlockStartEvent = {\n    type: EventType.CONTENT_BLOCK_START,\n    content_block: {\n      type: 'text',\n      name,\n    },\n    timestamp: Date.now(),\n  };\n  sendSSEEvent(res, contentBlockStartEvent);\n};\n\n/**\n * Send content block delta event to client\n */\nconst sendContentBlockDelta = (res: NextApiResponse, text: string) => {\n  const contentBlockDeltaEvent: ContentBlockDeltaEvent = {\n    type: EventType.CONTENT_BLOCK_DELTA,\n    delta: {\n      type: 'text_delta',\n      text,\n    },\n    timestamp: Date.now(),\n  };\n  sendSSEEvent(res, contentBlockDeltaEvent);\n};\n\n/**\n * Send content block stop event to client\n */\nconst sendContentBlockStop = (res: NextApiResponse) => {\n  const contentBlockStopEvent: ContentBlockStopEvent = {\n    type: EventType.CONTENT_BLOCK_STOP,\n    timestamp: Date.now(),\n  };\n  sendSSEEvent(res, contentBlockStopEvent);\n};\n\nexport default async function handler(\n  req: NextApiRequest,\n  res: NextApiResponse,\n) {\n  const { question, sampleSize, language, threadId } =\n    req.body as AsyncAskRequest;\n  const startTime = Date.now();\n  let project;\n\n  try {\n    project = await projectService.getCurrentProject();\n\n    // Only allow POST method\n    if (req.method !== 'POST') {\n      throw new ApiError('Method not allowed', 405);\n    }\n\n    // Input validation\n    if (!question) {\n      throw new ApiError('Question is required', 400);\n    }\n\n    // Set up SSE headers\n    res.setHeader('Content-Type', 'text/event-stream');\n    res.setHeader('Cache-Control', 'no-cache, no-transform');\n    res.setHeader('Connection', 'keep-alive');\n    res.flushHeaders();\n\n    // Send message start event\n    sendMessageStart(res);\n\n    // Get current project's last deployment\n    const lastDeploy = await deployService.getLastDeployment(project.id);\n    if (!lastDeploy) {\n      throw new ApiError(\n        'No deployment found, please deploy your project first',\n        400,\n        Errors.GeneralErrorCodes.NO_DEPLOYMENT_FOUND,\n      );\n    }\n\n    // Create a new thread if it's a new question\n    const newThreadId = threadId || uuidv4();\n\n    // Get conversation history if threadId is provided\n    const histories = threadId\n      ? await apiHistoryRepository.findAllBy({ threadId })\n      : undefined;\n\n    // Step 1: Generate SQL\n    sendStateUpdate(res, StateType.SQL_GENERATION_START, {\n      question,\n      threadId: newThreadId,\n      language:\n        language || WrenAILanguage[project.language] || WrenAILanguage.EN,\n    });\n    const askTask = await wrenAIAdaptor.ask({\n      query: question,\n      deployId: lastDeploy.hash,\n      histories: transformHistoryInput(histories) as any,\n      configurations: {\n        language:\n          language || WrenAILanguage[project.language] || WrenAILanguage.EN,\n      },\n    });\n\n    // Poll for the SQL generation result\n    const deadline = Date.now() + MAX_WAIT_TIME;\n    let askResult: AskResult;\n    let pollCount = 0;\n    let previousStatus: AskResultStatus | null = null;\n\n    while (true) {\n      askResult = await wrenAIAdaptor.getAskResult(askTask.queryId);\n\n      // Send status change updates when AskResultStatus changes\n      if (askResult.status !== previousStatus) {\n        const sqlGenerationState = getSqlGenerationState(askResult.status);\n        sendStateUpdate(res, sqlGenerationState, {\n          pollCount: pollCount + 1,\n          rephrasedQuestion: askResult.rephrasedQuestion,\n          intentReasoning: askResult.intentReasoning,\n          sqlGenerationReasoning: askResult.sqlGenerationReasoning,\n          retrievedTables: askResult.retrievedTables,\n          invalidSql: askResult.invalidSql,\n          traceId: askResult.traceId,\n        });\n        previousStatus = askResult.status;\n      }\n\n      pollCount++;\n\n      // Check if the result is finished\n      if (isAskResultFinished(askResult)) {\n        break;\n      }\n\n      // Check if we've exceeded the maximum wait time\n      if (Date.now() > deadline) {\n        throw new ApiError(\n          'Request timeout',\n          400,\n          Errors.GeneralErrorCodes.POLLING_TIMEOUT,\n        );\n      }\n\n      // Wait before polling again\n      await new Promise((resolve) => setTimeout(resolve, 1000));\n    }\n\n    // Validate the ask result\n    // Check for error in result\n    if (askResult.error) {\n      const errorMessage =\n        (askResult.error as WrenAIError).message || 'Unknown error';\n      const additionalData: Record<string, any> = {};\n\n      // Include invalid SQL if available\n      if (askResult.invalidSql) {\n        additionalData.invalidSql = askResult.invalidSql;\n      }\n\n      throw new ApiError(\n        errorMessage,\n        400,\n        askResult.error.code,\n        additionalData,\n      );\n    }\n\n    // Check for general type response\n    // Stream the content to client\n    if (askResult.type === AskResultType.GENERAL) {\n      // Send content block start for explanation\n      sendContentBlockStart(res, ContentBlockContentType.EXPLANATION);\n\n      const stream = await wrenAIAdaptor.getAskStreamingResult(askTask.queryId);\n\n      // Stream the content in real-time\n      let explanation = '';\n      const streamPromise = new Promise<void>((resolve, reject) => {\n        stream.on('data', (chunk) => {\n          const chunkString = chunk.toString('utf-8');\n          const match = chunkString.match(/data: {\"message\":\"([\\s\\S]*?)\"}/);\n          if (match && match[1]) {\n            // Send incremental content updates\n            explanation += match[1];\n            sendContentBlockDelta(res, match[1]);\n          }\n        });\n\n        stream.on('end', () => {\n          resolve();\n        });\n\n        stream.on('error', (error) => {\n          reject(error);\n        });\n\n        // Handle client disconnect\n        req.on('close', () => {\n          stream.destroy();\n          reject(new Error('Client disconnected'));\n        });\n      });\n\n      try {\n        await streamPromise;\n        // Send content block stop\n        sendContentBlockStop(res);\n      } catch (_streamError) {\n        throw new ApiError(\n          'Error streaming explanation content',\n          400,\n          Errors.GeneralErrorCodes.INTERNAL_SERVER_ERROR,\n        );\n      }\n\n      // Log the API call and end the stream\n      await apiHistoryRepository.createOne({\n        id: uuidv4(),\n        projectId: project.id,\n        apiType: ApiType.STREAM_ASK,\n        threadId: newThreadId,\n        headers: req.headers as Record<string, string>,\n        requestPayload: { question, sampleSize, language },\n        responsePayload: {\n          explanation,\n        },\n        statusCode: 200,\n        durationMs: Date.now() - startTime,\n      });\n\n      endStream(res, newThreadId, startTime);\n      return;\n    }\n\n    // Get the generated SQL\n    const sql = askResult.response?.[0]?.sql;\n    if (!sql) {\n      throw new ApiError(\n        'No SQL generated',\n        400,\n        Errors.GeneralErrorCodes.INTERNAL_SERVER_ERROR,\n      );\n    }\n\n    // Send SQL generation success with the SQL content\n    sendStateUpdate(res, StateType.SQL_GENERATION_SUCCESS, { sql });\n\n    // Step 2: Execute SQL to get data\n    sendStateUpdate(res, StateType.SQL_EXECUTION_START, { sql });\n    let sqlData;\n    try {\n      const queryResult = await queryService.preview(sql, {\n        project,\n        limit: sampleSize || 500,\n        manifest: lastDeploy.manifest,\n        modelingOnly: false,\n      });\n      sqlData = queryResult;\n      sendStateUpdate(res, StateType.SQL_EXECUTION_END);\n    } catch (queryError) {\n      throw new ApiError(\n        `SQL execution failed: ${queryError.message || 'Unknown error'}`,\n        400,\n        Errors.GeneralErrorCodes.SQL_EXECUTION_ERROR,\n      );\n    }\n\n    // Step 3: Generate summary using text-based answer\n    const textBasedAnswerInput: TextBasedAnswerInput = {\n      query: question,\n      sql,\n      sqlData,\n      threadId: newThreadId,\n      configurations: {\n        language:\n          language || WrenAILanguage[project.language] || WrenAILanguage.EN,\n      },\n    };\n\n    // Start the summary generation task\n    const summaryTask =\n      await wrenAIAdaptor.createTextBasedAnswer(textBasedAnswerInput);\n\n    if (!summaryTask || !summaryTask.queryId) {\n      throw new ApiError(\n        'Failed to start summary generation task',\n        400,\n        Errors.GeneralErrorCodes.INTERNAL_SERVER_ERROR,\n      );\n    }\n\n    // Poll for the summary generation result\n    const summaryDeadline = Date.now() + MAX_WAIT_TIME;\n    let summaryResult: TextBasedAnswerResult;\n\n    while (true) {\n      summaryResult = await wrenAIAdaptor.getTextBasedAnswerResult(\n        summaryTask.queryId,\n      );\n\n      if (\n        summaryResult.status === TextBasedAnswerStatus.SUCCEEDED ||\n        summaryResult.status === TextBasedAnswerStatus.FAILED\n      ) {\n        break;\n      }\n\n      // Check if we've exceeded the maximum wait time\n      if (Date.now() > summaryDeadline) {\n        throw new ApiError(\n          'Summary generation timeout',\n          400,\n          Errors.GeneralErrorCodes.POLLING_TIMEOUT,\n        );\n      }\n\n      // Wait before polling again\n      await new Promise((resolve) => setTimeout(resolve, 1000));\n    }\n\n    // Validate the summary result\n    validateSummaryResult(summaryResult);\n\n    // Step 4: Stream the content to get the summary\n    let summary = '';\n    if (summaryResult.status === TextBasedAnswerStatus.SUCCEEDED) {\n      // Send content block start\n      sendContentBlockStart(res, ContentBlockContentType.SUMMARY_GENERATION);\n\n      const stream = await wrenAIAdaptor.streamTextBasedAnswer(\n        summaryTask.queryId,\n      );\n\n      // Stream the content in real-time\n      const streamPromise = new Promise<void>((resolve, reject) => {\n        stream.on('data', (chunk) => {\n          const chunkString = chunk.toString('utf-8');\n          const match = chunkString.match(/data: {\"message\":\"([\\s\\S]*?)\"}/);\n          if (match && match[1]) {\n            summary += match[1];\n            // Send incremental content updates\n            sendContentBlockDelta(res, match[1]);\n          }\n        });\n\n        stream.on('end', () => {\n          resolve();\n        });\n\n        stream.on('error', (error) => {\n          reject(error);\n        });\n\n        // Handle client disconnect\n        req.on('close', () => {\n          stream.destroy();\n          reject(new Error('Client disconnected'));\n        });\n      });\n\n      try {\n        await streamPromise;\n        // Send content block stop\n        sendContentBlockStop(res);\n      } catch (_streamError) {\n        throw new ApiError(\n          'Error streaming summary content',\n          400,\n          Errors.GeneralErrorCodes.INTERNAL_SERVER_ERROR,\n        );\n      }\n    }\n\n    // Log the API call\n    await apiHistoryRepository.createOne({\n      id: uuidv4(),\n      projectId: project.id,\n      apiType: ApiType.STREAM_ASK,\n      threadId: newThreadId,\n      headers: req.headers as Record<string, string>,\n      requestPayload: { question, sampleSize, language },\n      responsePayload: {\n        sql,\n        summary,\n      },\n      statusCode: 200,\n      durationMs: Date.now() - startTime,\n    });\n\n    endStream(res, newThreadId, startTime);\n  } catch (error) {\n    logger.error('Error in stream ask API:', error);\n\n    // Log the error\n    await apiHistoryRepository.createOne({\n      id: uuidv4(),\n      projectId: project?.id || 0,\n      apiType: ApiType.STREAM_ASK,\n      threadId: threadId || uuidv4(),\n      headers: req.headers as Record<string, string>,\n      requestPayload: { question, sampleSize, language },\n      responsePayload: {\n        error: error instanceof Error ? error.message : String(error),\n      },\n      statusCode: 500,\n      durationMs: Date.now() - startTime,\n    });\n\n    sendError(\n      res,\n      error instanceof Error ? error.message : 'Internal server error',\n      error.code || Errors.GeneralErrorCodes.INTERNAL_SERVER_ERROR,\n      error.additionalData,\n    );\n    endStream(res, threadId || uuidv4(), startTime);\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/pages/api/v1/stream/generate_sql.ts",
    "content": "import { NextApiRequest, NextApiResponse } from 'next';\nimport { components } from '@/common';\nimport { ApiType } from '@server/repositories/apiHistoryRepository';\nimport * as Errors from '@/apollo/server/utils/error';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n  ApiError,\n  MAX_WAIT_TIME,\n  isAskResultFinished,\n  transformHistoryInput,\n  validateAskResult,\n} from '@/apollo/server/utils/apiUtils';\nimport {\n  AskResult,\n  AskResultStatus,\n  WrenAILanguage,\n} from '@/apollo/server/models/adaptor';\nimport { getLogger } from '@server/utils';\nimport {\n  StateType,\n  AsyncAskRequest,\n  sendMessageStart,\n  sendStateUpdate,\n  sendError,\n  getSqlGenerationState,\n  endStream,\n} from '@/apollo/server/utils';\n\nconst logger = getLogger('API_STREAM_GENERATE_SQL');\nlogger.level = 'debug';\n\nconst { apiHistoryRepository, projectService, deployService, wrenAIAdaptor } =\n  components;\n\nexport default async function handler(\n  req: NextApiRequest,\n  res: NextApiResponse,\n) {\n  const { question, language, threadId } = req.body as AsyncAskRequest;\n  const startTime = Date.now();\n  let project;\n\n  try {\n    project = await projectService.getCurrentProject();\n\n    // Only allow POST method\n    if (req.method !== 'POST') {\n      throw new ApiError('Method not allowed', 405);\n    }\n\n    // Input validation\n    if (!question) {\n      throw new ApiError('Question is required', 400);\n    }\n\n    // Set up SSE headers\n    res.setHeader('Content-Type', 'text/event-stream');\n    res.setHeader('Cache-Control', 'no-cache, no-transform');\n    res.setHeader('Connection', 'keep-alive');\n    res.flushHeaders();\n\n    // Create a new thread if it's a new question\n    const newThreadId = threadId || uuidv4();\n\n    // Send message start event\n    sendMessageStart(res);\n\n    // Get current project's last deployment\n    const lastDeploy = await deployService.getLastDeployment(project.id);\n    if (!lastDeploy) {\n      throw new ApiError(\n        'No deployment found, please deploy your project first',\n        400,\n        Errors.GeneralErrorCodes.NO_DEPLOYMENT_FOUND,\n      );\n    }\n\n    // Get conversation history if threadId is provided\n    const histories = threadId\n      ? await apiHistoryRepository.findAllBy({ threadId })\n      : undefined;\n\n    // Step 1: Generate SQL\n    sendStateUpdate(res, StateType.SQL_GENERATION_START, {\n      question,\n      threadId: newThreadId,\n      language:\n        language || WrenAILanguage[project.language] || WrenAILanguage.EN,\n    });\n\n    const askTask = await wrenAIAdaptor.ask({\n      query: question,\n      deployId: lastDeploy.hash,\n      histories: transformHistoryInput(histories) as any,\n      configurations: {\n        language:\n          language || WrenAILanguage[project.language] || WrenAILanguage.EN,\n      },\n    });\n\n    // Poll for the SQL generation result\n    const deadline = Date.now() + MAX_WAIT_TIME;\n    let askResult: AskResult;\n    let pollCount = 0;\n    let previousStatus: AskResultStatus | null = null;\n\n    while (true) {\n      askResult = await wrenAIAdaptor.getAskResult(askTask.queryId);\n\n      // Send status change updates when AskResultStatus changes\n      if (askResult.status !== previousStatus) {\n        const sqlGenerationState = getSqlGenerationState(askResult.status);\n        sendStateUpdate(res, sqlGenerationState, {\n          pollCount: pollCount + 1,\n          rephrasedQuestion: askResult.rephrasedQuestion,\n          intentReasoning: askResult.intentReasoning,\n          sqlGenerationReasoning: askResult.sqlGenerationReasoning,\n          retrievedTables: askResult.retrievedTables,\n          invalidSql: askResult.invalidSql,\n          traceId: askResult.traceId,\n        });\n        previousStatus = askResult.status;\n      }\n\n      pollCount++;\n\n      // Check if the result is finished\n      if (isAskResultFinished(askResult)) {\n        break;\n      }\n\n      // Check if we've exceeded the maximum wait time\n      if (Date.now() > deadline) {\n        throw new ApiError(\n          'Request timeout',\n          400,\n          Errors.GeneralErrorCodes.POLLING_TIMEOUT,\n        );\n      }\n\n      // Wait before polling again\n      await new Promise((resolve) => setTimeout(resolve, 1000));\n    }\n\n    // Validate the result\n    validateAskResult(askResult, askTask.queryId);\n\n    // Get the generated SQL\n    const sql = askResult.response?.[0]?.sql;\n    if (!sql) {\n      throw new ApiError(\n        'No SQL generated',\n        400,\n        Errors.GeneralErrorCodes.INTERNAL_SERVER_ERROR,\n      );\n    }\n\n    // Send SQL generation success with the SQL content\n    sendStateUpdate(res, StateType.SQL_GENERATION_SUCCESS, { sql });\n\n    // Log the API call\n    await apiHistoryRepository.createOne({\n      id: uuidv4(),\n      projectId: project.id,\n      apiType: ApiType.STREAM_GENERATE_SQL,\n      threadId: newThreadId,\n      headers: req.headers as Record<string, string>,\n      requestPayload: { question, language },\n      responsePayload: { sql },\n      statusCode: 200,\n      durationMs: Date.now() - startTime,\n    });\n\n    endStream(res, newThreadId, startTime);\n  } catch (error) {\n    logger.error('Error in stream generate SQL API:', error);\n\n    // Log the error\n    await apiHistoryRepository.createOne({\n      id: uuidv4(),\n      projectId: project?.id || 0,\n      apiType: ApiType.STREAM_GENERATE_SQL,\n      threadId: threadId || uuidv4(),\n      headers: req.headers as Record<string, string>,\n      requestPayload: { question, language },\n      responsePayload: {\n        error: error instanceof Error ? error.message : String(error),\n      },\n      statusCode: 500,\n      durationMs: Date.now() - startTime,\n    });\n\n    sendError(\n      res,\n      error instanceof Error ? error.message : 'Internal server error',\n      error.code || Errors.GeneralErrorCodes.INTERNAL_SERVER_ERROR,\n      error.additionalData,\n    );\n    endStream(res, threadId || uuidv4(), startTime);\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/pages/api/v1/stream_explanation.ts",
    "content": "import type { NextApiRequest, NextApiResponse } from 'next';\nimport { components } from '@/common';\n\nconst { wrenAIAdaptor } = components;\n\nexport default async function handler(\n  req: NextApiRequest,\n  res: NextApiResponse,\n) {\n  res.setHeader('Content-Type', 'text/event-stream');\n  res.setHeader('Cache-Control', 'no-cache, no-transform');\n  res.setHeader('Connection', 'keep-alive');\n  res.flushHeaders();\n\n  const { queryId } = req.query;\n  if (!queryId) {\n    res.status(400).json({ error: 'queryId is required' });\n    return;\n  }\n\n  try {\n    const stream = await wrenAIAdaptor.getAskStreamingResult(queryId as string);\n\n    stream.on('data', (chunk) => {\n      // pass the chunk directly to the client\n      res.write(chunk);\n    });\n\n    stream.on('end', () => {\n      res.write(`data: ${JSON.stringify({ done: true })}\\n\\n`);\n      res.end();\n    });\n\n    // destroy the stream if the client closes the connection\n    req.on('close', () => {\n      stream.destroy();\n    });\n  } catch (error) {\n    console.error(error);\n    res.status(500).json({ error: error.message });\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/pages/api-management/history.tsx",
    "content": "import Link from 'next/link';\nimport { useState } from 'react';\nimport { Table, TableColumnsType, Button, Tag, Typography } from 'antd';\nimport { getAbsoluteTime } from '@/utils/time';\nimport useDrawerAction from '@/hooks/useDrawerAction';\nimport { getColumnSearchProps } from '@/utils/table';\nimport SiderLayout from '@/components/layouts/SiderLayout';\nimport PageLayout from '@/components/layouts/PageLayout';\nimport ApiOutlined from '@ant-design/icons/ApiOutlined';\nimport EyeOutlined from '@ant-design/icons/EyeOutlined';\nimport CheckCircleOutlined from '@ant-design/icons/CheckCircleOutlined';\nimport CloseCircleOutlined from '@ant-design/icons/CloseCircleOutlined';\nimport SQLCodeBlock from '@/components/code/SQLCodeBlock';\nimport DetailsDrawer from '@/components/pages/apiManagement/DetailsDrawer';\nimport { useApiHistoryQuery } from '@/apollo/client/graphql/apiManagement.generated';\nimport { ApiType, ApiHistoryResponse } from '@/apollo/client/graphql/__types__';\n\nconst PAGE_SIZE = 10;\n\nexport default function APIHistory() {\n  const detailsDrawer = useDrawerAction();\n  const [currentPage, setCurrentPage] = useState<number>(1);\n  const [filters, setFilters] = useState<Record<string, any>>({});\n\n  const { data, loading } = useApiHistoryQuery({\n    fetchPolicy: 'cache-and-network',\n    variables: {\n      pagination: {\n        offset: (currentPage - 1) * PAGE_SIZE,\n        limit: PAGE_SIZE,\n      },\n      filter: {\n        apiType: filters['apiType']?.[0],\n        statusCode: filters['statusCode']?.[0],\n        threadId: filters['threadId']?.[0],\n      },\n    },\n    onError: (error) => console.error(error),\n  });\n\n  const columns: TableColumnsType<ApiHistoryResponse> = [\n    {\n      title: 'Timestamp',\n      dataIndex: 'createdAt',\n      key: 'createdAt',\n      width: 180,\n      render: (timestamp: string) => (\n        <div className=\"gray-7\">{getAbsoluteTime(timestamp)}</div>\n      ),\n    },\n    {\n      title: 'API type',\n      dataIndex: 'apiType',\n      key: 'apiType',\n      width: 180,\n      render: (type: ApiHistoryResponse['apiType']) => (\n        <Tag className=\"gray-8\">{type.toLowerCase()}</Tag>\n      ),\n      filters: Object.keys(ApiType).map((type) => ({\n        text: type.toLowerCase(),\n        value: type,\n      })),\n      filteredValue: filters['apiType'],\n      filterMultiple: false,\n    },\n    {\n      title: 'Status',\n      dataIndex: 'statusCode',\n      key: 'statusCode',\n      width: 100,\n      render: (status: number) => {\n        const icon =\n          status >= 200 && status < 300 ? (\n            <CheckCircleOutlined />\n          ) : (\n            <CloseCircleOutlined />\n          );\n        const color = status >= 200 && status < 300 ? 'success' : 'error';\n        return (\n          <Tag icon={icon} color={color}>\n            {status}\n          </Tag>\n        );\n      },\n      filters: [\n        { text: 'Successful (code: 2xx)', value: 200 },\n        { text: 'Client error (code: 4xx)', value: 400 },\n        { text: 'Server error (code: 5xx)', value: 500 },\n      ],\n      filteredValue: filters['statusCode'],\n      filterMultiple: false,\n    },\n    {\n      title: 'Question / SQL',\n      dataIndex: 'requestPayload',\n      key: 'requestPayload',\n      render: (payload: Record<string, any>, record: ApiHistoryResponse) => {\n        if (record.apiType === ApiType.RUN_SQL && payload.sql) {\n          return (\n            <div style={{ width: '100%' }}>\n              <SQLCodeBlock code={payload.sql} maxHeight=\"130\" />\n            </div>\n          );\n        }\n        return (\n          <div className=\"gray-8\">\n            {payload?.question || payload?.sql || '-'}\n          </div>\n        );\n      },\n    },\n    {\n      title: 'Thread ID',\n      dataIndex: 'threadId',\n      key: 'threadId',\n      width: 200,\n      render: (threadId: string) => {\n        if (!threadId) return <div className=\"gray-7\">-</div>;\n        return (\n          <Typography.Text\n            ellipsis\n            className=\"gray-7\"\n            copyable={{ text: threadId }}\n          >\n            {threadId}\n          </Typography.Text>\n        );\n      },\n      ...getColumnSearchProps({\n        dataIndex: 'threadId',\n        placeholder: 'thread ID',\n        filteredValue: filters['threadId'],\n      }),\n    },\n    {\n      title: 'Duration (ms)',\n      dataIndex: 'durationMs',\n      key: 'durationMs',\n      width: 124,\n      render: (durationMs: number) => (\n        <div className=\"gray-7 text-right\">{durationMs || '-'}</div>\n      ),\n    },\n    {\n      title: 'Actions',\n      key: 'actions',\n      width: 110,\n      align: 'center',\n      fixed: 'right',\n      render: (record) => (\n        <Button\n          className=\"gray-8\"\n          type=\"text\"\n          size=\"small\"\n          onClick={() => detailsDrawer.openDrawer(record)}\n        >\n          <EyeOutlined /> Details\n        </Button>\n      ),\n    },\n  ];\n\n  return (\n    <SiderLayout loading={false} sidebar={null}>\n      <PageLayout\n        title={\n          <>\n            <ApiOutlined className=\"mr-2 gray-8\" />\n            API history\n          </>\n        }\n        description={\n          <>\n            <div>\n              Here you can view the full history of API calls, including request\n              inputs, responses, and execution details.{' '}\n              <Link\n                className=\"gray-8 underline mr-2\"\n                href=\"https://docs.getwren.ai/oss/guide/api-access/history\"\n                target=\"_blank\"\n                rel=\"noopener noreferrer\"\n              >\n                Learn more.\n              </Link>\n            </div>\n          </>\n        }\n      >\n        <Table\n          className=\"ant-table-has-header\"\n          dataSource={data?.apiHistory.items || []}\n          loading={loading}\n          columns={columns}\n          rowKey=\"id\"\n          pagination={{\n            hideOnSinglePage: true,\n            pageSize: PAGE_SIZE,\n            size: 'small',\n            total: data?.apiHistory.total,\n          }}\n          scroll={{ x: 1200 }}\n          onChange={(pagination, filters, _sorter) => {\n            setCurrentPage(pagination.current);\n            setFilters(filters);\n          }}\n        />\n        <DetailsDrawer\n          {...detailsDrawer.state}\n          onClose={detailsDrawer.closeDrawer}\n        />\n      </PageLayout>\n    </SiderLayout>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/pages/home/[id].tsx",
    "content": "import { useRouter } from 'next/router';\nimport { useParams } from 'next/navigation';\nimport {\n  ComponentRef,\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from 'react';\nimport { isEmpty } from 'lodash';\nimport { message } from 'antd';\nimport { Path } from '@/utils/enum';\nimport useHomeSidebar from '@/hooks/useHomeSidebar';\nimport SiderLayout from '@/components/layouts/SiderLayout';\nimport Prompt from '@/components/pages/home/prompt';\nimport useAskPrompt, {\n  getIsFinished,\n  canFetchThreadResponse,\n  isRecommendedFinished,\n} from '@/hooks/useAskPrompt';\nimport useAdjustAnswer from '@/hooks/useAdjustAnswer';\nimport useModalAction from '@/hooks/useModalAction';\nimport PromptThread from '@/components/pages/home/promptThread';\nimport SaveAsViewModal from '@/components/modals/SaveAsViewModal';\nimport QuestionSQLPairModal from '@/components/modals/QuestionSQLPairModal';\nimport AdjustReasoningStepsModal from '@/components/modals/AdjustReasoningStepsModal';\nimport AdjustSQLModal from '@/components/modals/AdjustSQLModal';\nimport { getAnswerIsFinished } from '@/components/pages/home/promptThread/TextBasedAnswer';\nimport { getIsChartFinished } from '@/components/pages/home/promptThread/ChartAnswer';\nimport { PromptThreadProvider } from '@/components/pages/home/promptThread/store';\nimport {\n  useCreateThreadResponseMutation,\n  useThreadQuery,\n  useThreadResponseLazyQuery,\n  useUpdateThreadResponseMutation,\n  useGenerateThreadRecommendationQuestionsMutation,\n  useGetThreadRecommendationQuestionsLazyQuery,\n  useGenerateThreadResponseAnswerMutation,\n  useGenerateThreadResponseChartMutation,\n  useAdjustThreadResponseChartMutation,\n} from '@/apollo/client/graphql/home.generated';\nimport { useCreateViewMutation } from '@/apollo/client/graphql/view.generated';\nimport {\n  AdjustThreadResponseChartInput,\n  CreateThreadResponseInput,\n  ThreadResponse,\n  CreateSqlPairInput,\n} from '@/apollo/client/graphql/__types__';\nimport { useCreateSqlPairMutation } from '@/apollo/client/graphql/sqlPairs.generated';\n\nconst getThreadResponseIsFinished = (threadResponse: ThreadResponse) => {\n  const { answerDetail, breakdownDetail, chartDetail } = threadResponse || {};\n  // it means it's the old data before support text based answer\n  const isBreakdownOnly = answerDetail === null && !isEmpty(breakdownDetail);\n\n  // false make it keep polling when the text based answer is default needed.\n  let isAnswerFinished = isBreakdownOnly ? null : false;\n  let isChartFinished = null;\n\n  // answerDetail status can be FAILED before getting queryId from Wren AI adapter\n  if (answerDetail?.queryId || answerDetail?.status) {\n    isAnswerFinished = getAnswerIsFinished(answerDetail?.status);\n  }\n\n  if (chartDetail?.queryId) {\n    isChartFinished = getIsChartFinished(chartDetail?.status);\n  }\n  // if equal false, it means it has task & the task is not finished\n  return isAnswerFinished !== false && isChartFinished !== false;\n};\n\nexport default function HomeThread() {\n  const $prompt = useRef<ComponentRef<typeof Prompt>>(null);\n  const router = useRouter();\n  const params = useParams();\n  const homeSidebar = useHomeSidebar();\n  const threadId = useMemo(() => Number(params?.id) || null, [params]);\n  const askPrompt = useAskPrompt(threadId);\n  const adjustAnswer = useAdjustAnswer(threadId);\n  const saveAsViewModal = useModalAction();\n  const questionSqlPairModal = useModalAction();\n  const adjustReasoningStepsModal = useModalAction();\n  const adjustSqlModal = useModalAction();\n\n  const [showRecommendedQuestions, setShowRecommendedQuestions] =\n    useState<boolean>(false);\n\n  const [createViewMutation, { loading: creating }] = useCreateViewMutation({\n    onError: (error) => console.error(error),\n    onCompleted: () => message.success('Successfully created view.'),\n  });\n\n  const { data, updateQuery: updateThreadQuery } = useThreadQuery({\n    variables: { threadId },\n    fetchPolicy: 'cache-and-network',\n    skip: threadId === null,\n    onError: () => router.push(Path.Home),\n  });\n  const [createThreadResponse] = useCreateThreadResponseMutation({\n    onError: (error) => console.error(error),\n    onCompleted(next) {\n      const nextResponse = next.createThreadResponse;\n      updateThreadQuery((prev) => {\n        return {\n          ...prev,\n          thread: {\n            ...prev.thread,\n            responses: [...prev.thread.responses, nextResponse],\n          },\n        };\n      });\n    },\n  });\n  const [updateThreadResponse, { loading: threadResponseUpdating }] =\n    useUpdateThreadResponseMutation({\n      onError: (error) => console.error(error),\n      onCompleted: (data) => {\n        message.success('Successfully updated the SQL statement');\n        // trigger generate answer after sql statement updated\n        onGenerateThreadResponseAnswer(data.updateThreadResponse.id);\n      },\n    });\n  const [fetchThreadResponse, threadResponseResult] =\n    useThreadResponseLazyQuery({\n      pollInterval: 1000,\n      onCompleted(next) {\n        const nextResponse = next.threadResponse;\n        updateThreadQuery((prev) => ({\n          ...prev,\n          thread: {\n            ...prev.thread,\n            responses: prev.thread.responses.map((response) =>\n              response.id === nextResponse.id ? nextResponse : response,\n            ),\n          },\n        }));\n      },\n    });\n\n  const [generateThreadRecommendationQuestions] =\n    useGenerateThreadRecommendationQuestionsMutation({\n      onError: (error) => console.error(error),\n    });\n\n  const [\n    fetchThreadRecommendationQuestions,\n    threadRecommendationQuestionsResult,\n  ] = useGetThreadRecommendationQuestionsLazyQuery({\n    pollInterval: 1000,\n  });\n\n  const [generateThreadResponseAnswer] =\n    useGenerateThreadResponseAnswerMutation({\n      onError: (error) => console.error(error),\n    });\n\n  const [generateThreadResponseChart] = useGenerateThreadResponseChartMutation({\n    onError: (error) => console.error(error),\n  });\n  const [adjustThreadResponseChart] = useAdjustThreadResponseChartMutation({\n    onError: (error) => console.error(error),\n  });\n\n  const [createSqlPairMutation, { loading: createSqlPairLoading }] =\n    useCreateSqlPairMutation({\n      refetchQueries: ['SqlPairs'],\n      awaitRefetchQueries: true,\n      onError: (error) => console.error(error),\n      onCompleted: () => {\n        message.success('Successfully created question-sql pair.');\n      },\n    });\n\n  const thread = useMemo(() => data?.thread || null, [data]);\n  const responses = useMemo(() => thread?.responses || [], [thread]);\n  const pollingResponse = useMemo(\n    () => threadResponseResult.data?.threadResponse || null,\n    [threadResponseResult.data],\n  );\n  const isPollingResponseFinished = useMemo(\n    () => getThreadResponseIsFinished(pollingResponse),\n    [pollingResponse],\n  );\n\n  const onFixSQLStatement = async (responseId: number, sql: string) => {\n    await updateThreadResponse({\n      variables: { where: { id: responseId }, data: { sql } },\n    });\n  };\n\n  const onGenerateThreadResponseAnswer = async (responseId: number) => {\n    await generateThreadResponseAnswer({ variables: { responseId } });\n    fetchThreadResponse({ variables: { responseId } });\n  };\n\n  const onGenerateThreadResponseChart = async (responseId: number) => {\n    await generateThreadResponseChart({ variables: { responseId } });\n    fetchThreadResponse({ variables: { responseId } });\n  };\n\n  const onAdjustThreadResponseChart = async (\n    responseId: number,\n    data: AdjustThreadResponseChartInput,\n  ) => {\n    await adjustThreadResponseChart({\n      variables: { responseId, data },\n    });\n    fetchThreadResponse({ variables: { responseId } });\n  };\n\n  const onGenerateThreadRecommendedQuestions = async () => {\n    await generateThreadRecommendationQuestions({ variables: { threadId } });\n    fetchThreadRecommendationQuestions({ variables: { threadId } });\n  };\n\n  const handleUnfinishedTasks = useCallback(\n    (responses: ThreadResponse[]) => {\n      // unfinished asking task\n      const unfinishedAskingResponse = (responses || []).find(\n        (response) =>\n          response?.askingTask && !getIsFinished(response?.askingTask?.status),\n      );\n      if (unfinishedAskingResponse) {\n        askPrompt.onFetching(unfinishedAskingResponse?.askingTask?.queryId);\n        return;\n      }\n\n      // unfinished thread response\n      const unfinishedThreadResponse = (responses || []).find(\n        (response) => !getThreadResponseIsFinished(response),\n      );\n\n      if (\n        canFetchThreadResponse(unfinishedThreadResponse?.askingTask) &&\n        unfinishedThreadResponse\n      ) {\n        fetchThreadResponse({\n          variables: { responseId: unfinishedThreadResponse.id },\n        });\n      }\n    },\n    [askPrompt, fetchThreadResponse],\n  );\n\n  // store thread questions for instant recommended questions\n  const storeQuestionsToAskPrompt = useCallback(\n    (responses: ThreadResponse[]) => {\n      const questions = responses.flatMap((res) => res.question || []);\n      if (questions) askPrompt.onStoreThreadQuestions(questions);\n    },\n    [askPrompt],\n  );\n\n  // stop all requests when change thread\n  useEffect(() => {\n    if (threadId !== null) {\n      fetchThreadRecommendationQuestions({ variables: { threadId } });\n      setShowRecommendedQuestions(true);\n    }\n    return () => {\n      askPrompt.onStopPolling();\n      threadResponseResult.stopPolling();\n      threadRecommendationQuestionsResult.stopPolling();\n      $prompt.current?.close();\n    };\n  }, [threadId]);\n\n  // initialize asking task\n  useEffect(() => {\n    if (!responses) return;\n    handleUnfinishedTasks(responses);\n    storeQuestionsToAskPrompt(responses);\n  }, [responses]);\n\n  useEffect(() => {\n    if (isPollingResponseFinished) {\n      threadResponseResult.stopPolling();\n      setShowRecommendedQuestions(true);\n    }\n  }, [isPollingResponseFinished]);\n\n  const recommendedQuestions = useMemo(\n    () =>\n      threadRecommendationQuestionsResult.data\n        ?.getThreadRecommendationQuestions || null,\n    [threadRecommendationQuestionsResult.data],\n  );\n\n  useEffect(() => {\n    if (isRecommendedFinished(recommendedQuestions?.status)) {\n      threadRecommendationQuestionsResult.stopPolling();\n    }\n  }, [recommendedQuestions]);\n\n  const onCreateResponse = async (payload: CreateThreadResponseInput) => {\n    try {\n      askPrompt.onStopPolling();\n\n      const threadId = thread.id;\n      await createThreadResponse({\n        variables: { threadId, data: payload },\n      });\n      setShowRecommendedQuestions(false);\n    } catch (error) {\n      console.error(error);\n    }\n  };\n\n  const providerValue = {\n    data: thread,\n    recommendedQuestions,\n    showRecommendedQuestions,\n    preparation: {\n      askingStreamTask: askPrompt.data?.askingStreamTask,\n      onStopAskingTask: askPrompt.onStop,\n      onReRunAskingTask: askPrompt.onReRun,\n      onStopAdjustTask: adjustAnswer.onStop,\n      onReRunAdjustTask: adjustAnswer.onReRun,\n      onFixSQLStatement,\n      fixStatementLoading: threadResponseUpdating,\n    },\n    onOpenSaveAsViewModal: saveAsViewModal.openModal,\n    onSelectRecommendedQuestion: onCreateResponse,\n    onGenerateThreadRecommendedQuestions: onGenerateThreadRecommendedQuestions,\n    onGenerateTextBasedAnswer: onGenerateThreadResponseAnswer,\n    onGenerateChartAnswer: onGenerateThreadResponseChart,\n    onAdjustChartAnswer: onAdjustThreadResponseChart,\n    onOpenSaveToKnowledgeModal: questionSqlPairModal.openModal,\n    onOpenAdjustReasoningStepsModal: adjustReasoningStepsModal.openModal,\n    onOpenAdjustSQLModal: adjustSqlModal.openModal,\n  };\n\n  return (\n    <SiderLayout loading={false} sidebar={homeSidebar}>\n      <PromptThreadProvider value={providerValue}>\n        <PromptThread />\n      </PromptThreadProvider>\n\n      <div className=\"py-12\" />\n      <Prompt\n        ref={$prompt}\n        {...askPrompt}\n        onCreateResponse={onCreateResponse}\n      />\n      <SaveAsViewModal\n        {...saveAsViewModal.state}\n        loading={creating}\n        onClose={saveAsViewModal.closeModal}\n        onSubmit={async (values) => {\n          await createViewMutation({\n            variables: { data: values },\n          });\n        }}\n      />\n      <QuestionSQLPairModal\n        {...questionSqlPairModal.state}\n        onClose={questionSqlPairModal.closeModal}\n        loading={createSqlPairLoading}\n        onSubmit={async ({ data }: { data: CreateSqlPairInput }) => {\n          await createSqlPairMutation({ variables: { data } });\n        }}\n      />\n\n      <AdjustReasoningStepsModal\n        {...adjustReasoningStepsModal.state}\n        onClose={adjustReasoningStepsModal.closeModal}\n        loading={adjustAnswer.loading}\n        onSubmit={async (values) => {\n          await adjustAnswer.onAdjustReasoningSteps(\n            values.responseId,\n            values.data,\n          );\n        }}\n      />\n\n      <AdjustSQLModal\n        {...adjustSqlModal.state}\n        onClose={adjustSqlModal.closeModal}\n        loading={adjustAnswer.loading}\n        onSubmit={async (values) =>\n          await adjustAnswer.onAdjustSQL(values.responseId, values.sql)\n        }\n      />\n    </SiderLayout>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/pages/home/dashboard.tsx",
    "content": "import { useMemo, useRef } from 'react';\nimport { message } from 'antd';\nimport { Path } from '@/utils/enum';\nimport { useRouter } from 'next/router';\nimport SiderLayout from '@/components/layouts/SiderLayout';\nimport useHomeSidebar from '@/hooks/useHomeSidebar';\nimport useDrawerAction from '@/hooks/useDrawerAction';\nimport { LoadingWrapper } from '@/components/PageLoading';\nimport DashboardGrid from '@/components/pages/home/dashboardGrid';\nimport EmptyDashboard from '@/components/pages/home/dashboardGrid/EmptyDashboard';\nimport DashboardHeader from '@/components/pages/home/dashboardGrid/DashboardHeader';\nimport CacheSettingsDrawer, {\n  Schedule,\n} from '@/components/pages/home/dashboardGrid/CacheSettingsDrawer';\nimport {\n  useDashboardQuery,\n  useDeleteDashboardItemMutation,\n  useUpdateDashboardItemLayoutsMutation,\n  useSetDashboardScheduleMutation,\n} from '@/apollo/client/graphql/dashboard.generated';\nimport { useGetSettingsQuery } from '@/apollo/client/graphql/settings.generated';\nimport {\n  DataSource,\n  DataSourceName,\n  ItemLayoutInput,\n} from '@/apollo/client/graphql/__types__';\n\nconst isSupportCachedSettings = (dataSource: DataSource) => {\n  // DuckDB not supported, sample dataset as well\n  return (\n    !dataSource?.sampleDataset && dataSource?.type !== DataSourceName.DUCKDB\n  );\n};\n\nexport default function Dashboard() {\n  const router = useRouter();\n  const dashboardGridRef = useRef<{ onRefreshAll: () => void }>(null);\n  const homeSidebar = useHomeSidebar();\n  const cacheSettingsDrawer = useDrawerAction();\n  const { data: settingsResult } = useGetSettingsQuery();\n  const settings = settingsResult?.settings;\n  const isSupportCached = useMemo(\n    () => isSupportCachedSettings(settings?.dataSource),\n    [settings?.dataSource],\n  );\n\n  const {\n    data,\n    loading,\n    updateQuery: updateDashboardQuery,\n  } = useDashboardQuery({\n    fetchPolicy: 'cache-and-network',\n    onError: () => {\n      message.error('Failed to fetch dashboard items.');\n      router.push(Path.Home);\n    },\n  });\n  const dashboardItems = useMemo(\n    () => data?.dashboard?.items || [],\n    [data?.dashboard?.items],\n  );\n\n  const [setDashboardSchedule] = useSetDashboardScheduleMutation({\n    refetchQueries: ['Dashboard'],\n    onCompleted: () => {\n      message.success('Successfully updated dashboard schedule.');\n    },\n    onError: (error) => console.error(error),\n  });\n\n  const [updateDashboardItemLayouts] = useUpdateDashboardItemLayoutsMutation({\n    onError: () => {\n      message.error('Failed to update dashboard item layouts.');\n    },\n  });\n  const [deleteDashboardItem] = useDeleteDashboardItemMutation({\n    onError: (error) => console.error(error),\n    onCompleted: (_, query) => {\n      message.success('Successfully deleted dashboard item.');\n      onRemoveDashboardItemFromQueryCache(query.variables.where.id);\n    },\n  });\n\n  const onRemoveDashboardItemFromQueryCache = (id: number) => {\n    updateDashboardQuery((prev) => {\n      return {\n        ...prev,\n        dashboard: {\n          ...prev.dashboard,\n          items: prev?.dashboard?.items?.filter((item) => item.id !== id) || [],\n        },\n      };\n    });\n  };\n\n  const onUpdateChange = async (layouts: ItemLayoutInput[]) => {\n    if (layouts && layouts.length > 0) {\n      await updateDashboardItemLayouts({ variables: { data: { layouts } } });\n    }\n  };\n\n  const onDelete = async (id: number) => {\n    await deleteDashboardItem({ variables: { where: { id } } });\n  };\n\n  return (\n    <SiderLayout loading={false} color=\"gray-3\" sidebar={homeSidebar}>\n      <LoadingWrapper loading={loading}>\n        <>\n          <EmptyDashboard show={dashboardItems.length === 0}>\n            <DashboardHeader\n              isSupportCached={isSupportCached}\n              schedule={data?.dashboard?.schedule as Schedule}\n              nextScheduleTime={data?.dashboard?.nextScheduledAt}\n              onCacheSettings={() => {\n                cacheSettingsDrawer.openDrawer({\n                  cacheEnabled: data?.dashboard?.cacheEnabled,\n                  schedule: data?.dashboard?.schedule,\n                });\n              }}\n              onRefreshAll={() => {\n                dashboardGridRef?.current?.onRefreshAll();\n              }}\n            />\n            <DashboardGrid\n              ref={dashboardGridRef}\n              items={dashboardItems}\n              isSupportCached={isSupportCached}\n              onUpdateChange={onUpdateChange}\n              onDelete={onDelete}\n            />\n          </EmptyDashboard>\n          {isSupportCached && (\n            <CacheSettingsDrawer\n              {...cacheSettingsDrawer.state}\n              onClose={cacheSettingsDrawer.closeDrawer}\n              onSubmit={async (values) => {\n                await setDashboardSchedule({ variables: { data: values } });\n              }}\n            />\n          )}\n        </>\n      </LoadingWrapper>\n    </SiderLayout>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/pages/home/index.tsx",
    "content": "import { ComponentRef, useMemo, useRef } from 'react';\nimport { useRouter } from 'next/router';\nimport { Button, Typography } from 'antd';\nimport { Logo } from '@/components/Logo';\nimport { Path } from '@/utils/enum';\nimport SiderLayout from '@/components/layouts/SiderLayout';\nimport Prompt from '@/components/pages/home/prompt';\nimport DemoPrompt from '@/components/pages/home/prompt/DemoPrompt';\nimport useHomeSidebar from '@/hooks/useHomeSidebar';\nimport useAskPrompt from '@/hooks/useAskPrompt';\nimport useRecommendedQuestionsInstruction from '@/hooks/useRecommendedQuestionsInstruction';\nimport RecommendedQuestionsPrompt from '@/components/pages/home/prompt/RecommendedQuestionsPrompt';\nimport {\n  useSuggestedQuestionsQuery,\n  useCreateThreadMutation,\n  useThreadLazyQuery,\n} from '@/apollo/client/graphql/home.generated';\nimport { useGetSettingsQuery } from '@/apollo/client/graphql/settings.generated';\nimport { CreateThreadInput } from '@/apollo/client/graphql/__types__';\n\nconst { Text } = Typography;\n\nconst Wrapper = ({ children }) => {\n  return (\n    <div\n      className=\"d-flex align-center justify-center flex-column\"\n      style={{ height: '100%' }}\n    >\n      <Logo size={48} color=\"var(--gray-8)\" />\n      <div className=\"text-md text-medium gray-8 mt-3\">\n        Know more about your data\n      </div>\n      {children}\n    </div>\n  );\n};\n\nconst SampleQuestionsInstruction = (props) => {\n  const { sampleQuestions, onSelect } = props;\n\n  return (\n    <Wrapper>\n      <DemoPrompt demo={sampleQuestions} onSelect={onSelect} />\n    </Wrapper>\n  );\n};\n\nfunction RecommendedQuestionsInstruction(props) {\n  const { onSelect, loading } = props;\n\n  const {\n    buttonProps,\n    generating,\n    recommendedQuestions,\n    showRetry,\n    showRecommendedQuestionsPromptMode,\n  } = useRecommendedQuestionsInstruction();\n\n  return showRecommendedQuestionsPromptMode ? (\n    <div\n      className=\"d-flex align-center flex-column pt-10\"\n      style={{ margin: 'auto' }}\n    >\n      <RecommendedQuestionsPrompt\n        recommendedQuestions={recommendedQuestions}\n        onSelect={onSelect}\n        loading={loading}\n      />\n      <div className=\"py-12\" />\n    </div>\n  ) : (\n    <Wrapper>\n      <Button className=\"mt-6\" {...buttonProps} />\n      {generating && (\n        <Text className=\"mt-3 text-sm gray-6\">\n          Thinking of good questions for you... (about 1 minute)\n        </Text>\n      )}\n      {!generating && showRetry && (\n        <Text className=\"mt-3 text-sm gray-6 text-center\">\n          We couldn't think of questions right now.\n          <br />\n          Let's try again later.\n        </Text>\n      )}\n    </Wrapper>\n  );\n}\n\nexport default function Home() {\n  const $prompt = useRef<ComponentRef<typeof Prompt>>(null);\n  const router = useRouter();\n  const homeSidebar = useHomeSidebar();\n  const askPrompt = useAskPrompt();\n\n  const { data: suggestedQuestionsData } = useSuggestedQuestionsQuery({\n    fetchPolicy: 'cache-and-network',\n  });\n  const [createThread, { loading: threadCreating }] = useCreateThreadMutation({\n    onError: (error) => console.error(error),\n    onCompleted: () => homeSidebar.refetch(),\n  });\n  const [preloadThread] = useThreadLazyQuery({\n    fetchPolicy: 'cache-and-network',\n  });\n\n  const { data: settingsResult } = useGetSettingsQuery();\n  const settings = settingsResult?.settings;\n  const isSampleDataset = useMemo(\n    () => Boolean(settings?.dataSource?.sampleDataset),\n    [settings],\n  );\n\n  const sampleQuestions = useMemo(\n    () => suggestedQuestionsData?.suggestedQuestions.questions || [],\n    [suggestedQuestionsData],\n  );\n\n  const onSelectQuestion = async ({ question }) => {\n    $prompt.current.submit(question);\n  };\n\n  const onCreateResponse = async (payload: CreateThreadInput) => {\n    try {\n      askPrompt.onStopPolling();\n      const response = await createThread({ variables: { data: payload } });\n      const threadId = response.data.createThread.id;\n      await preloadThread({ variables: { threadId } });\n      router.push(Path.Home + `/${threadId}`);\n    } catch (error) {\n      console.error(error);\n    }\n  };\n\n  return (\n    <SiderLayout loading={false} sidebar={homeSidebar}>\n      {isSampleDataset && (\n        <SampleQuestionsInstruction\n          sampleQuestions={sampleQuestions}\n          onSelect={onSelectQuestion}\n        />\n      )}\n\n      {!isSampleDataset && (\n        <RecommendedQuestionsInstruction\n          onSelect={onCreateResponse}\n          loading={threadCreating}\n        />\n      )}\n      <Prompt\n        ref={$prompt}\n        {...askPrompt}\n        onCreateResponse={onCreateResponse}\n      />\n    </SiderLayout>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/pages/index.tsx",
    "content": "import { useWithOnboarding } from '@/hooks/useCheckOnboarding';\nimport PageLoading from '@/components/PageLoading';\n\nexport default function Index() {\n  useWithOnboarding();\n\n  return <PageLoading visible />;\n}\n"
  },
  {
    "path": "wren-ui/src/pages/knowledge/instructions.tsx",
    "content": "import Link from 'next/link';\nimport {\n  Button,\n  Tag,\n  Table,\n  TableColumnsType,\n  Typography,\n  message,\n} from 'antd';\nimport styled from 'styled-components';\nimport SiderLayout from '@/components/layouts/SiderLayout';\nimport PageLayout from '@/components/layouts/PageLayout';\nimport { InstructionsSVG } from '@/utils/svgs';\nimport QuestionOutlined from '@ant-design/icons/QuestionOutlined';\nimport { MORE_ACTION } from '@/utils/enum';\nimport { getCompactTime } from '@/utils/time';\nimport { MoreButton } from '@/components/ActionButton';\nimport { InstructionDropdown } from '@/components/diagram/CustomDropdown';\nimport useDrawerAction from '@/hooks/useDrawerAction';\nimport useModalAction from '@/hooks/useModalAction';\nimport GlobalLabel from '@/components/pages/knowledge/GlobalLabel';\nimport InstructionModal from '@/components/modals/InstructionModal';\nimport InstructionDrawer from '@/components/pages/knowledge/InstructionDrawer';\nimport { Instruction } from '@/apollo/client/graphql/__types__';\nimport {\n  useInstructionsQuery,\n  useCreateInstructionMutation,\n  useUpdateInstructionMutation,\n  useDeleteInstructionMutation,\n} from '@/apollo/client/graphql/instructions.generated';\n\nconst { Paragraph, Text } = Typography;\n\nconst StyledQuestionsBlock = styled.div`\n  margin: -2px -4px;\n`;\n\nconst StyledTag = styled(Tag)`\n  &.ant-tag.ant-tag {\n    display: inline-block;\n    margin: 2px 4px;\n    max-width: 100%;\n  }\n`;\n\nconst StyledInstructionsIcon = styled(InstructionsSVG)`\n  width: 20px;\n  height: 20px;\n`;\n\nexport default function ManageInstructions() {\n  const instructionModal = useModalAction();\n  const instructionDrawer = useDrawerAction();\n\n  const { data, loading } = useInstructionsQuery({\n    fetchPolicy: 'cache-and-network',\n  });\n  const instructions = data?.instructions || [];\n\n  const getBaseOptions = (options) => {\n    return {\n      onError: (error) => console.error(error),\n      refetchQueries: ['Instructions'],\n      awaitRefetchQueries: true,\n      ...options,\n    };\n  };\n\n  const [createInstructionMutation, { loading: createInstructionLoading }] =\n    useCreateInstructionMutation(\n      getBaseOptions({\n        onCompleted: () => {\n          message.success('Successfully created instruction.');\n        },\n      }),\n    );\n\n  const [updateInstructionMutation, { loading: updateInstructionLoading }] =\n    useUpdateInstructionMutation(\n      getBaseOptions({\n        onCompleted: () => {\n          message.success('Successfully updated instruction.');\n        },\n      }),\n    );\n\n  const [deleteInstructionMutation] = useDeleteInstructionMutation(\n    getBaseOptions({\n      onCompleted: () => {\n        message.success('Successfully deleted instruction.');\n      },\n    }),\n  );\n\n  const onMoreClick = async (payload) => {\n    const { type, data } = payload;\n    if (type === MORE_ACTION.DELETE) {\n      await deleteInstructionMutation({\n        variables: { where: { id: data.id } },\n      });\n    } else if (type === MORE_ACTION.EDIT) {\n      instructionModal.openModal(data);\n    } else if (type === MORE_ACTION.VIEW_INSTRUCTION) {\n      instructionDrawer.openDrawer(data);\n    }\n  };\n\n  const columns: TableColumnsType<Instruction> = [\n    {\n      title: 'Instruction details',\n      dataIndex: 'instruction',\n      render: (instruction) => (\n        <Paragraph title={instruction} ellipsis={{ rows: 3 }}>\n          {instruction}\n        </Paragraph>\n      ),\n    },\n    {\n      title: 'Matching questions',\n      dataIndex: 'questions',\n      width: '50%',\n      render: (questions, record) => {\n        if (record.isDefault) return <GlobalLabel />;\n\n        const displayQuestions = questions.slice(0, 2);\n        const moreCount = questions.length - 2;\n\n        return (\n          <StyledQuestionsBlock>\n            {displayQuestions.map((question) => (\n              <div key={question} className=\"mb-1\">\n                <StyledTag className=\"bg-gray-1 border-gray-5 text-truncate\">\n                  <QuestionOutlined className=\"geekblue-6\" />\n                  <Text className=\"gray-9\" title={question}>\n                    {question}\n                  </Text>\n                </StyledTag>\n              </div>\n            ))}\n            {moreCount > 0 && (\n              <div className=\"text-sm gray-7 pl-1\">\n                +{moreCount} more question{moreCount > 1 ? 's' : ''}\n              </div>\n            )}\n          </StyledQuestionsBlock>\n        );\n      },\n    },\n    {\n      title: 'Created time',\n      dataIndex: 'createdAt',\n      width: 130,\n      render: (time) => <Text className=\"gray-7\">{getCompactTime(time)}</Text>,\n    },\n    {\n      key: 'action',\n      width: 64,\n      align: 'center',\n      fixed: 'right',\n      render: (_, record) => (\n        <InstructionDropdown onMoreClick={onMoreClick} data={record}>\n          <MoreButton className=\"gray-8\" />\n        </InstructionDropdown>\n      ),\n    },\n  ];\n\n  return (\n    <SiderLayout loading={false}>\n      <PageLayout\n        title={\n          <>\n            <StyledInstructionsIcon className=\"mr-2 gray-8\" />\n            Manage instruction\n          </>\n        }\n        titleExtra={\n          <Button type=\"primary\" onClick={() => instructionModal.openModal()}>\n            Add an instruction\n          </Button>\n        }\n        description={\n          <>\n            On this page, you can manage saved instructions that guide Wren AI\n            in generating SQL queries. These instructions help Wren AI\n            understand your data model and business rules, improving query\n            accuracy and reducing the need for manual refinements.{' '}\n            <Link\n              className=\"gray-8 underline\"\n              href=\"https://docs.getwren.ai/oss/guide/knowledge/instructions\"\n              rel=\"noopener noreferrer\"\n              target=\"_blank\"\n            >\n              Learn more.\n            </Link>\n          </>\n        }\n      >\n        <Table\n          className=\"ant-table-has-header\"\n          dataSource={instructions}\n          loading={loading}\n          columns={columns}\n          rowKey=\"id\"\n          pagination={{\n            hideOnSinglePage: true,\n            pageSize: 10,\n            size: 'small',\n          }}\n          scroll={{ x: 1080 }}\n        />\n        <InstructionDrawer\n          {...instructionDrawer.state}\n          onClose={instructionDrawer.closeDrawer}\n        />\n        <InstructionModal\n          {...instructionModal.state}\n          onClose={instructionModal.closeModal}\n          loading={createInstructionLoading || updateInstructionLoading}\n          onSubmit={async ({ id, data }) => {\n            if (id) {\n              await updateInstructionMutation({\n                variables: { where: { id }, data },\n              });\n            } else {\n              await createInstructionMutation({ variables: { data } });\n            }\n          }}\n        />\n      </PageLayout>\n    </SiderLayout>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/pages/knowledge/question-sql-pairs.tsx",
    "content": "import dynamic from 'next/dynamic';\nimport Link from 'next/link';\nimport { Button, message, Table, TableColumnsType, Typography } from 'antd';\nimport { format } from 'sql-formatter';\nimport SiderLayout from '@/components/layouts/SiderLayout';\nimport PageLayout from '@/components/layouts/PageLayout';\nimport FunctionOutlined from '@ant-design/icons/FunctionOutlined';\nimport { MORE_ACTION } from '@/utils/enum';\nimport { getCompactTime } from '@/utils/time';\nimport useDrawerAction from '@/hooks/useDrawerAction';\nimport useModalAction from '@/hooks/useModalAction';\nimport { MoreButton } from '@/components/ActionButton';\nimport { SQLPairDropdown } from '@/components/diagram/CustomDropdown';\nimport QuestionSQLPairModal from '@/components/modals/QuestionSQLPairModal';\nimport SQLPairDrawer from '@/components/pages/knowledge/SQLPairDrawer';\nimport { SqlPair } from '@/apollo/client/graphql/__types__';\nimport {\n  useSqlPairsQuery,\n  useCreateSqlPairMutation,\n  useUpdateSqlPairMutation,\n  useDeleteSqlPairMutation,\n} from '@/apollo/client/graphql/sqlPairs.generated';\n\nconst SQLCodeBlock = dynamic(() => import('@/components/code/SQLCodeBlock'), {\n  ssr: false,\n});\n\nconst { Paragraph, Text } = Typography;\n\nexport default function ManageQuestionSQLPairs() {\n  const questionSqlPairModal = useModalAction();\n  const sqlPairDrawer = useDrawerAction();\n\n  const { data, loading } = useSqlPairsQuery({\n    fetchPolicy: 'cache-and-network',\n  });\n  const sqlPairs = data?.sqlPairs || [];\n\n  const getBaseOptions = (options) => {\n    return {\n      onError: (error) => console.error(error),\n      refetchQueries: ['SqlPairs'],\n      awaitRefetchQueries: true,\n      ...options,\n    };\n  };\n\n  const [createSqlPairMutation, { loading: createSqlPairLoading }] =\n    useCreateSqlPairMutation(\n      getBaseOptions({\n        onCompleted: () => {\n          message.success('Successfully created question-sql pair.');\n        },\n      }),\n    );\n\n  const [deleteSqlPairMutation] = useDeleteSqlPairMutation(\n    getBaseOptions({\n      onCompleted: () => {\n        message.success('Successfully deleted question-sql pair.');\n      },\n    }),\n  );\n\n  const [editSqlPairMutation, { loading: editSqlPairLoading }] =\n    useUpdateSqlPairMutation(\n      getBaseOptions({\n        onCompleted: () => {\n          message.success('Successfully updated question-sql pair.');\n        },\n      }),\n    );\n\n  const onMoreClick = async (payload) => {\n    const { type, data } = payload;\n    if (type === MORE_ACTION.DELETE) {\n      await deleteSqlPairMutation({\n        variables: { where: { id: data.id } },\n      });\n    } else if (type === MORE_ACTION.EDIT) {\n      questionSqlPairModal.openModal(data);\n    } else if (type === MORE_ACTION.VIEW_SQL_PAIR) {\n      sqlPairDrawer.openDrawer({ ...data, sql: format(data.sql) });\n    }\n  };\n\n  const columns: TableColumnsType<SqlPair> = [\n    {\n      title: 'Question',\n      dataIndex: 'question',\n      width: 300,\n      render: (question) => (\n        <Paragraph title={question} ellipsis={{ rows: 2 }}>\n          {question}\n        </Paragraph>\n      ),\n    },\n    {\n      title: 'SQL statement',\n      dataIndex: 'sql',\n      width: '60%',\n      render: (sql) => (\n        <div style={{ width: '100%' }}>\n          <SQLCodeBlock code={sql} maxHeight=\"130\" />\n        </div>\n      ),\n    },\n    {\n      title: 'Created time',\n      dataIndex: 'createdAt',\n      width: 130,\n      render: (time) => <Text className=\"gray-7\">{getCompactTime(time)}</Text>,\n    },\n    {\n      key: 'action',\n      width: 64,\n      align: 'center',\n      fixed: 'right',\n      render: (_, record) => (\n        <SQLPairDropdown onMoreClick={onMoreClick} data={record}>\n          <MoreButton className=\"gray-8\" />\n        </SQLPairDropdown>\n      ),\n    },\n  ];\n\n  return (\n    <SiderLayout loading={false}>\n      <PageLayout\n        title={\n          <>\n            <FunctionOutlined className=\"mr-2 gray-8\" />\n            Manage question-SQL pairs\n          </>\n        }\n        titleExtra={\n          <Button\n            type=\"primary\"\n            className=\"\"\n            onClick={() => questionSqlPairModal.openModal()}\n          >\n            Add question-SQL pair\n          </Button>\n        }\n        description={\n          <>\n            On this page, you can manage your saved question-SQL pairs. These\n            pairs help Wren AI learn how your organization writes SQL, allowing\n            it to generate queries that better align with your expectations.{' '}\n            <Link\n              className=\"gray-8 underline\"\n              href=\"https://docs.getwren.ai/oss/guide/knowledge/question-sql-pairs\"\n              rel=\"noopener noreferrer\"\n              target=\"_blank\"\n            >\n              Learn more.\n            </Link>\n          </>\n        }\n      >\n        <Table\n          className=\"ant-table-has-header\"\n          dataSource={sqlPairs}\n          loading={loading}\n          columns={columns}\n          rowKey=\"id\"\n          pagination={{\n            hideOnSinglePage: true,\n            pageSize: 10,\n            size: 'small',\n          }}\n          scroll={{ x: 1080 }}\n        />\n        <SQLPairDrawer\n          {...sqlPairDrawer.state}\n          onClose={sqlPairDrawer.closeDrawer}\n        />\n        <QuestionSQLPairModal\n          {...questionSqlPairModal.state}\n          onClose={questionSqlPairModal.closeModal}\n          loading={createSqlPairLoading || editSqlPairLoading}\n          onSubmit={async ({ id, data }) => {\n            if (id) {\n              await editSqlPairMutation({\n                variables: { where: { id }, data },\n              });\n            } else {\n              await createSqlPairMutation({ variables: { data } });\n            }\n          }}\n        />\n      </PageLayout>\n    </SiderLayout>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/pages/modeling.tsx",
    "content": "import dynamic from 'next/dynamic';\nimport { useRouter } from 'next/router';\nimport { useSearchParams } from 'next/navigation';\nimport { forwardRef, useEffect, useMemo, useRef } from 'react';\nimport { message } from 'antd';\nimport styled from 'styled-components';\nimport { MORE_ACTION, NODE_TYPE } from '@/utils/enum';\nimport { editCalculatedField } from '@/utils/modelingHelper';\nimport SiderLayout from '@/components/layouts/SiderLayout';\nimport MetadataDrawer from '@/components/pages/modeling/MetadataDrawer';\nimport EditMetadataModal from '@/components/pages/modeling/EditMetadataModal';\nimport CalculatedFieldModal from '@/components/modals/CalculatedFieldModal';\nimport ModelDrawer from '@/components/pages/modeling/ModelDrawer';\nimport RelationModal, {\n  RelationFormValues,\n} from '@/components/modals/RelationModal';\nimport useDrawerAction from '@/hooks/useDrawerAction';\nimport useModalAction from '@/hooks/useModalAction';\nimport useRelationshipModal from '@/hooks/useRelationshipModal';\nimport { convertFormValuesToIdentifier } from '@/hooks/useCombineFieldOptions';\nimport { ClickPayload } from '@/components/diagram/Context';\nimport { DeployStatusContext } from '@/components/deploy/Context';\nimport { DIAGRAM } from '@/apollo/client/graphql/diagram';\nimport { LIST_MODELS } from '@/apollo/client/graphql/model';\nimport { useDiagramQuery } from '@/apollo/client/graphql/diagram.generated';\nimport { useDeployStatusQuery } from '@/apollo/client/graphql/deploy.generated';\nimport { useDeleteViewMutation } from '@/apollo/client/graphql/view.generated';\nimport {\n  useCreateModelMutation,\n  useDeleteModelMutation,\n  useUpdateModelMutation,\n} from '@/apollo/client/graphql/model.generated';\nimport {\n  useUpdateModelMetadataMutation,\n  useUpdateViewMetadataMutation,\n} from '@/apollo/client/graphql/metadata.generated';\nimport {\n  useCreateCalculatedFieldMutation,\n  useUpdateCalculatedFieldMutation,\n  useDeleteCalculatedFieldMutation,\n} from '@/apollo/client/graphql/calculatedField.generated';\nimport {\n  useCreateRelationshipMutation,\n  useDeleteRelationshipMutation,\n  useUpdateRelationshipMutation,\n} from '@/apollo/client/graphql/relationship.generated';\nimport * as events from '@/utils/events';\n\nconst Diagram = dynamic(() => import('@/components/diagram'), { ssr: false });\n// https://github.com/vercel/next.js/issues/4957#issuecomment-413841689\nconst ForwardDiagram = forwardRef(function ForwardDiagram(props: any, ref) {\n  return <Diagram {...props} forwardRef={ref} />;\n});\n\nconst DiagramWrapper = styled.div`\n  position: relative;\n  height: 100%;\n`;\n\nexport default function Modeling() {\n  const router = useRouter();\n  const searchParams = useSearchParams();\n  const diagramRef = useRef(null);\n\n  const { data } = useDiagramQuery({\n    fetchPolicy: 'cache-and-network',\n    onCompleted: () => {\n      diagramRef.current?.fitView();\n    },\n  });\n\n  const deployStatusQueryResult = useDeployStatusQuery({\n    pollInterval: 1000,\n    fetchPolicy: 'no-cache',\n  });\n\n  const refetchQueries = [{ query: DIAGRAM }];\n  const refetchQueriesForModel = [...refetchQueries, { query: LIST_MODELS }];\n  const getBaseOptions = (options) => {\n    return {\n      onError: (error) => console.error(error),\n      refetchQueries,\n      awaitRefetchQueries: true,\n      ...options,\n      onCompleted: () => {\n        // refetch to get latest deploy status\n        deployStatusQueryResult.refetch();\n\n        options.onCompleted && options.onCompleted();\n      },\n    };\n  };\n\n  const [createCalculatedField, { loading: calculatedFieldCreating }] =\n    useCreateCalculatedFieldMutation(\n      getBaseOptions({\n        onError: null,\n        onCompleted: () => {\n          message.success('Successfully created calculated field.');\n        },\n      }),\n    );\n\n  const [updateCalculatedField, { loading: calculatedFieldUpdating }] =\n    useUpdateCalculatedFieldMutation(\n      getBaseOptions({\n        onError: null,\n        onCompleted: () => {\n          message.success('Successfully updated calculated field.');\n        },\n      }),\n    );\n\n  const [deleteCalculatedField] = useDeleteCalculatedFieldMutation(\n    getBaseOptions({\n      onCompleted: () => {\n        message.success('Successfully deleted calculated field.');\n      },\n    }),\n  );\n\n  const [createModelMutation, { loading: modelCreating }] =\n    useCreateModelMutation(\n      getBaseOptions({\n        onCompleted: () => {\n          message.success('Successfully created model.');\n        },\n        refetchQueries: refetchQueriesForModel,\n      }),\n    );\n\n  const [deleteModelMutation] = useDeleteModelMutation(\n    getBaseOptions({\n      onCompleted: () => {\n        message.success('Successfully deleted model.');\n      },\n      refetchQueries: refetchQueriesForModel,\n    }),\n  );\n\n  const [updateModelMutation, { loading: modelUpdating }] =\n    useUpdateModelMutation(\n      getBaseOptions({\n        onCompleted: () => {\n          message.success('Successfully updated model.');\n        },\n        refetchQueries: refetchQueriesForModel,\n      }),\n    );\n\n  const [deleteViewMutation] = useDeleteViewMutation(\n    getBaseOptions({\n      onCompleted: () => {\n        message.success('Successfully deleted view.');\n      },\n    }),\n  );\n\n  const [updateModelMetadata, { loading: modelMetadataUpdating }] =\n    useUpdateModelMetadataMutation(\n      getBaseOptions({\n        onCompleted: () => {\n          message.success('Successfully updated model metadata.');\n        },\n      }),\n    );\n\n  const [createRelationshipMutation, { loading: relationshipCreating }] =\n    useCreateRelationshipMutation(\n      getBaseOptions({\n        onCompleted: () => {\n          message.success('Successfully created relationship.');\n        },\n      }),\n    );\n\n  const [deleteRelationshipMutation] = useDeleteRelationshipMutation(\n    getBaseOptions({\n      onCompleted: () => {\n        message.success('Successfully deleted relationship.');\n      },\n    }),\n  );\n\n  const [updateRelationshipMutation, { loading: relationshipUpdating }] =\n    useUpdateRelationshipMutation(\n      getBaseOptions({\n        onCompleted: () => {\n          message.success('Successfully updated relationship.');\n        },\n      }),\n    );\n\n  const [updateViewMetadata, { loading: viewMetadataUpdating }] =\n    useUpdateViewMetadataMutation(\n      getBaseOptions({\n        onCompleted: () => {\n          message.success('Successfully updated view metadata.');\n        },\n      }),\n    );\n\n  const diagramData = useMemo(() => {\n    if (!data) return null;\n    return data?.diagram;\n  }, [data]);\n\n  const metadataDrawer = useDrawerAction();\n  const modelDrawer = useDrawerAction();\n  const editMetadataModal = useModalAction();\n  const calculatedFieldModal = useModalAction();\n  const relationshipModal = useRelationshipModal(diagramData);\n\n  const queryParams = {\n    viewId: searchParams.get('viewId'),\n    openMetadata: searchParams.get('openMetadata'),\n  };\n\n  // doing actions if the route has specific query params\n  useEffect(() => {\n    if (!diagramData) return;\n    // open view metadata drawer\n    if (queryParams.viewId && queryParams.openMetadata) {\n      const searchedView = diagramData.views.find(\n        (view) => view.viewId === Number(queryParams.viewId),\n      );\n      !!searchedView && metadataDrawer.openDrawer(searchedView);\n      // clear query params after opening the drawer\n      router.replace(router.pathname);\n    }\n  }, [queryParams, diagramData]);\n\n  useEffect(() => {\n    if (metadataDrawer.state.visible) {\n      const data = metadataDrawer.state.defaultValue;\n      let currentNodeData = null;\n      switch (data.nodeType) {\n        case NODE_TYPE.MODEL: {\n          currentNodeData = diagramData.models.find(\n            (model) => model.modelId === data.modelId,\n          );\n          break;\n        }\n\n        case NODE_TYPE.VIEW: {\n          currentNodeData = diagramData.views.find(\n            (view) => view.viewId === data.viewId,\n          );\n          break;\n        }\n\n        default:\n          break;\n      }\n\n      metadataDrawer.updateState(currentNodeData);\n    }\n  }, [diagramData]);\n\n  // register event listener for global\n  useEffect(() => {\n    events.subscribe(events.EVENT_NAME.GO_TO_FIRST_MODEL, goToFirstModel);\n    return () => {\n      events.unsubscribe(events.EVENT_NAME.GO_TO_FIRST_MODEL, goToFirstModel);\n    };\n  }, []);\n\n  const goToFirstModel = () => {\n    if (diagramRef.current) {\n      const { getNodes } = diagramRef.current;\n      const node = getNodes()[0];\n      node?.id && onSelect([node.id]);\n    }\n  };\n\n  const onSelect = (selectKeys) => {\n    if (diagramRef.current) {\n      const { getNodes, fitBounds } = diagramRef.current;\n      const node = getNodes().find((node) => node.id === selectKeys[0]);\n      const position = {\n        ...node.position,\n        width: node.width,\n        height: node.height,\n      };\n      fitBounds(position);\n    }\n  };\n\n  const onNodeClick = async (payload: ClickPayload) => {\n    metadataDrawer.openDrawer(payload.data);\n  };\n\n  const onMoreClick = (payload) => {\n    const { type, data } = payload;\n    const { nodeType } = data;\n    const action = {\n      [MORE_ACTION.UPDATE_COLUMNS]: () => {\n        switch (nodeType) {\n          case NODE_TYPE.MODEL:\n            modelDrawer.openDrawer(data);\n            break;\n          default:\n            console.log(data);\n            break;\n        }\n      },\n      [MORE_ACTION.EDIT]: () => {\n        switch (nodeType) {\n          case NODE_TYPE.CALCULATED_FIELD:\n            editCalculatedField(\n              { ...payload, diagramData },\n              calculatedFieldModal.openModal,\n            );\n            break;\n          case NODE_TYPE.RELATION:\n            relationshipModal.openModal(data);\n            break;\n\n          default:\n            console.log(data);\n            break;\n        }\n      },\n      [MORE_ACTION.DELETE]: async () => {\n        switch (nodeType) {\n          case NODE_TYPE.MODEL:\n            await deleteModelMutation({\n              variables: { where: { id: data.modelId } },\n            });\n            break;\n          case NODE_TYPE.CALCULATED_FIELD:\n            await deleteCalculatedField({\n              variables: { where: { id: data.columnId } },\n            });\n            break;\n          case NODE_TYPE.RELATION:\n            await deleteRelationshipMutation({\n              variables: { where: { id: data.relationId } },\n            });\n            break;\n          case NODE_TYPE.VIEW:\n            await deleteViewMutation({\n              variables: { where: { id: data.viewId } },\n            });\n            break;\n\n          default:\n            console.log(data);\n            break;\n        }\n      },\n    };\n    action[type] && action[type]();\n  };\n\n  const onAddClick = (payload) => {\n    const { targetNodeType, data } = payload;\n    switch (targetNodeType) {\n      case NODE_TYPE.CALCULATED_FIELD:\n        calculatedFieldModal.openModal(null, {\n          models: diagramData.models,\n          sourceModel: data,\n        });\n        break;\n      case NODE_TYPE.RELATION:\n        relationshipModal.openModal(data);\n        break;\n      default:\n        console.log('add', targetNodeType);\n        break;\n    }\n  };\n\n  const calculatedFieldLoading =\n    calculatedFieldCreating || calculatedFieldUpdating;\n  const editMetadataLoading = modelMetadataUpdating || viewMetadataUpdating;\n  const modelLoading = modelCreating || modelUpdating;\n  const relationshipLoading = relationshipUpdating || relationshipCreating;\n\n  return (\n    <DeployStatusContext.Provider value={{ ...deployStatusQueryResult }}>\n      <SiderLayout\n        loading={diagramData === null}\n        sidebar={{\n          data: diagramData,\n          onOpenModelDrawer: modelDrawer.openDrawer,\n          onSelect,\n        }}\n      >\n        <DiagramWrapper>\n          <ForwardDiagram\n            ref={diagramRef}\n            data={diagramData}\n            onMoreClick={onMoreClick}\n            onNodeClick={onNodeClick}\n            onAddClick={onAddClick}\n          />\n        </DiagramWrapper>\n        <MetadataDrawer\n          {...metadataDrawer.state}\n          onClose={metadataDrawer.closeDrawer}\n          onEditClick={editMetadataModal.openModal}\n        />\n        <EditMetadataModal\n          {...editMetadataModal.state}\n          onClose={editMetadataModal.closeModal}\n          loading={editMetadataLoading}\n          onSubmit={async ({ nodeType, data }) => {\n            const { modelId, viewId, ...metadata } = data;\n            switch (nodeType) {\n              case NODE_TYPE.MODEL: {\n                await updateModelMetadata({\n                  variables: { where: { id: modelId }, data: metadata },\n                });\n                break;\n              }\n\n              case NODE_TYPE.VIEW: {\n                await updateViewMetadata({\n                  variables: { where: { id: viewId }, data: metadata },\n                });\n                break;\n              }\n\n              default:\n                console.log('onSubmit', nodeType, data);\n                break;\n            }\n          }}\n        />\n        <ModelDrawer\n          {...modelDrawer.state}\n          onClose={modelDrawer.closeDrawer}\n          submitting={modelLoading}\n          onSubmit={async ({ id, data }) => {\n            if (id) {\n              await updateModelMutation({ variables: { where: { id }, data } });\n            } else {\n              await createModelMutation({ variables: { data } });\n            }\n          }}\n        />\n        <CalculatedFieldModal\n          {...calculatedFieldModal.state}\n          onClose={calculatedFieldModal.closeModal}\n          loading={calculatedFieldLoading}\n          onSubmit={async ({ id, data }) => {\n            if (id) {\n              await updateCalculatedField({\n                variables: { where: { id }, data },\n              });\n            } else {\n              await createCalculatedField({ variables: { data } });\n            }\n          }}\n        />\n        <RelationModal\n          {...relationshipModal.state}\n          onClose={relationshipModal.onClose}\n          loading={relationshipLoading}\n          onSubmit={async (\n            values: RelationFormValues & { relationId?: number },\n          ) => {\n            const relation = convertFormValuesToIdentifier(values);\n            if (values.relationId) {\n              await updateRelationshipMutation({\n                variables: {\n                  where: { id: values.relationId },\n                  data: { type: relation.type },\n                },\n              });\n            } else {\n              await createRelationshipMutation({\n                variables: {\n                  data: {\n                    fromModelId: Number(relation.fromField.modelId),\n                    fromColumnId: Number(relation.fromField.fieldId),\n                    toModelId: Number(relation.toField.modelId),\n                    toColumnId: Number(relation.toField.fieldId),\n                    type: relation.type,\n                  },\n                },\n              });\n            }\n          }}\n        />\n      </SiderLayout>\n    </DeployStatusContext.Provider>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/pages/setup/connection.tsx",
    "content": "import { useMemo } from 'react';\nimport SimpleLayout from '@/components/layouts/SimpleLayout';\nimport ContainerCard from '@/components/pages/setup/ContainerCard';\nimport useSetupConnection from '@/hooks/useSetupConnection';\nimport { SETUP_STEPS } from '@/components/pages/setup/utils';\n\nexport default function SetupConnection() {\n  const { connectError, dataSource, onBack, onNext, stepKey, submitting } =\n    useSetupConnection();\n\n  const current = useMemo(() => SETUP_STEPS[stepKey], [stepKey]);\n\n  return (\n    <SimpleLayout>\n      <ContainerCard step={current.step} maxWidth={current.maxWidth}>\n        <current.component\n          connectError={connectError}\n          dataSource={dataSource}\n          onNext={onNext}\n          onBack={onBack}\n          submitting={submitting}\n        />\n      </ContainerCard>\n    </SimpleLayout>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/pages/setup/models.tsx",
    "content": "import { useMemo } from 'react';\nimport SimpleLayout from '@/components/layouts/SimpleLayout';\nimport ContainerCard from '@/components/pages/setup/ContainerCard';\nimport useSetupModels from '@/hooks/useSetupModels';\nimport { SETUP_STEPS } from '@/components/pages/setup/utils';\n\nexport default function SetupModels() {\n  const { fetching, stepKey, tables, onNext, onBack, submitting } =\n    useSetupModels();\n\n  const current = useMemo(() => SETUP_STEPS[stepKey], [stepKey]);\n\n  return (\n    <SimpleLayout>\n      <ContainerCard step={current.step} maxWidth={current.maxWidth}>\n        <current.component\n          fetching={fetching}\n          onBack={onBack}\n          onNext={onNext}\n          submitting={submitting}\n          tables={tables}\n        />\n      </ContainerCard>\n    </SimpleLayout>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/pages/setup/relationships.tsx",
    "content": "import { useMemo } from 'react';\nimport SimpleLayout from '@/components/layouts/SimpleLayout';\nimport ContainerCard from '@/components/pages/setup/ContainerCard';\nimport useSetupRelations from '@/hooks/useSetupRelations';\nimport { SETUP_STEPS } from '@/components/pages/setup/utils';\n\nexport default function SetupRelationships() {\n  const {\n    fetching,\n    stepKey,\n    recommendRelationsResult,\n    onNext,\n    onBack,\n    onSkip,\n    submitting,\n  } = useSetupRelations();\n\n  const current = useMemo(() => SETUP_STEPS[stepKey], [stepKey]);\n\n  return (\n    <SimpleLayout>\n      <ContainerCard step={current.step} maxWidth={current.maxWidth}>\n        <current.component\n          fetching={fetching}\n          {...recommendRelationsResult}\n          onNext={onNext}\n          onBack={onBack}\n          onSkip={onSkip}\n          submitting={submitting}\n        />\n      </ContainerCard>\n    </SimpleLayout>\n  );\n}\n"
  },
  {
    "path": "wren-ui/src/styles/antd-variables.less",
    "content": "// Using in appendData, only for variables defination\n@import '~antd/lib/style/themes/default.less';\n\n@prefix: adm;\n\n// -------- Colors\n// >> Secondary\n@citrus-base: #f58433;\n@citrus-1: #fff9f0;\n@citrus-2: #ffedd9;\n@citrus-3: #ffd9b0;\n@citrus-4: #ffc187;\n@citrus-5: #ffa75e;\n@citrus-6: @citrus-base;\n@citrus-7: #cf6421;\n@citrus-8: #a84713;\n@citrus-9: #822f08;\n@citrus-10: #5c1d05;\n\n// >> Neutral\n@gray-1: #fff;\n@gray-2: #fafafa;\n@gray-3: #f5f5f5;\n@gray-4: #f0f0f0;\n@gray-5: #d9d9d9;\n@gray-6: #bfbfbf;\n@gray-7: #8c8c8c;\n@gray-8: #65676c;\n@gray-9: #434343;\n@gray-10: #262626;\n@gray-11: #1f1f1f;\n@gray-12: #141414;\n@gray-13: #000;\n\n@preset-colors: pink, magenta, red, volcano, orange, yellow, gold, cyan, lime,\n  green, blue, geekblue, purple, citrus, gray;\n\n@black: @gray-13;\n@white: @gray-1;\n\n@primary-color: @geekblue-6;\n\n@text-color: @gray-10;\n@heading-color: @gray-9;\n@success-color: @green-6;\n@warning-color: @gold-6;\n@error-color: @red-5;\n@disabled-color: rgba(0, 0, 0, 0.25);\n\n// Functions\n.make-color-variables(@i: length(@preset-colors)) when (@i > 0) {\n  .make-color-variables(@i - 1);\n  @color: extract(@preset-colors, @i);\n  each(range(1, 10, 1), {\n    @colorVar: '@{color}-@{index}';\n    --@{color}-@{index}: @@colorVar;\n  });\n}\n\n// Header\n@layout-header-height: 20px;\n\n// Components\n@layout-body-background: #fff;\n@layout-header-background: #fff;\n\n@card-background: #fff;\n@breadcrumb-last-item-color: @text-color;\n@table-padding-vertical: 12px;\n@table-header-cell-split-color: transparent;\n@border-radius-base: 4px;\n\n// Typography\n@typography-title-font-weight: 700;\n@heading-1-size: ceil(@font-size-base * 2.85);\n// @heading-2-size: ceil(@font-size-base * 2.14);\n// @heading-3-size: ceil(@font-size-base * 1.71);\n// @heading-4-size: ceil(@font-size-base * 1.42);\n// @heading-5-size: ceil(@font-size-base * 1.14);\n\n// Avatar\n@avatar-size-xs: 16px;\n@avatar-font-size-xs: 12px;\n\n@tooltip-bg: @gray-10;"
  },
  {
    "path": "wren-ui/src/styles/components/alert.less",
    "content": ".ant-alert {\n  align-items: flex-start;\n  .anticon-exclamation-circle, .anticon-warning {\n    margin-top: 4px;\n  }\n  .ant-alert-message {\n    color: currentColor;\n  }\n}"
  },
  {
    "path": "wren-ui/src/styles/components/avatar.less",
    "content": ".adm-avatar {\n  &-xs {\n    .avatar-size(@avatar-size-xs, @avatar-font-size-xs);\n  }\n}"
  },
  {
    "path": "wren-ui/src/styles/components/button.less",
    "content": ".adm-btn-no-style {\n  cursor: pointer;\n  background: transparent;\n  line-height: 1.2;\n  height: auto;\n  border: none;\n}\n\n.adm-onboarding-btn {\n  width: 130px;\n}\n\n.adm-modeling-header-btn {\n  width: 60px;\n}\n\n.adm-fix-it-btn {\n  border-color: @citrus-6;\n  color: @citrus-6;\n  background-color: @citrus-1;\n  &:hover,&:focus {\n    background-color: @citrus-1;\n    border-color: @citrus-4;\n    color: @citrus-5;\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/styles/components/chart.less",
    "content": ".@{prefix}-chart {\n  position: relative;\n  margin: 0 auto;\n  padding: 16px 0;\n\n  &-additional {\n    position: absolute;\n    z-index: 1;\n    top: 16px;\n    right: 36px;\n\n    button {\n      background: white;\n      border: 1px solid @gray-5;\n      border-radius: 4px;\n      padding: 0 2px;\n      cursor: pointer;\n      width: 28px;\n      height: 28px;\n      opacity: 0.4;\n      color: @gray-8;\n      transition: all 0.4s ease-in;\n\n      &:hover {\n        opacity: 1;\n      }\n\n      +button {\n        margin-left: 8px;\n      }\n    }\n  }\n\n  &--no-actions {\n    padding: 0;\n    .vega-embed .chart-wrapper {\n      padding-top: 0 !important;\n    }\n    .vega-embed summary {\n      display: none;\n    }\n  }\n\n  .vega-embed {\n    &:hover {\n      summary {\n        opacity: 0.4 !important;\n      }\n    }\n\n    summary {\n      border-radius: 4px;\n      border: 1px solid @gray-5;\n      box-shadow: none;\n      transition: all 0.4s ease-in;\n      color: @gray-8;\n      opacity: 0.4 !important;\n\n      &:hover {\n        opacity: 1 !important;\n      }\n    }\n\n    .chart-wrapper {\n      padding-top: 40px;\n    }\n\n    &.has-actions {\n      padding-right: 0;\n    }\n\n    .vega-actions {\n      border: 1px solid @gray-5;\n      box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1);\n\n      a {\n        font-size: 12px;\n        padding: 6px 16px;\n      }\n    }\n  }\n\n  &__fullscreen {\n    position: absolute;\n    top: 32px;\n    right: 0px;\n  }\n\n  .ant-btn-icon-only {\n    width: auto;\n    height: auto;\n    padding: 6px;\n  }\n}\n\n#vg-tooltip-element.vg-tooltip.custom-theme {\n  display: none;\n  background-color: @gray-10;\n  color: @gray-1;\n  border-color: @gray-9;\n  animation: fade-in 0.2s ease-out;\n\n  table tr td.key {\n    color: @gray-6;\n  }\n}\n\n#vg-tooltip-element.visible {\n  display: block !important;\n}"
  },
  {
    "path": "wren-ui/src/styles/components/driver.less",
    "content": "body {\n  .driver-popover {\n    background-color: @gray-10;\n    color: white;\n    box-shadow: none;\n    border-radius: 10px;\n    padding: 16px 0;\n\n    .driver-popover-close-btn {\n      color: @gray-7;\n      &:hover {\n        color: @gray-1;\n      }\n    }\n  }\n\n  .driver-popover-title,\n  .driver-popover-description,\n  .driver-popover-footer {\n    padding: 0 16px;\n  }\n\n  .driver-popover-title {\n    img {\n      display: block;\n      width: 100%;\n    }\n\n    &[style*=block] +.driver-popover-description {\n      margin-top: 8px;\n    }\n  }\n\n  .driver-popover-description {\n    color: @gray-5;\n  }\n\n  .driver-popover-arrow-side-left {\n    border-left-color: @gray-10;\n  }\n  .driver-popover-arrow-side-right {\n    border-right-color: @gray-10;\n  }\n  .driver-popover-arrow-side-top {\n    border-top-color: @gray-10;\n  }\n  .driver-popover-arrow-side-bottom {\n    border-bottom-color: @gray-10;\n  }\n\n  .driver-popover-progress-text {\n    color: @gray-7;\n  }\n\n  .driver-popover-footer button {\n    font-size: @font-size-base;\n    border-radius: 4px;\n    border: none;\n    min-width: 76px;\n    text-align: center;\n    + button {\n      margin-left: 8px;\n    }\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/styles/components/scrollbar.less",
    "content": ".adm-scrollbar-track {\n  scrollbar-width: thin;\n  scrollbar-color: @gray-5 transparent;\n}"
  },
  {
    "path": "wren-ui/src/styles/components/select.less",
    "content": ".adm-model-field-select-dropdown {\n  .ant-select-item-option-grouped {\n    padding: 5px 12px;\n  }\n}"
  },
  {
    "path": "wren-ui/src/styles/components/table.less",
    "content": "// override antd styles\n.ant-table {\n  border: 1px @gray-4 solid;\n\n  .ant-table-row:last-child .ant-table-cell {\n    border-bottom: none;\n  }\n\n  &.ant-table-empty {\n    .ant-table-body {\n      overflow: auto !important;\n    }\n\n    .ant-table-tbody .ant-table-cell {\n      border-bottom: none;\n    }\n  }\n\n  .ant-table-expanded-row {\n    > .ant-table-cell {\n      background-color: @gray-3;\n    }\n  }\n\n  .adm-nested-table {\n    .ant-table {\n      border: none;\n      border-radius: 0;\n\n      .ant-table-thead > tr > th {\n        background: @gray-2;\n      }\n\n      .ant-table-tbody > tr.ant-table-row:hover > td,\n      .ant-table-tbody > tr > td.ant-table-cell-row-hover {\n        background: @gray-2;\n      }\n    }\n  }\n\n  &--text-sm {\n    .ant-table {\n      font-size: @font-size-sm !important;\n    }\n  }\n}\n\n.ant-table-wrapper:not(.ant-table-has-header) {\n  .ant-table-empty {\n    border: none;\n\n    .ant-empty-normal {\n      margin: 80px 0;\n    }\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/styles/components/tag.less",
    "content": ".ant-tag {\n  &--geekblue {\n    color: @geekblue-6;\n    background: @geekblue-1;\n    border-color: @geekblue-6;\n  }\n  &--citrus {\n    color: @citrus-6;\n    background: @citrus-1;\n    border-color: @citrus-6;\n  }\n}"
  },
  {
    "path": "wren-ui/src/styles/components/transfer.less",
    "content": ".ant-transfer {\n  .ant-transfer-list {\n    min-width: 0;\n  }\n\n  .ant-table-wrapper:not(.ant-table-has-header) {\n    .ant-table-empty {\n      .ant-empty-normal {\n        margin: 58px 0px;\n      }\n    }\n  }\n}"
  },
  {
    "path": "wren-ui/src/styles/index.less",
    "content": "@import '~antd/dist/antd.less';\n\n// Components\n@import './components/table.less';\n@import './components/avatar.less';\n@import './components/button.less';\n@import './components/transfer.less';\n@import './components/select.less';\n@import './components/alert.less';\n@import './components/tag.less';\n@import './components/driver.less';\n@import './components/chart.less';\n@import './components/scrollbar.less';\n\n// Layouts\n@import './layouts/global.less';\n@import './layouts/main.less';\n\n// Utilities\n@import './utilities/animation.less';\n@import './utilities/display.less';\n@import './utilities/flex.less';\n@import './utilities/grid.less';\n@import './utilities/text.less';\n@import './utilities/color.less';\n@import './utilities/spacing.less';\n@import './utilities/border.less';\n"
  },
  {
    "path": "wren-ui/src/styles/layouts/global.less",
    "content": ":root {\n  .make-color-variables();\n  --disabled: @disabled-color;\n}\n\nbody {\n  min-width: 360px;\n}\n\n@media (prefers-color-scheme: dark) {\n  html body {\n    background: #fff;\n  }\n  h1.next-error-h1 {\n    border-right: 1px solid rgba(0, 0, 0, 0.3);\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/styles/layouts/main.less",
    "content": ".@{prefix}-main {\n  min-height: 100vh;\n  height: 100%;\n}\n\n.adm-layout {\n  height: 100%;\n}\n\n.adm-content {\n  height: calc(100vh - 48px);\n  overflow: auto;\n}\n"
  },
  {
    "path": "wren-ui/src/styles/utilities/animation.less",
    "content": "@keyframes fade-in {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/styles/utilities/border.less",
    "content": ".border {\n  border-width: 1px !important;\n  border-style: solid !important;\n\n  &-t {\n    border-top-width: 1px !important;\n    border-top-style: solid !important;\n  }\n  &-r {\n    border-right-width: 1px !important;\n    border-right-style: solid !important;\n  }\n  &-l {\n    border-left-width: 1px !important;\n    border-left-style: solid !important;\n  }\n  &-b {\n    border-bottom-width: 1px !important;\n    border-bottom-style: solid !important;\n  }\n}\n\n.rounded {\n  border-radius: 4px !important;\n}\n\n.rounded-pill {\n  border-radius: 999px !important;\n}"
  },
  {
    "path": "wren-ui/src/styles/utilities/color.less",
    "content": ".make-color-classes(@i: length(@preset-colors)) when (@i > 0) {\n  .make-color-classes(@i - 1);\n  @color: extract(@preset-colors, @i);\n  each(range(1, 10), {\n    @colorVar: ~'var(--@{color}-@{index})';\n    .bg-@{color}-@{index} {\n      background-color: @colorVar !important;\n    }\n    .@{color}-@{index} {\n      color: @colorVar !important;\n    }\n    .border-@{color}-@{index} {\n      border-color: @colorVar !important;\n    }\n  });\n}\n\n.make-color-classes();\n\n*[class*='hover\\:'] {\n  transition: color 0.3s ease;\n}\n\n.hover\\:text:hover {\n  color: var(--geekblue-6) !important;\n}"
  },
  {
    "path": "wren-ui/src/styles/utilities/display.less",
    "content": ".make-display-classes() {\n  @preset-display: {\n    block: block;\n    inline: inline;\n    inline-block: inline-block;\n    flex: flex;\n    inline-flex: inline-flex;\n    grid: grid;\n    none: none;\n  };\n  each(@preset-display, {\n    .d-@{key} {\n      display: @value !important;\n    }\n  });\n}\n\n.make-display-classes();\n\n.cursor-pointer {\n  cursor: pointer !important;\n}\n\n.cursor-wait {\n  cursor: wait !important;\n}\n\n.cursor-not-allowed {\n  cursor: not-allowed !important;\n}\n\n.select-none {\n  user-select: none !important;\n}\n\n.overflow-hidden {\n  overflow: hidden !important;\n}\n\n.scrollable-y {\n  overflow: hidden auto !important;\n}\n\n.scrollable-x {\n  overflow: auto hidden !important;\n}\n"
  },
  {
    "path": "wren-ui/src/styles/utilities/flex.less",
    "content": ".justify {\n  &-start {\n    justify-content: flex-start !important;\n  }\n  &-end {\n    justify-content: flex-end !important;\n  }\n  &-center {\n    justify-content: center !important;\n  }\n  &-space-between {\n    justify-content: space-between !important;\n  }\n}\n\n.align {\n  &-start {\n    align-items: flex-start !important;\n  }\n  &-end {\n    align-items: flex-end !important;\n  }\n  &-center {\n    align-items: center !important;\n  }\n  &-baseline {\n    align-items: baseline !important;\n  }\n}\n\n.flex {\n  &-shrink-0 {\n    flex-shrink: 0 !important;\n  }\n\n  &-shrink-1 {\n    flex-shrink: 1 !important;\n  }\n\n  &-grow-0 {\n    flex-grow: 0 !important;\n  }\n\n  &-grow-1 {\n    flex-grow: 1 !important;\n  }\n\n  &-row {\n    flex-direction: row !important;\n  }\n\n  &-column {\n    flex-direction: column !important;\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/styles/utilities/grid.less",
    "content": "\n.make-grid-classes(@i: 6) when (@i >= 1) {\n  .make-grid-classes(@i - 1);\n  .grid-columns-@{i} {\n    grid-template-columns: repeat(@i, 1fr) !important;\n  }\n\n  // grid gap\n  @base-gap: 4px;\n  @gap: @i * @base-gap;\n\n  .g-@{i} {\n    column-gap: @gap !important;\n    row-gap: @gap !important;\n  }\n  .gx-@{i} {\n    column-gap: @gap !important;\n  }\n  .gy-@{i} {\n    row-gap: @gap !important;\n  }\n}\n\n.make-grid-classes();"
  },
  {
    "path": "wren-ui/src/styles/utilities/spacing.less",
    "content": ".make-spacing-classes(@i: 15) when (@i >= 0) {\n  .make-spacing-classes(@i - 1);\n  @preset: {\n    m: margin;\n    p: padding;\n  };\n  @base-spacing: 4px;\n  @spacing: @i * @base-spacing;\n\n  each(@preset, {\n    .@{key}-@{i} {\n      @{value}: @spacing !important;\n    }\n    .@{key}x-@{i} {\n      @{value}-left: @spacing !important;\n      @{value}-right: @spacing !important;\n    }\n    .@{key}y-@{i} {\n      @{value}-top: @spacing !important;\n      @{value}-bottom: @spacing !important;\n    }\n    .@{key}t-@{i} {\n      @{value}-top: @spacing !important;\n    }\n    .@{key}l-@{i} {\n      @{value}-left: @spacing !important;\n    }\n    .@{key}r-@{i} {\n      @{value}-right: @spacing !important;\n    }\n    .@{key}b-@{i} {\n      @{value}-bottom: @spacing !important;\n    }\n\n    // Negative spacing\n    .-@{key}-@{i} {\n      @{value}: -@spacing !important;\n    }\n    .-@{key}x-@{i} {\n      @{value}-left: -@spacing !important;\n      @{value}-right: -@spacing !important;\n    }\n    .-@{key}y-@{i} {\n      @{value}-top: -@spacing !important;\n      @{value}-bottom: -@spacing !important;\n    }\n    .-@{key}t-@{i} {\n      @{value}-top: -@spacing !important;\n    }\n    .-@{key}l-@{i} {\n      @{value}-left: -@spacing !important;\n    }\n    .-@{key}r-@{i} {\n      @{value}-right: -@spacing !important;\n    }\n    .-@{key}b-@{i} {\n      @{value}-bottom: -@spacing !important;\n    }\n  });\n}\n\n.make-spacing-classes();\n"
  },
  {
    "path": "wren-ui/src/styles/utilities/text.less",
    "content": ".make-text-classes() {\n  @preset-text: {\n    base: @font-size-base;\n    xs: @font-size-sm - 2px;\n    sm: @font-size-sm;\n    md: @font-size-lg;\n    lg: @font-size-lg + 2px;\n  };\n  each(@preset-text, {\n    .text-@{key} {\n      font-size: @value !important;\n    }\n  });\n}\n\n.text-left {\n  text-align: left !important;\n}\n\n.text-right {\n  text-align: right !important;\n}\n\n.text-center {\n  text-align: center !important;\n}\n\n.text-extra-bold {\n  font-weight: 800 !important;\n}\n\n.text-bold {\n  font-weight: 700 !important;\n}\n\n.text-semi-bold {\n  font-weight: 600 !important;\n}\n\n.text-medium {\n  font-weight: 500 !important;\n}\n\n.make-text-classes();\n\n.text-truncate {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.text-family-base {\n  font-family: @font-family !important;\n}\n\n.text-nowrap {\n  white-space: nowrap !important;\n}\n\n.underline {\n  text-decoration: underline !important;\n}\n\n.hover\\:underline:hover {\n  text-decoration: underline !important;\n}\n\n.text-break-word {\n  overflow-wrap: break-word !important;\n  word-break: break-word !important;\n}\n"
  },
  {
    "path": "wren-ui/src/utils/columnType.tsx",
    "content": "import {\n  NumericIcon,\n  ColumnsIcon,\n  JsonBracesIcon,\n  StringIcon,\n  TextIcon,\n  CalendarIcon,\n  TickIcon,\n  IdIcon,\n  BinaryIcon,\n} from './icons';\nimport { COLUMN_TYPE } from './enum';\n\nexport const getColumnTypeIcon = (payload: { type: string }, attrs?: any) => {\n  const { type } = payload;\n  const compareString = type.toUpperCase();\n  switch (compareString) {\n    case COLUMN_TYPE.BOOLEAN:\n      return <TickIcon {...attrs} />;\n\n    case COLUMN_TYPE.JSON:\n    case COLUMN_TYPE.RECORD:\n      return <JsonBracesIcon {...attrs} />;\n\n    case COLUMN_TYPE.TEXT:\n      return <TextIcon {...attrs} />;\n\n    case COLUMN_TYPE.BYTEA:\n    case COLUMN_TYPE.VARBINARY:\n      return <BinaryIcon {...attrs} />;\n\n    case COLUMN_TYPE.UUID:\n    case COLUMN_TYPE.OID:\n      return <IdIcon {...attrs} />;\n\n    case COLUMN_TYPE.TINYINT:\n    case COLUMN_TYPE.INT2:\n    case COLUMN_TYPE.SMALLINT:\n    case COLUMN_TYPE.INT4:\n    case COLUMN_TYPE.INTEGER:\n    case COLUMN_TYPE.INT8:\n    case COLUMN_TYPE.BIGINT:\n    case COLUMN_TYPE.INT64:\n    case COLUMN_TYPE.NUMERIC:\n    case COLUMN_TYPE.DECIMAL:\n    case COLUMN_TYPE.FLOAT4:\n    case COLUMN_TYPE.REAL:\n    case COLUMN_TYPE.FLOAT8:\n    case COLUMN_TYPE.DOUBLE:\n    case COLUMN_TYPE.INET:\n      return <NumericIcon {...attrs} />;\n\n    case COLUMN_TYPE.VARCHAR:\n    case COLUMN_TYPE.CHAR:\n    case COLUMN_TYPE.BPCHAR:\n    case COLUMN_TYPE.STRING:\n    case COLUMN_TYPE.NAME:\n      return <StringIcon {...attrs} />;\n\n    case COLUMN_TYPE.TIMESTAMP:\n    case COLUMN_TYPE.TIMESTAMPTZ:\n    case COLUMN_TYPE.DATE:\n    case COLUMN_TYPE.INTERVAL:\n      return <CalendarIcon {...attrs} />;\n\n    default: {\n      return <ColumnsIcon {...attrs} />;\n    }\n  }\n};\n"
  },
  {
    "path": "wren-ui/src/utils/data/dictionary.ts",
    "content": "import { ExpressionName } from '@/apollo/client/graphql/__types__';\nimport { JOIN_TYPE } from '@/utils/enum';\n\nconst DefaultText = 'Unknown';\n\nexport const getJoinTypeText = (type) =>\n  ({\n    [JOIN_TYPE.MANY_TO_ONE]: 'Many-to-one',\n    [JOIN_TYPE.ONE_TO_MANY]: 'One-to-many',\n    [JOIN_TYPE.ONE_TO_ONE]: 'One-to-one',\n  })[type] || DefaultText;\n\nexport const getExpressionTexts = (type) =>\n  ({\n    // Aggregations\n    [ExpressionName.AVG]: {\n      name: 'Average',\n      syntax: 'avg(column)',\n      description: 'Returns the average of the values in the column.',\n    },\n    [ExpressionName.COUNT]: {\n      name: 'Count',\n      syntax: 'count(column)',\n      description:\n        'Returns the count of non-null rows (also known as records) in the selected data.',\n    },\n    [ExpressionName.MAX]: {\n      name: 'Max',\n      syntax: 'max(column)',\n      description: 'Returns the largest value found in the column.',\n    },\n    [ExpressionName.MIN]: {\n      name: 'Min',\n      syntax: 'min(column)',\n      description: 'Returns the smallest value found in the column.',\n    },\n    [ExpressionName.SUM]: {\n      name: 'Sum',\n      syntax: 'sum(column)',\n      description: 'Adds up all the values of the column.',\n    },\n\n    // Math functions\n    [ExpressionName.ABS]: {\n      name: 'Absolute',\n      syntax: 'abs(column)',\n      description:\n        'Returns the absolute (positive) value of the specified column.',\n    },\n    [ExpressionName.CBRT]: {\n      name: 'Cube root',\n      syntax: 'cbrt(column)',\n      description: 'Returns the cube root of the number.',\n    },\n    [ExpressionName.CEIL]: {\n      name: 'Ceil',\n      syntax: 'ceil(column)',\n      description: 'Rounds a decimal up (ceil as in ceiling).',\n    },\n    [ExpressionName.EXP]: {\n      name: 'Exponential',\n      syntax: 'exp(column)',\n      description:\n        'Returns Euler’s number, e, raised to the power of the supplied number.',\n    },\n    [ExpressionName.FLOOR]: {\n      name: 'Floor',\n      syntax: 'floor(column)',\n      description: 'Rounds a decimal number down.',\n    },\n    [ExpressionName.LN]: {\n      name: 'Natural logarithm',\n      syntax: 'ln(column)',\n      description: 'Returns the natural logarithm of the number.',\n    },\n    [ExpressionName.LOG10]: {\n      name: 'Log10',\n      syntax: 'log10(column)',\n      description: 'Returns the base 10 log of the number.',\n    },\n    [ExpressionName.ROUND]: {\n      name: 'Round',\n      syntax: 'round(column)',\n      description:\n        'Rounds a decimal number either up or down to the nearest integer value.',\n    },\n    [ExpressionName.SIGN]: {\n      name: 'Signum',\n      syntax: 'sign(column)',\n      description: 'Returns the signum function of the number.',\n    },\n\n    // String functions\n    [ExpressionName.LENGTH]: {\n      name: 'Length',\n      syntax: 'length(column)',\n      description: 'Returns the number of characters in string.',\n    },\n    [ExpressionName.REVERSE]: {\n      name: 'Reverse',\n      syntax: 'reverse(column)',\n      description: 'Returns string with the characters in reverse order.',\n    },\n  })[type] || {\n    name: DefaultText,\n    syntax: DefaultText,\n    description: DefaultText,\n  };\n"
  },
  {
    "path": "wren-ui/src/utils/data/index.ts",
    "content": "export * from './type';\nexport * from './dictionary';\n"
  },
  {
    "path": "wren-ui/src/utils/data/type/index.ts",
    "content": "export * from './modeling';\n"
  },
  {
    "path": "wren-ui/src/utils/data/type/modeling.ts",
    "content": "import {\n  DiagramModel,\n  DiagramModelField,\n  DiagramModelRelationField,\n  DiagramView,\n  DiagramViewField,\n} from '@/apollo/client/graphql/__types__';\nexport type {\n  Diagram,\n  DiagramModel,\n  DiagramModelField,\n  DiagramModelRelationField,\n  DiagramView,\n} from '@/apollo/client/graphql/__types__';\n\nexport type ComposeDiagram = (DiagramModel | DiagramView) &\n  Partial<\n    Pick<\n      DiagramModel,\n      | 'modelId'\n      | 'calculatedFields'\n      | 'relationFields'\n      | 'refSql'\n      | 'refreshTime'\n      | 'cached'\n      | 'sourceTableName'\n    >\n  > &\n  Partial<Pick<DiagramView, 'viewId' | 'statement'>>;\n\nexport type ComposeDiagramField = (\n  | DiagramModelField\n  | DiagramModelRelationField\n  | DiagramViewField\n) &\n  Partial<Pick<DiagramModel, 'description'>> &\n  Partial<\n    Pick<DiagramModelField, 'isPrimaryKey' | 'columnId' | 'nestedFields'>\n  > &\n  Partial<\n    Pick<\n      DiagramModelRelationField,\n      | 'fromModelName'\n      | 'fromModelDisplayName'\n      | 'fromColumnName'\n      | 'fromColumnDisplayName'\n      | 'toModelName'\n      | 'toModelDisplayName'\n      | 'toColumnName'\n      | 'toColumnDisplayName'\n      | 'relationId'\n    >\n  >;\n\nexport type CachedProps = {\n  cached: boolean;\n  refreshTime?: string;\n};\n"
  },
  {
    "path": "wren-ui/src/utils/dataSourceType.ts",
    "content": "import { DATA_SOURCES } from '@/utils/enum';\nimport BigQueryProperties from '@/components/pages/setup/dataSources/BigQueryProperties';\nimport DuckDBProperties from '@/components/pages/setup/dataSources/DuckDBProperties';\nimport MySQLProperties from '@/components/pages/setup/dataSources/MySQLProperties';\nimport OracleProperties from '@/components/pages/setup/dataSources/OracleProperties';\nimport PostgreSQLProperties from '@/components/pages/setup/dataSources/PostgreSQLProperties';\nimport SQLServerProperties from '@/components/pages/setup/dataSources/SQLServerProperties';\nimport ClickHouseProperties from '@/components/pages/setup/dataSources/ClickHouseProperties';\nimport TrinoProperties from '@/components/pages/setup/dataSources/TrinoProperties';\nimport SnowflakeProperties from '@/components/pages/setup/dataSources/SnowflakeProperties';\nimport AthenaProperties from '@/components/pages/setup/dataSources/AthenaProperties';\nimport RedshiftProperties from '@/components/pages/setup/dataSources/RedshiftProperties';\nimport DatabricksProperties from '@/components/pages/setup/dataSources/DatabricksProperties';\n\nexport const getDataSourceImage = (dataSource: DATA_SOURCES | string) => {\n  switch (dataSource) {\n    case DATA_SOURCES.BIG_QUERY:\n      return '/images/dataSource/bigQuery.svg';\n    case DATA_SOURCES.POSTGRES:\n      return '/images/dataSource/postgreSql.svg';\n    case DATA_SOURCES.MYSQL:\n      return '/images/dataSource/mysql.svg';\n    case DATA_SOURCES.ORACLE:\n      return '/images/dataSource/oracle.svg';\n    case DATA_SOURCES.MSSQL:\n      return '/images/dataSource/sqlserver.svg';\n    case DATA_SOURCES.CLICK_HOUSE:\n      return '/images/dataSource/clickhouse.svg';\n    case DATA_SOURCES.DUCKDB:\n      return '/images/dataSource/duckDb.svg';\n    case DATA_SOURCES.TRINO:\n      return '/images/dataSource/trino.svg';\n    case DATA_SOURCES.SNOWFLAKE:\n      return '/images/dataSource/snowflake.svg';\n    case DATA_SOURCES.ATHENA:\n      return '/images/dataSource/athena.svg';\n    case DATA_SOURCES.REDSHIFT:\n      return '/images/dataSource/redshift.svg';\n    case DATA_SOURCES.DATABRICKS:\n      return '/images/dataSource/databricks.svg';\n    default:\n      return null;\n  }\n};\n\nexport const getDataSourceName = (dataSource: DATA_SOURCES | string) => {\n  switch (dataSource) {\n    case DATA_SOURCES.BIG_QUERY:\n      return 'BigQuery';\n    case DATA_SOURCES.POSTGRES:\n      return 'PostgreSQL';\n    case DATA_SOURCES.MYSQL:\n      return 'MySQL';\n    case DATA_SOURCES.ORACLE:\n      return 'Oracle';\n    case DATA_SOURCES.MSSQL:\n      return 'SQL Server';\n    case DATA_SOURCES.CLICK_HOUSE:\n      return 'ClickHouse';\n    case DATA_SOURCES.DUCKDB:\n      return 'DuckDB';\n    case DATA_SOURCES.TRINO:\n      return 'Trino';\n    case DATA_SOURCES.SNOWFLAKE:\n      return 'Snowflake';\n    case DATA_SOURCES.ATHENA:\n      return 'Athena (Trino)';\n    case DATA_SOURCES.REDSHIFT:\n      return 'Redshift';\n    case DATA_SOURCES.DATABRICKS:\n      return 'Databricks';\n    default:\n      return '';\n  }\n};\n\nexport const getDataSourceProperties = (dataSource: DATA_SOURCES | string) => {\n  switch (dataSource) {\n    case DATA_SOURCES.BIG_QUERY:\n      return BigQueryProperties;\n    case DATA_SOURCES.POSTGRES:\n      return PostgreSQLProperties;\n    case DATA_SOURCES.MYSQL:\n      return MySQLProperties;\n    case DATA_SOURCES.ORACLE:\n      return OracleProperties;\n    case DATA_SOURCES.MSSQL:\n      return SQLServerProperties;\n    case DATA_SOURCES.CLICK_HOUSE:\n      return ClickHouseProperties;\n    case DATA_SOURCES.DUCKDB:\n      return DuckDBProperties;\n    case DATA_SOURCES.TRINO:\n      return TrinoProperties;\n    case DATA_SOURCES.SNOWFLAKE:\n      return SnowflakeProperties;\n    case DATA_SOURCES.ATHENA:\n      return AthenaProperties;\n    case DATA_SOURCES.REDSHIFT:\n      return RedshiftProperties;\n    case DATA_SOURCES.DATABRICKS:\n      return DatabricksProperties;\n    default:\n      return null;\n  }\n};\n\nexport const getDataSourceConfig = (dataSource: DATA_SOURCES | string) => {\n  return {\n    label: getDataSourceName(dataSource),\n    logo: getDataSourceImage(dataSource),\n    value: DATA_SOURCES[dataSource],\n  };\n};\n\nexport const getDataSourceFormComponent = (\n  dataSource: DATA_SOURCES | string,\n) => {\n  return { component: getDataSourceProperties(dataSource) || (() => null) };\n};\n"
  },
  {
    "path": "wren-ui/src/utils/diagram/creator.ts",
    "content": "import { Edge, Node, Viewport, ReactFlowJsonObject } from 'reactflow';\nimport { Diagram } from '@/utils/data/type';\nimport { Transformer } from './transformer';\n\nexport class DiagramCreator {\n  private nodes: Node[];\n  private edges: Edge[];\n  private viewport: Viewport = { x: 0, y: 0, zoom: 1 };\n\n  constructor(data: Diagram) {\n    const transformedData = new Transformer(data);\n    this.nodes = transformedData.nodes;\n    this.edges = transformedData.edges;\n  }\n\n  public toJsonObject(): ReactFlowJsonObject {\n    return {\n      nodes: this.nodes,\n      edges: this.edges,\n      viewport: this.viewport,\n    };\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/utils/diagram/index.ts",
    "content": "export * from './creator';\nexport * from './transformer';\n"
  },
  {
    "path": "wren-ui/src/utils/diagram/transformer.ts",
    "content": "import { Edge, Node, Position } from 'reactflow';\nimport { EDGE_TYPE, MARKER_TYPE, NODE_TYPE, JOIN_TYPE } from '@/utils/enum';\nimport {\n  ComposeDiagram,\n  Diagram,\n  DiagramModel,\n  DiagramModelRelationField,\n  DiagramView,\n} from '@/utils/data';\n\nexport const Config = {\n  // the number of nodes in one row\n  nodesInRow: 4,\n  // the width of the model\n  width: 200,\n  // height should be calculated depending on the number of columns\n  height: undefined,\n  // the height of the model header\n  headerHeight: 32,\n  // the height of the model column\n  columnHeight: 32,\n  // the height of more tip\n  moreTipHeight: 25,\n  // the columns limit\n  columnsLimit: 10,\n  // the overflow of the model body\n  bodyOverflow: 'auto',\n  // the margin x between the model and the other models\n  marginX: 100,\n  // the margin y between the model and the other models\n  marginY: 50,\n  // the model preserved height, for example: the model has 3 subtitles\n  modelNodePreservedHeight: 32 * 3,\n  // the view preserved height, for example: the view has 1 subtitle\n  viewNodePreservedHeight: 32 * 1,\n};\n\nconst convertBooleanToNumber = (value) => (value ? 1 : 0);\n\nconst getLimitedColumnsLengthProps = (columns: any[] = []) => {\n  const isOverLimit = columns.length > Config.columnsLimit;\n  const limitedLength = isOverLimit ? Config.columnsLimit : columns.length;\n  return {\n    isOverLimit,\n    limitedLength,\n    originalLength: columns.length,\n  };\n};\n\ntype NodeWithData = Node<{\n  originalData: ComposeDiagram;\n  index: number;\n  // highlight column ids inside\n  highlight: string[];\n}>;\n\ntype EdgeWithData = Edge<{\n  relation?: DiagramModelRelationField;\n  highlight: boolean;\n}>;\n\ntype StartPoint = { x: number; y: number; floor: number };\n\nexport class Transformer {\n  private readonly config: typeof Config = Config;\n  private models: DiagramModel[];\n  public nodes: NodeWithData[] = [];\n  private views: DiagramView[];\n  public edges: Edge[] = [];\n  private start: StartPoint = {\n    x: 0,\n    y: 0,\n    floor: 0,\n  };\n\n  constructor(data: Diagram) {\n    this.models = data?.models || [];\n    this.views = data?.views || [];\n    this.init();\n  }\n\n  public init() {\n    const allNodeData = [...this.models, ...this.views];\n    for (const data of allNodeData) {\n      this.addOne(data);\n    }\n  }\n\n  public addOne(data: ComposeDiagram) {\n    const { nodeType } = data;\n    // set position\n    const nodeX = this.start.x;\n    const nodeY = this.start.y;\n    const node = this.createNode({ nodeType, data, x: nodeX, y: nodeY });\n\n    // from the first model\n    this.nodes.push(node);\n\n    // update started point\n    this.updateNextStartedPoint();\n  }\n\n  private updateNextStartedPoint() {\n    const width = this.getNodeWidth();\n    let floorHeight = 0;\n    const { length } = this.nodes;\n    const { marginX, marginY, nodesInRow } = this.config;\n    const isNextFloor = length % nodesInRow === 0;\n    if (isNextFloor) {\n      this.start.floor++;\n      const lastFloorIndex = nodesInRow * (this.start.floor - 1);\n      const composeDiagrams: ComposeDiagram[] = [\n        ...this.models,\n        ...this.views,\n      ].slice(lastFloorIndex, lastFloorIndex + 4);\n\n      const modelWithMostColumns = composeDiagrams.reduce((prev, current) => {\n        const prevColumns = [\n          ...prev.fields,\n          ...(prev?.calculatedFields || []),\n          ...(current?.relationFields || []),\n        ];\n        const currentColumns = [\n          ...current.fields,\n          ...(current?.calculatedFields || []),\n          ...(current?.relationFields || []),\n        ];\n        return prevColumns.length > currentColumns.length ? prev : current;\n      }, composeDiagrams[0]);\n\n      floorHeight = this.getNodeHeight(modelWithMostColumns) + marginY;\n    }\n\n    this.start.x = this.start.x + width + marginX;\n    if (isNextFloor) this.start.x = 0;\n    this.start.y = this.start.y + floorHeight;\n  }\n\n  private createNode(props: {\n    nodeType: NODE_TYPE | string;\n    data: ComposeDiagram;\n    x: number;\n    y: number;\n  }): NodeWithData {\n    const { nodeType, data, x, y } = props;\n    // check nodeType and add edge\n    switch (nodeType) {\n      case NODE_TYPE.MODEL:\n        this.addModelEdge(data as DiagramModel);\n        break;\n      default:\n        break;\n    }\n\n    return {\n      id: data.id,\n      type: nodeType,\n      position: { x, y },\n      dragHandle: '.dragHandle',\n      data: {\n        originalData: data,\n        index: this.nodes.length,\n        highlight: [],\n      },\n    };\n  }\n\n  private addModelEdge(data: DiagramModel) {\n    const { relationFields } = data;\n    for (const relationField of relationFields) {\n      // check if edge already exist\n      const hasEdgeExist = this.edges.some((edge) => {\n        // the edge should be unique as relationId\n        const edgeRelationId = edge.data?.relation?.relationId;\n        return edgeRelationId === relationField.relationId;\n      });\n      if (hasEdgeExist) continue;\n\n      // prepare to add new edge\n      const targetModel = this.models.find(\n        (model) =>\n          model.id !== data.id &&\n          [relationField.fromModelName, relationField.toModelName].includes(\n            model.referenceName,\n          ),\n      )!;\n\n      // skip the edge if model not found\n      if (!targetModel) continue;\n\n      const targetField = targetModel.relationFields.find(\n        (field) =>\n          [\n            `${field.fromModelName}.${field.fromColumnName}`,\n            `${field.toModelName}.${field.toColumnName}`,\n          ].toString() ===\n          [\n            `${relationField.fromModelName}.${relationField.fromColumnName}`,\n            `${relationField.toModelName}.${relationField.toColumnName}`,\n          ].toString(),\n      );\n\n      // check what source and target relation order\n      const relationModels = [\n        relationField.fromModelName,\n        relationField.toModelName,\n      ];\n      const sourceJoinIndex = relationModels.findIndex(\n        (name) => name === data.referenceName,\n      );\n      const targetJoinIndex = relationModels.findIndex(\n        (name) => name === targetModel?.referenceName,\n      );\n\n      targetModel &&\n        this.edges.push(\n          this.createEdge({\n            type: EDGE_TYPE.MODEL,\n            joinType: relationField.type,\n            sourceModel: data,\n            sourceField: relationField,\n            sourceJoinIndex,\n            targetModel,\n            targetField,\n            targetJoinIndex,\n          }),\n        );\n    }\n  }\n\n  private createEdge(props: {\n    type?: EDGE_TYPE;\n    sourceModel: ComposeDiagram;\n    sourceField?: DiagramModelRelationField;\n    sourceJoinIndex?: number;\n    targetModel: ComposeDiagram;\n    targetField?: DiagramModelRelationField;\n    targetJoinIndex?: number;\n    joinType?: JOIN_TYPE | string;\n    animated?: boolean;\n  }): EdgeWithData {\n    const {\n      type,\n      sourceModel,\n      sourceField,\n      sourceJoinIndex,\n      targetModel,\n      targetField,\n      targetJoinIndex,\n      joinType,\n      animated,\n    } = props;\n    const source = sourceModel.id;\n    const target = targetModel.id;\n    const [sourcePos, targetPos] = this.detectEdgePosition(source, target);\n    const sourceHandle = `${sourceField?.id || source}_${sourcePos}`;\n    const targetHandle = `${targetField?.id || target}_${targetPos}`;\n\n    const markerStart = this.getMarker(joinType!, sourceJoinIndex!, sourcePos);\n    const markerEnd = this.getMarker(joinType!, targetJoinIndex!, targetPos);\n\n    return {\n      id: `${sourceHandle}_${targetHandle}`,\n      type,\n      source,\n      target,\n      sourceHandle,\n      targetHandle,\n      markerStart,\n      markerEnd,\n      data: {\n        relation: sourceField,\n        highlight: false,\n      },\n      animated,\n    };\n  }\n\n  private getFloorIndex(index: number): number {\n    const { nodesInRow } = this.config;\n    return index % nodesInRow;\n  }\n\n  private detectEdgePosition(source: string, target: string) {\n    const position = [];\n    const [sourceIndex, targetIndex] = [...this.models].reduce(\n      (result, current, index) => {\n        if (current.id === source) result[0] = index;\n        if (current.id === target) result[1] = index;\n        return result;\n      },\n      [-1, -1],\n    );\n    const sourceFloorIndex = this.getFloorIndex(sourceIndex);\n    const targetFloorIndex = this.getFloorIndex(targetIndex);\n\n    if (sourceFloorIndex === targetFloorIndex) {\n      position[0] = Position.Left;\n      position[1] = Position.Left;\n    } else if (sourceFloorIndex > targetFloorIndex) {\n      position[0] = Position.Left;\n      position[1] = Position.Right;\n    } else {\n      position[0] = Position.Right;\n      position[1] = Position.Left;\n    }\n    return position;\n  }\n\n  private getMarker(\n    joinType: JOIN_TYPE | string,\n    joinIndex: number,\n    position?: Position,\n  ) {\n    const markers =\n      {\n        [JOIN_TYPE.ONE_TO_ONE]: [MARKER_TYPE.ONE, MARKER_TYPE.ONE],\n        [JOIN_TYPE.ONE_TO_MANY]: [MARKER_TYPE.ONE, MARKER_TYPE.MANY],\n        [JOIN_TYPE.MANY_TO_ONE]: [MARKER_TYPE.MANY, MARKER_TYPE.ONE],\n      }[joinType] || [];\n    return markers[joinIndex] + (position ? `_${position}` : '');\n  }\n\n  private getNodeWidth() {\n    return this.config.width;\n  }\n\n  private getNodeHeight(composeDiagram: ComposeDiagram) {\n    const {\n      height: nodeHeight,\n      headerHeight,\n      columnHeight,\n      moreTipHeight,\n      modelNodePreservedHeight,\n      viewNodePreservedHeight,\n    } = this.config;\n\n    // get preserved height setting\n    const preservedHeightMap = {\n      [NODE_TYPE.MODEL]: modelNodePreservedHeight,\n      [NODE_TYPE.VIEW]: viewNodePreservedHeight,\n    };\n    const preservedHeight = preservedHeightMap[composeDiagram.nodeType];\n\n    // check if columns limit is reached\n    const { limitedLength: fieldsLength, isOverLimit: isFieldsOverLimit } =\n      getLimitedColumnsLengthProps(composeDiagram.fields);\n    const {\n      limitedLength: calculatedFieldsLength,\n      isOverLimit: isCalculatedFieldsOverLimit,\n    } = getLimitedColumnsLengthProps(composeDiagram?.calculatedFields);\n    const {\n      limitedLength: relationFieldsLength,\n      isOverLimit: isRelationsOverLimit,\n    } = getLimitedColumnsLengthProps(composeDiagram?.relationFields);\n\n    // count more tip\n    const moreTipCount =\n      convertBooleanToNumber(isFieldsOverLimit) +\n      convertBooleanToNumber(isCalculatedFieldsOverLimit) +\n      convertBooleanToNumber(isRelationsOverLimit);\n\n    // calculate all block height\n    const displayHeaderHeight = headerHeight;\n    const displayColumnHeight =\n      nodeHeight ||\n      columnHeight *\n        (fieldsLength + calculatedFieldsLength + relationFieldsLength);\n    const displayMoreTipHeight = moreTipHeight * moreTipCount;\n    // padding remain\n    const paddingHeight = 4;\n\n    return (\n      displayHeaderHeight +\n      displayColumnHeight +\n      displayMoreTipHeight +\n      preservedHeight +\n      paddingHeight\n    );\n  }\n}\n"
  },
  {
    "path": "wren-ui/src/utils/enum/columnType.ts",
    "content": "// Refer to backend connector types:\n// src/apollo/server/connectors/types.ts\n\nexport enum COLUMN_TYPE {\n  // Boolean Types\n  BOOLEAN = 'BOOLEAN',\n\n  // Numeric Types\n  TINYINT = 'TINYINT',\n\n  INT2 = 'INT2',\n  SMALLINT = 'SMALLINT', // alias for INT2\n\n  INT4 = 'INT4',\n  INTEGER = 'INTEGER', // alias for INT4\n\n  INT8 = 'INT8',\n  BIGINT = 'BIGINT', // alias for INT8\n\n  INT64 = 'INT64',\n\n  NUMERIC = 'NUMERIC',\n  DECIMAL = 'DECIMAL',\n\n  // Floating-Point Types\n  FLOAT4 = 'FLOAT4',\n  REAL = 'REAL', // alias for FLOAT4\n\n  FLOAT8 = 'FLOAT8',\n  DOUBLE = 'DOUBLE', // alias for FLOAT8\n\n  // Character Types\n  VARCHAR = 'VARCHAR',\n  CHAR = 'CHAR',\n  BPCHAR = 'BPCHAR', // BPCHAR is fixed-length, blank padded string\n  TEXT = 'TEXT', // alias for VARCHAR\n  STRING = 'STRING', // alias for VARCHAR\n  NAME = 'NAME', // alias for VARCHAR\n\n  // Date/Time Types\n  TIMESTAMP = 'TIMESTAMP',\n  TIMESTAMPTZ = 'TIMESTAMP WITH TIME ZONE',\n  DATE = 'DATE',\n  INTERVAL = 'INTERVAL',\n\n  // JSON Types\n  JSON = 'JSON',\n\n  // Record Types\n  RECORD = 'RECORD',\n\n  // Object identifiers (OIDs) are used internally by PostgreSQL as primary keys for various system tables.\n  // https://www.postgresql.org/docs/current/datatype-oid.html\n  OID = 'OID',\n\n  // Binary Data Types\n  BYTEA = 'BYTEA',\n  VARBINARY = 'VARBINARY',\n\n  // UUID Type\n  UUID = 'UUID',\n\n  // Network Address Types\n  INET = 'INET',\n\n  // Unknown Type\n  UNKNOWN = 'UNKNOWN',\n}\n"
  },
  {
    "path": "wren-ui/src/utils/enum/dataSources.ts",
    "content": "export {\n  RedshiftConnectionType as REDSHIFT_AUTH_METHOD,\n  DatabricksConnectionType as DATABRICKS_AUTH_METHOD,\n} from '@/apollo/client/graphql/__types__';\n\nexport enum DATA_SOURCES {\n  BIG_QUERY = 'BIG_QUERY',\n  DUCKDB = 'DUCKDB',\n  POSTGRES = 'POSTGRES',\n  MYSQL = 'MYSQL',\n  ORACLE = 'ORACLE',\n  MSSQL = 'MSSQL',\n  CLICK_HOUSE = 'CLICK_HOUSE',\n  TRINO = 'TRINO',\n  SNOWFLAKE = 'SNOWFLAKE',\n  ATHENA = 'ATHENA',\n  REDSHIFT = 'REDSHIFT',\n  DATABRICKS = 'DATABRICKS',\n}\n\nexport enum ATHENA_AUTH_METHOD {\n  classic = 'classic',\n  oidc = 'oidc',\n  instance_profile = 'instance_profile',\n}\n"
  },
  {
    "path": "wren-ui/src/utils/enum/diagram.ts",
    "content": "export enum MARKER_TYPE {\n  MANY = 'many',\n  ONE = 'one',\n}\n\nexport enum EDGE_TYPE {\n  STEP = 'step',\n  SMOOTHSTEP = 'smoothstep',\n  BEZIER = 'bezier',\n  MODEL = 'model',\n  METRIC = 'metric',\n}\n"
  },
  {
    "path": "wren-ui/src/utils/enum/dropdown.ts",
    "content": "export enum MORE_ACTION {\n  EDIT = 'edit',\n  DELETE = 'delete',\n  UPDATE_COLUMNS = 'update_columns',\n  CACHE_SETTINGS = 'cache_settings',\n  REFRESH = 'refresh',\n  HIDE_CATEGORY = 'hide_category',\n  VIEW_SQL_PAIR = 'view_sql_pair',\n  VIEW_INSTRUCTION = 'view_instruction',\n  ADJUST_SQL = 'adjust_sql',\n  ADJUST_STEPS = 'adjust_steps',\n}\n"
  },
  {
    "path": "wren-ui/src/utils/enum/form.ts",
    "content": "export enum FORM_MODE {\n  CREATE = 'CREATE',\n  EDIT = 'EDIT',\n}\n\n// identifier separated by special & unique symbol\nconst specialSymbol = '☺';\n\nexport const convertObjectToIdentifier = <T>(obj: T, paths: string[]): string =>\n  paths.map((path) => `${path}:${obj[path] || ''}`).join(specialSymbol);\n\nexport const convertIdentifierToObject = <T>(identifier: string): T =>\n  Object.fromEntries(\n    identifier.split(specialSymbol).map((str) => str.split(':')),\n  );\n"
  },
  {
    "path": "wren-ui/src/utils/enum/home.ts",
    "content": "export enum COLLAPSE_CONTENT_TYPE {\n  NONE = 'none',\n  VIEW_SQL = 'view_sql',\n  PREVIEW_DATA = 'preview_data',\n}\n\nexport enum PROCESS_STATE {\n  IDLE,\n  UNDERSTANDING,\n  SEARCHING,\n  PLANNING,\n  GENERATING,\n  CORRECTING,\n  FINISHED,\n  FAILED,\n  STOPPED,\n  NO_RESULT,\n}\n\nexport enum ANSWER_TAB_KEYS {\n  ANSWER = 'answer',\n  VIEW_SQL = 'view-sql',\n  CHART = 'chart',\n}\n"
  },
  {
    "path": "wren-ui/src/utils/enum/index.ts",
    "content": "export * from './form';\nexport * from './setup';\nexport * from './dataSources';\nexport * from './columnType';\nexport * from './modeling';\nexport * from './path';\nexport * from './diagram';\nexport * from './home';\nexport * from './settings';\nexport * from './dropdown';\nexport * from './menu';\n"
  },
  {
    "path": "wren-ui/src/utils/enum/menu.ts",
    "content": "export enum MENU_KEY {\n  QUESTION_SQL_PAIRS = 'question-sql-pairs',\n  INSTRUCTIONS = 'instructions',\n  API_HISTORY = 'api-history',\n  API_REFERENCE = 'api-reference',\n}\n"
  },
  {
    "path": "wren-ui/src/utils/enum/modeling.ts",
    "content": "export {\n  NodeType as NODE_TYPE,\n  RelationType as JOIN_TYPE,\n} from '@/apollo/client/graphql/__types__';\n"
  },
  {
    "path": "wren-ui/src/utils/enum/path.ts",
    "content": "export enum Path {\n  Home = '/home',\n  HomeDashboard = '/home/dashboard',\n  Thread = '/home/[id]',\n  Modeling = '/modeling',\n  Onboarding = '/setup',\n  OnboardingConnection = '/setup/connection',\n  OnboardingModels = '/setup/models',\n  OnboardingRelationships = '/setup/relationships',\n  Knowledge = '/knowledge',\n  KnowledgeQuestionSQLPairs = '/knowledge/question-sql-pairs',\n  KnowledgeInstructions = '/knowledge/instructions',\n  APIManagement = '/api-management',\n  APIManagementHistory = '/api-management/history',\n}\n"
  },
  {
    "path": "wren-ui/src/utils/enum/settings.ts",
    "content": "export enum SETTINGS {\n  DATA_SOURCE = 'DATA_SOURCE',\n  PROJECT = 'PROJECT',\n}\n"
  },
  {
    "path": "wren-ui/src/utils/enum/setup.ts",
    "content": "export enum SETUP {\n  STARTER = 'starter',\n  CREATE_DATA_SOURCE = 'createDataSource',\n  SELECT_MODELS = 'selectModels',\n  RECOMMEND_RELATIONS = 'recommendRelations',\n  DEFINE_RELATIONS = 'defineRelations',\n}\n"
  },
  {
    "path": "wren-ui/src/utils/env.ts",
    "content": "const env = {\n  isDevelopment: process.env.NODE_ENV === 'development',\n  isProduction: process.env.NODE_ENV === 'production',\n};\n\nexport default env;\n\nexport type UserConfig = {\n  isTelemetryEnabled: boolean;\n  telemetryKey: string;\n  telemetryHost: string;\n  userUUID: string;\n};\n\n// Get the user configuration\nexport const getUserConfig = async (): Promise<UserConfig> => {\n  const config = await fetch('/api/config').then((res) => res.json());\n  const decodedTelemetryKey = Buffer.from(\n    config.telemetryKey,\n    'base64',\n  ).toString();\n  return { ...config, telemetryKey: decodedTelemetryKey };\n};\n"
  },
  {
    "path": "wren-ui/src/utils/error/dictionary.ts",
    "content": "export const ERROR_TEXTS = {\n  CONNECTION: {\n    DISPLAY_NAME: {\n      REQUIRED: 'Please input display name.',\n    },\n    PROJECT_ID: {\n      REQUIRED: 'Please input project id.',\n    },\n    DATASET_ID: {\n      REQUIRED: 'Please input dataset ID.',\n    },\n    CREDENTIAL: {\n      REQUIRED: 'Please upload credential.',\n    },\n    INIT_SQL: {\n      REQUIRED: 'Please input initial SQL statements.',\n    },\n    CONFIGURATION: {\n      KEY: {\n        REQUIRED: 'Please input configuration key.',\n      },\n      VALUE: {\n        REQUIRED: 'Please input configuration value.',\n      },\n    },\n    HOST: {\n      REQUIRED: 'Please input host.',\n      INVALID:\n        \"Invalid host. Use 'host.docker.internal' on macOS/Windows to connect to the local database.\",\n    },\n    PORT: {\n      REQUIRED: 'Please input port.',\n    },\n    USER: {\n      REQUIRED: 'Please input user.',\n    },\n    USERNAME: {\n      REQUIRED: 'Please input username.',\n    },\n    PASSWORD: {\n      REQUIRED: 'Please input password.',\n    },\n    DATABASE: {\n      REQUIRED: 'Please input database name.',\n    },\n    SCHEMA: {\n      REQUIRED: 'Please input schema name.',\n    },\n    SCHEMAS: {\n      REQUIRED: 'Please input list of catalog.schema separated by comma.',\n    },\n    ACCOUNT: {\n      REQUIRED: 'Please input account.',\n    },\n    S3_STAGING_DIR: {\n      REQUIRED: 'Please input S3 staging directory.',\n    },\n    AWS_REGION: {\n      REQUIRED: 'Please input AWS region.',\n    },\n    AWS_ACCESS_KEY: {\n      REQUIRED: 'Please input AWS access key ID.',\n    },\n    AWS_SECRET_KEY: {\n      REQUIRED: 'Please input AWS secret access key.',\n    },\n    AWS_ROLE_ARN: {\n      REQUIRED: 'Please input AWS role ARN.',\n    },\n    WEB_IDENTITY_TOKEN: {\n      REQUIRED: 'Please input web identity token.',\n    },\n    CLUSTER_IDENTIFIER: {\n      REQUIRED: 'Please input cluster identifier.',\n    },\n    PRIVATE_KEY_FILE: {\n      REQUIRED: 'Please upload a private key file.',\n    },\n    HTTP_PATH: {\n      REQUIRED: 'Please input HTTP path.',\n    },\n    PERSONAL_ACCESS_TOKEN: {\n      REQUIRED: 'Please input personal access token.',\n    },\n    CLIENT_ID: {\n      REQUIRED: 'Please input client ID.',\n    },\n    CLIENT_SECRET: {\n      REQUIRED: 'Please input client secret.',\n    },\n  },\n  ADD_RELATION: {\n    FROM_FIELD: {\n      REQUIRED: 'Please select a field.',\n    },\n    TO_FIELD: {\n      REQUIRED: 'Please select a field.',\n    },\n    RELATION_TYPE: {\n      REQUIRED: 'Please select a relationship type.',\n    },\n    RELATIONSHIP: {\n      EXIST: 'This relationship already exists.',\n    },\n  },\n  SETUP_MODEL: {\n    TABLE: {\n      REQUIRED: 'Please select at least one table.',\n    },\n  },\n  SAVE_AS_VIEW: {\n    NAME: {\n      REQUIRED: 'Please input view name.',\n    },\n  },\n  MODELING_CREATE_MODEL: {\n    TABLE: {\n      REQUIRED: 'Please select a table.',\n    },\n    COLUMNS: {\n      REQUIRED: 'Please select at least one column.',\n    },\n    PRIMARY_KEY: {\n      INVALID:\n        'Please select again, the primary key must be one of the selected columns.',\n    },\n  },\n  CALCULATED_FIELD: {\n    NAME: {\n      REQUIRED: 'Please input field name.',\n    },\n    EXPRESSION: {\n      REQUIRED: 'Please select an expression.',\n    },\n    LINEAGE: {\n      REQUIRED: 'Please select a field.',\n      INVALID_STRING_TYPE: 'Please select a string type field.',\n      INVALID_NUMBER_TYPE: 'Please select a number type field.',\n    },\n  },\n  SQL_PAIR: {\n    SQL: {\n      REQUIRED: 'Please input SQL statement.',\n    },\n    QUESTION: {\n      REQUIRED: 'Please input a matching question.',\n      MAX_LENGTH: 'Question must be 300 characters or fewer.',\n    },\n  },\n  INSTRUCTION: {\n    DETAILS: {\n      REQUIRED: 'Please input an instruction details.',\n    },\n    QUESTIONS: {\n      REQUIRED: 'Please input a matching question.',\n    },\n    IS_DEFAULT_GLOBAL: {\n      REQUIRED: 'Please select how to apply this instruction.',\n    },\n  },\n  FIX_SQL: {\n    SQL: {\n      REQUIRED: 'Please input SQL statement.',\n    },\n  },\n  ADJUST_REASONING: {\n    SELECTED_MODELS: {\n      REQUIRED: 'Please select at least one model',\n    },\n    STEPS: {\n      REQUIRED: 'Please input reasoning steps',\n      MAX_LENGTH: 'Reasoning steps must be 6000 characters or fewer.',\n    },\n  },\n  IMPORT_DATA_SOURCE_SQL: {\n    SQL: {\n      REQUIRED: 'Please input SQL statement.',\n    },\n  },\n  CRON: {\n    REQUIRED: 'Please input cron expression.',\n    INVALID: 'Invalid cron expression.',\n  },\n  CACHE_SETTINGS: {\n    DAY: {\n      REQUIRED: 'Please select day.',\n    },\n    TIME: {\n      REQUIRED: 'Please select time.',\n    },\n  },\n};\n"
  },
  {
    "path": "wren-ui/src/utils/error/index.ts",
    "content": "export * from './dictionary';\n"
  },
  {
    "path": "wren-ui/src/utils/errorHandler.tsx",
    "content": "import { GraphQLError } from 'graphql';\nimport { ErrorResponse } from '@apollo/client/link/error';\nimport { ApolloError } from '@apollo/client';\nimport { message } from 'antd';\n\n// Refer to backend GeneralErrorCodes for mapping\nexport const ERROR_CODES = {\n  INVALID_CALCULATED_FIELD: 'INVALID_CALCULATED_FIELD',\n  CONNECTION_REFUSED: 'CONNECTION_REFUSED',\n  NO_CHART: 'NO_CHART',\n};\n\n/**\n * Replace the token %{s} in the message with the detail message.\n * For example:\n *\n *  Input: ('Failed to update %{data source}.')\n *  Output: Failed to update data source.\n *\n *  Input: ('Failed to update %{data source}.', 'The data source is not found.')\n *  Output: Failed to update - The data source is not found.\n *\n * @param message The default message with replace token %{s}.\n * @param detailMessage The detail message.\n * @returns string\n */\nconst replaceMessage = (message: string, detailMessage?: string) => {\n  const regex = /\\%\\{.+\\}/;\n  const textWithoutTokenRegex = /(?<=\\%\\{).+(?=\\})/;\n  const matchText = message.match(textWithoutTokenRegex);\n  if (matchText === null) {\n    console.warn('Replace token not found in message:', message);\n    return message;\n  }\n  return detailMessage\n    ? message.replace(regex, `- ${detailMessage}`)\n    : message.replace(regex, matchText[0]);\n};\n\nabstract class ErrorHandler {\n  public handle(error: GraphQLError) {\n    const errorMessage = this.getErrorMessage(error);\n    if (errorMessage) message.error(errorMessage);\n  }\n\n  abstract getErrorMessage(error: GraphQLError): string | null;\n}\n\nconst errorHandlers = new Map<string, ErrorHandler>();\n\nclass SaveTablesErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to create model(s).';\n    }\n  }\n}\n\nclass SaveRelationsErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to define relations.';\n    }\n  }\n}\n\nclass CreateAskingTaskErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to create asking task.';\n    }\n  }\n}\n\nclass CreateThreadErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to create thread.';\n    }\n  }\n}\n\nclass UpdateThreadErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to update thread.';\n    }\n  }\n}\n\nclass DeleteThreadErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to delete thread.';\n    }\n  }\n}\n\nclass CreateThreadResponseErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to create thread response.';\n    }\n  }\n}\n\nclass UpdateThreadResponseErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to update thread response.';\n    }\n  }\n}\n\nclass GenerateThreadResponseAnswerErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to generate thread response answer.';\n    }\n  }\n}\n\nclass AdjustThreadResponseErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to adjust thread response answer.';\n    }\n  }\n}\n\nclass CreateViewErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to create view.';\n    }\n  }\n}\n\nclass UpdateDataSourceErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return replaceMessage(\n          `Failed to update %{data source}.`,\n          error.message,\n        );\n    }\n  }\n}\n\nclass CreateModelErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to create model.';\n    }\n  }\n}\n\nclass UpdateModelErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to update model.';\n    }\n  }\n}\n\nclass DeleteModelErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to delete model.';\n    }\n  }\n}\n\nclass UpdateModelMetadataErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to update model metadata.';\n    }\n  }\n}\n\nclass CreateCalculatedFieldErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to create calculated field.';\n    }\n  }\n}\n\nclass UpdateCalculatedFieldErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to update calculated field.';\n    }\n  }\n}\n\nclass DeleteCalculatedFieldErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to delete calculated field.';\n    }\n  }\n}\n\nclass CreateRelationshipErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to create relationship.';\n    }\n  }\n}\n\nclass UpdateRelationshipErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to update relationship.';\n    }\n  }\n}\n\nclass DeleteRelationshipErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to delete relationship.';\n    }\n  }\n}\n\nclass UpdateViewMetadataErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to update view metadata.';\n    }\n  }\n}\n\nclass TriggerDataSourceDetectionErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to scan data source.';\n    }\n  }\n}\n\nclass ResolveSchemaChangeErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to resolve schema change.';\n    }\n  }\n}\n\nclass CreateDashboardItemErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to create dashboard item.';\n    }\n  }\n}\n\nclass UpdateDashboardItemErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to update dashboard item.';\n    }\n  }\n}\n\nclass UpdateDashboardItemLayoutsErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to update dashboard item layouts.';\n    }\n  }\n}\n\nclass DeleteDashboardItemErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to delete dashboard item.';\n    }\n  }\n}\n\nclass SetDashboardScheduleErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to set dashboard schedule.';\n    }\n  }\n}\n\nclass CreateSqlPairErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to create question-sql pair.';\n    }\n  }\n}\n\nclass UpdateSqlPairErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to update question-sql pair.';\n    }\n  }\n}\n\nclass DeleteSqlPairErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to delete question-sql pair.';\n    }\n  }\n}\n\nclass CreateInstructionErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to create instruction.';\n    }\n  }\n}\n\nclass UpdateInstructionErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to update instruction.';\n    }\n  }\n}\n\nclass DeleteInstructionErrorHandler extends ErrorHandler {\n  public getErrorMessage(error: GraphQLError) {\n    switch (error.extensions?.code) {\n      default:\n        return 'Failed to delete instruction.';\n    }\n  }\n}\n\nerrorHandlers.set('SaveTables', new SaveTablesErrorHandler());\nerrorHandlers.set('SaveRelations', new SaveRelationsErrorHandler());\nerrorHandlers.set('CreateAskingTask', new CreateAskingTaskErrorHandler());\nerrorHandlers.set('CreateThread', new CreateThreadErrorHandler());\nerrorHandlers.set('UpdateThread', new UpdateThreadErrorHandler());\nerrorHandlers.set('DeleteThread', new DeleteThreadErrorHandler());\nerrorHandlers.set(\n  'CreateThreadResponse',\n  new CreateThreadResponseErrorHandler(),\n);\nerrorHandlers.set(\n  'UpdateThreadResponse',\n  new UpdateThreadResponseErrorHandler(),\n);\nerrorHandlers.set(\n  'GenerateThreadResponseAnswer',\n  new GenerateThreadResponseAnswerErrorHandler(),\n);\nerrorHandlers.set(\n  'AdjustThreadResponse',\n  new AdjustThreadResponseErrorHandler(),\n);\n\nerrorHandlers.set('CreateView', new CreateViewErrorHandler());\nerrorHandlers.set('UpdateDataSource', new UpdateDataSourceErrorHandler());\nerrorHandlers.set('CreateModel', new CreateModelErrorHandler());\nerrorHandlers.set('UpdateModel', new UpdateModelErrorHandler());\nerrorHandlers.set('DeleteModel', new DeleteModelErrorHandler());\nerrorHandlers.set('UpdateModelMetadata', new UpdateModelMetadataErrorHandler());\nerrorHandlers.set('UpdateViewMetadata', new UpdateViewMetadataErrorHandler());\nerrorHandlers.set(\n  'CreateCalculatedField',\n  new CreateCalculatedFieldErrorHandler(),\n);\nerrorHandlers.set(\n  'UpdateCalculatedField',\n  new UpdateCalculatedFieldErrorHandler(),\n);\nerrorHandlers.set(\n  'DeleteCalculatedField',\n  new DeleteCalculatedFieldErrorHandler(),\n);\n\n// Relationship\nerrorHandlers.set('CreateRelationship', new CreateRelationshipErrorHandler());\nerrorHandlers.set('UpdateRelationship', new UpdateRelationshipErrorHandler());\nerrorHandlers.set('DeleteRelationship', new DeleteRelationshipErrorHandler());\n\n// Schema change\nerrorHandlers.set(\n  'TriggerDataSourceDetection',\n  new TriggerDataSourceDetectionErrorHandler(),\n);\nerrorHandlers.set('ResolveSchemaChange', new ResolveSchemaChangeErrorHandler());\n\n// Dashboard\nerrorHandlers.set('CreateDashboardItem', new CreateDashboardItemErrorHandler());\nerrorHandlers.set('UpdateDashboardItem', new UpdateDashboardItemErrorHandler());\nerrorHandlers.set(\n  'UpdateDashboardItemLayouts',\n  new UpdateDashboardItemLayoutsErrorHandler(),\n);\nerrorHandlers.set('DeleteDashboardItem', new DeleteDashboardItemErrorHandler());\nerrorHandlers.set(\n  'SetDashboardSchedule',\n  new SetDashboardScheduleErrorHandler(),\n);\n\n// SQL Pair\nerrorHandlers.set('CreateSqlPair', new CreateSqlPairErrorHandler());\nerrorHandlers.set('UpdateSqlPair', new UpdateSqlPairErrorHandler());\nerrorHandlers.set('DeleteSqlPair', new DeleteSqlPairErrorHandler());\n\n// Instruction\nerrorHandlers.set('CreateInstruction', new CreateInstructionErrorHandler());\nerrorHandlers.set('UpdateInstruction', new UpdateInstructionErrorHandler());\nerrorHandlers.set('DeleteInstruction', new DeleteInstructionErrorHandler());\n\nconst errorHandler = (error: ErrorResponse) => {\n  // networkError\n  if (error.networkError) {\n    message.error(\n      'No internet. Please check your network connection and try again.',\n    );\n  }\n\n  const operationName = error?.operation?.operationName || '';\n  if (error.graphQLErrors) {\n    for (const err of error.graphQLErrors) {\n      errorHandlers.get(operationName)?.handle(err);\n    }\n  }\n};\n\nexport default errorHandler;\n\nexport const parseGraphQLError = (error: ApolloError) => {\n  if (!error) return null;\n  const graphQLErrors: GraphQLError = error.graphQLErrors?.[0];\n  const extensions = graphQLErrors?.extensions || {};\n  return {\n    message: extensions.message as string,\n    shortMessage: extensions.shortMessage as string,\n    code: extensions.code as string,\n    stacktrace: extensions?.stacktrace as Array<string> | undefined,\n  };\n};\n"
  },
  {
    "path": "wren-ui/src/utils/events.tsx",
    "content": "export const subscribe = (eventName: string, listener: any) => {\n  document.addEventListener(eventName, listener);\n};\n\nexport const unsubscribe = (eventName: string, listener: any) => {\n  document.removeEventListener(eventName, listener);\n};\n\nexport const dispatch = (eventName: string, detail?: any) => {\n  const event = new CustomEvent(eventName, { detail });\n  document.dispatchEvent(event);\n};\n\nexport const EVENT_NAME = {\n  GO_TO_FIRST_MODEL: 'goToFirstModel',\n};\n"
  },
  {
    "path": "wren-ui/src/utils/expressionType.ts",
    "content": "import { ExpressionName } from '@/apollo/client/graphql/__types__';\n\nexport const aggregations = [\n  ExpressionName.AVG,\n  ExpressionName.COUNT,\n  ExpressionName.MAX,\n  ExpressionName.MIN,\n  ExpressionName.SUM,\n];\n\nexport const mathFunctions = [\n  ExpressionName.ABS,\n  ExpressionName.CBRT,\n  ExpressionName.CEIL,\n  ExpressionName.EXP,\n  ExpressionName.FLOOR,\n  ExpressionName.LN,\n  ExpressionName.LOG10,\n  ExpressionName.ROUND,\n  ExpressionName.SIGN,\n];\n\nexport const stringFunctions = [ExpressionName.LENGTH, ExpressionName.REVERSE];\n"
  },
  {
    "path": "wren-ui/src/utils/file.ts",
    "content": "export function readFileContent(file: File): Promise<string> {\n  return new Promise((resolve, reject) => {\n    const reader = new FileReader();\n\n    reader.onload = (event) => {\n      const result = event.target?.result;\n      if (typeof result === 'string') {\n        resolve(result);\n      } else {\n        reject(new Error('Failed to read file as text'));\n      }\n    };\n\n    reader.onerror = () => {\n      reject(new Error('Failed to read file'));\n    };\n\n    reader.readAsText(file);\n  });\n}\n\nexport const extractPrivateKeyString = (content: string) => {\n  // Try to match PEM format first (both regular and encrypted)\n  const pemMatch = content.match(\n    /-----BEGIN (?:ENCRYPTED )?PRIVATE KEY-----([\\s\\S]*?)-----END (?:ENCRYPTED )?PRIVATE KEY-----/,\n  );\n  if (pemMatch) {\n    return pemMatch[1].replace(/\\s/g, '');\n  }\n  return content.trim();\n};\n"
  },
  {
    "path": "wren-ui/src/utils/helper.ts",
    "content": "import { omitBy, isUndefined } from 'lodash';\n\n/**\n * @function\n * @description Remove undefined property value in an object\n */\nexport const compactObject = <T>(obj: T) => {\n  return omitBy(obj, isUndefined) as T;\n};\n\n/**\n * @function\n * @description Retrieve json without error\n */\nexport const parseJson = (data) => {\n  try {\n    return JSON.parse(data);\n  } catch (_e) {\n    return data;\n  }\n};\n\nexport const attachLoading = (\n  asyncRequest: (...args: any[]) => Promise<any>,\n  setLoading: React.Dispatch<React.SetStateAction<boolean>>,\n) => {\n  return async (...args) => {\n    setLoading(true);\n    try {\n      await asyncRequest(...args);\n    } finally {\n      setLoading(false);\n    }\n  };\n};\n"
  },
  {
    "path": "wren-ui/src/utils/icons.ts",
    "content": "import styled from 'styled-components';\nimport { Columns } from '@styled-icons/fa-solid';\nimport {\n  Calendar,\n  Text,\n  InfoCircle,\n  Cube,\n  LineChart,\n  IdCard,\n} from '@styled-icons/boxicons-regular';\nimport { Braces, Map2 } from '@styled-icons/remix-line';\nimport {\n  SortNumerically,\n  SortAlphabetically,\n  Tick,\n} from '@styled-icons/typicons';\nimport {\n  VpnKey,\n  CenterFocusWeak,\n  Refresh,\n  Pageview,\n  Explore,\n  Translate,\n  OpenInNew,\n} from '@styled-icons/material-outlined';\nimport FieldBinaryOutlined from '@ant-design/icons/FieldBinaryOutlined';\nimport MonitorOutlined from '@ant-design/icons/MonitorOutlined';\nimport SwapOutlined from '@ant-design/icons/SwapOutlined';\nimport ShareAltOutlined from '@ant-design/icons/ShareAltOutlined';\nimport { Binoculars, LightningCharge } from '@styled-icons/bootstrap';\nimport MoreOutlined from '@ant-design/icons/MoreOutlined';\nimport { Sparkles } from '@styled-icons/ionicons-outline';\nimport { Discord, Github } from '@styled-icons/fa-brands';\n\nexport const NumericIcon = styled(SortNumerically)`\n  height: 1em;\n`;\nexport const TickIcon = styled(Tick)`\n  height: 1em;\n`;\nexport const StringIcon = styled(SortAlphabetically)`\n  height: 1em;\n`;\nexport const TextIcon = styled(Text)`\n  height: 1em;\n`;\nexport const CalendarIcon = styled(Calendar)`\n  height: 1em;\n`;\nexport const IdIcon = styled(IdCard)`\n  height: 1em;\n`;\nexport const JsonBracesIcon = styled(Braces)`\n  height: 1em;\n`;\nexport const BinaryIcon = styled(FieldBinaryOutlined)`\n  height: 1em;\n`;\nexport const ColumnsIcon = styled(Columns)`\n  height: 1em;\n`;\nexport const InfoIcon = styled(InfoCircle)`\n  height: 1em;\n`;\nexport const PrimaryKeyIcon = styled(VpnKey)`\n  height: 1em;\n`;\nexport const ModelIcon = styled(Cube)`\n  height: 1em;\n`;\nexport const FocusIcon = styled(CenterFocusWeak)`\n  height: 1em;\n`;\nexport const MapIcon = styled(Map2)`\n  height: 1em;\n`;\nexport const RelationshipIcon = styled(SwapOutlined)`\n  height: 1em;\n`;\nexport const MonitorIcon = styled(MonitorOutlined)`\n  height: 1em;\n`;\nexport const RefreshIcon = styled(Refresh)``;\nexport const MetricIcon = styled(LineChart)`\n  height: 1em;\n`;\nexport const ShareIcon = styled(ShareAltOutlined)``;\nexport const LightningIcon = styled(LightningCharge)`\n  height: 1em;\n`;\nexport const MoreIcon = styled(MoreOutlined)``;\nexport const ViewIcon = styled(Pageview)`\n  height: 1em;\n`;\nexport const ExploreIcon = styled(Explore)`\n  height: 1em;\n`;\nexport const SparklesIcon = styled(Sparkles)`\n  height: 1em;\n`;\n\nexport const BinocularsIcon = styled(Binoculars)`\n  height: 16px;\n  width: 14px;\n`;\n\nexport const DiscordIcon = styled(Discord)`\n  height: 1em;\n`;\n\nexport const GithubIcon = styled(Github)`\n  height: 1em;\n`;\n\nexport const TranslateIcon = styled(Translate)`\n  height: 1em;\n`;\n\nexport const OpenInNewIcon = styled(OpenInNew)`\n  height: 1em;\n`;\n"
  },
  {
    "path": "wren-ui/src/utils/iteration.tsx",
    "content": "interface Props {\n  [key: string]: any;\n  data: any[];\n  // by default it will use item['key'] as keyIndex unless specifying keyIndex\n  keyIndex?: string | ((item: any) => string);\n}\n\nexport type IterableComponent<T = any> = {\n  data: T[];\n  index: number;\n  key: string;\n} & T;\n\nexport const makeIterable = (Template: React.FC<IterableComponent<any>>) => {\n  const Iterator = (props: Props) => {\n    const { data, keyIndex = 'key', ...restProps } = props;\n    const result = data.map((item, index) => {\n      const key =\n        typeof keyIndex === 'function' ? keyIndex(item) : item[keyIndex];\n      return (\n        <Template\n          data={data}\n          index={index}\n          key={`${index}-${key}`}\n          {...restProps}\n          {...item}\n        />\n      );\n    });\n    return <>{result}</>;\n  };\n\n  return Iterator;\n};\n"
  },
  {
    "path": "wren-ui/src/utils/language.ts",
    "content": "import { ProjectLanguage } from '@/apollo/client/graphql/__types__';\n\nexport const getLanguageText = (language: ProjectLanguage) =>\n  ({\n    [ProjectLanguage.EN]: 'English',\n    [ProjectLanguage.ES]: 'Spanish',\n    [ProjectLanguage.FR]: 'French',\n    [ProjectLanguage.ZH_TW]: 'Traditional Chinese',\n    [ProjectLanguage.ZH_CN]: 'Simplified Chinese',\n    [ProjectLanguage.DE]: 'German',\n    [ProjectLanguage.PT]: 'Portuguese',\n    [ProjectLanguage.RU]: 'Russian',\n    [ProjectLanguage.JA]: 'Japanese',\n    [ProjectLanguage.KO]: 'Korean',\n    [ProjectLanguage.IT]: 'Italian',\n    [ProjectLanguage.FA_IR]: 'Persian',\n    [ProjectLanguage.AR]: 'Arabic',\n    [ProjectLanguage.NL]: 'Dutch',\n    [ProjectLanguage.AZ_AZ]: 'Azerbaijani',\n    [ProjectLanguage.TR]: 'Turkish',\n  })[language] || language;\n"
  },
  {
    "path": "wren-ui/src/utils/modelingHelper.ts",
    "content": "import { keyBy } from 'lodash';\nimport { Diagram, DiagramModel } from '@/utils/data/type';\nimport { getFieldValue } from '@/components/selectors/lineageSelector/FieldSelect';\n\nexport const editCalculatedField = (\n  payload: { diagramData: Diagram; data: any },\n  openCalculatedFieldModal: (defaultValue: any, payload: any) => void,\n) => {\n  const { diagramData, data } = payload;\n  const sourceModel = diagramData.models.find(\n    (model) => model.modelId === data.modelId,\n  );\n\n  const getField = (model: DiagramModel, columnId: number) => {\n    return [...(model?.fields || []), ...(model?.calculatedFields || [])].find(\n      (field) => field.columnId === columnId,\n    );\n  };\n\n  // Retrieve from the source model directly if only one id in lineage\n  const isSourceModelField = data.lineage.length === 1;\n  if (isSourceModelField) {\n    const field = getField(sourceModel, data.lineage[0]);\n    openCalculatedFieldModal &&\n      openCalculatedFieldModal(\n        {\n          columnId: data.columnId,\n          name: data.displayName,\n          expression: data.aggregation,\n          lineage: [getFieldValue(field)],\n        },\n        {\n          models: diagramData.models,\n          sourceModel,\n        },\n      );\n    return;\n  }\n\n  // Otherwise, retrieve all relations and column by their id\n  const allModelsMap = keyBy(diagramData.models, 'referenceName');\n  const relationIds = [...data.lineage];\n  const lastColumnId = relationIds.pop(); // it will also remove the last column id from relationIds\n\n  let nextModel = null;\n  const relations = relationIds.reduce((result, relationId) => {\n    const relation = (nextModel || sourceModel).relationFields.find(\n      (relation) => relation.relationId === relationId,\n    );\n    nextModel = allModelsMap[relation.referenceName];\n    return [...result, relation];\n  }, []);\n\n  const lastRelation = relations[relations.length - 1];\n  const lastModel = allModelsMap[lastRelation.referenceName];\n  const field = getField(lastModel, lastColumnId);\n\n  openCalculatedFieldModal &&\n    openCalculatedFieldModal(\n      {\n        columnId: data.columnId,\n        name: data.displayName,\n        expression: data.aggregation,\n        lineage: [...relations, field].map(getFieldValue),\n      },\n      {\n        models: diagramData.models,\n        sourceModel,\n      },\n    );\n};\n"
  },
  {
    "path": "wren-ui/src/utils/nodeType.tsx",
    "content": "import { getColumnTypeIcon } from './columnType';\nimport { COLUMN_TYPE, NODE_TYPE } from './enum';\nimport { MetricIcon, ModelIcon, RelationshipIcon, ViewIcon } from './icons';\n\nexport const getNodeTypeIcon = (\n  payload: { nodeType: NODE_TYPE | string; type?: COLUMN_TYPE | string },\n  attrs?: any,\n) => {\n  const { nodeType, type } = payload;\n  switch (nodeType) {\n    case NODE_TYPE.MODEL:\n      return <ModelIcon title=\"Model\" {...attrs} />;\n    case NODE_TYPE.METRIC:\n      return <MetricIcon title=\"Metric\" {...attrs} />;\n    case NODE_TYPE.VIEW:\n      return <ViewIcon title=\"View\" {...attrs} />;\n    case NODE_TYPE.RELATION:\n      return <RelationshipIcon title=\"Relationship\" {...attrs} />;\n\n    case NODE_TYPE.FIELD:\n      return type ? getColumnTypeIcon({ type }, attrs) : null;\n\n    default:\n      return null;\n  }\n};\n"
  },
  {
    "path": "wren-ui/src/utils/svgs/BrainSVG.tsx",
    "content": "export const BrainSVG = ({\n  fillCurrentColor = true,\n  className,\n}: {\n  fillCurrentColor?: boolean;\n  className?: string;\n}) => (\n  <svg\n    className={className}\n    width=\"20\"\n    height=\"20\"\n    viewBox=\"0 0 20 20\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <path\n      d=\"M14.165 5.93877C14.4319 5.86994 14.7117 5.83333 15 5.83333C16.8409 5.83333 18.3334 7.32572 18.3334 9.16667C18.3334 11.0076 16.8409 12.5 15 12.5C14.7043 12.5 14.4174 12.4615 14.1444 12.3892M14.165 5.93877C14.1661 5.90376 14.1667 5.86861 14.1667 5.83333C14.1667 3.99238 12.6743 2.5 10.8334 2.5C9.23535 2.5 7.89997 3.62449 7.57536 5.12536M14.165 5.93877C14.1474 6.50636 13.9879 7.0382 13.7208 7.5M14.1444 12.3892C14.1591 12.2893 14.1667 12.1872 14.1667 12.0833C14.1667 11.0754 13.4509 10.2347 12.5 10.0417M14.1444 12.3892C13.9964 13.3947 13.13 14.1667 12.0834 14.1667H11.6667C9.82577 14.1667 8.33335 15.6591 8.33335 17.5M7.57536 5.12536C7.2865 5.04369 6.9817 5 6.66669 5C4.82574 5 3.33335 6.49238 3.33335 8.33333C3.33335 8.65717 3.37954 8.97025 3.46567 9.26625M7.57536 5.12536C8.41794 5.36354 9.12485 5.92471 9.5541 6.66667M3.46567 9.26625C2.42619 9.56933 1.66669 10.5293 1.66669 11.6667C1.66669 13.0474 2.78598 14.1667 4.16669 14.1667C5.2552 14.1667 6.18124 13.471 6.52443 12.5M3.46567 9.26625C3.54103 9.52525 3.64695 9.77125 3.7793 10\"\n      stroke={fillCurrentColor ? 'currentColor' : undefined}\n      strokeWidth=\"1.5\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n    />\n    <path\n      d=\"M9.86341 9.78626C9.43808 10.1961 8.71083 10.2668 8.08927 9.91734C7.46766 9.56784 7.15026 8.90976 7.27946 8.33334\"\n      stroke={fillCurrentColor ? 'currentColor' : undefined}\n      strokeWidth=\"1.5\"\n      strokeLinecap=\"round\"\n    />\n  </svg>\n);\n"
  },
  {
    "path": "wren-ui/src/utils/svgs/CopilotSVG.tsx",
    "content": "export const CopilotSVG = ({\n  fillCurrentColor = true,\n  className,\n}: {\n  fillCurrentColor?: boolean;\n  className?: string;\n}) => (\n  <svg\n    className={className}\n    width=\"14\"\n    height=\"14\"\n    viewBox=\"0 0 24 24\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <path\n      d=\"M18.6562 11.7478L13.9791 10.0247L12.2522 5.34375C12.1201 4.98542 11.8813 4.67621 11.5679 4.45781C11.2546 4.2394 10.8819 4.12231 10.5 4.12231C10.1181 4.12231 9.74535 4.2394 9.43205 4.45781C9.11875 4.67621 8.87993 4.98542 8.74781 5.34375L7.02469 10.0247L2.34375 11.7478C1.98542 11.8799 1.67621 12.1187 1.45781 12.432C1.2394 12.7454 1.12231 13.1181 1.12231 13.5C1.12231 13.8819 1.2394 14.2546 1.45781 14.568C1.67621 14.8813 1.98542 15.1201 2.34375 15.2522L7.02094 16.9753L8.74781 21.6562C8.87993 22.0146 9.11875 22.3238 9.43205 22.5422C9.74535 22.7606 10.1181 22.8777 10.5 22.8777C10.8819 22.8777 11.2546 22.7606 11.5679 22.5422C11.8813 22.3238 12.1201 22.0146 12.2522 21.6562L13.9753 16.9791L18.6562 15.2522C19.0146 15.1201 19.3238 14.8813 19.5422 14.568C19.7606 14.2546 19.8777 13.8819 19.8777 13.5C19.8777 13.1181 19.7606 12.7454 19.5422 12.432C19.3238 12.1187 19.0146 11.8799 18.6562 11.7478ZM13.0312 14.9259C12.7777 15.0192 12.5475 15.1664 12.3565 15.3574C12.1655 15.5484 12.0183 15.7787 11.925 16.0322L10.5 19.9012L9.07406 16.0312C8.98079 15.778 8.83365 15.548 8.64282 15.3572C8.45198 15.1663 8.222 15.0192 7.96875 14.9259L4.09875 13.5L7.96875 12.0741C8.222 11.9808 8.45198 11.8337 8.64282 11.6428C8.83365 11.452 8.98079 11.222 9.07406 10.9688L10.5 7.09875L11.9259 10.9688C12.0192 11.2223 12.1664 11.4525 12.3574 11.6435C12.5484 11.8345 12.7787 11.9817 13.0322 12.075L16.9012 13.5L13.0312 14.9259ZM13.125 3.75C13.125 3.45163 13.2435 3.16548 13.4545 2.9545C13.6655 2.74353 13.9516 2.625 14.25 2.625H15.375V1.5C15.375 1.20163 15.4935 0.915483 15.7045 0.704505C15.9155 0.493526 16.2016 0.375 16.5 0.375C16.7984 0.375 17.0845 0.493526 17.2955 0.704505C17.5065 0.915483 17.625 1.20163 17.625 1.5V2.625H18.75C19.0484 2.625 19.3345 2.74353 19.5455 2.9545C19.7565 3.16548 19.875 3.45163 19.875 3.75C19.875 4.04837 19.7565 4.33452 19.5455 4.5455C19.3345 4.75647 19.0484 4.875 18.75 4.875H17.625V6C17.625 6.29837 17.5065 6.58452 17.2955 6.7955C17.0845 7.00647 16.7984 7.125 16.5 7.125C16.2016 7.125 15.9155 7.00647 15.7045 6.7955C15.4935 6.58452 15.375 6.29837 15.375 6V4.875H14.25C13.9516 4.875 13.6655 4.75647 13.4545 4.5455C13.2435 4.33452 13.125 4.04837 13.125 3.75ZM23.625 8.25C23.625 8.54837 23.5065 8.83452 23.2955 9.0455C23.0845 9.25647 22.7984 9.375 22.5 9.375H22.125V9.75C22.125 10.0484 22.0065 10.3345 21.7955 10.5455C21.5845 10.7565 21.2984 10.875 21 10.875C20.7016 10.875 20.4155 10.7565 20.2045 10.5455C19.9935 10.3345 19.875 10.0484 19.875 9.75V9.375H19.5C19.2016 9.375 18.9155 9.25647 18.7045 9.0455C18.4935 8.83452 18.375 8.54837 18.375 8.25C18.375 7.95163 18.4935 7.66548 18.7045 7.4545C18.9155 7.24353 19.2016 7.125 19.5 7.125H19.875V6.75C19.875 6.45163 19.9935 6.16548 20.2045 5.9545C20.4155 5.74353 20.7016 5.625 21 5.625C21.2984 5.625 21.5845 5.74353 21.7955 5.9545C22.0065 6.16548 22.125 6.45163 22.125 6.75V7.125H22.5C22.7984 7.125 23.0845 7.24353 23.2955 7.4545C23.5065 7.66548 23.625 7.95163 23.625 8.25Z\"\n      fill={fillCurrentColor ? 'currentColor' : undefined}\n    />\n  </svg>\n);\n"
  },
  {
    "path": "wren-ui/src/utils/svgs/EditSVG.tsx",
    "content": "export const EditSVG = ({\n  fillCurrentColor = true,\n  className,\n}: {\n  fillCurrentColor?: boolean;\n  className?: string;\n}) => (\n  <svg\n    className={className}\n    width=\"14\"\n    height=\"14\"\n    viewBox=\"0 0 14 14\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M10.9929 5.04652L10.3083 5.7311L11.602 7.0247L12.2867 6.34012C12.2652 6.26694 12.2367 6.18523 12.2012 6.0998C12.1016 5.86038 11.968 5.64205 11.8296 5.5036C11.6911 5.36514 11.4727 5.23157 11.2333 5.13201C11.1479 5.09648 11.0661 5.06797 10.9929 5.04652ZM10.6592 7.96748L9.36549 6.67388L5.92291 10.1162C5.50551 10.5335 5.25873 11.2125 5.12676 11.8724C5.09852 12.0136 5.07652 12.1489 5.0594 12.2738C5.18415 12.2566 5.31921 12.2346 5.46023 12.2064C6.11984 12.0744 6.79883 11.8275 7.21669 11.4097L10.6592 7.96748ZM4.33325 13C3.66659 13 3.66659 12.9996 3.66659 12.9996L3.66659 12.9983L3.66659 12.9957L3.66664 12.9882L3.66695 12.9637C3.66728 12.9432 3.66793 12.9146 3.66917 12.8787C3.67164 12.807 3.67649 12.7058 3.68602 12.5818C3.70502 12.3349 3.74295 11.9928 3.81931 11.611C3.96692 10.8728 4.27927 9.87414 4.98014 9.17333L10.2919 3.8619C10.4156 3.73825 10.5829 3.66813 10.7578 3.66667C11.0504 3.66422 11.4208 3.76595 11.7452 3.90087C12.0828 4.04124 12.47 4.25846 12.7723 4.56075C13.0747 4.86305 13.2919 5.25027 13.4323 5.58782C13.5672 5.91229 13.669 6.28262 13.6665 6.57528C13.6651 6.75017 13.5949 6.91748 13.4713 7.04115L8.15946 12.3525C7.45837 13.0536 6.45995 13.3661 5.72188 13.5138C5.34011 13.5902 4.99815 13.6282 4.75126 13.6472C4.62736 13.6567 4.5262 13.6616 4.4545 13.6641C4.41863 13.6653 4.39004 13.6659 4.36957 13.6663L4.34504 13.6666L4.33751 13.6666L4.33497 13.6666L4.33401 13.6666C4.33401 13.6666 4.33325 13.6666 4.33325 13ZM4.33325 13V13.6666C3.96506 13.6666 3.66659 13.3678 3.66659 12.9996L4.33325 13Z\"\n      fill={fillCurrentColor ? 'currentColor' : undefined}\n    />\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M3.99992 0.333313C4.28687 0.333313 4.54163 0.516933 4.63237 0.789161L5.27697 2.72293L7.21074 3.36752C7.48297 3.45827 7.66659 3.71303 7.66659 3.99998C7.66659 4.28693 7.48297 4.54169 7.21074 4.63244L5.27697 5.27703L4.63237 7.2108C4.54163 7.48303 4.28687 7.66665 3.99992 7.66665C3.71297 7.66665 3.45821 7.48303 3.36746 7.2108L2.72287 5.27703L0.7891 4.63244C0.516872 4.54169 0.333252 4.28693 0.333252 3.99998C0.333252 3.71303 0.516872 3.45827 0.7891 3.36752L2.72287 2.72293L3.36746 0.789161C3.45821 0.516933 3.71297 0.333313 3.99992 0.333313ZM3.99992 3.10816L3.88237 3.4608C3.81602 3.65987 3.65981 3.81608 3.46074 3.88244L3.1081 3.99998L3.46074 4.11752C3.65981 4.18388 3.81602 4.34009 3.88237 4.53916L3.99992 4.89179L4.11746 4.53916C4.18382 4.34009 4.34003 4.18388 4.5391 4.11752L4.89173 3.99998L4.5391 3.88244C4.34003 3.81608 4.18382 3.65987 4.11746 3.4608L3.99992 3.10816Z\"\n      fill={fillCurrentColor ? 'currentColor' : undefined}\n    />\n  </svg>\n);\n"
  },
  {
    "path": "wren-ui/src/utils/svgs/InstructionsSVG.tsx",
    "content": "export const InstructionsSVG = ({\n  fillCurrentColor = true,\n  className,\n}: {\n  fillCurrentColor?: boolean;\n  className?: string;\n}) => (\n  <svg\n    className={className}\n    width=\"14\"\n    height=\"14\"\n    viewBox=\"0 0 14 15\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M2.63962 1.97296L3.36755 -0.210815H4.63246L5.36038 1.97296L7.54415 2.70088V3.96579L5.36038 4.69372L4.63246 6.87749H3.36755L2.63962 4.69372L0.455849 3.96579V2.70088L2.63962 1.97296ZM4 2.10819L3.79912 2.71082L3.37749 3.13246L2.77485 3.33334L3.37749 3.53421L3.79912 3.95585L4 4.55849L4.20088 3.95585L4.62252 3.53421L5.22515 3.33334L4.62252 3.13246L4.20088 2.71082L4 2.10819ZM11.3926 4.02504C11.0926 4.00053 10.7044 4.00001 10.1333 4.00001H9.33332V2.66668H10.1609C10.6975 2.66667 11.1404 2.66666 11.5012 2.69614C11.8759 2.72675 12.2204 2.79246 12.544 2.95732C13.0457 3.21299 13.4537 3.62094 13.7093 4.1227C13.8742 4.44626 13.9399 4.79073 13.9705 5.16546C14 5.52625 14 5.96915 14 6.50579V8.82719C14 9.36383 14 9.80673 13.9705 10.1675C13.9399 10.5423 13.8742 10.8867 13.7093 11.2103C13.4537 11.712 13.0457 12.12 12.544 12.3757C12.2204 12.5405 11.8759 12.6062 11.5012 12.6368C11.1404 12.6663 10.6975 12.6663 10.1609 12.6663H10.0209L8.5062 14.4338L7.49378 14.4338L5.97905 12.6663H5.83911C5.30247 12.6663 4.85957 12.6663 4.49877 12.6368C4.12404 12.6062 3.77957 12.5405 3.45602 12.3757C2.95425 12.12 2.5463 11.712 2.29064 11.2103C2.12578 10.8867 2.06007 10.5422 2.02945 10.1675C1.99997 9.80672 1.99998 9.36382 1.99999 8.82717L1.99999 8.33315H3.33332V8.79963C3.33332 9.37069 3.33384 9.75888 3.35836 10.0589C3.38224 10.3512 3.42552 10.5007 3.47865 10.605C3.60648 10.8558 3.81045 11.0598 4.06134 11.1876C4.1656 11.2408 4.31507 11.2841 4.60735 11.3079C4.90741 11.3324 5.2956 11.333 5.86666 11.333H6.59237L7.99999 12.9755L9.40763 11.333H10.1333C10.7044 11.333 11.0926 11.3324 11.3926 11.3079C11.6849 11.2841 11.8344 11.2408 11.9386 11.1876C12.1895 11.0598 12.3935 10.8558 12.5213 10.605C12.5745 10.5007 12.6177 10.3512 12.6416 10.0589C12.6661 9.75888 12.6667 9.37069 12.6667 8.79964V6.53334C12.6667 5.96229 12.6661 5.57409 12.6416 5.27403C12.6177 4.98176 12.5745 4.83229 12.5213 4.72802C12.3935 4.47714 12.1895 4.27316 11.9386 4.14533C11.8344 4.09221 11.6849 4.04892 11.3926 4.02504Z\"\n      fill={fillCurrentColor ? 'currentColor' : undefined}\n    />\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M7.18377 7.18378L7.62053 5.87351H8.37947L8.81623 7.18378L10.1265 7.62053V8.37948L8.81623 8.81623L8.37947 10.1265H7.62053L7.18377 8.81623L5.87351 8.37948V7.62053L7.18377 7.18378Z\"\n      fill={fillCurrentColor ? 'currentColor' : undefined}\n    />\n  </svg>\n);\n"
  },
  {
    "path": "wren-ui/src/utils/svgs/RobotSVG.tsx",
    "content": "export const RobotSVG = ({\n  fillCurrentColor = true,\n  className,\n}: {\n  fillCurrentColor?: boolean;\n  className?: string;\n}) => (\n  <svg\n    className={className}\n    width=\"14\"\n    height=\"14\"\n    viewBox=\"0 0 17 20\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M5.21025 5.02381H11.0755C11.8038 5.0238 12.4049 5.02379 12.8945 5.06379C13.4031 5.10535 13.8706 5.19452 14.3097 5.41826C14.9906 5.76523 15.5443 6.31888 15.8913 6.99984C16.115 7.43896 16.2042 7.90645 16.2457 8.41501C16.2857 8.90466 16.2857 9.50574 16.2857 10.234V14.2898C16.2857 15.0181 16.2857 15.6191 16.2457 16.1088C16.2042 16.6174 16.115 17.0849 15.8913 17.524C15.5443 18.2049 14.9906 18.7586 14.3097 19.1055C13.8706 19.3293 13.4031 19.4185 12.8945 19.46C12.4049 19.5 11.8038 19.5 11.0754 19.5H5.21027C4.48196 19.5 3.88086 19.5 3.39121 19.46C2.88264 19.4185 2.41515 19.3293 1.97603 19.1055C1.29507 18.7586 0.741424 18.2049 0.394453 17.524C0.170714 17.0849 0.0815369 16.6174 0.0399855 16.1088C-2.06409e-05 15.6191 -1.11504e-05 15.0181 3.90216e-07 14.2897V10.2341C-1.11504e-05 9.50576 -2.06409e-05 8.90467 0.0399855 8.41502C0.0815369 7.90645 0.170714 7.43896 0.394453 6.99984C0.741424 6.31888 1.29507 5.76523 1.97603 5.41826C2.41515 5.19452 2.88264 5.10535 3.39121 5.06379C3.88086 5.02379 4.48195 5.0238 5.21025 5.02381ZM3.53856 6.86731C3.1419 6.89972 2.93905 6.95846 2.79754 7.03056C2.45706 7.20404 2.18024 7.48087 2.00675 7.82135C1.93465 7.96285 1.87591 8.16571 1.8435 8.56237C1.81023 8.96959 1.80952 9.49643 1.80952 10.2714V14.2524C1.80952 15.0274 1.81023 15.5542 1.8435 15.9614C1.87591 16.3581 1.93465 16.561 2.00675 16.7025C2.18024 17.0429 2.45706 17.3198 2.79754 17.4932C2.93905 17.5653 3.1419 17.6241 3.53856 17.6565C3.94578 17.6898 4.47262 17.6905 5.24762 17.6905H11.0381C11.8131 17.6905 12.3399 17.6898 12.7472 17.6565C13.1438 17.6241 13.3467 17.5653 13.4882 17.4932C13.8287 17.3198 14.1055 17.0429 14.279 16.7025C14.3511 16.561 14.4098 16.3581 14.4422 15.9614C14.4755 15.5542 14.4762 15.0274 14.4762 14.2524V10.2714C14.4762 9.49643 14.4755 8.96959 14.4422 8.56237C14.4098 8.16571 14.3511 7.96285 14.279 7.82135C14.1055 7.48087 13.8287 7.20404 13.4882 7.03056C13.3467 6.95846 13.1438 6.89972 12.7472 6.86731C12.3399 6.83404 11.8131 6.83333 11.0381 6.83333H5.24762C4.47262 6.83333 3.94578 6.83404 3.53856 6.86731Z\"\n      fill={fillCurrentColor ? 'currentColor' : undefined}\n    />\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M6.33337 2.69857L6.33333 3.21434C6.3333 3.71403 5.9282 4.11908 5.42852 4.11905C4.92883 4.11902 4.52378 3.71392 4.52381 3.21423L4.52387 2.30947C4.52388 2.07611 4.61406 1.85178 4.77557 1.68334C4.99499 1.4545 5.32229 1.12171 5.89443 0.873475C6.44775 0.6334 7.16129 0.5 8.1429 0.5C9.12451 0.5 9.83805 0.63341 10.3914 0.873493C10.9635 1.12173 11.2908 1.45452 11.5102 1.68332C11.6717 1.85177 11.7619 2.07613 11.7619 2.30952V3.21429C11.7619 3.71397 11.3568 4.11905 10.8571 4.11905C10.3575 4.11905 9.95238 3.71397 9.95238 3.21429V2.69856C9.8723 2.63607 9.78449 2.58269 9.67111 2.53349C9.4179 2.42363 8.97077 2.30952 8.1429 2.30952C7.31502 2.30952 6.86788 2.42362 6.61467 2.53348C6.50127 2.58269 6.41345 2.63607 6.33337 2.69857Z\"\n      fill={fillCurrentColor ? 'currentColor' : undefined}\n    />\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M4.70476 13.5286C5.00457 13.1288 5.57168 13.0478 5.97143 13.3476C6.70123 13.895 7.4087 14.0718 8.14237 14.0714C8.87603 14.071 9.58508 13.8945 10.3143 13.3476C10.714 13.0478 11.2811 13.1288 11.581 13.5286C11.8808 13.9283 11.7997 14.4954 11.4 14.7952C10.3197 15.6055 9.21764 15.8804 8.14335 15.881C7.06593 15.8815 5.96543 15.605 4.88572 14.7952C4.48597 14.4954 4.40495 13.9283 4.70476 13.5286Z\"\n      fill={fillCurrentColor ? 'currentColor' : undefined}\n    />\n    <path\n      d=\"M3.61905 10.9048C3.61905 10.1552 4.22666 9.54762 4.97619 9.54762C5.72572 9.54762 6.33333 10.1552 6.33333 10.9048C6.33333 11.6543 5.72572 12.2619 4.97619 12.2619C4.22666 12.2619 3.61905 11.6543 3.61905 10.9048Z\"\n      fill={fillCurrentColor ? 'currentColor' : undefined}\n    />\n    <path\n      d=\"M9.95238 10.9048C9.95238 10.1552 10.56 9.54762 11.3095 9.54762C12.0591 9.54762 12.6667 10.1552 12.6667 10.9048C12.6667 11.6543 12.0591 12.2619 11.3095 12.2619C10.56 12.2619 9.95238 11.6543 9.95238 10.9048Z\"\n      fill={fillCurrentColor ? 'currentColor' : undefined}\n    />\n  </svg>\n);\n"
  },
  {
    "path": "wren-ui/src/utils/svgs/index.ts",
    "content": "export * from './CopilotSVG';\nexport * from './RobotSVG';\nexport * from './InstructionsSVG';\nexport * from './EditSVG';\nexport * from './BrainSVG';\n"
  },
  {
    "path": "wren-ui/src/utils/table.tsx",
    "content": "import { useEffect } from 'react';\nimport moment from 'moment';\nimport { Input, Button, Space, DatePicker, Divider } from 'antd';\nimport SearchOutlined from '@ant-design/icons/SearchOutlined';\nimport CalendarOutlined from '@ant-design/icons/CalendarOutlined';\n\nexport const getColumnSearchProps = (props: {\n  dataIndex: string;\n  placeholder?: string;\n  onFilter?: (value: string, record: any) => boolean;\n  filteredValue?: any[];\n}) => ({\n  filterDropdown: (filters: any) => {\n    return <SearchFilter {...filters} {...props} />;\n  },\n  filterIcon: (filtered: boolean) => (\n    <SearchOutlined\n      style={{ color: filtered ? 'var(--geekblue-6)' : undefined }}\n    />\n  ),\n  filteredValue: props.filteredValue,\n});\n\nexport const getColumnDateFilterProps = (props: {\n  dataIndex: string;\n  onFilter?: (value: any, record: any) => boolean;\n  filteredValue?: [string, string] | null;\n}) => ({\n  filterDropdown: (filters) => {\n    return <DateFilter {...filters} {...props} />;\n  },\n  filterIcon: (filtered: boolean) => (\n    <CalendarOutlined\n      style={{ color: filtered ? 'var(--geekblue-6)' : undefined }}\n    />\n  ),\n  filteredValue: props.filteredValue,\n});\n\nconst SearchFilter = ({\n  setSelectedKeys,\n  selectedKeys,\n  confirm,\n  clearFilters,\n  visible,\n  dataIndex,\n  placeholder,\n  filteredValue,\n}) => {\n  useEffect(() => {\n    if (!visible && selectedKeys.length === 0) confirm();\n  }, [visible]);\n  return (\n    <>\n      <Space className=\"p-2\">\n        <Input\n          size=\"small\"\n          placeholder={`Search ${placeholder || dataIndex}`}\n          value={selectedKeys[0]}\n          onChange={(e) =>\n            setSelectedKeys(e.target.value ? [e.target.value] : [])\n          }\n          onPressEnter={() => confirm()}\n          style={{ width: 188 }}\n        />\n      </Space>\n      <Divider style={{ margin: 0 }} />\n      <Space className=\"d-flex justify-end p-2\">\n        <Button\n          type=\"link\"\n          onClick={() => clearFilters()}\n          size=\"small\"\n          disabled={!filteredValue}\n        >\n          Reset\n        </Button>\n        <Button type=\"primary\" onClick={() => confirm()} size=\"small\">\n          Search\n        </Button>\n      </Space>\n    </>\n  );\n};\n\nconst DateFilter = ({\n  filteredValue,\n  setSelectedKeys,\n  selectedKeys,\n  confirm,\n  clearFilters,\n  visible,\n}) => {\n  useEffect(() => {\n    if (!visible && selectedKeys.length === 0) confirm();\n  }, [visible]);\n  return (\n    <>\n      <Space className=\"p-2\">\n        <DatePicker.RangePicker\n          placeholder={['Start Date', 'End Date']}\n          value={[\n            selectedKeys[0] ? moment(selectedKeys[0]) : null,\n            selectedKeys[1] ? moment(selectedKeys[1]) : null,\n          ]}\n          onChange={(dates) => {\n            const values = dates\n              ? [dates[0]?.format('YYYY-MM-DD'), dates[1]?.format('YYYY-MM-DD')]\n              : [];\n            setSelectedKeys(values);\n          }}\n          style={{ width: 250 }}\n        />\n      </Space>\n      <Divider style={{ margin: 0 }} />\n      <Space className=\"d-flex justify-end p-2\">\n        <Button\n          type=\"link\"\n          onClick={() => clearFilters()}\n          size=\"small\"\n          disabled={!filteredValue}\n        >\n          Reset\n        </Button>\n        <Button type=\"primary\" onClick={() => confirm()} size=\"small\">\n          OK\n        </Button>\n      </Space>\n    </>\n  );\n};\n"
  },
  {
    "path": "wren-ui/src/utils/telemetry.ts",
    "content": "import posthog from 'posthog-js';\nimport { NextRouter } from 'next/router';\nimport env, { UserConfig } from '@/utils/env';\n\nconst setupPostHog = (userConfig) => {\n  // Check that PostHog is client-side (used to handle Next.js SSR)\n  if (typeof window !== 'undefined') {\n    posthog.init(userConfig.telemetryKey, {\n      api_host: userConfig.telemetryHost,\n      autocapture: {\n        dom_event_allowlist: ['click'],\n        css_selector_allowlist: ['[data-ph-capture=\"true\"]'],\n      },\n      session_recording: {\n        maskAllInputs: false,\n        maskInputOptions: {\n          password: true,\n        },\n      },\n      disable_session_recording: env.isDevelopment,\n      debug: false,\n      loaded: () => {\n        console.log('PostHog initialized.');\n      },\n    });\n    // set up distinct id to posthog\n    if (userConfig.userUUID) posthog.identify(userConfig.userUUID);\n  }\n};\n\nexport const trackUserTelemetry = (router: NextRouter, config: UserConfig) => {\n  const handlePostHogPageView = () => {\n    posthog.capture('$pageview');\n  };\n\n  // Track PostHog\n  if (config.isTelemetryEnabled) {\n    setupPostHog(config);\n    router.events.on('routeChangeComplete', handlePostHogPageView);\n  }\n\n  return () => {\n    router.events.off('routeChangeComplete', handlePostHogPageView);\n  };\n};\n"
  },
  {
    "path": "wren-ui/src/utils/time.ts",
    "content": "import dayJs from 'dayjs';\nimport utc from 'dayjs/plugin/utc';\nimport relativeTime from 'dayjs/plugin/relativeTime';\n\ndayJs.extend(utc);\ndayJs.extend(relativeTime);\n\nexport const browserTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n\nexport const nextTick = (ms = 1) =>\n  new Promise((resolve) => setTimeout(resolve, ms));\n\nexport const getRelativeTime = (time: string) => {\n  return dayJs(time).fromNow();\n};\n\nexport const getAbsoluteTime = (time: string) => {\n  return dayJs(time).format('YYYY-MM-DD HH:mm:ss');\n};\n\nexport const getCompactTime = (time: string) => {\n  return dayJs(time).format('YYYY-MM-DD HH:mm');\n};\n\nexport const getFullNameDate = (time: string) => {\n  return dayJs(time).format('MMMM DD, YYYY');\n};\n\nexport const getShortDate = (time: string) => {\n  return dayJs(time).format('MMM DD');\n};\n"
  },
  {
    "path": "wren-ui/src/utils/validator/calculatedFieldValidator.ts",
    "content": "import { COLUMN_TYPE, NODE_TYPE } from '@/utils/enum';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { mathFunctions, stringFunctions } from '@/utils/expressionType';\nimport { ExpressionName } from '@/apollo/client/graphql/__types__';\n\nexport const createLineageSelectorNameValidator =\n  (validateCalculatedField: any) => async (_rule: any, value: string) => {\n    if (!value) {\n      return Promise.reject(ERROR_TEXTS.CALCULATED_FIELD.NAME.REQUIRED);\n    }\n\n    const result = await validateCalculatedField(value);\n\n    const { valid, message } = result?.data?.validateCalculatedField;\n\n    if (!valid) {\n      return Promise.reject(message);\n    }\n\n    return Promise.resolve();\n  };\n\nconst makeCheckAllowType =\n  (functions: ExpressionName[], allowTypes: COLUMN_TYPE[]) =>\n  (expression: ExpressionName, value) => {\n    const isField = [NODE_TYPE.FIELD, NODE_TYPE.CALCULATED_FIELD].includes(\n      value.nodeType,\n    );\n\n    // ignore if not a column or not a string function\n    if (!isField || !functions.includes(expression)) {\n      return true;\n    }\n\n    return allowTypes.includes(value.type.toLocaleUpperCase());\n  };\n\nexport const checkStringFunctionAllowType = makeCheckAllowType(\n  stringFunctions,\n  [\n    COLUMN_TYPE.VARCHAR,\n    COLUMN_TYPE.CHAR,\n    COLUMN_TYPE.BPCHAR,\n    COLUMN_TYPE.TEXT,\n    COLUMN_TYPE.STRING,\n    COLUMN_TYPE.NAME,\n  ],\n);\n\nexport const checkNumberFunctionAllowType = makeCheckAllowType(mathFunctions, [\n  COLUMN_TYPE.TINYINT,\n  COLUMN_TYPE.INT2,\n  COLUMN_TYPE.SMALLINT,\n  COLUMN_TYPE.INT4,\n  COLUMN_TYPE.INTEGER,\n  COLUMN_TYPE.INT8,\n  COLUMN_TYPE.BIGINT,\n  COLUMN_TYPE.INT64,\n  COLUMN_TYPE.NUMERIC,\n  COLUMN_TYPE.DECIMAL,\n  COLUMN_TYPE.FLOAT4,\n  COLUMN_TYPE.REAL,\n  COLUMN_TYPE.FLOAT8,\n  COLUMN_TYPE.DOUBLE,\n]);\n\nexport const createLineageSelectorValidator =\n  (expression: ExpressionName) =>\n  (_rule: any, value: Record<string, any>[]) => {\n    if (!value)\n      return Promise.reject(\n        new Error(ERROR_TEXTS.CALCULATED_FIELD.LINEAGE.REQUIRED),\n      );\n\n    const lastValue = value[value.length - 1];\n    if (\n      ![NODE_TYPE.FIELD, NODE_TYPE.CALCULATED_FIELD].includes(\n        lastValue.nodeType,\n      )\n    ) {\n      return Promise.reject(\n        new Error(ERROR_TEXTS.CALCULATED_FIELD.LINEAGE.REQUIRED),\n      );\n    }\n\n    if (!checkStringFunctionAllowType(expression, lastValue)) {\n      return Promise.reject(\n        new Error(ERROR_TEXTS.CALCULATED_FIELD.LINEAGE.INVALID_STRING_TYPE),\n      );\n    }\n\n    if (!checkNumberFunctionAllowType(expression, lastValue)) {\n      return Promise.reject(\n        new Error(ERROR_TEXTS.CALCULATED_FIELD.LINEAGE.INVALID_NUMBER_TYPE),\n      );\n    }\n\n    return Promise.resolve();\n  };\n"
  },
  {
    "path": "wren-ui/src/utils/validator/cronValidator.ts",
    "content": "import { CronExpressionParser } from 'cron-parser';\nimport { ERROR_TEXTS } from '@/utils/error';\n\nexport const isValidCronLength = (cron: string) => {\n  return cron?.trim().split(' ').length === 5;\n};\n\nexport const cronValidator = (_, value: string) => {\n  if (!value) return Promise.reject(ERROR_TEXTS.CRON.REQUIRED);\n  if (!isValidCronLength(value)) {\n    return Promise.reject(ERROR_TEXTS.CRON.INVALID);\n  }\n  try {\n    CronExpressionParser.parse(value, { tz: 'UTC' });\n    return Promise.resolve();\n  } catch (error) {\n    return Promise.reject(error.message);\n  }\n};\n"
  },
  {
    "path": "wren-ui/src/utils/validator/hostValidator.ts",
    "content": "import { ERROR_TEXTS } from '@/utils/error';\n\nexport const hostValidator = (_, value) => {\n  if (!value) {\n    return Promise.reject(ERROR_TEXTS.CONNECTION.HOST.REQUIRED);\n  }\n\n  if (['localhost', '127.0.0.1'].includes(value)) {\n    return Promise.reject(ERROR_TEXTS.CONNECTION.HOST.INVALID);\n  }\n\n  return Promise.resolve();\n};\n"
  },
  {
    "path": "wren-ui/src/utils/validator/index.ts",
    "content": "export * from './calculatedFieldValidator';\nexport * from './viewValidator';\nexport * from './relationshipValidator';\nexport * from './hostValidator';\nexport * from './sqlPairValidator';\nexport * from './cronValidator';\n"
  },
  {
    "path": "wren-ui/src/utils/validator/relationshipValidator.ts",
    "content": "import { FormInstance } from 'antd';\nimport { ERROR_TEXTS } from '@/utils/error';\nimport { RelationsDataType } from '@/components/table/ModelRelationSelectionTable';\nimport { SelectedRecommendRelations } from '@/components/pages/setup/DefineRelations';\nimport { convertFormValuesToIdentifier } from '@/hooks/useCombineFieldOptions';\nimport { FormFieldKey } from '@/components/modals/RelationModal';\n\n/**\n * Check if the relationship already exists\n *\n * Consider: Assume we have an existing relationship: Customers.orderId -> Orders.orderId, One-to-Many\n * There are two cases to check:\n * 1. Same as from and to of existing relationship\n *    (E.g., add new relationship: Customers.orderId -> Orders.orderId)\n * 2. Reverse of from and to of existing relationship\n *    (E.g., add new relationship: Orders.orderId -> Customers.orderId)\n *\n * @param existingRelationships\n * @param formValues\n * @returns boolean\n */\nconst isExistRelationship = (\n  relationships: SelectedRecommendRelations,\n  formValues: RelationsDataType,\n) => {\n  const relationshipsByFromFieldModel =\n    relationships[formValues.fromField.modelName];\n  const isDuplicate = Boolean(\n    relationshipsByFromFieldModel.find(\n      (relationship) =>\n        relationship.fromField.modelId === formValues.fromField.modelId &&\n        relationship.fromField.fieldId === formValues.fromField.fieldId &&\n        relationship.toField.modelId === formValues.toField.modelId &&\n        relationship.toField.fieldId === formValues.toField.fieldId,\n    ),\n  );\n\n  if (isDuplicate) return true;\n\n  const relationshipsbyToFieldModel =\n    relationships[formValues.toField.modelName];\n  const isReverseDuplicate = Boolean(\n    relationshipsbyToFieldModel.find(\n      (relationship) =>\n        relationship.fromField.modelId === formValues.toField.modelId &&\n        relationship.fromField.fieldId === formValues.toField.fieldId &&\n        relationship.toField.modelId === formValues.fromField.modelId &&\n        relationship.toField.fieldId === formValues.fromField.fieldId,\n    ),\n  );\n\n  return isReverseDuplicate;\n};\n\nexport const createRelationshipFromFieldValidator =\n  (\n    skip = false,\n    relationships: SelectedRecommendRelations,\n    getFieldValue: FormInstance['getFieldValue'],\n  ) =>\n  async (_, value: any) => {\n    if (!value || !value.field) {\n      return Promise.reject(ERROR_TEXTS.ADD_RELATION.FROM_FIELD.REQUIRED);\n    }\n\n    if (!skip) {\n      const toField = getFieldValue(FormFieldKey.TO_FIELD);\n      if (toField && toField.model && toField.field) {\n        if (\n          isExistRelationship(\n            relationships,\n            convertFormValuesToIdentifier({\n              fromField: value,\n              toField,\n            }),\n          )\n        ) {\n          return Promise.reject(ERROR_TEXTS.ADD_RELATION.RELATIONSHIP.EXIST);\n        }\n      }\n    }\n\n    return Promise.resolve();\n  };\n\nexport const createRelationshipToFieldValidator =\n  (\n    skip = false,\n    relationships: SelectedRecommendRelations,\n    getFieldValue: FormInstance['getFieldValue'],\n  ) =>\n  async (_, value: any) => {\n    if (!value || !value.field) {\n      return Promise.reject(ERROR_TEXTS.ADD_RELATION.TO_FIELD.REQUIRED);\n    }\n\n    if (!skip) {\n      const fromField = getFieldValue(FormFieldKey.FROM_FIELD);\n      if (fromField && fromField.model && fromField.field) {\n        if (\n          isExistRelationship(\n            relationships,\n            convertFormValuesToIdentifier({\n              fromField,\n              toField: value,\n            }),\n          )\n        ) {\n          return Promise.reject(ERROR_TEXTS.ADD_RELATION.RELATIONSHIP.EXIST);\n        }\n      }\n    }\n\n    return Promise.resolve();\n  };\n"
  },
  {
    "path": "wren-ui/src/utils/validator/sqlPairValidator.ts",
    "content": "export const createSQLPairQuestionValidator =\n  (errorObj: any) => async (_rule: any, value: string) => {\n    if (!value) {\n      return Promise.reject(errorObj.REQUIRED);\n    }\n\n    if (value.trim() === '') {\n      return Promise.reject(errorObj.REQUIRED);\n    }\n\n    if (value.length > 300) {\n      return Promise.reject(errorObj.MAX_LENGTH);\n    }\n\n    return Promise.resolve();\n  };\n"
  },
  {
    "path": "wren-ui/src/utils/validator/viewValidator.ts",
    "content": "import { ERROR_TEXTS } from '@/utils/error';\n\nexport const createViewNameValidator =\n  (validateViewMutation: any) => async (_rule: any, value: string) => {\n    if (!value) {\n      return Promise.reject(ERROR_TEXTS.SAVE_AS_VIEW.NAME.REQUIRED);\n    }\n\n    const validateViewResult = await validateViewMutation({\n      variables: { data: { name: value } },\n    });\n\n    const { valid, message } = validateViewResult?.data?.validateView;\n\n    if (!valid) {\n      return Promise.reject(message);\n    }\n\n    return Promise.resolve();\n  };\n"
  },
  {
    "path": "wren-ui/src/utils/vegaSpecUtils.test.ts",
    "content": "import { enhanceVegaSpec } from './vegaSpecUtils';\n\ndescribe('vegaSpecUtils', () => {\n  describe('enhanceVegaSpec', () => {\n    it('should enhance a bar chart with proper styling and interactivity', () => {\n      // Input Vega spec\n      const inputSpec = {\n        title: 'Total Payments by Customer State',\n        mark: {\n          type: 'bar',\n        },\n        encoding: {\n          x: {\n            field: 'customer_state',\n            type: 'nominal',\n            title: 'Customer State',\n          },\n          y: {\n            field: 'total_payment_value',\n            type: 'quantitative',\n            title: 'Total Payment Value',\n          },\n        },\n        $schema: 'https://vega.github.io/schema/vega-lite/v5.json',\n        data: {\n          values: [],\n        },\n      };\n\n      // Sample data\n      const dataValues = [\n        {\n          customer_state: 'RR',\n          total_payment_value: 10064.62,\n        },\n        {\n          customer_state: 'PI',\n          total_payment_value: 108523.97000000003,\n        },\n        {\n          customer_state: 'PE',\n          total_payment_value: 324850.4399999999,\n        },\n        {\n          customer_state: 'PB',\n          total_payment_value: 141545.7199999999,\n        },\n        {\n          customer_state: 'RO',\n          total_payment_value: 60866.2,\n        },\n        {\n          customer_state: 'SE',\n          total_payment_value: 75246.25,\n        },\n        {\n          customer_state: 'TO',\n          total_payment_value: 61485.32999999993,\n        },\n        {\n          customer_state: 'AP',\n          total_payment_value: 16262.8,\n        },\n        {\n          customer_state: 'GO',\n          total_payment_value: 350092.3100000009,\n        },\n        {\n          customer_state: 'ES',\n          total_payment_value: 325967.55000000045,\n        },\n        {\n          customer_state: 'AM',\n          total_payment_value: 27966.93,\n        },\n        {\n          customer_state: 'SC',\n          total_payment_value: 623086.43,\n        },\n        {\n          customer_state: 'PA',\n          total_payment_value: 218295.85,\n        },\n        {\n          customer_state: 'MT',\n          total_payment_value: 187029.28999999986,\n        },\n        {\n          customer_state: 'AL',\n          total_payment_value: 96962.06000000003,\n        },\n        {\n          customer_state: 'SP',\n          total_payment_value: 5998226.959999885,\n        },\n        {\n          customer_state: 'MG',\n          total_payment_value: 1872257.2600000093,\n        },\n        {\n          customer_state: 'DF',\n          total_payment_value: 355141.0799999998,\n        },\n        {\n          customer_state: 'MA',\n          total_payment_value: 152523.02000000002,\n        },\n        {\n          customer_state: 'MS',\n          total_payment_value: 137534.84000000003,\n        },\n        {\n          customer_state: 'BA',\n          total_payment_value: 616645.8200000012,\n        },\n        {\n          customer_state: 'RJ',\n          total_payment_value: 2144379.68999999,\n        },\n        {\n          customer_state: 'PR',\n          total_payment_value: 811156.379999998,\n        },\n        {\n          customer_state: 'RN',\n          total_payment_value: 102718.13,\n        },\n        {\n          customer_state: 'AC',\n          total_payment_value: 19680.62,\n        },\n        {\n          customer_state: 'RS',\n          total_payment_value: 890898.5399999967,\n        },\n        {\n          customer_state: 'CE',\n          total_payment_value: 279464.0300000001,\n        },\n      ];\n\n      // Process spec with our utility\n      const enhancedSpec: any = enhanceVegaSpec(inputSpec, dataValues);\n      console.log(JSON.stringify(enhancedSpec, null, 2));\n\n      // Define expected values for important properties\n      expect(enhancedSpec).toEqual(\n        expect.objectContaining({\n          $schema: 'https://vega.github.io/schema/vega-lite/v5.json',\n          title: 'Total Payments by Customer State',\n          width: 'container',\n          height: 'container',\n          autosize: expect.objectContaining({\n            type: 'fit',\n            contains: 'padding',\n          }),\n          mark: expect.objectContaining({\n            type: 'bar',\n          }),\n        }),\n      );\n\n      // Check for config\n      expect(enhancedSpec.config).toEqual(\n        expect.objectContaining({\n          mark: { tooltip: true },\n          font: 'Roboto, Arial, Noto Sans, sans-serif',\n          bar: { color: '#1570EF' },\n          axisX: { labelAngle: -45 },\n        }),\n      );\n\n      // Check for data values\n      expect(enhancedSpec.data).toEqual({\n        values: dataValues,\n      });\n\n      // Check for encodings\n      expect(enhancedSpec.encoding).toEqual(\n        expect.objectContaining({\n          x: {\n            field: 'customer_state',\n            type: 'nominal',\n            title: 'Customer State',\n          },\n          y: {\n            field: 'total_payment_value',\n            type: 'quantitative',\n            title: 'Total Payment Value',\n          },\n          color: expect.objectContaining({\n            field: 'customer_state',\n            type: 'nominal',\n            title: 'Customer State',\n            scale: expect.objectContaining({\n              range: expect.arrayContaining(['#7763CF', '#1570EF']),\n            }),\n          }),\n          opacity: {\n            condition: {\n              param: 'hover',\n              value: 1,\n            },\n            value: 0.3,\n          },\n        }),\n      );\n\n      // Check for interaction params\n      expect(enhancedSpec.params).toEqual([\n        {\n          name: 'hover',\n          select: {\n            type: 'point',\n            on: 'mouseover',\n            clear: 'mouseout',\n            fields: ['customer_state'],\n          },\n        },\n      ]);\n    });\n\n    it('should handle line charts appropriately', () => {\n      const lineSpec = {\n        title: 'Value Over Time',\n        mark: 'line',\n        encoding: {\n          x: {\n            field: 'month',\n            type: 'temporal',\n            title: 'Month',\n          },\n          y: {\n            field: 'value',\n            type: 'quantitative',\n            title: 'Value',\n          },\n        },\n      };\n\n      const data = [\n        { month: '2023-01', value: 10 },\n        { month: '2023-02', value: 20 },\n        { month: '2023-03', value: 15 },\n      ];\n\n      const enhanced: any = enhanceVegaSpec(lineSpec, data);\n\n      // Check that line chart gets point property set to true\n      expect(enhanced.mark).toEqual(\n        expect.objectContaining({\n          type: 'line',\n          point: true,\n        }),\n      );\n    });\n\n    it('should handle pie/arc charts appropriately', () => {\n      const pieSpec = {\n        title: 'Distribution by Category',\n        mark: 'arc',\n        encoding: {\n          theta: {\n            field: 'value',\n            type: 'quantitative',\n          },\n          color: {\n            field: 'category',\n            type: 'nominal',\n          },\n        },\n      };\n\n      const data = [\n        { category: 'A', value: 30 },\n        { category: 'B', value: 45 },\n        { category: 'C', value: 25 },\n      ];\n\n      const enhanced: any = enhanceVegaSpec(pieSpec, data);\n\n      // Check that arc chart gets innerRadius for donut style\n      expect(enhanced.mark).toEqual(\n        expect.objectContaining({\n          type: 'arc',\n          innerRadius: 60,\n        }),\n      );\n    });\n\n    it('should handle stacked bar charts appropriately', () => {\n      const stackedBarSpec = {\n        title: 'Sales by Region and Product',\n        mark: 'bar',\n        encoding: {\n          x: {\n            field: 'region',\n            type: 'nominal',\n            title: 'Region',\n          },\n          y: {\n            field: 'sales',\n            type: 'quantitative',\n            title: 'Sales',\n            stack: true,\n          },\n          color: {\n            field: 'product',\n            type: 'nominal',\n          },\n        },\n      };\n\n      const data = [\n        { region: 'North', product: 'A', sales: 100 },\n        { region: 'North', product: 'B', sales: 150 },\n        { region: 'South', product: 'A', sales: 120 },\n        { region: 'South', product: 'B', sales: 180 },\n        { region: 'East', product: 'A', sales: 90 },\n        { region: 'East', product: 'B', sales: 110 },\n        { region: 'West', product: 'A', sales: 140 },\n        { region: 'West', product: 'B', sales: 160 },\n      ];\n\n      const enhanced: any = enhanceVegaSpec(stackedBarSpec, data);\n\n      // Check that bar chart gets proper stacking\n      expect(enhanced.encoding.y.stack).toBe('zero');\n    });\n  });\n});\n"
  },
  {
    "path": "wren-ui/src/utils/vegaSpecUtils.ts",
    "content": "import { TopLevelSpec, Config } from 'vega-lite';\n\n// Enum for mark types matching the frontend implementation\nexport enum MarkType {\n  ARC = 'arc',\n  AREA = 'area',\n  BAR = 'bar',\n  BOXPLOT = 'boxplot',\n  CIRCLE = 'circle',\n  ERRORBAND = 'errorband',\n  ERRORBAR = 'errorbar',\n  IMAGE = 'image',\n  LINE = 'line',\n  POINT = 'point',\n  RECT = 'rect',\n  RULE = 'rule',\n  SQUARE = 'square',\n  TEXT = 'text',\n  TICK = 'tick',\n  TRAIL = 'trail',\n}\n\n// Constants from handler.ts\nconst COLOR = {\n  GRAY_10: '#262626',\n  GRAY_9: '#434343',\n  GRAY_8: '#65676c',\n  GRAY_5: '#d9d9d9',\n};\n\n// Default color scheme\nconst colorScheme = [\n  '#7763CF',\n  '#444CE7',\n  '#1570EF',\n  '#0086C9',\n  '#3E4784',\n  '#E31B54',\n  '#EC4A0A',\n  '#EF8D0C',\n  '#EBC405',\n  '#5381AD',\n];\n\nconst DEFAULT_COLOR = colorScheme[2];\n\n// Configuration object identical to handler.ts\nconst config: Config = {\n  mark: { tooltip: true },\n  font: 'Roboto, Arial, Noto Sans, sans-serif',\n  padding: {\n    top: 30,\n    bottom: 20,\n    left: 0,\n    right: 0,\n  },\n  title: {\n    color: COLOR.GRAY_10,\n    fontSize: 14,\n  },\n  axis: {\n    labelPadding: 0,\n    labelOffset: 0,\n    labelFontSize: 10,\n    gridColor: COLOR.GRAY_5,\n    titleColor: COLOR.GRAY_9,\n    labelColor: COLOR.GRAY_8,\n    labelFont: ' Roboto, Arial, Noto Sans, sans-serif',\n  },\n  axisX: { labelAngle: -45 },\n  line: {\n    color: DEFAULT_COLOR,\n  },\n  bar: {\n    color: DEFAULT_COLOR,\n  },\n  legend: {\n    symbolLimit: 15,\n    columns: 1,\n    labelFontSize: 10,\n    labelColor: COLOR.GRAY_8,\n    titleColor: COLOR.GRAY_9,\n    titleFontSize: 14,\n  },\n  range: {\n    category: colorScheme,\n    ordinal: colorScheme,\n    diverging: colorScheme,\n    symbol: colorScheme,\n    heatmap: colorScheme,\n    ramp: colorScheme,\n  },\n  point: { size: 60, color: DEFAULT_COLOR },\n};\n\n/**\n * VegaSpecHandler provides methods to enhance and standardize Vega specifications\n * Similar to the frontend handler.ts but focusing only on core styling needs\n */\nexport class VegaSpecHandler {\n  public config: Config;\n  public data: { values: any[] };\n  public encoding: any;\n  public mark: any;\n  public width: 'container';\n  public height: 'container';\n  public autosize: { type: string; contains: string };\n  public params: any[];\n  public title: string;\n  public $schema: string;\n\n  constructor(spec: any, dataValues: any[]) {\n    this.config = config;\n    this.$schema = 'https://vega.github.io/schema/vega-lite/v5.json';\n    this.title = spec.title;\n    this.width = 'container';\n    this.height = 'container';\n    this.autosize = { type: 'fit', contains: 'padding' };\n    this.data = { values: dataValues };\n    this.params = [\n      {\n        name: 'hover',\n        select: {\n          type: 'point',\n          on: 'mouseover',\n          clear: 'mouseout',\n        },\n      },\n    ];\n\n    // Clone to avoid mutating the original spec\n    const clonedSpec = { ...spec };\n    this.parseSpec(clonedSpec);\n  }\n\n  /**\n   * Returns the complete enhanced Vega specification\n   */\n  public getChartSpec(): TopLevelSpec {\n    return {\n      $schema: this.$schema,\n      config: this.config,\n      title: this.title,\n      data: this.data,\n      mark: this.mark,\n      width: this.width,\n      height: this.height,\n      autosize: this.autosize,\n      encoding: this.encoding,\n      params: this.params,\n    } as TopLevelSpec;\n  }\n\n  /**\n   * Parses the input specification to extract and enhance components\n   */\n  private parseSpec(spec: any): void {\n    if ('mark' in spec) {\n      const mark =\n        typeof spec.mark === 'string' ? { type: spec.mark } : spec.mark;\n      this.addMark(mark);\n    }\n\n    if ('encoding' in spec) {\n      this.addEncoding(spec.encoding);\n    }\n  }\n\n  /**\n   * Processes and enhances the mark specification\n   */\n  private addMark(mark: any): void {\n    this.mark = {\n      type: mark.type,\n    };\n\n    // Handle specific mark types if needed\n    if (mark.type === MarkType.LINE) {\n      this.mark.point = true;\n    } else if (mark.type === MarkType.ARC) {\n      // Default inner radius for donut charts\n      this.mark.innerRadius = 60;\n    }\n  }\n\n  /**\n   * Processes and enhances encoding with proper color and interactivity\n   */\n  private addEncoding(encoding: any): void {\n    this.encoding = { ...encoding };\n\n    // Add color field if not provided\n    this.addColorEncoding();\n\n    // Handle special case for bar charts\n    this.handleBarChartEncoding();\n\n    // Add interactivity through opacity\n    this.addOpacityForInteractivity();\n  }\n\n  /**\n   * Handles special encoding for bar charts\n   */\n  private handleBarChartEncoding(): void {\n    if (this.mark.type === MarkType.BAR) {\n      // Handle stacking for bar charts\n      if (this.encoding.y && 'stack' in this.encoding.y) {\n        this.encoding.y.stack = 'zero';\n      }\n\n      // Handle xOffset titles if present\n      if (this.encoding.xOffset) {\n        const xOffset = this.encoding.xOffset;\n        let title = xOffset.title;\n\n        // Find xOffset title if not provided\n        if (!title && xOffset.field) {\n          title = this.findFieldTitleInEncoding(xOffset.field);\n        }\n\n        if (title) {\n          this.encoding.xOffset.title = title;\n        }\n      }\n    }\n  }\n\n  /**\n   * Utility to find a field's title from other encodings\n   */\n  private findFieldTitleInEncoding(field: string): string | undefined {\n    const axes = ['x', 'y', 'xOffset', 'color'];\n\n    for (const axis of axes) {\n      if (this.encoding[axis]?.field === field && this.encoding[axis]?.title) {\n        return this.encoding[axis].title;\n      }\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Adds or enhances color encoding\n   */\n  private addColorEncoding(): void {\n    // If no color encoding exists, use a nominal axis\n    if (!this.encoding.color) {\n      const nominalAxis = ['x', 'y'].find(\n        (axis) => this.encoding[axis]?.type === 'nominal',\n      );\n\n      if (nominalAxis) {\n        const category = this.encoding[nominalAxis];\n        this.encoding.color = {\n          field: category.field,\n          type: category.type,\n          title: category.title || category.field,\n          scale: {\n            range: colorScheme,\n          },\n        };\n      }\n    } else if (this.encoding.color && !this.encoding.color.scale) {\n      // Add color scale if not present\n      this.encoding.color.scale = {\n        range: colorScheme,\n      };\n    }\n\n    // Set up hover fields for the interactive parameter\n    if (this.params && this.encoding.color?.field) {\n      this.params[0].select.fields = [this.encoding.color.field];\n    }\n  }\n\n  /**\n   * Adds opacity encoding for hover interactivity\n   */\n  private addOpacityForInteractivity(): void {\n    // Add opacity for hover effect\n    if (!this.encoding.opacity) {\n      this.encoding.opacity = {\n        condition: {\n          param: 'hover',\n          value: 1,\n        },\n        value: 0.3,\n      };\n    }\n  }\n}\n\n/**\n * Enhances a Vega specification with standard configuration and styling\n *\n * @param vegaSpec The original Vega specification from the AI model\n * @param dataValues The data to be visualized\n * @returns Enhanced Vega specification with consistent styling\n */\nexport function enhanceVegaSpec(\n  vegaSpec: any,\n  dataValues: any[],\n): TopLevelSpec {\n  const handler = new VegaSpecHandler(vegaSpec, dataValues);\n  return handler.getChartSpec();\n}\n"
  },
  {
    "path": "wren-ui/tools/knex.js",
    "content": "const DB_TYPE = process.env.DB_TYPE; // export DB_TYPE=pg\nconst PG_URL = process.env.PG_URL;\nconst DEBUG = process.env.DEBUG === 'true'; // export DEBUG=true\nconst SQLITE_FILE = process.env.SQLITE_FILE; // export SQLITE_FILE=./db.sqlite3\n\nconst getKnex = () => {\n  if (DB_TYPE === 'pg') {\n    console.log('using pg');\n    /* eslint-disable @typescript-eslint/no-var-requires */\n    return require('knex')({\n      client: 'pg',\n      connection: PG_URL,\n      debug: DEBUG,\n      pool: { min: 2, max: 10 },\n    });\n  } else {\n    console.log('using sqlite');\n    /* eslint-disable @typescript-eslint/no-var-requires */\n    return require('knex')({\n      client: 'better-sqlite3',\n      connection: {\n        filename: SQLITE_FILE,\n      },\n      useNullAsDefault: true,\n    });\n  }\n};\n\nconst main = async () => {\n  const knex = getKnex();\n  const query = knex.queryBuilder();\n\n  const projects = await query\n    .select('*')\n    .from('instruction')\n    .whereIn('id', [7, 8]);\n\n  console.log(projects);\n  process.exit(0);\n};\n\nmain();\n"
  },
  {
    "path": "wren-ui/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es2015\",\n    \"lib\": [\"es2017\", \"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"skipDefaultLibCheck\": true,\n    \"strict\": false,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"preserve\",\n    \"incremental\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"experimentalDecorators\": true,\n    \"plugins\": [\n      {\n        \"name\": \"next\"\n      }\n    ],\n    \"paths\": {\n      \"@/*\": [\"./src/*\"],\n      \"@server\": [\"./src/apollo/server/index.ts\"],\n      \"@server/*\": [\"./src/apollo/server/*\"],\n    }\n  },\n  \"include\": [\"next-env.d.ts\", \"**/*.ts\", \"**/*.tsx\", \".next/types/**/*.ts\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  }
]